PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/compiler/analysis/block_scope.h

https://github.com/tstarling/hiphop-php
C Header | 374 lines | 284 code | 49 blank | 41 comment | 10 complexity | 4cdb6aafac171eb337acd9f32ac4a7fb MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  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. +----------------------------------------------------------------------+
  15. */
  16. #ifndef incl_HPHP_BLOCK_SCOPE_H_
  17. #define incl_HPHP_BLOCK_SCOPE_H_
  18. #include "hphp/compiler/hphp.h"
  19. #include "hphp/util/bits.h"
  20. #include "hphp/util/lock.h"
  21. #include "hphp/runtime/base/macros.h"
  22. #include <tbb/concurrent_hash_map.h>
  23. #include <list>
  24. #include <memory>
  25. #include <set>
  26. #include <utility>
  27. #include <vector>
  28. namespace HPHP {
  29. ///////////////////////////////////////////////////////////////////////////////
  30. class CodeGenerator;
  31. DECLARE_BOOST_TYPES(Statement);
  32. DECLARE_BOOST_TYPES(AnalysisResult);
  33. DECLARE_BOOST_TYPES(VariableTable);
  34. DECLARE_BOOST_TYPES(ConstantTable);
  35. DECLARE_BOOST_TYPES(ModifierExpression);
  36. DECLARE_BOOST_TYPES(IncludeExpression);
  37. DECLARE_BOOST_TYPES(StatementList);
  38. DECLARE_BOOST_TYPES(BlockScope);
  39. DECLARE_BOOST_TYPES(ClassScope);
  40. DECLARE_BOOST_TYPES(FunctionScope);
  41. DECLARE_BOOST_TYPES(FileScope);
  42. typedef hphp_hash_map<BlockScopeRawPtr, int,
  43. smart_pointer_hash<BlockScopeRawPtr>
  44. > BlockScopeRawPtrFlagsHashMap;
  45. typedef hphp_hash_set<BlockScopeRawPtr,
  46. smart_pointer_hash<BlockScopeRawPtr>
  47. > BlockScopeRawPtrHashSet;
  48. typedef tbb::concurrent_hash_map<BlockScopeRawPtr, int,
  49. smart_pointer_hash<BlockScopeRawPtr> >
  50. ConcurrentBlockScopeRawPtrIntHashMap;
  51. typedef std::vector<BlockScopeRawPtr> BlockScopeRawPtrVec;
  52. typedef std::list<BlockScopeRawPtr> BlockScopeRawPtrQueue;
  53. typedef std::vector<BlockScopeRawPtrFlagsHashMap::
  54. value_type*> BlockScopeRawPtrFlagsVec;
  55. typedef std::pair< BlockScopeRawPtr, int* >
  56. BlockScopeRawPtrFlagsPtrPair;
  57. typedef std::vector< std::pair< BlockScopeRawPtr, int* > >
  58. BlockScopeRawPtrFlagsPtrVec;
  59. typedef SimpleMutex InferTypesMutex;
  60. /**
  61. * Base class of ClassScope and FunctionScope.
  62. */
  63. class BlockScope : private boost::noncopyable,
  64. public std::enable_shared_from_this<BlockScope> {
  65. public:
  66. enum KindOf {
  67. ClassScope,
  68. FunctionScope,
  69. FileScope,
  70. ProgramScope,
  71. };
  72. enum UseKinds {
  73. /* Callers */
  74. UseKindCallerInline = 0x1,
  75. UseKindCallerParam = 0x1 << 1,
  76. UseKindCallerReturn = 0x1 << 2,
  77. UseKindCaller = (UseKindCallerInline |
  78. UseKindCallerParam |
  79. UseKindCallerReturn),
  80. /* Static references */
  81. UseKindStaticRef = 0x1 << 3,
  82. /* 16 bits of Non static references */
  83. UseKindNonStaticRef0 = 0x1 << 4,
  84. UseKindNonStaticRef1 = 0x1 << 5,
  85. UseKindNonStaticRef2 = 0x1 << 6,
  86. UseKindNonStaticRef3 = 0x1 << 7,
  87. UseKindNonStaticRef4 = 0x1 << 8,
  88. UseKindNonStaticRef5 = 0x1 << 9,
  89. UseKindNonStaticRef6 = 0x1 << 10,
  90. UseKindNonStaticRef7 = 0x1 << 11,
  91. UseKindNonStaticRef8 = 0x1 << 12,
  92. UseKindNonStaticRef9 = 0x1 << 13,
  93. UseKindNonStaticRef10 = 0x1 << 14,
  94. UseKindNonStaticRef11 = 0x1 << 15,
  95. UseKindNonStaticRef12 = 0x1 << 16,
  96. UseKindNonStaticRef13 = 0x1 << 17,
  97. UseKindNonStaticRef14 = 0x1 << 18,
  98. UseKindNonStaticRef15 = 0x1 << 19,
  99. UseKindNonStaticRef = (UseKindNonStaticRef0 |
  100. UseKindNonStaticRef1 |
  101. UseKindNonStaticRef2 |
  102. UseKindNonStaticRef3 |
  103. UseKindNonStaticRef4 |
  104. UseKindNonStaticRef5 |
  105. UseKindNonStaticRef6 |
  106. UseKindNonStaticRef7 |
  107. UseKindNonStaticRef8 |
  108. UseKindNonStaticRef9 |
  109. UseKindNonStaticRef10 |
  110. UseKindNonStaticRef11 |
  111. UseKindNonStaticRef12 |
  112. UseKindNonStaticRef13 |
  113. UseKindNonStaticRef14 |
  114. UseKindNonStaticRef15),
  115. /* Constants */
  116. UseKindConstRef = 0x1 << 20,
  117. /* Other types */
  118. UseKindParentRef = 0x1 << 21,
  119. UseKindInclude = 0x1 << 22,
  120. UseKindClosure = 0x1 << 23,
  121. UseKindAny = (unsigned)-1
  122. };
  123. /* Assert the size and bit-consecutiveness of UseKindNonStaticRef */
  124. static_assert(BitCount<UseKindNonStaticRef>::value == 16,
  125. "UseKindNonStaticRef should have 16 bits set");
  126. static_assert(BitPhase<UseKindNonStaticRef>::value <= 2,
  127. "UseKindNonStaticRef set bits should be consecutive");
  128. static int GetNonStaticRefUseKind(unsigned int hash) {
  129. int res = ((int)UseKindNonStaticRef0) << (hash % 16);
  130. assert(res >= ((int)UseKindNonStaticRef0) &&
  131. res <= ((int)UseKindNonStaticRef15));
  132. return res;
  133. }
  134. enum Marks {
  135. MarkWaitingInQueue,
  136. MarkProcessingDeps,
  137. MarkReady,
  138. MarkWaiting,
  139. MarkProcessing,
  140. MarkProcessedInQueue,
  141. MarkProcessed
  142. };
  143. class ScopeCompare {
  144. public:
  145. bool operator()(const BlockScopeRawPtr &p1,
  146. const BlockScopeRawPtr &p2) const {
  147. return cmp(p1,p2) < 0;
  148. }
  149. int cmp(const BlockScopeRawPtr &p1, const BlockScopeRawPtr &p2) const;
  150. };
  151. typedef std::set<BlockScopeRawPtr, ScopeCompare> BlockScopeSet;
  152. friend class ScopeCompare;
  153. BlockScope(const std::string &name, const std::string &docComment,
  154. StatementPtr stmt, KindOf kind);
  155. virtual ~BlockScope() {}
  156. bool is(KindOf kind) const { return kind == m_kind;}
  157. const std::string &getName() const { return m_name;}
  158. void setName(const std::string name) { m_name = name;}
  159. virtual bool isBuiltin() const { return false; }
  160. StatementPtr getStmt() const { return m_stmt;}
  161. VariableTableConstPtr getVariables() const { return m_variables;}
  162. ConstantTableConstPtr getConstants() const { return m_constants;}
  163. VariableTablePtr getVariables() { return m_variables;}
  164. ConstantTablePtr getConstants() { return m_constants;}
  165. ClassScopeRawPtr getContainingClass();
  166. FunctionScopeRawPtr getContainingNonClosureFunction();
  167. FunctionScopeRawPtr getContainingFunction() const {
  168. return FunctionScopeRawPtr(is(FunctionScope) ?
  169. (HPHP::FunctionScope*)this : 0);
  170. }
  171. FileScopeRawPtr getContainingFile();
  172. AnalysisResultRawPtr getContainingProgram();
  173. ClassScopeRawPtr findExactClass(ClassScopeRawPtr cls);
  174. FunctionScopeRawPtr findExactFunction(FunctionScopeRawPtr func);
  175. bool hasUser(BlockScopeRawPtr user, int useFlags) const;
  176. void addUse(BlockScopeRawPtr user, int useFlags);
  177. /**
  178. * Helpers for keeping track of break/continue nested level.
  179. */
  180. void incLoopNestedLevel();
  181. void decLoopNestedLevel();
  182. int getLoopNestedLevel() const { return m_loopNestedLevel;}
  183. /**
  184. * Helpers for parsing class functions and variables.
  185. */
  186. ModifierExpressionPtr setModifiers(ModifierExpressionPtr modifiers);
  187. ModifierExpressionPtr getModifiers() { return m_modifiers;}
  188. void setClassInfoAttribute(int flag) {
  189. m_attributeClassInfo |= flag;
  190. }
  191. const std::string &getDocComment() const { return m_docComment;}
  192. void setDocComment(const std::string &doc) { m_docComment = doc;}
  193. /**
  194. * Triggers type inference of all statements inside this block.
  195. */
  196. void inferTypes(AnalysisResultPtr ar);
  197. /**
  198. * Code gen
  199. */
  200. virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
  201. virtual bool inPseudoMain() const {
  202. return false;
  203. }
  204. virtual ClassScopePtr getParentScope(AnalysisResultConstPtr ar) const {
  205. return ClassScopePtr();
  206. }
  207. void setOuterScope(BlockScopePtr o) { m_outerScope = o; }
  208. BlockScopePtr getOuterScope() { return m_outerScope.lock(); }
  209. bool isOuterScope() { return m_outerScope.expired(); }
  210. const BlockScopeRawPtrFlagsPtrVec &getDeps() const {
  211. return m_orderedDeps;
  212. }
  213. const BlockScopeRawPtrFlagsVec &getOrderedUsers() const {
  214. return m_orderedUsers;
  215. }
  216. void setMark(Marks m) { m_mark = m; }
  217. Marks getMark() const { return m_mark; }
  218. void setLockedMark(Marks m) { Lock l(s_jobStateMutex); m_mark = m; }
  219. Marks getLockedMark() const { Lock l(s_jobStateMutex); return m_mark; }
  220. void incPass() { m_pass++; }
  221. bool isFirstPass() const { return !m_pass; }
  222. void incRunId() { m_runId++; }
  223. int getRunId() const { return m_runId; }
  224. void clearUpdated() { m_updated = 0; }
  225. void addUpdates(int f);
  226. void announceUpdates(int f);
  227. int getUpdated() const { return m_updated; }
  228. void setInTypeInference(bool inTypeInference) {
  229. m_inTypeInference = inTypeInference;
  230. }
  231. bool inTypeInference() const { return m_inTypeInference; }
  232. void setInVisitScopes(bool inVisitScopes) {
  233. m_inVisitScopes = inVisitScopes;
  234. }
  235. bool inVisitScopes() const { return m_inVisitScopes; }
  236. void setNeedsReschedule(bool needsReschedule) {
  237. m_needsReschedule = needsReschedule;
  238. }
  239. bool needsReschedule() const { return m_needsReschedule; }
  240. void setRescheduleFlags(int rescheduleFlags) {
  241. m_rescheduleFlags = rescheduleFlags;
  242. }
  243. int rescheduleFlags() const { return m_rescheduleFlags; }
  244. void incEffectsTag() { m_effectsTag++; }
  245. int getEffectsTag() const { return m_effectsTag; }
  246. Mutex &getMutex() { return m_mutex; }
  247. InferTypesMutex &getInferTypesMutex() { return m_inferTypesMutex; }
  248. void setNumDepsToWaitFor(int n) {
  249. assert(n >= 0);
  250. m_numDepsToWaitFor = n;
  251. }
  252. int getNumDepsToWaitFor() const {
  253. return m_numDepsToWaitFor;
  254. }
  255. int incNumDepsToWaitFor() {
  256. return ++m_numDepsToWaitFor;
  257. }
  258. int decNumDepsToWaitFor() {
  259. assert(m_numDepsToWaitFor > 0);
  260. return --m_numDepsToWaitFor;
  261. }
  262. inline void assertNumDepsSanity() const {
  263. #ifdef HPHP_DETAILED_TYPE_INF_ASSERT
  264. int waiting = 0;
  265. const BlockScopeRawPtrFlagsPtrVec &deps = getDeps();
  266. for (BlockScopeRawPtrFlagsPtrVec::const_iterator it = deps.begin(),
  267. end = deps.end(); it != end; ++it) {
  268. const BlockScopeRawPtrFlagsPtrPair &p(*it);
  269. int m = p.first->getMark();
  270. if (m == MarkWaiting ||
  271. m == MarkReady ||
  272. m == MarkProcessing) {
  273. waiting++;
  274. } else {
  275. assert(m == MarkProcessed);
  276. }
  277. }
  278. // >= b/c of cycles
  279. assert(waiting >= getNumDepsToWaitFor());
  280. #endif /* HPHP_DETAILED_TYPE_INF_ASSERT */
  281. }
  282. void setForceRerun(bool v) { m_forceRerun = v; }
  283. bool forceRerun() const { return m_forceRerun; }
  284. int selfUser() const { return m_selfUser; }
  285. protected:
  286. std::string m_originalName;
  287. std::string m_name;
  288. int m_attributeClassInfo;
  289. std::string m_docComment;
  290. StatementPtr m_stmt;
  291. KindOf m_kind;
  292. VariableTablePtr m_variables;
  293. ConstantTablePtr m_constants;
  294. BlockScopeRawPtr m_outerScope;
  295. int m_loopNestedLevel;
  296. ModifierExpressionPtr m_modifiers;
  297. StatementListPtr m_includes;
  298. int m_pass;
  299. int m_updated;
  300. int m_runId;
  301. private:
  302. Marks m_mark;
  303. BlockScopeRawPtrFlagsPtrVec m_orderedDeps;
  304. BlockScopeRawPtrFlagsVec m_orderedUsers;
  305. BlockScopeRawPtrFlagsHashMap m_userMap;
  306. int m_effectsTag;
  307. int m_numDepsToWaitFor;
  308. Mutex m_mutex;
  309. InferTypesMutex m_inferTypesMutex;
  310. bool m_forceRerun; /* do we need to be re-run (allows deps to run during
  311. * re-schedule) */
  312. bool m_inTypeInference; /* are we in AnalysisResult::inferTypes() */
  313. bool m_inVisitScopes; /* are we in visitScope() */
  314. bool m_needsReschedule; /* do we need to be re-scheduled (does not allow deps
  315. * to run during re-schedule) */
  316. int m_rescheduleFlags; /* who do we need to run after a re-schedule */
  317. int m_selfUser;
  318. public:
  319. static Mutex s_jobStateMutex;
  320. static Mutex s_depsMutex;
  321. static Mutex s_constMutex;
  322. };
  323. ///////////////////////////////////////////////////////////////////////////////
  324. }
  325. #endif // incl_HPHP_BLOCK_SCOPE_H_