Scope.h 7.2 KB

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