Symbol.h 11 KB

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