ptree.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  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. #pragma once
  6. struct Ident;
  7. typedef Ident *IdentPtr;
  8. class Scope;
  9. /***************************************************************************
  10. Flags for classifying node operators.
  11. ***************************************************************************/
  12. const uint fnopNone = 0x0000;
  13. const uint fnopConst = 0x0001; // constant
  14. const uint fnopLeaf = 0x0002; // leaf
  15. const uint fnopUni = 0x0004; // unary
  16. const uint fnopBin = 0x0008; // binary
  17. const uint fnopRel = 0x0010; // relational
  18. const uint fnopAsg = 0x0020; // assignment
  19. const uint fnopBreak = 0x0040; // break can be used within this statement
  20. const uint fnopContinue = 0x0080; // continue can be used within this statement
  21. const uint fnopCleanup = 0x0100; // requires cleanup (eg, with or for-in).
  22. const uint fnopJump = 0x0200;
  23. const uint fnopNotExprStmt = 0x0400;
  24. const uint fnopBinList = 0x0800;
  25. const uint fnopExprMask = (fnopLeaf|fnopUni|fnopBin);
  26. const uint fnopAllowDefer = 0x1000; // allow to be created during defer parse
  27. /***************************************************************************
  28. Flags for classifying parse nodes.
  29. ***************************************************************************/
  30. enum PNodeFlags : ushort
  31. {
  32. fpnNone = 0x0000,
  33. // knopFncDecl nodes.
  34. fpnArguments_overriddenByDecl = 0x0001, // function has a let/const decl, class or nested function named 'arguments', which overrides the built-in arguments object in the body
  35. fpnArguments_overriddenInParam = 0x0002, // function has a parameter named arguments
  36. fpnArguments_varDeclaration = 0x0004, // function has a var declaration named 'arguments', which may change the way an 'arguments' identifier is resolved
  37. // knopVarDecl nodes.
  38. fpnArguments = 0x0008,
  39. fpnHidden = 0x0010,
  40. // Statement nodes.
  41. fpnExplicitSemicolon = 0x0020, // statement terminated by an explicit semicolon
  42. fpnAutomaticSemicolon = 0x0040, // statement terminated by an automatic semicolon
  43. fpnMissingSemicolon = 0x0080, // statement missing terminating semicolon, and is not applicable for automatic semicolon insertion
  44. fpnDclList = 0x0100, // statement is a declaration list
  45. fpnSyntheticNode = 0x0200, // node is added by the parser or does it represent user code
  46. fpnIndexOperator = 0x0400, // dot operator is an optimization of an index operator
  47. fpnJumbStatement = 0x0800, // break or continue that was removed by error recovery
  48. // Unary/Binary nodes
  49. fpnCanFlattenConcatExpr = 0x1000, // the result of the binary operation can participate in concat N
  50. // Potentially overlapping traversal flags
  51. // These flags are set and cleared during a single node traversal and their values can be used in other node traversals.
  52. fpnMemberReference = 0x2000, // The node is a member reference symbol
  53. fpnCapturesSyms = 0x4000, // The node is a statement (or contains a sub-statement)
  54. // that captures symbols.
  55. fpnSpecialSymbol = 0x8000,
  56. };
  57. /***************************************************************************
  58. Data structs for ParseNodes.
  59. ***************************************************************************/
  60. class ParseNodeUni;
  61. class ParseNodeBin;
  62. class ParseNodeTri;
  63. class ParseNodeInt;
  64. class ParseNodeBigInt;
  65. class ParseNodeFloat;
  66. class ParseNodeRegExp;
  67. class ParseNodeStr;
  68. class ParseNodeName;
  69. class ParseNodeVar;
  70. class ParseNodeCall;
  71. class ParseNodeSuperCall;
  72. class ParseNodeSpecialName;
  73. class ParseNodeExportDefault;
  74. class ParseNodeStrTemplate;
  75. class ParseNodeSuperReference;
  76. class ParseNodeArrLit;
  77. class ParseNodeObjLit;
  78. class ParseNodeClass;
  79. class ParseNodeParamPattern;
  80. class ParseNodeStmt;
  81. class ParseNodeBlock;
  82. class ParseNodeJump;
  83. class ParseNodeWith;
  84. class ParseNodeIf;
  85. class ParseNodeSwitch;
  86. class ParseNodeCase;
  87. class ParseNodeReturn;
  88. class ParseNodeTryFinally;
  89. class ParseNodeTryCatch;
  90. class ParseNodeTry;
  91. class ParseNodeCatch;
  92. class ParseNodeFinally;
  93. class ParseNodeWhile;
  94. class ParseNodeFor;
  95. class ParseNodeForInOrForOf;
  96. class ParseNodeFnc;
  97. class ParseNodeProg;
  98. class ParseNodeModule;
  99. class ParseNode
  100. {
  101. public:
  102. ParseNode(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  103. ParseNodeUni * AsParseNodeUni();
  104. ParseNodeBin * AsParseNodeBin();
  105. ParseNodeTri * AsParseNodeTri();
  106. ParseNodeInt * AsParseNodeInt();
  107. ParseNodeBigInt * AsParseNodeBigInt();
  108. ParseNodeFloat * AsParseNodeFloat();
  109. ParseNodeRegExp * AsParseNodeRegExp();
  110. ParseNodeVar * AsParseNodeVar();
  111. ParseNodeStr * AsParseNodeStr();
  112. ParseNodeName * AsParseNodeName();
  113. ParseNodeSpecialName * AsParseNodeSpecialName();
  114. ParseNodeExportDefault * AsParseNodeExportDefault();
  115. ParseNodeStrTemplate * AsParseNodeStrTemplate();
  116. ParseNodeSuperReference * AsParseNodeSuperReference();
  117. ParseNodeArrLit * AsParseNodeArrLit();
  118. ParseNodeObjLit * AsParseNodeObjLit();
  119. ParseNodeCall * AsParseNodeCall();
  120. ParseNodeSuperCall * AsParseNodeSuperCall();
  121. ParseNodeClass * AsParseNodeClass();
  122. ParseNodeParamPattern * AsParseNodeParamPattern();
  123. ParseNodeStmt * AsParseNodeStmt();
  124. ParseNodeBlock * AsParseNodeBlock();
  125. ParseNodeJump * AsParseNodeJump();
  126. ParseNodeWith * AsParseNodeWith();
  127. ParseNodeIf * AsParseNodeIf();
  128. ParseNodeSwitch * AsParseNodeSwitch();
  129. ParseNodeCase * AsParseNodeCase();
  130. ParseNodeReturn * AsParseNodeReturn();
  131. ParseNodeTryFinally * AsParseNodeTryFinally();
  132. ParseNodeTryCatch * AsParseNodeTryCatch();
  133. ParseNodeTry * AsParseNodeTry();
  134. ParseNodeCatch * AsParseNodeCatch();
  135. ParseNodeFinally * AsParseNodeFinally();
  136. ParseNodeWhile * AsParseNodeWhile();
  137. ParseNodeFor * AsParseNodeFor();
  138. ParseNodeForInOrForOf * AsParseNodeForInOrForOf();
  139. ParseNodeFnc * AsParseNodeFnc();
  140. ParseNodeProg * AsParseNodeProg();
  141. ParseNodeModule * AsParseNodeModule();
  142. static uint Grfnop(int nop)
  143. {
  144. Assert(nop < knopLim);
  145. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  146. }
  147. BOOL IsStatement()
  148. {
  149. return nop >= knopList || ((Grfnop(nop) & fnopAsg) != 0);
  150. }
  151. uint Grfnop(void)
  152. {
  153. Assert(nop < knopLim);
  154. return nop < knopLim ? mpnopgrfnop[nop] : fnopNone;
  155. }
  156. IdentPtr name();
  157. charcount_t LengthInCodepoints() const
  158. {
  159. return (this->ichLim - this->ichMin);
  160. }
  161. // This node is a function decl node and function has a var declaration named 'arguments',
  162. bool HasVarArguments() const
  163. {
  164. return ((nop == knopFncDecl) && (grfpn & PNodeFlags::fpnArguments_varDeclaration));
  165. }
  166. bool CapturesSyms() const
  167. {
  168. return (grfpn & PNodeFlags::fpnCapturesSyms) != 0;
  169. }
  170. void SetCapturesSyms()
  171. {
  172. grfpn |= PNodeFlags::fpnCapturesSyms;
  173. }
  174. bool IsInList() const { return this->isInList; }
  175. void SetIsInList() { this->isInList = true; }
  176. bool IsNotEscapedUse() const { return this->notEscapedUse; }
  177. void SetNotEscapedUse() { this->notEscapedUse = true; }
  178. bool CanFlattenConcatExpr() const { return !!(this->grfpn & PNodeFlags::fpnCanFlattenConcatExpr); }
  179. bool IsCallApplyTargetLoad() { return isCallApplyTargetLoad; }
  180. void SetIsCallApplyTargetLoad() { isCallApplyTargetLoad = true; }
  181. bool IsPatternDeclaration() { return isPatternDeclaration; }
  182. void SetIsPatternDeclaration() { isPatternDeclaration = true; }
  183. bool IsUserIdentifier();
  184. bool IsVarLetOrConst() const
  185. {
  186. return this->nop == knopVarDecl || this->nop == knopLetDecl || this->nop == knopConstDecl;
  187. }
  188. ParseNodePtr GetFormalNext();
  189. bool IsPattern() const
  190. {
  191. return nop == knopObjectPattern || nop == knopArrayPattern;
  192. }
  193. #if DBG_DUMP
  194. void Dump();
  195. #endif
  196. public:
  197. static const uint mpnopgrfnop[knopLim];
  198. OpCode nop;
  199. bool isUsed : 1; // indicates whether an expression such as x++ is used
  200. private:
  201. bool isInList : 1;
  202. // Use by byte code generator
  203. bool notEscapedUse : 1; // Currently, only used by child of knopComma
  204. bool isCallApplyTargetLoad : 1;
  205. // Use by bytecodegen to identify the current node is a destructuring pattern declaration node.
  206. bool isPatternDeclaration : 1;
  207. public:
  208. ushort grfpn;
  209. charcount_t ichMin; // start offset into the original source buffer
  210. charcount_t ichLim; // end offset into the original source buffer
  211. Js::RegSlot location;
  212. #ifdef EDIT_AND_CONTINUE
  213. ParseNodePtr parent;
  214. #endif
  215. };
  216. #define DISABLE_SELF_CAST(T) private: T * As##T()
  217. // unary operators
  218. class ParseNodeUni : public ParseNode
  219. {
  220. public:
  221. ParseNodeUni(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1);
  222. ParseNodePtr pnode1;
  223. DISABLE_SELF_CAST(ParseNodeUni);
  224. };
  225. // binary operators
  226. class ParseNodeBin : public ParseNode
  227. {
  228. public:
  229. ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2);
  230. ParseNodePtr pnode1;
  231. ParseNodePtr pnode2;
  232. DISABLE_SELF_CAST(ParseNodeBin);
  233. };
  234. // ternary operator
  235. class ParseNodeTri : public ParseNode
  236. {
  237. public:
  238. ParseNodeTri(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  239. ParseNodePtr pnode1;
  240. ParseNodePtr pnode2;
  241. ParseNodePtr pnode3;
  242. DISABLE_SELF_CAST(ParseNodeTri);
  243. };
  244. // integer constant
  245. class ParseNodeInt : public ParseNode
  246. {
  247. public:
  248. ParseNodeInt(charcount_t ichMin, charcount_t ichMax, int32 lw);
  249. int32 lw;
  250. DISABLE_SELF_CAST(ParseNodeInt);
  251. };
  252. // bigint constant
  253. class ParseNodeBigInt : public ParseNode
  254. {
  255. public:
  256. ParseNodeBigInt(charcount_t ichMin, charcount_t ichLim, IdentPtr pid);
  257. IdentPtr const pid;
  258. bool isNegative : 1;
  259. DISABLE_SELF_CAST(ParseNodeBigInt);
  260. };
  261. // double constant
  262. class ParseNodeFloat : public ParseNode
  263. {
  264. public:
  265. ParseNodeFloat(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  266. double dbl;
  267. bool maybeInt : 1;
  268. DISABLE_SELF_CAST(ParseNodeFloat);
  269. };
  270. class ParseNodeRegExp : public ParseNode
  271. {
  272. public:
  273. ParseNodeRegExp(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  274. UnifiedRegex::RegexPattern* regexPattern;
  275. uint regexPatternIndex;
  276. DISABLE_SELF_CAST(ParseNodeRegExp);
  277. };
  278. // identifier or string
  279. class ParseNodeStr : public ParseNode
  280. {
  281. public:
  282. ParseNodeStr(charcount_t ichMin, charcount_t ichLim, IdentPtr pid);
  283. IdentPtr const pid;
  284. DISABLE_SELF_CAST(ParseNodeStr);
  285. };
  286. class Symbol;
  287. struct PidRefStack;
  288. class ParseNodeName : public ParseNode
  289. {
  290. public:
  291. ParseNodeName(charcount_t ichMin, charcount_t ichLim, IdentPtr pid);
  292. IdentPtr const pid;
  293. private:
  294. Symbol **symRef;
  295. public:
  296. Symbol *sym;
  297. void SetSymRef(PidRefStack *ref);
  298. void ClearSymRef() { symRef = nullptr; }
  299. Symbol **GetSymRef() const { return symRef; }
  300. Js::PropertyId PropertyIdFromNameNode() const;
  301. bool IsSpecialName() { return isSpecialName; }
  302. DISABLE_SELF_CAST(ParseNodeName);
  303. protected:
  304. void SetIsSpecialName() { isSpecialName = true; }
  305. private:
  306. bool isSpecialName; // indicates a PnPid (knopName) is a special name like 'this' or 'super'
  307. };
  308. // variable declaration
  309. class ParseNodeVar : public ParseNode
  310. {
  311. public:
  312. ParseNodeVar(OpCode nop, charcount_t ichMin, charcount_t ichLim, IdentPtr name);
  313. ParseNodePtr pnodeNext;
  314. IdentPtr const pid;
  315. Symbol *sym;
  316. Symbol **symRef;
  317. ParseNodePtr pnodeInit;
  318. BOOLEAN isSwitchStmtDecl;
  319. BOOLEAN isBlockScopeFncDeclVar;
  320. DISABLE_SELF_CAST(ParseNodeVar);
  321. };
  322. // Array literal
  323. class ParseNodeArrLit : public ParseNodeUni
  324. {
  325. public:
  326. ParseNodeArrLit(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  327. uint count;
  328. uint spreadCount;
  329. BYTE arrayOfTaggedInts:1; // indicates that array initializer nodes are all tagged ints
  330. BYTE arrayOfInts:1; // indicates that array initializer nodes are all ints
  331. BYTE arrayOfNumbers:1; // indicates that array initializer nodes are all numbers
  332. BYTE hasMissingValues:1;
  333. DISABLE_SELF_CAST(ParseNodeArrLit);
  334. };
  335. class ParseNodeObjLit : public ParseNodeUni
  336. {
  337. public:
  338. ParseNodeObjLit(OpCode nop, charcount_t ichMin, charcount_t ichLim, uint staticCnt=0, uint computedCnt=0, bool rest=false);
  339. uint staticCount;
  340. uint computedCount;
  341. bool hasRest;
  342. DISABLE_SELF_CAST(ParseNodeObjLit);
  343. };
  344. class FuncInfo;
  345. enum PnodeBlockType : unsigned
  346. {
  347. Global,
  348. Function,
  349. Regular,
  350. Parameter
  351. };
  352. enum FncFlags : uint
  353. {
  354. kFunctionNone = 0,
  355. kFunctionNested = 1 << 0, // True if function is nested in another.
  356. kFunctionDeclaration = 1 << 1, // is this a declaration or an expression?
  357. kFunctionCallsEval = 1 << 2, // function uses eval
  358. kFunctionUsesArguments = 1 << 3, // function uses arguments
  359. kFunctionHasHeapArguments = 1 << 4, // function's "arguments" escape the scope
  360. kFunctionHasReferenceableBuiltInArguments = 1 << 5, // the built-in 'arguments' object is referenceable in the function
  361. kFunctionIsAccessor = 1 << 6, // function is a property getter or setter
  362. kFunctionHasNonThisStmt = 1 << 7,
  363. kFunctionStrictMode = 1 << 8,
  364. kFunctionHasDestructuredParams = 1 << 9,
  365. kFunctionIsModule = 1 << 10, // function is a module body
  366. kFunctionHasComputedName = 1 << 11,
  367. kFunctionHasWithStmt = 1 << 12, // function (or child) uses with
  368. kFunctionIsLambda = 1 << 13,
  369. kFunctionChildCallsEval = 1 << 14,
  370. kFunctionHasNonSimpleParameterList = 1 << 15,
  371. kFunctionHasSuperReference = 1 << 16,
  372. kFunctionIsMethod = 1 << 17,
  373. kFunctionIsClassConstructor = 1 << 18, // function is a class constructor
  374. kFunctionIsBaseClassConstructor = 1 << 19, // function is a base class constructor
  375. kFunctionIsClassMember = 1 << 20, // function is a class member
  376. kFunctionHasHomeObj = 1 << 21, // function has home object. Class or member functions need to have home obj.
  377. kFunctionIsGeneratedDefault = 1 << 22, // Is the function generated by us as a default (e.g. default class constructor)
  378. kFunctionHasDefaultArguments = 1 << 23, // Function has one or more ES6 default arguments
  379. kFunctionIsStaticMember = 1 << 24,
  380. kFunctionIsGenerator = 1 << 25, // Function is an ES6 generator function
  381. kFunctionAsmjsMode = 1 << 26,
  382. kFunctionIsDeclaredInParamScope = 1 << 27, // Function is declared in parameter scope (ex: inside default argument)
  383. kFunctionIsAsync = 1 << 28, // function is async
  384. kFunctionHasDirectSuper = 1 << 29, // super()
  385. kFunctionIsDefaultModuleExport = 1 << 30, // function is the default export of a module
  386. kFunctionHasAnyWriteToFormals = (uint)1 << 31 // To Track if there are any writes to formals.
  387. };
  388. struct RestorePoint;
  389. struct DeferredFunctionStub;
  390. namespace SuperRestrictionState {
  391. enum State {
  392. Disallowed = 0,
  393. CallAndPropertyAllowed = 1,
  394. PropertyAllowed = 2
  395. };
  396. }
  397. // function declaration
  398. class ParseNodeFnc : public ParseNode
  399. {
  400. public:
  401. ParseNodeFnc(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  402. ParseNodePtr pnodeNext;
  403. ParseNodeVar * pnodeName;
  404. IdentPtr pid;
  405. LPCOLESTR hint;
  406. uint32 hintLength;
  407. uint32 hintOffset;
  408. ParseNodeBlock * pnodeScopes;
  409. ParseNodeBlock * pnodeBodyScope;
  410. ParseNodePtr pnodeParams;
  411. ParseNodePtr pnodeVars;
  412. ParseNodePtr pnodeBody;
  413. ParseNodePtr pnodeRest;
  414. FuncInfo *funcInfo; // function information gathered during byte code generation
  415. Scope *scope;
  416. uint nestedCount; // Nested function count (valid until children have been processed)
  417. uint nestedIndex; // Index within the parent function (Used by ByteCodeGenerator)
  418. FncFlags fncFlags;
  419. int32 astSize;
  420. size_t cbMin; // Min an Lim UTF8 offsets.
  421. size_t cbStringMin;
  422. size_t cbStringLim;
  423. size_t cbLim;
  424. ULONG lineNumber; // Line number relative to the current source buffer of the function declaration.
  425. ULONG columnNumber; // Column number of the declaration.
  426. Js::LocalFunctionId functionId;
  427. #if DBG
  428. Js::LocalFunctionId deferredParseNextFunctionId;
  429. #endif
  430. RestorePoint *pRestorePoint;
  431. DeferredFunctionStub *deferredStub;
  432. IdentPtrSet *capturedNames;
  433. uint16 firstDefaultArg; // Position of the first default argument, if any
  434. bool isNameIdentifierRef;
  435. bool nestedFuncEscapes;
  436. bool canBeDeferred;
  437. bool isBodyAndParamScopeMerged; // Indicates whether the param scope and the body scope of the function can be merged together or not.
  438. // We cannot merge both scopes together if there is any closure capture or eval is present in the param scope.
  439. Js::RegSlot homeObjLocation; // Stores the RegSlot from where the home object needs to be copied
  440. static const int32 MaxStackClosureAST = 800000;
  441. SuperRestrictionState::State superRestrictionState;
  442. static bool CanBeRedeferred(FncFlags flags) { return !(flags & (kFunctionIsGenerator | kFunctionIsAsync)); }
  443. private:
  444. void SetFlags(uint flags, bool set)
  445. {
  446. if (set)
  447. {
  448. fncFlags = (FncFlags)(fncFlags | flags);
  449. }
  450. else
  451. {
  452. fncFlags = (FncFlags)(fncFlags & ~flags);
  453. }
  454. }
  455. bool HasFlags(uint flags) const
  456. {
  457. return (fncFlags & flags) == flags;
  458. }
  459. bool HasAnyFlags(uint flags) const
  460. {
  461. return (fncFlags & flags) != 0;
  462. }
  463. bool HasNoFlags(uint flags) const
  464. {
  465. return (fncFlags & flags) == 0;
  466. }
  467. public:
  468. void ClearFlags()
  469. {
  470. fncFlags = kFunctionNone;
  471. canBeDeferred = false;
  472. isBodyAndParamScopeMerged = true;
  473. }
  474. void SetAsmjsMode(bool set = true) { SetFlags(kFunctionAsmjsMode, set); }
  475. void SetCallsEval(bool set = true) { SetFlags(kFunctionCallsEval, set); }
  476. void SetChildCallsEval(bool set = true) { SetFlags(kFunctionChildCallsEval, set); }
  477. void SetDeclaration(bool set = true) { SetFlags(kFunctionDeclaration, set); }
  478. void SetHasDefaultArguments(bool set = true) { SetFlags(kFunctionHasDefaultArguments, set); }
  479. void SetHasDestructuredParams(bool set = true) { SetFlags(kFunctionHasDestructuredParams, set); }
  480. void SetHasHeapArguments(bool set = true) { SetFlags(kFunctionHasHeapArguments, set); }
  481. void SetHasAnyWriteToFormals(bool set = true) { SetFlags((uint)kFunctionHasAnyWriteToFormals, set); }
  482. void SetHasNonSimpleParameterList(bool set = true) { SetFlags(kFunctionHasNonSimpleParameterList, set); }
  483. void SetHasNonThisStmt(bool set = true) { SetFlags(kFunctionHasNonThisStmt, set); }
  484. void SetHasReferenceableBuiltInArguments(bool set = true) { SetFlags(kFunctionHasReferenceableBuiltInArguments, set); }
  485. void SetHasSuperReference(bool set = true) { SetFlags(kFunctionHasSuperReference, set); }
  486. void SetHasDirectSuper(bool set = true) { SetFlags(kFunctionHasDirectSuper, set); }
  487. void SetHasWithStmt(bool set = true) { SetFlags(kFunctionHasWithStmt, set); }
  488. void SetIsAccessor(bool set = true) { SetFlags(kFunctionIsAccessor, set); }
  489. void SetIsAsync(bool set = true) { SetFlags(kFunctionIsAsync, set); }
  490. void SetIsClassConstructor(bool set = true) { SetFlags(kFunctionIsClassConstructor, set); }
  491. void SetIsBaseClassConstructor(bool set = true) { SetFlags(kFunctionIsBaseClassConstructor, set); }
  492. void SetIsClassMember(bool set = true) { SetFlags(kFunctionIsClassMember, set); }
  493. void SetIsGeneratedDefault(bool set = true) { SetFlags(kFunctionIsGeneratedDefault, set); }
  494. void SetIsGenerator(bool set = true) { SetFlags(kFunctionIsGenerator, set); }
  495. void SetIsLambda(bool set = true) { SetFlags(kFunctionIsLambda, set); }
  496. void SetIsMethod(bool set = true) { SetFlags(kFunctionIsMethod, set); }
  497. void SetIsStaticMember(bool set = true) { SetFlags(kFunctionIsStaticMember, set); }
  498. void SetNested(bool set = true) { SetFlags(kFunctionNested, set); }
  499. void SetStrictMode(bool set = true) { SetFlags(kFunctionStrictMode, set); }
  500. void SetIsModule(bool set = true) { SetFlags(kFunctionIsModule, set); }
  501. void SetHasComputedName(bool set = true) { SetFlags(kFunctionHasComputedName, set); }
  502. void SetHasHomeObj(bool set = true) { SetFlags(kFunctionHasHomeObj, set); }
  503. void SetUsesArguments(bool set = true) { SetFlags(kFunctionUsesArguments, set); }
  504. void SetIsDefaultModuleExport(bool set = true) { SetFlags(kFunctionIsDefaultModuleExport, set); }
  505. void SetIsDeclaredInParamScope(bool set = true) { SetFlags(kFunctionIsDeclaredInParamScope, set); }
  506. void SetNestedFuncEscapes(bool set = true) { nestedFuncEscapes = set; }
  507. void SetCanBeDeferred(bool set = true) { canBeDeferred = set; }
  508. void ResetBodyAndParamScopeMerged() { isBodyAndParamScopeMerged = false; }
  509. void SetHomeObjLocation(Js::RegSlot location) { this->homeObjLocation = location; }
  510. bool CallsEval() const { return HasFlags(kFunctionCallsEval); }
  511. bool ChildCallsEval() const { return HasFlags(kFunctionChildCallsEval); }
  512. bool GetArgumentsObjectEscapes() const { return HasFlags(kFunctionHasHeapArguments); }
  513. bool GetAsmjsMode() const { return HasFlags(kFunctionAsmjsMode); }
  514. bool GetStrictMode() const { return HasFlags(kFunctionStrictMode); }
  515. bool HasDefaultArguments() const { return HasFlags(kFunctionHasDefaultArguments); }
  516. bool HasDestructuredParams() const { return HasFlags(kFunctionHasDestructuredParams); }
  517. bool HasHeapArguments() const { return true; /* HasFlags(kFunctionHasHeapArguments); Disabling stack arguments. Always return HeapArguments as True */ }
  518. bool HasAnyWriteToFormals() const { return HasFlags((uint)kFunctionHasAnyWriteToFormals); }
  519. bool HasOnlyThisStmts() const { return !HasFlags(kFunctionHasNonThisStmt); }
  520. bool HasReferenceableBuiltInArguments() const { return HasFlags(kFunctionHasReferenceableBuiltInArguments); }
  521. bool HasSuperReference() const { return HasFlags(kFunctionHasSuperReference); }
  522. bool HasDirectSuper() const { return HasFlags(kFunctionHasDirectSuper); }
  523. bool HasNonSimpleParameterList() { return HasFlags(kFunctionHasNonSimpleParameterList); }
  524. bool HasWithStmt() const { return HasFlags(kFunctionHasWithStmt); }
  525. bool IsAccessor() const { return HasFlags(kFunctionIsAccessor); }
  526. bool IsAsync() const { return HasFlags(kFunctionIsAsync); }
  527. bool IsConstructor() const { return HasNoFlags(kFunctionIsAsync|kFunctionIsLambda|kFunctionIsAccessor); }
  528. bool IsClassConstructor() const { return HasFlags(kFunctionIsClassConstructor); }
  529. bool IsBaseClassConstructor() const { return HasFlags(kFunctionIsBaseClassConstructor); }
  530. bool IsDerivedClassConstructor() const { return IsClassConstructor() && !IsBaseClassConstructor(); }
  531. bool IsClassMember() const { return HasFlags(kFunctionIsClassMember); }
  532. bool IsDeclaration() const { return HasFlags(kFunctionDeclaration); }
  533. bool IsGeneratedDefault() const { return HasFlags(kFunctionIsGeneratedDefault); }
  534. bool IsGenerator() const { return HasFlags(kFunctionIsGenerator); }
  535. bool IsCoroutine() const { return HasAnyFlags(kFunctionIsGenerator | kFunctionIsAsync); }
  536. bool IsLambda() const { return HasFlags(kFunctionIsLambda); }
  537. bool IsMethod() const { return HasFlags(kFunctionIsMethod); }
  538. bool IsNested() const { return HasFlags(kFunctionNested); }
  539. bool IsStaticMember() const { return HasFlags(kFunctionIsStaticMember); }
  540. bool IsModule() const { return HasFlags(kFunctionIsModule); }
  541. bool HasComputedName() const { return HasFlags(kFunctionHasComputedName); }
  542. bool HasHomeObj() const { return HasFlags(kFunctionHasHomeObj); }
  543. bool UsesArguments() const { return HasFlags(kFunctionUsesArguments); }
  544. bool IsDefaultModuleExport() const { return HasFlags(kFunctionIsDefaultModuleExport); }
  545. bool IsDeclaredInParamScope() const { return HasFlags(kFunctionIsDeclaredInParamScope); }
  546. bool NestedFuncEscapes() const { return nestedFuncEscapes; }
  547. bool CanBeDeferred() const { return canBeDeferred; }
  548. bool IsBodyAndParamScopeMerged() { return isBodyAndParamScopeMerged; }
  549. Js::RegSlot GetHomeObjLocation() const { return homeObjLocation; }
  550. // Only allow the normal functions to be asm.js
  551. bool IsAsmJsAllowed() const { return (fncFlags & ~(
  552. kFunctionAsmjsMode |
  553. kFunctionNested |
  554. kFunctionDeclaration |
  555. kFunctionStrictMode |
  556. kFunctionHasReferenceableBuiltInArguments |
  557. kFunctionHasNonThisStmt |
  558. // todo:: we shouldn't accept kFunctionHasAnyWriteToFormals on the asm module, but it looks like a bug is setting that flag incorrectly
  559. kFunctionHasAnyWriteToFormals
  560. )) == 0; }
  561. size_t LengthInBytes()
  562. {
  563. return cbLim - cbMin;
  564. }
  565. Symbol *GetFuncSymbol();
  566. void SetFuncSymbol(Symbol *sym);
  567. ParseNodePtr GetParamScope() const;
  568. ParseNodePtr GetBodyScope() const;
  569. ParseNodePtr GetTopLevelScope() const
  570. {
  571. // Top level scope will be the same for knopProg and knopFncDecl.
  572. return GetParamScope();
  573. }
  574. template<typename Fn>
  575. void MapContainerScopes(Fn fn)
  576. {
  577. fn(this->pnodeScopes->pnodeScopes);
  578. if (this->pnodeBodyScope != nullptr)
  579. {
  580. fn(this->pnodeBodyScope->pnodeScopes);
  581. }
  582. }
  583. IdentPtrSet* EnsureCapturedNames(ArenaAllocator* alloc);
  584. IdentPtrSet* GetCapturedNames();
  585. bool HasAnyCapturedNames();
  586. DISABLE_SELF_CAST(ParseNodeFnc);
  587. };
  588. // class declaration
  589. class ParseNodeClass : public ParseNode
  590. {
  591. public:
  592. ParseNodeClass(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  593. ParseNodeVar * pnodeName;
  594. ParseNodeVar * pnodeDeclName;
  595. ParseNodeBlock * pnodeBlock;
  596. ParseNodeFnc * pnodeConstructor;
  597. ParseNodePtr pnodeMembers;
  598. ParseNodePtr pnodeExtends;
  599. bool isDefaultModuleExport;
  600. void SetIsDefaultModuleExport(bool set) { isDefaultModuleExport = set; }
  601. bool IsDefaultModuleExport() const { return isDefaultModuleExport; }
  602. DISABLE_SELF_CAST(ParseNodeClass);
  603. };
  604. // export default expr
  605. class ParseNodeExportDefault : public ParseNode
  606. {
  607. public:
  608. ParseNodeExportDefault(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  609. ParseNodePtr pnodeExpr;
  610. DISABLE_SELF_CAST(ParseNodeExportDefault);
  611. };
  612. // string template declaration
  613. class ParseNodeStrTemplate : public ParseNode
  614. {
  615. public:
  616. ParseNodeStrTemplate(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  617. ParseNodePtr pnodeStringLiterals;
  618. ParseNodePtr pnodeStringRawLiterals;
  619. ParseNodePtr pnodeSubstitutionExpressions;
  620. uint16 countStringLiterals;
  621. BYTE isTaggedTemplate:1;
  622. DISABLE_SELF_CAST(ParseNodeStrTemplate);
  623. };
  624. // global program
  625. class ParseNodeProg : public ParseNodeFnc
  626. {
  627. public:
  628. ParseNodeProg(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  629. ParseNodePtr pnodeLastValStmt; // Used by ByteCodeGenerator
  630. bool m_UsesArgumentsAtGlobal;
  631. DISABLE_SELF_CAST(ParseNodeProg);
  632. };
  633. // global module
  634. class ParseNodeModule : public ParseNodeProg
  635. {
  636. public:
  637. ParseNodeModule(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  638. ModuleImportOrExportEntryList* localExportEntries;
  639. ModuleImportOrExportEntryList* indirectExportEntries;
  640. ModuleImportOrExportEntryList* starExportEntries;
  641. ModuleImportOrExportEntryList* importEntries;
  642. IdentPtrList* requestedModules;
  643. DISABLE_SELF_CAST(ParseNodeModule);
  644. };
  645. // function call
  646. class ParseNodeCall : public ParseNode
  647. {
  648. public:
  649. ParseNodeCall(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNodePtr pnodeTarget, ParseNodePtr pnodeArgs);
  650. ParseNodePtr pnodeTarget;
  651. ParseNodePtr pnodeArgs;
  652. uint16 argCount;
  653. uint16 spreadArgCount;
  654. BYTE callOfConstants : 1;
  655. BYTE isApplyCall : 1;
  656. BYTE isEvalCall : 1;
  657. BYTE isSuperCall : 1;
  658. BYTE hasDestructuring : 1;
  659. DISABLE_SELF_CAST(ParseNodeCall);
  660. };
  661. // base for statement nodes
  662. class ParseNodeStmt : public ParseNode
  663. {
  664. public:
  665. ParseNodeStmt(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  666. // Set by parsing code, used by code gen.
  667. uint grfnop;
  668. // Needed for byte code gen.
  669. Js::ByteCodeLabel breakLabel;
  670. Js::ByteCodeLabel continueLabel;
  671. bool emitLabels;
  672. DISABLE_SELF_CAST(ParseNodeStmt);
  673. };
  674. // block { }
  675. class ParseNodeBlock : public ParseNodeStmt
  676. {
  677. public:
  678. ParseNodeBlock(charcount_t ichMin, charcount_t ichLim, int blockId, PnodeBlockType blockType);
  679. ParseNodePtr pnodeStmt;
  680. ParseNodePtr pnodeLastValStmt;
  681. ParseNodePtr pnodeLexVars;
  682. ParseNodePtr pnodeScopes;
  683. ParseNodePtr pnodeNext;
  684. Scope *scope;
  685. ParseNodeBlock * enclosingBlock;
  686. int blockId;
  687. PnodeBlockType blockType:2;
  688. BYTE callsEval:1;
  689. BYTE childCallsEval:1;
  690. void SetCallsEval(bool does) { callsEval = does; }
  691. bool GetCallsEval() const { return callsEval; }
  692. void SetChildCallsEval(bool does) { childCallsEval = does; }
  693. bool GetChildCallsEval() const { return childCallsEval; }
  694. void SetEnclosingBlock(ParseNodeBlock * pnode) { enclosingBlock = pnode; }
  695. ParseNodeBlock * GetEnclosingBlock() const { return enclosingBlock; }
  696. bool HasBlockScopedContent() const;
  697. DISABLE_SELF_CAST(ParseNodeBlock);
  698. };
  699. // break and continue
  700. class ParseNodeJump : public ParseNodeStmt
  701. {
  702. public:
  703. ParseNodeJump(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  704. ParseNodeStmt * pnodeTarget;
  705. bool hasExplicitTarget;
  706. DISABLE_SELF_CAST(ParseNodeJump);
  707. };
  708. // while and do-while loops
  709. class ParseNodeWhile : public ParseNodeStmt
  710. {
  711. public:
  712. ParseNodeWhile(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  713. ParseNodePtr pnodeCond;
  714. ParseNodePtr pnodeBody;
  715. DISABLE_SELF_CAST(ParseNodeWhile);
  716. };
  717. // with
  718. class ParseNodeWith : public ParseNodeStmt
  719. {
  720. public:
  721. ParseNodeWith(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  722. ParseNodePtr pnodeObj;
  723. ParseNodePtr pnodeBody;
  724. ParseNodePtr pnodeScopes;
  725. ParseNodePtr pnodeNext;
  726. Scope *scope;
  727. DISABLE_SELF_CAST(ParseNodeWith);
  728. };
  729. // Destructure pattern for function/catch parameter
  730. class ParseNodeParamPattern : public ParseNodeUni
  731. {
  732. public:
  733. ParseNodeParamPattern(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  734. ParseNodePtr pnodeNext;
  735. Js::RegSlot location;
  736. DISABLE_SELF_CAST(ParseNodeParamPattern);
  737. };
  738. // if
  739. class ParseNodeIf : public ParseNodeStmt
  740. {
  741. public:
  742. ParseNodeIf(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  743. ParseNodePtr pnodeCond;
  744. ParseNodePtr pnodeTrue;
  745. ParseNodePtr pnodeFalse;
  746. DISABLE_SELF_CAST(ParseNodeIf);
  747. };
  748. // for-in loop
  749. class ParseNodeForInOrForOf : public ParseNodeStmt
  750. {
  751. public:
  752. ParseNodeForInOrForOf(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  753. ParseNodePtr pnodeObj;
  754. ParseNodePtr pnodeBody;
  755. ParseNodePtr pnodeLval;
  756. ParseNodeBlock * pnodeBlock;
  757. Js::RegSlot itemLocation;
  758. Js::RegSlot shouldCallReturnFunctionLocation;
  759. Js::RegSlot shouldCallReturnFunctionLocationFinally;
  760. DISABLE_SELF_CAST(ParseNodeForInOrForOf);
  761. };
  762. // for loop
  763. class ParseNodeFor : public ParseNodeStmt
  764. {
  765. public:
  766. ParseNodeFor(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  767. ParseNodePtr pnodeCond;
  768. ParseNodePtr pnodeBody;
  769. ParseNodePtr pnodeInit;
  770. ParseNodePtr pnodeIncr;
  771. ParseNodeBlock * pnodeBlock;
  772. ParseNodeFor * pnodeInverted;
  773. DISABLE_SELF_CAST(ParseNodeFor);
  774. };
  775. // switch
  776. class ParseNodeSwitch : public ParseNodeStmt
  777. {
  778. public:
  779. ParseNodeSwitch(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  780. ParseNodePtr pnodeVal;
  781. ParseNodeCase * pnodeCases;
  782. ParseNodeCase * pnodeDefault;
  783. ParseNodeBlock * pnodeBlock;
  784. DISABLE_SELF_CAST(ParseNodeSwitch);
  785. };
  786. // switch case
  787. class ParseNodeCase : public ParseNodeStmt
  788. {
  789. public:
  790. ParseNodeCase(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  791. ParseNodeCase * pnodeNext;
  792. ParseNodePtr pnodeExpr; // nullptr for default
  793. ParseNodeBlock * pnodeBody;
  794. Js::ByteCodeLabel labelCase;
  795. DISABLE_SELF_CAST(ParseNodeCase);
  796. };
  797. // return [expr]
  798. class ParseNodeReturn : public ParseNodeStmt
  799. {
  800. public:
  801. ParseNodeReturn(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  802. ParseNodePtr pnodeExpr;
  803. DISABLE_SELF_CAST(ParseNodeReturn);
  804. };
  805. // try-catch-finally
  806. class ParseNodeTryFinally : public ParseNodeStmt
  807. {
  808. public:
  809. ParseNodeTryFinally(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  810. ParseNodeTry * pnodeTry;
  811. ParseNodeFinally * pnodeFinally;
  812. DISABLE_SELF_CAST(ParseNodeTryFinally);
  813. };
  814. // try-catch
  815. class ParseNodeTryCatch : public ParseNodeStmt
  816. {
  817. public:
  818. ParseNodeTryCatch(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  819. ParseNodeTry * pnodeTry;
  820. ParseNodeCatch * pnodeCatch;
  821. DISABLE_SELF_CAST(ParseNodeTryCatch);
  822. };
  823. // try-catch
  824. class ParseNodeTry : public ParseNodeStmt
  825. {
  826. public:
  827. ParseNodeTry(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  828. ParseNodePtr pnodeBody;
  829. DISABLE_SELF_CAST(ParseNodeTry);
  830. };
  831. // { catch(e : expr) {body} }
  832. class ParseNodeCatch : public ParseNodeStmt
  833. {
  834. public:
  835. ParseNodeCatch(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  836. bool HasPatternParam() { return pnodeParam != nullptr && pnodeParam->nop == knopParamPattern; }
  837. bool HasParam() { return pnodeParam != nullptr; }
  838. ParseNodePtr GetParam() { return pnodeParam; }
  839. void SetParam(ParseNodeName * pnode) { pnodeParam = pnode; }
  840. void SetParam(ParseNodeParamPattern * pnode) { pnodeParam = pnode; }
  841. ParseNodePtr pnodeNext;
  842. private:
  843. ParseNode * pnodeParam; // Name or ParamPattern
  844. public:
  845. ParseNodePtr pnodeBody;
  846. ParseNodePtr pnodeScopes;
  847. Scope *scope;
  848. DISABLE_SELF_CAST(ParseNodeCatch);
  849. };
  850. // finally
  851. class ParseNodeFinally : public ParseNodeStmt
  852. {
  853. public:
  854. ParseNodeFinally(OpCode nop, charcount_t ichMin, charcount_t ichLim);
  855. ParseNodePtr pnodeBody;
  856. DISABLE_SELF_CAST(ParseNodeFinally);
  857. };
  858. // special name like 'this'
  859. class ParseNodeSpecialName : public ParseNodeName
  860. {
  861. public:
  862. ParseNodeSpecialName(charcount_t ichMin, charcount_t ichLim, IdentPtr pid);
  863. bool isThis : 1;
  864. bool isSuper : 1;
  865. DISABLE_SELF_CAST(ParseNodeSpecialName);
  866. };
  867. // binary operator with super reference
  868. class ParseNodeSuperReference : public ParseNodeBin
  869. {
  870. public:
  871. ParseNodeSuperReference(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2);
  872. ParseNodeSpecialName * pnodeThis;
  873. DISABLE_SELF_CAST(ParseNodeSuperReference);
  874. };
  875. // call node with super target
  876. class ParseNodeSuperCall : public ParseNodeCall
  877. {
  878. public:
  879. ParseNodeSuperCall(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnodeTarget, ParseNode * pnodeArgs);
  880. ParseNodeSpecialName * pnodeThis;
  881. ParseNodeSpecialName * pnodeNewTarget;
  882. DISABLE_SELF_CAST(ParseNodeSuperCall);
  883. };
  884. typedef ParseNode ParseNodeNone;
  885. template <OpCode nop> class OpCodeTrait;
  886. #define PTNODE(nop,sn,pc,nk,ok,json) \
  887. template<> \
  888. class OpCodeTrait<nop> \
  889. { \
  890. public: \
  891. typedef ParseNode##nk ParseNodeType; \
  892. static const bool AllowDefer = ((ok) & fnopAllowDefer) != 0; \
  893. };
  894. #include "ptlist.h"