2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_BLOCK_SCOPE_H_
18 #define incl_HPHP_BLOCK_SCOPE_H_
20 #include "hphp/compiler/hphp.h"
22 #include "hphp/util/bits.h"
23 #include "hphp/util/lock.h"
24 #include "hphp/runtime/base/macros.h"
26 #include <tbb/concurrent_hash_map.h>
34 ///////////////////////////////////////////////////////////////////////////////
37 DECLARE_BOOST_TYPES(Statement
);
38 DECLARE_BOOST_TYPES(AnalysisResult
);
39 DECLARE_BOOST_TYPES(VariableTable
);
40 DECLARE_BOOST_TYPES(ConstantTable
);
41 DECLARE_BOOST_TYPES(ModifierExpression
);
42 DECLARE_BOOST_TYPES(IncludeExpression
);
43 DECLARE_BOOST_TYPES(StatementList
);
44 DECLARE_BOOST_TYPES(BlockScope
);
45 DECLARE_BOOST_TYPES(ClassScope
);
46 DECLARE_BOOST_TYPES(FunctionScope
);
47 DECLARE_BOOST_TYPES(FileScope
);
49 typedef hphp_hash_map
<BlockScopeRawPtr
, int,
50 smart_pointer_hash
<BlockScopeRawPtr
>
51 > BlockScopeRawPtrFlagsHashMap
;
52 typedef hphp_hash_set
<BlockScopeRawPtr
,
53 smart_pointer_hash
<BlockScopeRawPtr
>
54 > BlockScopeRawPtrHashSet
;
55 typedef tbb::concurrent_hash_map
<BlockScopeRawPtr
, int,
56 smart_pointer_hash
<BlockScopeRawPtr
> >
57 ConcurrentBlockScopeRawPtrIntHashMap
;
59 typedef std::vector
<BlockScopeRawPtr
> BlockScopeRawPtrVec
;
60 typedef std::list
<BlockScopeRawPtr
> BlockScopeRawPtrQueue
;
61 typedef std::vector
<BlockScopeRawPtrFlagsHashMap::
62 value_type
*> BlockScopeRawPtrFlagsVec
;
63 typedef std::pair
< BlockScopeRawPtr
, int* >
64 BlockScopeRawPtrFlagsPtrPair
;
65 typedef std::vector
< std::pair
< BlockScopeRawPtr
, int* > >
66 BlockScopeRawPtrFlagsPtrVec
;
68 typedef SimpleMutex InferTypesMutex
;
71 * Base class of ClassScope and FunctionScope.
73 class BlockScope
: private boost::noncopyable
,
74 public std::enable_shared_from_this
<BlockScope
> {
85 UseKindCallerInline
= 0x1,
86 UseKindCallerParam
= 0x1 << 1,
87 UseKindCallerReturn
= 0x1 << 2,
88 UseKindCaller
= (UseKindCallerInline
|
92 /* Static references */
93 UseKindStaticRef
= 0x1 << 3,
95 /* 16 bits of Non static references */
96 UseKindNonStaticRef0
= 0x1 << 4,
97 UseKindNonStaticRef1
= 0x1 << 5,
98 UseKindNonStaticRef2
= 0x1 << 6,
99 UseKindNonStaticRef3
= 0x1 << 7,
100 UseKindNonStaticRef4
= 0x1 << 8,
101 UseKindNonStaticRef5
= 0x1 << 9,
102 UseKindNonStaticRef6
= 0x1 << 10,
103 UseKindNonStaticRef7
= 0x1 << 11,
104 UseKindNonStaticRef8
= 0x1 << 12,
105 UseKindNonStaticRef9
= 0x1 << 13,
106 UseKindNonStaticRef10
= 0x1 << 14,
107 UseKindNonStaticRef11
= 0x1 << 15,
108 UseKindNonStaticRef12
= 0x1 << 16,
109 UseKindNonStaticRef13
= 0x1 << 17,
110 UseKindNonStaticRef14
= 0x1 << 18,
111 UseKindNonStaticRef15
= 0x1 << 19,
112 UseKindNonStaticRef
= (UseKindNonStaticRef0
|
113 UseKindNonStaticRef1
|
114 UseKindNonStaticRef2
|
115 UseKindNonStaticRef3
|
116 UseKindNonStaticRef4
|
117 UseKindNonStaticRef5
|
118 UseKindNonStaticRef6
|
119 UseKindNonStaticRef7
|
120 UseKindNonStaticRef8
|
121 UseKindNonStaticRef9
|
122 UseKindNonStaticRef10
|
123 UseKindNonStaticRef11
|
124 UseKindNonStaticRef12
|
125 UseKindNonStaticRef13
|
126 UseKindNonStaticRef14
|
127 UseKindNonStaticRef15
),
130 UseKindConstRef
= 0x1 << 20,
133 UseKindParentRef
= 0x1 << 21,
134 UseKindInclude
= 0x1 << 22,
135 UseKindClosure
= 0x1 << 23,
136 UseKindAny
= (unsigned)-1
139 /* Assert the size and bit-consecutiveness of UseKindNonStaticRef */
140 static_assert(BitCount
<UseKindNonStaticRef
>::value
== 16,
141 "UseKindNonStaticRef should have 16 bits set");
142 static_assert(BitPhase
<UseKindNonStaticRef
>::value
<= 2,
143 "UseKindNonStaticRef set bits should be consecutive");
145 static int GetNonStaticRefUseKind(unsigned int hash
) {
146 int res
= ((int)UseKindNonStaticRef0
) << (hash
% 16);
147 assert(res
>= ((int)UseKindNonStaticRef0
) &&
148 res
<= ((int)UseKindNonStaticRef15
));
158 MarkProcessedInQueue
,
164 bool operator()(const BlockScopeRawPtr
&p1
,
165 const BlockScopeRawPtr
&p2
) const {
166 return cmp(p1
,p2
) < 0;
168 int cmp(const BlockScopeRawPtr
&p1
, const BlockScopeRawPtr
&p2
) const;
170 typedef std::set
<BlockScopeRawPtr
, ScopeCompare
> BlockScopeSet
;
171 friend class ScopeCompare
;
173 BlockScope(const std::string
&name
, const std::string
&docComment
,
174 StatementPtr stmt
, KindOf kind
);
175 virtual ~BlockScope() {}
176 bool is(KindOf kind
) const { return kind
== m_kind
;}
177 const std::string
&getName() const { return m_name
;}
178 void setName(const std::string name
) { m_name
= name
;}
179 virtual bool isBuiltin() const { return false; }
180 StatementPtr
getStmt() const { return m_stmt
;}
181 VariableTableConstPtr
getVariables() const { return m_variables
;}
182 ConstantTableConstPtr
getConstants() const { return m_constants
;}
183 VariableTablePtr
getVariables() { return m_variables
;}
184 ConstantTablePtr
getConstants() { return m_constants
;}
185 ClassScopeRawPtr
getContainingClass();
186 FunctionScopeRawPtr
getContainingNonClosureFunction();
187 FunctionScopeRawPtr
getContainingFunction() const {
188 return FunctionScopeRawPtr(is(FunctionScope
) ?
189 (HPHP::FunctionScope
*)this : 0);
191 FileScopeRawPtr
getContainingFile();
192 AnalysisResultRawPtr
getContainingProgram();
194 ClassScopeRawPtr
findExactClass(ClassScopeRawPtr cls
);
195 FunctionScopeRawPtr
findExactFunction(FunctionScopeRawPtr func
);
197 bool hasUser(BlockScopeRawPtr user
, int useFlags
) const;
198 void addUse(BlockScopeRawPtr user
, int useFlags
);
201 * Helpers for keeping track of break/continue nested level.
203 void incLoopNestedLevel();
204 void decLoopNestedLevel();
205 int getLoopNestedLevel() const { return m_loopNestedLevel
;}
208 * Helpers for parsing class functions and variables.
210 ModifierExpressionPtr
setModifiers(ModifierExpressionPtr modifiers
);
211 ModifierExpressionPtr
getModifiers() { return m_modifiers
;}
213 void setClassInfoAttribute(int flag
) {
214 m_attributeClassInfo
|= flag
;
216 const std::string
&getDocComment() const { return m_docComment
;}
217 void setDocComment(const std::string
&doc
) { m_docComment
= doc
;}
220 * Triggers type inference of all statements inside this block.
222 void inferTypes(AnalysisResultPtr ar
);
227 virtual void outputPHP(CodeGenerator
&cg
, AnalysisResultPtr ar
);
229 virtual bool inPseudoMain() const {
233 virtual ClassScopePtr
getParentScope(AnalysisResultConstPtr ar
) const {
234 return ClassScopePtr();
237 void setOuterScope(BlockScopePtr o
) { m_outerScope
= o
; }
238 BlockScopePtr
getOuterScope() { return m_outerScope
.lock(); }
239 bool isOuterScope() { return m_outerScope
.expired(); }
241 const BlockScopeRawPtrFlagsPtrVec
&getDeps() const {
242 return m_orderedDeps
;
244 const BlockScopeRawPtrFlagsVec
&getOrderedUsers() const {
245 return m_orderedUsers
;
248 void setMark(Marks m
) { m_mark
= m
; }
249 Marks
getMark() const { return m_mark
; }
251 void setLockedMark(Marks m
) { Lock
l(s_jobStateMutex
); m_mark
= m
; }
252 Marks
getLockedMark() const { Lock
l(s_jobStateMutex
); return m_mark
; }
254 void incPass() { m_pass
++; }
255 bool isFirstPass() const { return !m_pass
; }
257 void incRunId() { m_runId
++; }
258 int getRunId() const { return m_runId
; }
260 void clearUpdated() { m_updated
= 0; }
261 void addUpdates(int f
);
262 void announceUpdates(int f
);
263 int getUpdated() const { return m_updated
; }
265 void setInTypeInference(bool inTypeInference
) {
266 m_inTypeInference
= inTypeInference
;
268 bool inTypeInference() const { return m_inTypeInference
; }
270 void setInVisitScopes(bool inVisitScopes
) {
271 m_inVisitScopes
= inVisitScopes
;
273 bool inVisitScopes() const { return m_inVisitScopes
; }
275 void setNeedsReschedule(bool needsReschedule
) {
276 m_needsReschedule
= needsReschedule
;
278 bool needsReschedule() const { return m_needsReschedule
; }
280 void setRescheduleFlags(int rescheduleFlags
) {
281 m_rescheduleFlags
= rescheduleFlags
;
283 int rescheduleFlags() const { return m_rescheduleFlags
; }
285 void incEffectsTag() { m_effectsTag
++; }
286 int getEffectsTag() const { return m_effectsTag
; }
288 Mutex
&getMutex() { return m_mutex
; }
289 InferTypesMutex
&getInferTypesMutex() { return m_inferTypesMutex
; }
291 void setNumDepsToWaitFor(int n
) {
293 m_numDepsToWaitFor
= n
;
295 int getNumDepsToWaitFor() const {
296 return m_numDepsToWaitFor
;
298 int incNumDepsToWaitFor() {
299 return ++m_numDepsToWaitFor
;
301 int decNumDepsToWaitFor() {
302 assert(m_numDepsToWaitFor
> 0);
303 return --m_numDepsToWaitFor
;
306 inline void assertNumDepsSanity() const {
307 #ifdef HPHP_DETAILED_TYPE_INF_ASSERT
309 const BlockScopeRawPtrFlagsPtrVec
&deps
= getDeps();
310 for (BlockScopeRawPtrFlagsPtrVec::const_iterator it
= deps
.begin(),
311 end
= deps
.end(); it
!= end
; ++it
) {
312 const BlockScopeRawPtrFlagsPtrPair
&p(*it
);
313 int m
= p
.first
->getMark();
314 if (m
== MarkWaiting
||
316 m
== MarkProcessing
) {
319 assert(m
== MarkProcessed
);
323 assert(waiting
>= getNumDepsToWaitFor());
324 #endif /* HPHP_DETAILED_TYPE_INF_ASSERT */
327 void setForceRerun(bool v
) { m_forceRerun
= v
; }
328 bool forceRerun() const { return m_forceRerun
; }
330 int selfUser() const { return m_selfUser
; }
333 std::string m_originalName
;
335 int m_attributeClassInfo
;
336 std::string m_docComment
;
339 VariableTablePtr m_variables
;
340 ConstantTablePtr m_constants
;
341 BlockScopeRawPtr m_outerScope
;
343 int m_loopNestedLevel
;
344 ModifierExpressionPtr m_modifiers
;
345 StatementListPtr m_includes
;
351 BlockScopeRawPtrFlagsPtrVec m_orderedDeps
;
352 BlockScopeRawPtrFlagsVec m_orderedUsers
;
353 BlockScopeRawPtrFlagsHashMap m_userMap
;
355 int m_numDepsToWaitFor
;
357 InferTypesMutex m_inferTypesMutex
;
358 bool m_forceRerun
; /* do we need to be re-run (allows deps to run during
360 bool m_inTypeInference
; /* are we in AnalysisResult::inferTypes() */
361 bool m_inVisitScopes
; /* are we in visitScope() */
362 bool m_needsReschedule
; /* do we need to be re-scheduled (does not allow deps
363 * to run during re-schedule) */
364 int m_rescheduleFlags
; /* who do we need to run after a re-schedule */
367 static Mutex s_jobStateMutex
;
368 static Mutex s_depsMutex
;
369 static Mutex s_constMutex
;
372 ///////////////////////////////////////////////////////////////////////////////
374 #endif // incl_HPHP_BLOCK_SCOPE_H_