Symbol.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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 SymbolType : byte
  6. {
  7. STFunction,
  8. STVariable,
  9. STMemberName,
  10. STFormal,
  11. STUnknown
  12. };
  13. typedef JsUtil::CharacterBuffer<WCHAR> SymbolName;
  14. class Symbol
  15. {
  16. private:
  17. const SymbolName name;
  18. IdentPtr pid;
  19. ParseNode *decl;
  20. Scope *scope; // scope defining this symbol
  21. Js::PropertyId position; // argument position in function declaration
  22. Js::RegSlot location; // register in which the symbol resides
  23. Js::PropertyId scopeSlot;
  24. Symbol *next;
  25. SymbolType symbolType;
  26. BYTE defCount;
  27. BYTE needDeclaration : 1;
  28. BYTE isBlockVar : 1;
  29. BYTE isGlobal : 1;
  30. BYTE isEval : 1;
  31. BYTE hasNonLocalReference : 1; // if true, then this symbol needs to be heap-allocated
  32. BYTE funcExpr : 1; // if true, then this symbol is allocated on it's on activation object
  33. BYTE isCatch : 1; // if true then this a catch identifier
  34. BYTE hasInit : 1;
  35. BYTE isUsed : 1;
  36. BYTE isGlobalCatch : 1;
  37. BYTE isCommittedToSlot : 1;
  38. BYTE hasNonCommittedReference : 1;
  39. BYTE hasVisitedCapturingFunc : 1;
  40. BYTE isTrackedForDebugger : 1; // Whether the sym is tracked for debugger scope. This is fine because a sym can only be added to (not more than) one scope.
  41. // These are get and set a lot, don't put it in bit fields, we are exceeding the number of bits anyway
  42. bool hasFuncAssignment;
  43. bool hasMaybeEscapedUse;
  44. bool isNonSimpleParameter;
  45. AssignmentState assignmentState;
  46. public:
  47. Symbol(SymbolName const& name, ParseNode *decl, SymbolType symbolType) :
  48. name(name),
  49. decl(decl),
  50. next(nullptr),
  51. location(Js::Constants::NoRegister),
  52. needDeclaration(false),
  53. isBlockVar(false),
  54. isGlobal(false),
  55. hasNonLocalReference(false),
  56. funcExpr(false),
  57. isCatch(false),
  58. hasInit(false),
  59. isUsed(false),
  60. defCount(0),
  61. position(Js::Constants::NoProperty),
  62. scopeSlot(Js::Constants::NoProperty),
  63. isGlobalCatch(false),
  64. isCommittedToSlot(false),
  65. hasNonCommittedReference(false),
  66. hasVisitedCapturingFunc(false),
  67. isTrackedForDebugger(false),
  68. isNonSimpleParameter(false),
  69. assignmentState(NotAssigned)
  70. {
  71. SetSymbolType(symbolType);
  72. // Set it so we don't have to check it explicitly
  73. isEval = MatchName(L"eval", 4);
  74. if (PHASE_TESTTRACE1(Js::StackFuncPhase) && hasFuncAssignment)
  75. {
  76. Output::Print(L"HasFuncDecl: %s\n", this->GetName().GetBuffer());
  77. Output::Flush();
  78. }
  79. }
  80. bool MatchName(const wchar_t *key, int length)
  81. {
  82. return name == SymbolName(key, length);
  83. }
  84. void SetScope(Scope *scope)
  85. {
  86. this->scope = scope;
  87. }
  88. Scope * GetScope() const { return scope; }
  89. void SetDecl(ParseNode *pnodeDecl) { decl = pnodeDecl; }
  90. ParseNode* GetDecl() const { return decl; }
  91. void SetScopeSlot(Js::PropertyId slot)
  92. {
  93. this->scopeSlot = slot;
  94. }
  95. Symbol *GetNext() const
  96. {
  97. return next;
  98. }
  99. void SetNext(Symbol *sym)
  100. {
  101. next = sym;
  102. }
  103. void SetIsGlobal(bool b)
  104. {
  105. isGlobal = b;
  106. }
  107. void SetHasNonLocalReference(bool b, ByteCodeGenerator *byteCodeGenerator);
  108. bool GetHasNonLocalReference() const
  109. {
  110. return hasNonLocalReference;
  111. }
  112. void SetFuncExpr(bool b)
  113. {
  114. funcExpr = b;
  115. }
  116. void SetIsBlockVar(bool is)
  117. {
  118. isBlockVar = is;
  119. }
  120. bool GetIsBlockVar() const
  121. {
  122. return isBlockVar;
  123. }
  124. void SetIsGlobalCatch(bool is)
  125. {
  126. isGlobalCatch = is;
  127. }
  128. bool GetIsGlobalCatch() const
  129. {
  130. return isGlobalCatch;
  131. }
  132. void SetIsCommittedToSlot()
  133. {
  134. this->isCommittedToSlot = true;
  135. }
  136. bool GetIsCommittedToSlot() const;
  137. void SetHasVisitedCapturingFunc()
  138. {
  139. this->hasVisitedCapturingFunc = true;
  140. }
  141. bool HasVisitedCapturingFunc() const
  142. {
  143. return hasVisitedCapturingFunc;
  144. }
  145. void SetHasNonCommittedReference(bool has)
  146. {
  147. this->hasNonCommittedReference = has;
  148. }
  149. bool GetHasNonCommittedReference() const
  150. {
  151. return hasNonCommittedReference;
  152. }
  153. void SetIsTrackedForDebugger(bool is)
  154. {
  155. isTrackedForDebugger = is;
  156. }
  157. bool GetIsTrackedForDebugger() const
  158. {
  159. return isTrackedForDebugger;
  160. }
  161. void SetNeedDeclaration(bool need)
  162. {
  163. needDeclaration = need;
  164. }
  165. bool GetNeedDeclaration() const
  166. {
  167. return needDeclaration;
  168. }
  169. bool GetFuncExpr() const
  170. {
  171. return funcExpr;
  172. }
  173. bool GetIsGlobal() const
  174. {
  175. return isGlobal;
  176. }
  177. bool GetIsMember() const
  178. {
  179. return symbolType == STMemberName;
  180. }
  181. bool GetIsFormal() const
  182. {
  183. return symbolType == STFormal;
  184. }
  185. bool GetIsEval() const
  186. {
  187. return isEval;
  188. }
  189. bool GetIsCatch() const
  190. {
  191. return isCatch;
  192. }
  193. void SetIsCatch(bool b)
  194. {
  195. isCatch = b;
  196. }
  197. bool GetHasInit() const
  198. {
  199. return hasInit;
  200. }
  201. void RecordDef()
  202. {
  203. defCount++;
  204. }
  205. bool SingleDef() const
  206. {
  207. return defCount == 1;
  208. }
  209. void SetHasInit(bool has)
  210. {
  211. hasInit = has;
  212. }
  213. bool GetIsUsed() const
  214. {
  215. return isUsed;
  216. }
  217. void SetIsUsed(bool is)
  218. {
  219. isUsed = is;
  220. }
  221. void PromoteAssignmentState()
  222. {
  223. if (assignmentState == NotAssigned)
  224. {
  225. assignmentState = AssignedOnce;
  226. }
  227. else if (assignmentState == AssignedOnce)
  228. {
  229. assignmentState = AssignedMultipleTimes;
  230. }
  231. }
  232. bool IsAssignedOnce()
  233. {
  234. return assignmentState == AssignedOnce;
  235. }
  236. // For stack nested function escape analysis
  237. bool GetHasMaybeEscapedUse() const { return hasMaybeEscapedUse; }
  238. void SetHasMaybeEscapedUse(ByteCodeGenerator * byteCodeGenerator);
  239. bool GetHasFuncAssignment() const { return hasFuncAssignment; }
  240. void SetHasFuncAssignment(ByteCodeGenerator * byteCodeGenerator);
  241. void RestoreHasFuncAssignment();
  242. bool GetIsNonSimpleParameter() const
  243. {
  244. return isNonSimpleParameter;
  245. }
  246. void SetIsNonSimpleParameter(bool is)
  247. {
  248. isNonSimpleParameter = is;
  249. }
  250. bool GetIsArguments() const;
  251. void SetPosition(Js::PropertyId pos)
  252. {
  253. position = pos;
  254. }
  255. Js::PropertyId GetPosition()
  256. {
  257. return position;
  258. }
  259. Js::PropertyId EnsurePosition(ByteCodeGenerator* byteCodeGenerator);
  260. Js::PropertyId EnsurePosition(FuncInfo *funcInfo);
  261. Js::PropertyId EnsurePositionNoCheck(FuncInfo *funcInfo);
  262. void SetLocation(Js::RegSlot location)
  263. {
  264. this->location = location;
  265. }
  266. Js::RegSlot GetLocation()
  267. {
  268. return location;
  269. }
  270. Js::PropertyId GetScopeSlot() const { return scopeSlot; }
  271. bool HasScopeSlot() const { return scopeSlot != Js::Constants::NoProperty; }
  272. SymbolType GetSymbolType()
  273. {
  274. return symbolType;
  275. }
  276. void SetSymbolType(SymbolType symbolType)
  277. {
  278. this->symbolType = symbolType;
  279. this->hasMaybeEscapedUse = GetIsFormal();
  280. this->hasFuncAssignment = (symbolType == STFunction);
  281. }
  282. #if DBG_DUMP
  283. const wchar_t *GetSymbolTypeName();
  284. #endif
  285. const JsUtil::CharacterBuffer<WCHAR>& GetName() const
  286. {
  287. return this->name;
  288. }
  289. Js::PropertyId EnsureScopeSlot(FuncInfo *funcInfo);
  290. bool IsInSlot(FuncInfo *funcInfo, bool ensureSlotAlloc = false);
  291. bool NeedsSlotAlloc(FuncInfo *funcInfo);
  292. static void SaveToPropIdArray(Symbol *sym, Js::PropertyIdArray *propIds, ByteCodeGenerator *byteCodeGenerator, Js::PropertyId *pFirstSlot = nullptr);
  293. Symbol * GetFuncScopeVarSym() const;
  294. void SetPid(IdentPtr pid)
  295. {
  296. this->pid = pid;
  297. }
  298. IdentPtr GetPid() const
  299. {
  300. return pid;
  301. }
  302. private:
  303. void SetHasMaybeEscapedUseInternal(ByteCodeGenerator * byteCodeGenerator);
  304. void SetHasFuncAssignmentInternal(ByteCodeGenerator * byteCodeGenerator);
  305. };
  306. // specialize toKey to use the name in the symbol as the key
  307. template <>
  308. SymbolName JsUtil::ValueToKey<SymbolName, Symbol *>::ToKey(Symbol * const& sym)
  309. {
  310. return sym->GetName();
  311. }
  312. typedef JsUtil::BaseHashSet<Symbol *, ArenaAllocator, PrimeSizePolicy, SymbolName, DefaultComparer, JsUtil::HashedEntry> SymbolTable;