Scope.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. enum ScopeType: int
  7. {
  8. ScopeType_Unknown,
  9. ScopeType_Global,
  10. ScopeType_GlobalEvalBlock,
  11. ScopeType_FunctionBody,
  12. ScopeType_FuncExpr,
  13. ScopeType_Block,
  14. ScopeType_Catch,
  15. ScopeType_CatchParamPattern,
  16. ScopeType_With,
  17. ScopeType_Parameter
  18. };
  19. class Scope
  20. {
  21. private:
  22. Scope *enclosingScope;
  23. Js::ScopeInfo *scopeInfo;
  24. Js::RegSlot location;
  25. FuncInfo *func;
  26. Symbol *m_symList;
  27. int m_count;
  28. ArenaAllocator *alloc;
  29. uint scopeSlotCount; // count of slots in the local scope
  30. uint innerScopeIndex;
  31. ScopeType const scopeType;
  32. BYTE isDynamic : 1;
  33. BYTE isObject : 1;
  34. BYTE canMerge : 1;
  35. BYTE capturesAll : 1;
  36. BYTE mustInstantiate : 1;
  37. BYTE hasCrossScopeFuncAssignment : 1;
  38. BYTE hasDuplicateFormals : 1;
  39. BYTE canMergeWithBodyScope : 1;
  40. BYTE hasLocalInClosure : 1;
  41. BYTE isBlockInLoop : 1;
  42. public:
  43. #if DBG
  44. BYTE isRestored : 1;
  45. #endif
  46. Scope(ArenaAllocator *alloc, ScopeType scopeType, int capacity = 0) :
  47. alloc(alloc),
  48. func(nullptr),
  49. enclosingScope(nullptr),
  50. scopeInfo(nullptr),
  51. isDynamic(false),
  52. isObject(false),
  53. canMerge(true),
  54. capturesAll(false),
  55. mustInstantiate(false),
  56. hasCrossScopeFuncAssignment(false),
  57. hasDuplicateFormals(false),
  58. canMergeWithBodyScope(true),
  59. hasLocalInClosure(false),
  60. isBlockInLoop(false),
  61. location(Js::Constants::NoRegister),
  62. m_symList(nullptr),
  63. m_count(0),
  64. scopeSlotCount(0),
  65. innerScopeIndex((uint)-1),
  66. scopeType(scopeType)
  67. #if DBG
  68. , isRestored(false)
  69. #endif
  70. {
  71. }
  72. Symbol *FindLocalSymbol(SymbolName const& key)
  73. {
  74. Symbol *sym;
  75. for (sym = m_symList; sym; sym = sym->GetNext())
  76. {
  77. if (sym->GetName() == key)
  78. {
  79. break;
  80. }
  81. }
  82. return sym;
  83. }
  84. template<class Fn>
  85. void ForEachSymbol(Fn fn)
  86. {
  87. for (Symbol *sym = m_symList; sym;)
  88. {
  89. Symbol *next = sym->GetNext();
  90. fn(sym);
  91. sym = next;
  92. }
  93. }
  94. template<class Fn>
  95. void ForEachSymbolUntil(Fn fn)
  96. {
  97. for (Symbol *sym = m_symList; sym;)
  98. {
  99. Symbol *next = sym->GetNext();
  100. if (fn(sym))
  101. {
  102. return;
  103. }
  104. sym = next;
  105. }
  106. }
  107. void AddSymbol(Symbol *sym)
  108. {
  109. if (enclosingScope == nullptr)
  110. {
  111. sym->SetIsGlobal(true);
  112. }
  113. sym->SetScope(this);
  114. for (Symbol *symInList = m_symList; symInList; symInList = symInList->GetNext())
  115. {
  116. if (symInList->GetName() == sym->GetName())
  117. {
  118. return;
  119. }
  120. }
  121. sym->SetNext(m_symList);
  122. m_symList = sym;
  123. m_count++;
  124. }
  125. void AddNewSymbol(Symbol *sym)
  126. {
  127. if (scopeType == ScopeType_Global)
  128. {
  129. sym->SetIsGlobal(true);
  130. }
  131. sym->SetScope(this);
  132. sym->SetNext(m_symList);
  133. m_symList = sym;
  134. m_count++;
  135. }
  136. bool HasStaticPathToAncestor(Scope const * target) const
  137. {
  138. return target == this || (!isDynamic && enclosingScope != nullptr && enclosingScope->HasStaticPathToAncestor(target));
  139. }
  140. void SetEnclosingScope(Scope *enclosingScope)
  141. {
  142. // Check for scope cycles
  143. Assert(enclosingScope != this);
  144. Assert(enclosingScope == nullptr || this != enclosingScope->GetEnclosingScope());
  145. this->enclosingScope = enclosingScope;
  146. }
  147. Scope *GetEnclosingScope() const
  148. {
  149. return enclosingScope;
  150. }
  151. void SetScopeInfo(Js::ScopeInfo * scopeInfo)
  152. {
  153. this->scopeInfo = scopeInfo;
  154. }
  155. Js::ScopeInfo * GetScopeInfo() const
  156. {
  157. return this->scopeInfo;
  158. }
  159. ScopeType GetScopeType() const
  160. {
  161. return this->scopeType;
  162. }
  163. bool IsInnerScope() const
  164. {
  165. return scopeType == ScopeType_Block
  166. || scopeType == ScopeType_Catch
  167. || scopeType == ScopeType_CatchParamPattern
  168. || scopeType == ScopeType_GlobalEvalBlock;
  169. }
  170. int Count() const
  171. {
  172. return m_count;
  173. }
  174. void SetFunc(FuncInfo *func)
  175. {
  176. this->func = func;
  177. }
  178. FuncInfo *GetFunc() const
  179. {
  180. return func;
  181. }
  182. FuncInfo *GetEnclosingFunc()
  183. {
  184. Scope *scope = this;
  185. while (scope && scope->func == nullptr)
  186. {
  187. scope = scope->GetEnclosingScope();
  188. }
  189. AnalysisAssert(scope);
  190. return scope->func;
  191. }
  192. void SetLocation(Js::RegSlot loc) { location = loc; }
  193. Js::RegSlot GetLocation() const { return location; }
  194. void SetIsDynamic(bool is) { isDynamic = is; }
  195. bool GetIsDynamic() const { return isDynamic; }
  196. bool IsEmpty() const;
  197. bool IsBlockScope(FuncInfo *funcInfo);
  198. void SetIsObject();
  199. bool GetIsObject() const { return isObject; }
  200. void SetCapturesAll(bool does) { capturesAll = does; }
  201. bool GetCapturesAll() const { return capturesAll; }
  202. void SetMustInstantiate(bool must) { mustInstantiate = must; }
  203. bool GetMustInstantiate() const { return mustInstantiate; }
  204. void SetCanMerge(bool can) { canMerge = can; }
  205. bool GetCanMerge() const { return canMerge && !mustInstantiate && !isObject; }
  206. void SetScopeSlotCount(uint i) { scopeSlotCount = i; }
  207. uint GetScopeSlotCount() const { return scopeSlotCount; }
  208. void SetHasDuplicateFormals() { hasDuplicateFormals = true; }
  209. bool GetHasDuplicateFormals() { return hasDuplicateFormals; }
  210. void SetHasOwnLocalInClosure(bool has) { hasLocalInClosure = has; }
  211. bool GetHasOwnLocalInClosure() const { return hasLocalInClosure; }
  212. void SetIsBlockInLoop(bool is = true) { isBlockInLoop = is; }
  213. bool IsBlockInLoop() const { return isBlockInLoop; }
  214. bool HasInnerScopeIndex() const { return innerScopeIndex != (uint)-1; }
  215. uint GetInnerScopeIndex() const { return innerScopeIndex; }
  216. void SetInnerScopeIndex(uint index) { innerScopeIndex = index; }
  217. int AddScopeSlot();
  218. void SetHasCrossScopeFuncAssignment() { hasCrossScopeFuncAssignment = true; }
  219. bool HasCrossScopeFuncAssignment() const { return hasCrossScopeFuncAssignment; }
  220. void ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator);
  221. bool IsGlobalEvalBlockScope() const;
  222. static void MergeParamAndBodyScopes(ParseNodeFnc *pnodeScope);
  223. static void RemoveParamScope(ParseNodeFnc *pnodeScope);
  224. };