Scope.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. enum ScopeType
  6. {
  7. ScopeType_Unknown,
  8. ScopeType_Global,
  9. ScopeType_GlobalEvalBlock,
  10. ScopeType_FunctionBody,
  11. ScopeType_FuncExpr,
  12. ScopeType_Block,
  13. ScopeType_Catch,
  14. ScopeType_CatchParamPattern,
  15. ScopeType_With,
  16. ScopeType_Parameter
  17. };
  18. class Scope
  19. {
  20. private:
  21. Scope *enclosingScope;
  22. Js::RegSlot location;
  23. FuncInfo *func;
  24. SymbolTable *symbolTable;
  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. public:
  38. #if DBG
  39. BYTE isRestored : 1;
  40. #endif
  41. Scope(ArenaAllocator *alloc, ScopeType scopeType, bool useSymbolTable = false, int capacity = 0) :
  42. alloc(alloc),
  43. func(nullptr),
  44. enclosingScope(nullptr),
  45. isDynamic(false),
  46. isObject(false),
  47. canMerge(true),
  48. capturesAll(false),
  49. mustInstantiate(false),
  50. hasCrossScopeFuncAssignment(false),
  51. location(Js::Constants::NoRegister),
  52. symbolTable(nullptr),
  53. m_symList(nullptr),
  54. m_count(0),
  55. scopeSlotCount(0),
  56. innerScopeIndex((uint)-1),
  57. scopeType(scopeType)
  58. #if DBG
  59. , isRestored(false)
  60. #endif
  61. {
  62. if (useSymbolTable)
  63. {
  64. symbolTable = Anew(alloc, SymbolTable, alloc, capacity);
  65. }
  66. }
  67. ~Scope()
  68. {
  69. if (symbolTable)
  70. {
  71. Adelete(alloc, symbolTable);
  72. symbolTable = nullptr;
  73. }
  74. }
  75. Symbol *FindLocalSymbol(SymbolName const& key)
  76. {
  77. Symbol *sym = nullptr;
  78. if (symbolTable)
  79. {
  80. return symbolTable->Lookup(key);
  81. }
  82. for (sym = m_symList; sym; sym = sym->GetNext())
  83. {
  84. if (sym->GetName() == key)
  85. {
  86. break;
  87. }
  88. }
  89. return sym;
  90. }
  91. template<class Fn>
  92. void ForEachSymbol(Fn fn)
  93. {
  94. if (symbolTable)
  95. {
  96. symbolTable->Map(fn);
  97. }
  98. else
  99. {
  100. for (Symbol *sym = m_symList; sym;)
  101. {
  102. Symbol *next = sym->GetNext();
  103. fn(sym);
  104. sym = next;
  105. }
  106. }
  107. }
  108. template<class Fn>
  109. void ForEachSymbolUntil(Fn fn)
  110. {
  111. if (symbolTable)
  112. {
  113. symbolTable->MapUntil(fn);
  114. }
  115. else
  116. {
  117. for (Symbol *sym = m_symList; sym;)
  118. {
  119. Symbol *next = sym->GetNext();
  120. if (fn(sym))
  121. {
  122. return;
  123. }
  124. sym = next;
  125. }
  126. }
  127. }
  128. // For JScript, this should not return NULL because
  129. // there is always an enclosing global scope.
  130. Symbol *FindSymbol(SymbolName const& name, SymbolType symbolType, bool fCreate = true)
  131. {
  132. Symbol *sym = FindLocalSymbol(name);
  133. if (sym == nullptr)
  134. {
  135. if (enclosingScope != nullptr)
  136. {
  137. sym = enclosingScope->FindSymbol(name, symbolType);
  138. }
  139. else if (fCreate)
  140. {
  141. sym = Anew(alloc, Symbol, name, nullptr, symbolType);
  142. AddNewSymbol(sym);
  143. }
  144. }
  145. return sym;
  146. }
  147. void AddSymbol(Symbol *sym)
  148. {
  149. if (enclosingScope == nullptr)
  150. {
  151. sym->SetIsGlobal(true);
  152. }
  153. sym->SetScope(this);
  154. if (symbolTable)
  155. {
  156. symbolTable->AddNew(sym);
  157. }
  158. else
  159. {
  160. for (Symbol *symInList = m_symList; symInList; symInList = symInList->GetNext())
  161. {
  162. if (symInList->GetName() == sym->GetName())
  163. {
  164. return;
  165. }
  166. }
  167. sym->SetNext(m_symList);
  168. m_symList = sym;
  169. m_count++;
  170. }
  171. }
  172. void AddNewSymbol(Symbol *sym)
  173. {
  174. if (scopeType == ScopeType_Global)
  175. {
  176. sym->SetIsGlobal(true);
  177. }
  178. sym->SetScope(this);
  179. if (symbolTable)
  180. {
  181. symbolTable->Add(sym);
  182. }
  183. else
  184. {
  185. sym->SetNext(m_symList);
  186. m_symList = sym;
  187. m_count++;
  188. }
  189. }
  190. bool HasStaticPathToAncestor(Scope const * target) const
  191. {
  192. return target == this || (!isDynamic && enclosingScope != nullptr && enclosingScope->HasStaticPathToAncestor(target));
  193. }
  194. void SetEnclosingScope(Scope *enclosingScope)
  195. {
  196. // Check for scope cycles
  197. Assert(enclosingScope != this);
  198. Assert(enclosingScope == nullptr || this != enclosingScope->GetEnclosingScope());
  199. this->enclosingScope = enclosingScope;
  200. }
  201. Scope *GetEnclosingScope() const
  202. {
  203. return enclosingScope;
  204. }
  205. ScopeType GetScopeType() const
  206. {
  207. return this->scopeType;
  208. }
  209. bool IsInnerScope() const
  210. {
  211. return scopeType == ScopeType_Block || scopeType == ScopeType_Catch || scopeType == ScopeType_CatchParamPattern || scopeType == ScopeType_GlobalEvalBlock;
  212. }
  213. int Count() const
  214. {
  215. if (symbolTable)
  216. {
  217. return symbolTable->Count();
  218. }
  219. return m_count;
  220. }
  221. void SetFunc(FuncInfo *func)
  222. {
  223. this->func = func;
  224. }
  225. FuncInfo *GetFunc() const
  226. {
  227. return func;
  228. }
  229. FuncInfo *GetEnclosingFunc()
  230. {
  231. Scope *scope = this;
  232. while (scope && scope->func == nullptr)
  233. {
  234. scope = scope->GetEnclosingScope();
  235. }
  236. AnalysisAssert(scope);
  237. return scope->func;
  238. }
  239. void SetLocation(Js::RegSlot loc) { location = loc; }
  240. Js::RegSlot GetLocation() const { return location; }
  241. void SetIsDynamic(bool is) { isDynamic = is; }
  242. bool GetIsDynamic() const { return isDynamic; }
  243. bool IsEmpty() const;
  244. bool IsBlockScope(FuncInfo *funcInfo);
  245. void SetIsObject();
  246. bool GetIsObject() const { return isObject; }
  247. void SetCapturesAll(bool does) { capturesAll = does; }
  248. bool GetCapturesAll() const { return capturesAll; }
  249. void SetMustInstantiate(bool must) { mustInstantiate = must; }
  250. bool GetMustInstantiate() const { return mustInstantiate; }
  251. void SetCanMerge(bool can) { canMerge = can; }
  252. bool GetCanMerge() const { return canMerge && !mustInstantiate && !isObject; }
  253. void SetScopeSlotCount(uint i) { scopeSlotCount = i; }
  254. uint GetScopeSlotCount() const { return scopeSlotCount; }
  255. void SetHasLocalInClosure(bool has);
  256. bool HasInnerScopeIndex() const { return innerScopeIndex != (uint)-1; }
  257. uint GetInnerScopeIndex() const { return innerScopeIndex; }
  258. void SetInnerScopeIndex(uint index) { Assert(innerScopeIndex == (uint)-1 || innerScopeIndex == index); innerScopeIndex = index; }
  259. int AddScopeSlot();
  260. void SetHasCrossScopeFuncAssignment() { hasCrossScopeFuncAssignment = true; }
  261. void ForceAllSymbolNonLocalReference(ByteCodeGenerator *byteCodeGenerator);
  262. bool IsGlobalEvalBlockScope() const;
  263. static void MergeParamAndBodyScopes(ParseNode *pnodeScope, ByteCodeGenerator * byteCodeGenerator);
  264. };