Symbol.h 11 KB

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