Scope.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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. BYTE hasNestedParamFunc : 1;
  43. public:
  44. #if DBG
  45. BYTE isRestored : 1;
  46. #endif
  47. Scope(ArenaAllocator *alloc, ScopeType scopeType, int capacity = 0) :
  48. alloc(alloc),
  49. func(nullptr),
  50. enclosingScope(nullptr),
  51. scopeInfo(nullptr),
  52. isDynamic(false),
  53. isObject(false),
  54. canMerge(true),
  55. capturesAll(false),
  56. mustInstantiate(false),
  57. hasCrossScopeFuncAssignment(false),
  58. hasDuplicateFormals(false),
  59. canMergeWithBodyScope(true),
  60. hasLocalInClosure(false),
  61. isBlockInLoop(false),
  62. hasNestedParamFunc(false),
  63. location(Js::Constants::NoRegister),
  64. m_symList(nullptr),
  65. m_count(0),
  66. scopeSlotCount(0),
  67. innerScopeIndex((uint)-1),
  68. scopeType(scopeType)
  69. #if DBG
  70. , isRestored(false)
  71. #endif
  72. {
  73. }
  74. Symbol *FindLocalSymbol(SymbolName const& key)
  75. {
  76. Symbol *sym;
  77. for (sym = m_symList; sym; sym = sym->GetNext())
  78. {
  79. if (sym->GetName() == key)
  80. {
  81. break;
  82. }
  83. }
  84. return sym;
  85. }
  86. template<class Fn>
  87. void ForEachSymbol(Fn fn)
  88. {
  89. for (Symbol *sym = m_symList; sym;)
  90. {
  91. Symbol *next = sym->GetNext();
  92. fn(sym);
  93. sym = next;
  94. }
  95. }
  96. template<class Fn>
  97. void ForEachSymbolUntil(Fn fn)
  98. {
  99. for (Symbol *sym = m_symList; sym;)
  100. {
  101. Symbol *next = sym->GetNext();
  102. if (fn(sym))
  103. {
  104. return;
  105. }
  106. sym = next;
  107. }
  108. }
  109. static bool HasSymbolName(Scope * scope, const JsUtil::CharacterBuffer<WCHAR>& name)
  110. {
  111. for (Symbol *sym = scope->m_symList; sym; sym = sym->GetNext())
  112. {
  113. if (sym->GetName() == name)
  114. {
  115. return true;
  116. }
  117. }
  118. return false;
  119. }
  120. void AddSymbol(Symbol *sym)
  121. {
  122. if (enclosingScope == nullptr)
  123. {
  124. sym->SetIsGlobal(true);
  125. }
  126. sym->SetScope(this);
  127. if (HasSymbolName(this, sym->GetName()))
  128. {
  129. return;
  130. }
  131. sym->SetNext(m_symList);
  132. m_symList = sym;
  133. m_count++;
  134. }
  135. void AddNewSymbol(Symbol *sym)
  136. {
  137. if (scopeType == ScopeType_Global)
  138. {
  139. sym->SetIsGlobal(true);
  140. }
  141. sym->SetScope(this);
  142. Assert(!HasSymbolName(this, sym->GetName()));
  143. sym->SetNext(m_symList);
  144. m_symList = sym;
  145. m_count++;
  146. }
  147. bool HasStaticPathToAncestor(Scope const * target) const
  148. {
  149. return target == this || (!isDynamic && enclosingScope != nullptr && enclosingScope->HasStaticPathToAncestor(target));
  150. }
  151. void SetEnclosingScope(Scope *enclosingScope)
  152. {
  153. // Check for scope cycles
  154. Assert(enclosingScope != this);
  155. Assert(enclosingScope == nullptr || this != enclosingScope->GetEnclosingScope());
  156. this->enclosingScope = enclosingScope;
  157. }
  158. Scope *GetEnclosingScope() const
  159. {
  160. return enclosingScope;
  161. }
  162. bool AncestorScopeIsParameter() const
  163. {
  164. // Check if the current scope is a parameter or a block which belongs to a parameter scope
  165. // In such cases, certain asynchronous behavior is forbidden
  166. const Scope *currentScope = this;
  167. while(currentScope->GetScopeType() != ScopeType_Global && currentScope->GetScopeType() != ScopeType_FunctionBody && currentScope->GetScopeType() != ScopeType_Parameter) currentScope = currentScope->GetEnclosingScope();
  168. return (currentScope->GetScopeType() == ScopeType_Parameter);
  169. }
  170. void SetScopeInfo(Js::ScopeInfo * scopeInfo)
  171. {
  172. this->scopeInfo = scopeInfo;
  173. }
  174. Js::ScopeInfo * GetScopeInfo() const
  175. {
  176. return this->scopeInfo;
  177. }
  178. ScopeType GetScopeType() const
  179. {
  180. return this->scopeType;
  181. }
  182. bool IsInnerScope() const
  183. {
  184. return scopeType == ScopeType_Block
  185. || scopeType == ScopeType_Catch
  186. || scopeType == ScopeType_CatchParamPattern
  187. || scopeType == ScopeType_GlobalEvalBlock;
  188. }
  189. int Count() const
  190. {
  191. return m_count;
  192. }
  193. void SetFunc(FuncInfo *func)
  194. {
  195. this->func = func;
  196. }
  197. FuncInfo *GetFunc() const
  198. {
  199. return func;
  200. }
  201. FuncInfo *GetEnclosingFunc()
  202. {
  203. Scope *scope = this;
  204. while (scope && scope->func == nullptr)
  205. {
  206. scope = scope->GetEnclosingScope();
  207. }
  208. AnalysisAssert(scope);
  209. return scope->func;
  210. }
  211. void SetLocation(Js::RegSlot loc) { location = loc; }
  212. Js::RegSlot GetLocation() const { return location; }
  213. void SetIsDynamic(bool is) { isDynamic = is; }
  214. bool GetIsDynamic() const { return isDynamic; }
  215. bool IsEmpty() const;
  216. bool IsBlockScope(FuncInfo *funcInfo);
  217. void SetIsObject();
  218. bool GetIsObject() const { return isObject; }
  219. void SetCapturesAll(bool does) { capturesAll = does; }
  220. bool GetCapturesAll() const { return capturesAll; }
  221. void SetMustInstantiate(bool must) { mustInstantiate = must; }
  222. bool GetMustInstantiate() const { return mustInstantiate; }
  223. void SetCanMerge(bool can) { canMerge = can; }
  224. bool GetCanMerge() const { return canMerge && !mustInstantiate && !isObject; }
  225. void SetScopeSlotCount(uint i) { scopeSlotCount = i; }
  226. uint GetScopeSlotCount() const { return scopeSlotCount; }
  227. void SetHasDuplicateFormals() { hasDuplicateFormals = true; }
  228. bool GetHasDuplicateFormals() { return hasDuplicateFormals; }
  229. void SetHasOwnLocalInClosure(bool has) { hasLocalInClosure = has; }
  230. bool GetHasOwnLocalInClosure() const { return hasLocalInClosure; }
  231. void SetIsBlockInLoop(bool is = true) { isBlockInLoop = is; }
  232. bool IsBlockInLoop() const { return isBlockInLoop; }
  233. void SetHasNestedParamFunc(bool is = true) { hasNestedParamFunc = is; }
  234. bool GetHasNestedParamFunc() const { return hasNestedParamFunc; }
  235. bool HasInnerScopeIndex() const { return innerScopeIndex != (uint)-1; }
  236. uint GetInnerScopeIndex() const { return innerScopeIndex; }
  237. void SetInnerScopeIndex(uint index) { innerScopeIndex = index; }
  238. int AddScopeSlot();
  239. void SetHasCrossScopeFuncAssignment() { hasCrossScopeFuncAssignment = true; }
  240. bool HasCrossScopeFuncAssignment() const { return hasCrossScopeFuncAssignment; }
  241. void ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator);
  242. bool IsGlobalEvalBlockScope() const;
  243. static void MergeParamAndBodyScopes(ParseNodeFnc *pnodeScope);
  244. static void RemoveParamScope(ParseNodeFnc *pnodeScope);
  245. };