Symbol.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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. Js::PropertyId moduleIndex;
  25. Symbol *next;
  26. SymbolType symbolType;
  27. BYTE defCount;
  28. BYTE needDeclaration : 1;
  29. BYTE isBlockVar : 1;
  30. BYTE isGlobal : 1;
  31. BYTE isEval : 1;
  32. BYTE hasNonLocalReference : 1; // if true, then this symbol needs to be heap-allocated
  33. BYTE isFuncExpr : 1; // if true, then this symbol is allocated on it's on activation object
  34. BYTE isCatch : 1; // if true then this a catch identifier
  35. BYTE hasInit : 1;
  36. BYTE isUsed : 1;
  37. BYTE isGlobalCatch : 1;
  38. BYTE isCommittedToSlot : 1;
  39. BYTE hasNonCommittedReference : 1;
  40. BYTE hasRealBlockVarRef : 1;
  41. BYTE hasBlockFncVarRedecl : 1;
  42. BYTE hasVisitedCapturingFunc : 1;
  43. 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.
  44. BYTE isModuleExportStorage : 1; // If true, this symbol should be stored in the global scope export storage array.
  45. BYTE isModuleImport : 1; // If true, this symbol is the local name of a module import statement
  46. // These are get and set a lot, don't put it in bit fields, we are exceeding the number of bits anyway
  47. bool hasFuncAssignment;
  48. bool hasMaybeEscapedUse;
  49. bool isNonSimpleParameter;
  50. AssignmentState assignmentState;
  51. public:
  52. Symbol(SymbolName const& name, ParseNode *decl, SymbolType symbolType) :
  53. name(name),
  54. decl(decl),
  55. next(nullptr),
  56. location(Js::Constants::NoRegister),
  57. needDeclaration(false),
  58. isBlockVar(false),
  59. isGlobal(false),
  60. hasNonLocalReference(false),
  61. isFuncExpr(false),
  62. isCatch(false),
  63. hasInit(false),
  64. isUsed(false),
  65. defCount(0),
  66. position(Js::Constants::NoProperty),
  67. scopeSlot(Js::Constants::NoProperty),
  68. isGlobalCatch(false),
  69. isCommittedToSlot(false),
  70. hasNonCommittedReference(false),
  71. hasRealBlockVarRef(false),
  72. hasBlockFncVarRedecl(false),
  73. hasVisitedCapturingFunc(false),
  74. isTrackedForDebugger(false),
  75. isNonSimpleParameter(false),
  76. assignmentState(NotAssigned),
  77. isModuleExportStorage(false),
  78. isModuleImport(false),
  79. moduleIndex(Js::Constants::NoProperty)
  80. {
  81. SetSymbolType(symbolType);
  82. // Set it so we don't have to check it explicitly
  83. isEval = MatchName(_u("eval"), 4);
  84. if (PHASE_TESTTRACE1(Js::StackFuncPhase) && hasFuncAssignment)
  85. {
  86. Output::Print(_u("HasFuncDecl: %s\n"), this->GetName().GetBuffer());
  87. Output::Flush();
  88. }
  89. }
  90. bool MatchName(const char16 *key, int length)
  91. {
  92. return name == SymbolName(key, length);
  93. }
  94. void SetScope(Scope *scope)
  95. {
  96. this->scope = scope;
  97. }
  98. Scope * GetScope() const { return scope; }
  99. void SetDecl(ParseNode *pnodeDecl) { decl = pnodeDecl; }
  100. ParseNode* GetDecl() const { return decl; }
  101. void SetScopeSlot(Js::PropertyId slot)
  102. {
  103. this->scopeSlot = slot;
  104. }
  105. Symbol *GetNext() const
  106. {
  107. return next;
  108. }
  109. void SetNext(Symbol *sym)
  110. {
  111. next = sym;
  112. }
  113. void SetIsGlobal(bool b)
  114. {
  115. isGlobal = b;
  116. }
  117. void SetHasNonLocalReference();
  118. bool GetHasNonLocalReference() const
  119. {
  120. return hasNonLocalReference;
  121. }
  122. void SetIsFuncExpr(bool b)
  123. {
  124. isFuncExpr = b;
  125. }
  126. void SetIsBlockVar(bool is)
  127. {
  128. isBlockVar = is;
  129. }
  130. bool GetIsBlockVar() const
  131. {
  132. return isBlockVar;
  133. }
  134. void SetIsModuleExportStorage(bool is)
  135. {
  136. isModuleExportStorage = is;
  137. }
  138. bool GetIsModuleExportStorage() const
  139. {
  140. return isModuleExportStorage;
  141. }
  142. void SetIsModuleImport(bool is)
  143. {
  144. isModuleImport = is;
  145. }
  146. bool GetIsModuleImport() const
  147. {
  148. return isModuleImport;
  149. }
  150. void SetModuleIndex(Js::PropertyId index)
  151. {
  152. moduleIndex = index;
  153. }
  154. Js::PropertyId GetModuleIndex()
  155. {
  156. return moduleIndex;
  157. }
  158. void SetIsGlobalCatch(bool is)
  159. {
  160. isGlobalCatch = is;
  161. }
  162. bool GetIsGlobalCatch() const
  163. {
  164. return isGlobalCatch;
  165. }
  166. void SetIsCommittedToSlot()
  167. {
  168. this->isCommittedToSlot = true;
  169. }
  170. bool GetIsCommittedToSlot() const;
  171. void SetHasVisitedCapturingFunc()
  172. {
  173. this->hasVisitedCapturingFunc = true;
  174. }
  175. bool HasVisitedCapturingFunc() const
  176. {
  177. return hasVisitedCapturingFunc;
  178. }
  179. void SetHasNonCommittedReference(bool has)
  180. {
  181. this->hasNonCommittedReference = has;
  182. }
  183. bool GetHasNonCommittedReference() const
  184. {
  185. return hasNonCommittedReference;
  186. }
  187. void SetIsTrackedForDebugger(bool is)
  188. {
  189. isTrackedForDebugger = is;
  190. }
  191. bool GetIsTrackedForDebugger() const
  192. {
  193. return isTrackedForDebugger;
  194. }
  195. void SetNeedDeclaration(bool need)
  196. {
  197. needDeclaration = need;
  198. }
  199. bool GetNeedDeclaration() const
  200. {
  201. return needDeclaration;
  202. }
  203. bool GetIsFuncExpr() const
  204. {
  205. return isFuncExpr;
  206. }
  207. bool GetIsGlobal() const
  208. {
  209. return isGlobal;
  210. }
  211. bool GetIsMember() const
  212. {
  213. return symbolType == STMemberName;
  214. }
  215. bool GetIsFormal() const
  216. {
  217. return symbolType == STFormal;
  218. }
  219. bool GetIsEval() const
  220. {
  221. return isEval;
  222. }
  223. bool GetIsCatch() const
  224. {
  225. return isCatch;
  226. }
  227. void SetIsCatch(bool b)
  228. {
  229. isCatch = b;
  230. }
  231. bool GetHasInit() const
  232. {
  233. return hasInit;
  234. }
  235. void RecordDef()
  236. {
  237. defCount++;
  238. }
  239. bool SingleDef() const
  240. {
  241. return defCount == 1;
  242. }
  243. void SetHasInit(bool has)
  244. {
  245. hasInit = has;
  246. }
  247. bool GetIsUsed() const
  248. {
  249. return isUsed;
  250. }
  251. void SetIsUsed(bool is)
  252. {
  253. isUsed = is;
  254. }
  255. bool HasRealBlockVarRef() const
  256. {
  257. return hasRealBlockVarRef;
  258. }
  259. void SetHasRealBlockVarRef(bool has = true)
  260. {
  261. hasRealBlockVarRef = has;
  262. }
  263. bool HasBlockFncVarRedecl() const
  264. {
  265. return hasBlockFncVarRedecl;
  266. }
  267. void SetHasBlockFncVarRedecl(bool has = true)
  268. {
  269. hasBlockFncVarRedecl = has;
  270. }
  271. AssignmentState GetAssignmentState() const
  272. {
  273. return assignmentState;
  274. }
  275. void PromoteAssignmentState()
  276. {
  277. if (assignmentState == NotAssigned)
  278. {
  279. assignmentState = AssignedOnce;
  280. }
  281. else if (assignmentState == AssignedOnce)
  282. {
  283. assignmentState = AssignedMultipleTimes;
  284. }
  285. }
  286. bool IsAssignedOnce()
  287. {
  288. return assignmentState == AssignedOnce;
  289. }
  290. // For stack nested function escape analysis
  291. bool GetHasMaybeEscapedUse() const { return hasMaybeEscapedUse; }
  292. void SetHasMaybeEscapedUse(ByteCodeGenerator * byteCodeGenerator);
  293. bool GetHasFuncAssignment() const { return hasFuncAssignment; }
  294. void SetHasFuncAssignment(ByteCodeGenerator * byteCodeGenerator);
  295. void RestoreHasFuncAssignment();
  296. bool GetIsNonSimpleParameter() const
  297. {
  298. return isNonSimpleParameter;
  299. }
  300. void SetIsNonSimpleParameter(bool is)
  301. {
  302. isNonSimpleParameter = is;
  303. }
  304. bool GetIsArguments() const;
  305. void SetPosition(Js::PropertyId pos)
  306. {
  307. position = pos;
  308. }
  309. Js::PropertyId GetPosition()
  310. {
  311. return position;
  312. }
  313. Js::PropertyId EnsurePosition(ByteCodeGenerator* byteCodeGenerator);
  314. Js::PropertyId EnsurePosition(FuncInfo *funcInfo);
  315. Js::PropertyId EnsurePositionNoCheck(FuncInfo *funcInfo);
  316. void SetLocation(Js::RegSlot location)
  317. {
  318. this->location = location;
  319. }
  320. Js::RegSlot GetLocation()
  321. {
  322. return location;
  323. }
  324. Js::PropertyId GetScopeSlot() const { return scopeSlot; }
  325. bool HasScopeSlot() const { return scopeSlot != Js::Constants::NoProperty; }
  326. SymbolType GetSymbolType()
  327. {
  328. return symbolType;
  329. }
  330. void SetSymbolType(SymbolType symbolType)
  331. {
  332. this->symbolType = symbolType;
  333. this->hasMaybeEscapedUse = GetIsFormal();
  334. this->hasFuncAssignment = (symbolType == STFunction);
  335. }
  336. #if DBG_DUMP
  337. const char16 *GetSymbolTypeName();
  338. #endif
  339. const JsUtil::CharacterBuffer<WCHAR>& GetName() const
  340. {
  341. return this->name;
  342. }
  343. Js::PropertyId EnsureScopeSlot(FuncInfo *funcInfo);
  344. bool IsInSlot(FuncInfo *funcInfo, bool ensureSlotAlloc = false);
  345. bool NeedsSlotAlloc(FuncInfo *funcInfo);
  346. static void SaveToPropIdArray(Symbol *sym, Js::PropertyIdArray *propIds, ByteCodeGenerator *byteCodeGenerator, Js::PropertyId *pFirstSlot = nullptr);
  347. Symbol * GetFuncScopeVarSym() const;
  348. void SetPid(IdentPtr pid)
  349. {
  350. this->pid = pid;
  351. }
  352. IdentPtr GetPid() const
  353. {
  354. return pid;
  355. }
  356. private:
  357. void SetHasMaybeEscapedUseInternal(ByteCodeGenerator * byteCodeGenerator);
  358. void SetHasFuncAssignmentInternal(ByteCodeGenerator * byteCodeGenerator);
  359. };
  360. // specialize toKey to use the name in the symbol as the key
  361. template <>
  362. inline SymbolName JsUtil::ValueToKey<SymbolName, Symbol *>::ToKey(Symbol * const& sym)
  363. {
  364. return sym->GetName();
  365. }
  366. typedef JsUtil::BaseHashSet<Symbol *, ArenaAllocator, PrimeSizePolicy, SymbolName, DefaultComparer, JsUtil::HashedEntry> SymbolTable;