ByteCodeGenerator.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. #if defined(_M_ARM32_OR_ARM64) || defined(_M_X64)
  7. const int32 AstBytecodeRatioEstimate = 4;
  8. #else
  9. const int32 AstBytecodeRatioEstimate = 5;
  10. #endif
  11. enum DynamicLoadKind
  12. {
  13. Invalid,
  14. Local,
  15. Env,
  16. LocalWith,
  17. EnvWith
  18. };
  19. struct DynamicLoadRecord
  20. {
  21. DynamicLoadRecord();
  22. DynamicLoadKind kind;
  23. Js::ByteCodeLabel label;
  24. union
  25. {
  26. uint32 index;
  27. Js::RegSlot instance;
  28. };
  29. };
  30. struct JumpCleanupInfo
  31. {
  32. // Used for loop nodes
  33. ParseNode* loopNode;
  34. uint loopId;
  35. // Used for try and finally nodes
  36. Js::OpCode tryOp;
  37. Js::ByteCodeLabel label;
  38. Js::RegSlot regSlot1;
  39. Js::RegSlot regSlot2;
  40. };
  41. class ByteCodeGenerator
  42. {
  43. private:
  44. Js::ScriptContext* scriptContext;
  45. ArenaAllocator *alloc;
  46. uint32 flags;
  47. SList<FuncInfo*> *funcInfoStack;
  48. ParseNodeBlock *currentBlock;
  49. ParseNode *currentTopStatement;
  50. Scope *currentScope;
  51. Scope *globalScope; // the global members will be in this scope
  52. Js::ScopeInfo* parentScopeInfo;
  53. Js::ByteCodeWriter m_writer;
  54. // pointer to the root function wrapper that will be invoked by the caller
  55. Js::ParseableFunctionInfo * pRootFunc;
  56. SList<FuncInfo*> * funcInfosToFinalize;
  57. SList<ParseNode*> * nodesToTrackForYield;
  58. SList<ParseNode*> * nodesWithYield;
  59. using JumpCleanupList = DList<JumpCleanupInfo, ArenaAllocator>;
  60. JumpCleanupList* jumpCleanupList;
  61. int32 maxAstSize;
  62. uint16 envDepth;
  63. uint sourceIndex;
  64. uint dynamicScopeCount;
  65. uint loopDepth;
  66. uint16 m_callSiteId;
  67. uint16 m_callApplyCallSiteCount;
  68. bool isBinding;
  69. bool trackEnvDepth;
  70. bool funcEscapes;
  71. bool inPrologue;
  72. bool inDestructuredPattern;
  73. Parser* parser; // currently active parser (used for AST transformation)
  74. Js::Utf8SourceInfo *m_utf8SourceInfo;
  75. // The stack walker won't be able to find the current function being defer parse, pass in
  76. // The address so we can patch it up if it is a stack function and we need to box it.
  77. Js::ScriptFunction ** functionRef;
  78. public:
  79. // This points to the current function body which can be reused when parsing a subtree (called due to deferred parsing logic).
  80. Js::FunctionBody * pCurrentFunction;
  81. bool InDestructuredPattern() const { return inDestructuredPattern; }
  82. void SetInDestructuredPattern(bool in) { inDestructuredPattern = in; }
  83. bool InPrologue() const { return inPrologue; }
  84. void SetInPrologue(bool val) { inPrologue = val; }
  85. Parser* GetParser() { return parser; }
  86. Js::ParseableFunctionInfo * GetRootFunc(){return pRootFunc;}
  87. void SetRootFuncInfo(FuncInfo* funcInfo);
  88. // Treat the return value register like a constant register so that the byte code writer maps it to the bottom
  89. // of the register range.
  90. static const Js::RegSlot ReturnRegister = REGSLOT_TO_CONSTREG(Js::FunctionBody::ReturnValueRegSlot);
  91. static const Js::RegSlot RootObjectRegister = REGSLOT_TO_CONSTREG(Js::FunctionBody::RootObjectRegSlot);
  92. static const unsigned int DefaultArraySize = 0; // This __must__ be '0' so that "(new Array()).length == 0"
  93. static const unsigned int MinArgumentsForCallOptimization = 16;
  94. bool forceNoNative;
  95. // A flag that when set will force bytecode opcodes to be emitted in strict mode when avaliable.
  96. // This flag is set outside of emit calls under the condition that the bytecode being emitted
  97. // corresponds to computed property names within classes. This fixes a bug where computed property
  98. // names would not enforce strict mode when inside a class even though the spec requires that
  99. // all code within a class must be strict.
  100. bool forceStrictModeForClassComputedPropertyName = false;
  101. ByteCodeGenerator(Js::ScriptContext* scriptContext, Js::ScopeInfo* parentScopeInfo);
  102. #if DBG_DUMP
  103. bool Trace() const
  104. {
  105. return Js::Configuration::Global.flags.Trace.IsEnabled(Js::ByteCodePhase);
  106. }
  107. #else
  108. bool Trace() const
  109. {
  110. return false;
  111. }
  112. #endif
  113. Js::ScriptContext* GetScriptContext() { return scriptContext; }
  114. Scope *GetCurrentScope() const { return currentScope; }
  115. void SetCurrentBlock(ParseNodeBlock *pnode) { currentBlock = pnode; }
  116. ParseNodeBlock *GetCurrentBlock() const { return currentBlock; }
  117. void SetCurrentTopStatement(ParseNode *pnode) { currentTopStatement = pnode; }
  118. ParseNode *GetCurrentTopStatement() const { return currentTopStatement; }
  119. Js::ModuleID GetModuleID() const
  120. {
  121. return m_utf8SourceInfo->GetSrcInfo()->moduleID;
  122. }
  123. void SetFlags(uint32 grfscr)
  124. {
  125. flags = grfscr;
  126. }
  127. uint32 GetFlags(void)
  128. {
  129. return flags;
  130. }
  131. bool IsConsoleScopeEval(void)
  132. {
  133. return (flags & fscrConsoleScopeEval) == fscrConsoleScopeEval;
  134. }
  135. bool IsModuleCode()
  136. {
  137. return (flags & fscrIsModuleCode) == fscrIsModuleCode;
  138. }
  139. bool IsBinding() const {
  140. return isBinding;
  141. }
  142. Js::ByteCodeWriter *Writer() {
  143. return &m_writer;
  144. }
  145. ArenaAllocator *GetAllocator() {
  146. return alloc;
  147. }
  148. bool IsEvalWithNoParentScopeInfo()
  149. {
  150. return (flags & fscrEvalCode) && !HasParentScopeInfo();
  151. }
  152. Js::ProfileId GetNextCallSiteId(Js::OpCode op)
  153. {
  154. if (m_writer.ShouldIncrementCallSiteId(op))
  155. {
  156. if (m_callSiteId != Js::Constants::NoProfileId)
  157. {
  158. return m_callSiteId++;
  159. }
  160. }
  161. return m_callSiteId;
  162. }
  163. Js::ProfileId GetCurrentCallSiteId() { return m_callSiteId; }
  164. Js::ProfileId GetNextCallApplyCallSiteId(Js::OpCode op)
  165. {
  166. if (m_writer.ShouldIncrementCallSiteId(op))
  167. {
  168. if (m_callApplyCallSiteCount != Js::Constants::NoProfileId)
  169. {
  170. return m_callApplyCallSiteCount++;
  171. }
  172. }
  173. return m_callApplyCallSiteCount;
  174. }
  175. Js::RegSlot NextVarRegister();
  176. Js::RegSlot NextConstRegister();
  177. FuncInfo *TopFuncInfo() const;
  178. void EnterLoop();
  179. void ExitLoop() { loopDepth--; }
  180. BOOL IsInLoop() const { return loopDepth > 0; }
  181. // TODO: per-function register assignment for env and global symbols
  182. void AssignRegister(Symbol *sym);
  183. void AddTargetStmt(ParseNodeStmt *pnodeStmt);
  184. Js::RegSlot AssignNullConstRegister();
  185. Js::RegSlot AssignUndefinedConstRegister();
  186. Js::RegSlot AssignTrueConstRegister();
  187. Js::RegSlot AssignFalseConstRegister();
  188. Js::RegSlot AssignThisConstRegister();
  189. void SetNeedEnvRegister();
  190. void AssignFrameObjRegister();
  191. void AssignFrameSlotsRegister();
  192. void AssignParamSlotsRegister();
  193. void AssignFrameDisplayRegister();
  194. void ProcessCapturedSym(Symbol *sym);
  195. void ProcessScopeWithCapturedSym(Scope *scope);
  196. void InitScopeSlotArray(FuncInfo * funcInfo);
  197. void FinalizeRegisters(FuncInfo * funcInfo, Js::FunctionBody * byteCodeFunction);
  198. void SetClosureRegisters(FuncInfo * funcInfo, Js::FunctionBody * byteCodeFunction);
  199. void SetHasTry(bool has);
  200. void SetHasFinally(bool has);
  201. void SetNumberOfInArgs(Js::ArgSlot argCount);
  202. Js::RegSlot EnregisterConstant(unsigned int constant);
  203. Js::RegSlot EnregisterStringConstant(IdentPtr pid);
  204. Js::RegSlot EnregisterDoubleConstant(double d);
  205. Js::RegSlot EnregisterBigIntConstant(ParseNodePtr pid);
  206. Js::RegSlot EnregisterStringTemplateCallsiteConstant(ParseNode* pnode);
  207. static Js::JavascriptArray* BuildArrayFromStringList(ParseNode* stringNodeList, uint arrayLength, Js::ScriptContext* scriptContext);
  208. bool HasParentScopeInfo() const
  209. {
  210. return this->parentScopeInfo != nullptr;
  211. }
  212. Js::RegSlot EmitLdObjProto(Js::OpCode op, Js::RegSlot objReg, FuncInfo *funcInfo)
  213. {
  214. // LdHomeObjProto protoReg, objReg
  215. // LdFuncObjProto protoReg, objReg
  216. Js::RegSlot protoReg = funcInfo->AcquireTmpRegister();
  217. this->Writer()->Reg2(op, protoReg, objReg);
  218. funcInfo->ReleaseTmpRegister(protoReg);
  219. return protoReg;
  220. }
  221. void RestoreScopeInfo(Js::ScopeInfo *scopeInfo, FuncInfo * func);
  222. void RestoreOneScope(Js::ScopeInfo * scopeInfo, FuncInfo * func);
  223. FuncInfo *StartBindGlobalStatements(ParseNodeProg *pnode);
  224. void AssignPropertyId(Symbol *sym, Js::ParseableFunctionInfo* functionInfo);
  225. void AssignPropertyId(IdentPtr pid);
  226. void ProcessCapturedSyms(ParseNode *pnodeFnc);
  227. void RecordAllIntConstants(FuncInfo * funcInfo);
  228. void RecordAllStrConstants(FuncInfo * funcInfo);
  229. void RecordAllBigIntConstants(FuncInfo * funcInfo);
  230. void RecordAllStringTemplateCallsiteConstants(FuncInfo* funcInfo);
  231. // For now, this just assigns field ids for the current script.
  232. // Later, we will combine this information with the global field ID map.
  233. // This temporary code will not work if a global member is accessed both with and without a LHS.
  234. void AssignPropertyIds(Js::ParseableFunctionInfo* functionInfo);
  235. void MapCacheIdsToPropertyIds(FuncInfo *funcInfo);
  236. void MapReferencedPropertyIds(FuncInfo *funcInfo);
  237. #if ENABLE_NATIVE_CODEGEN
  238. void MapCallSiteToCallApplyCallSiteMap(FuncInfo * funcInfo);
  239. #endif
  240. FuncInfo *StartBindFunction(const char16 *name, uint nameLength, uint shortNameOffset, bool* pfuncExprWithName, ParseNodeFnc *pnodeFnc, Js::ParseableFunctionInfo * reuseNestedFunc);
  241. void EndBindFunction(bool funcExprWithName);
  242. void StartBindCatch(ParseNode *pnode);
  243. // Block scopes related functions
  244. template<class Fn> void IterateBlockScopedVariables(ParseNodeBlock *pnodeBlock, Fn fn);
  245. void InitBlockScopedContent(ParseNodeBlock *pnodeBlock, Js::DebuggerScope *debuggerScope, FuncInfo *funcInfo);
  246. Js::DebuggerScope* RecordStartScopeObject(ParseNode *pnodeBlock, Js::DiagExtraScopesType scopeType, Js::RegSlot scopeLocation = Js::Constants::NoRegister, int* index = nullptr);
  247. void RecordEndScopeObject(ParseNode *pnodeBlock);
  248. void EndBindCatch();
  249. void StartEmitFunction(ParseNodeFnc *pnodeFnc);
  250. void EndEmitFunction(ParseNodeFnc *pnodeFnc);
  251. void StartEmitBlock(ParseNodeBlock *pnodeBlock);
  252. void EndEmitBlock(ParseNodeBlock *pnodeBlock);
  253. void StartEmitCatch(ParseNodeCatch *pnodeCatch);
  254. void EndEmitCatch(ParseNodeCatch *pnodeCatch);
  255. void StartEmitWith(ParseNode *pnodeWith);
  256. void EndEmitWith(ParseNode *pnodeWith);
  257. void EnsureFncScopeSlots(ParseNode *pnode, FuncInfo *funcInfo);
  258. void EnsureLetConstScopeSlots(ParseNodeBlock *pnodeBlock, FuncInfo *funcInfo);
  259. bool EnsureSymbolModuleSlots(Symbol* sym, FuncInfo* funcInfo);
  260. void EmitAssignmentToDefaultModuleExport(ParseNode* pnode, FuncInfo* funcInfo);
  261. void EmitModuleExportAccess(Symbol* sym, Js::OpCode opcode, Js::RegSlot location, FuncInfo* funcInfo);
  262. void PushScope(Scope *innerScope);
  263. void PopScope();
  264. void PushBlock(ParseNodeBlock *pnode);
  265. void PopBlock();
  266. void PushFuncInfo(char16 const * location, FuncInfo* funcInfo);
  267. void PopFuncInfo(char16 const * location);
  268. Js::RegSlot PrependLocalScopes(Js::RegSlot evalEnv, Js::RegSlot tempLoc, FuncInfo *funcInfo);
  269. Symbol *FindSymbol(Symbol **symRef, IdentPtr pid, bool forReference = false);
  270. Symbol *AddSymbolToScope(Scope *scope, const char16 *key, int keyLength, ParseNode *varDecl, SymbolType symbolType);
  271. Symbol *AddSymbolToFunctionScope(const char16 *key, int keyLength, ParseNode *varDecl, SymbolType symbolType);
  272. void FuncEscapes(Scope *scope);
  273. void EmitTopLevelStatement(ParseNode *stmt, FuncInfo *funcInfo, BOOL fReturnValue);
  274. void EmitInvertedLoop(ParseNodeStmt* outerLoop,ParseNodeFor* invertedLoop,FuncInfo* funcInfo);
  275. void DefineFunctions(FuncInfo *funcInfoParent);
  276. Js::RegSlot DefineOneFunction(ParseNodeFnc *pnodeFnc, FuncInfo *funcInfoParent, bool generateAssignment=true, Js::RegSlot regEnv = Js::Constants::NoRegister, Js::RegSlot frameDisplayTemp = Js::Constants::NoRegister);
  277. void DefineCachedFunctions(FuncInfo *funcInfoParent);
  278. void DefineUncachedFunctions(FuncInfo *funcInfoParent);
  279. void DefineUserVars(FuncInfo *funcInfo);
  280. void InitBlockScopedNonTemps(ParseNode *pnode, FuncInfo *funcInfo);
  281. // temporarily load all constants and special registers in a single block
  282. void LoadAllConstants(FuncInfo *funcInfo);
  283. void LoadHeapArguments(FuncInfo *funcInfo);
  284. void LoadUncachedHeapArguments(FuncInfo *funcInfo);
  285. void LoadCachedHeapArguments(FuncInfo *funcInfo);
  286. void LoadThisObject(FuncInfo *funcInfo, bool thisLoadedFromParams = false);
  287. void EmitThis(FuncInfo *funcInfo, Js::RegSlot lhsLocation, Js::RegSlot fromRegister);
  288. void LoadNewTargetObject(FuncInfo *funcInfo);
  289. void LoadImportMetaObject(FuncInfo* funcInfo);
  290. void LoadSuperObject(FuncInfo *funcInfo);
  291. void LoadSuperConstructorObject(FuncInfo *funcInfo);
  292. void EmitSuperCall(FuncInfo* funcInfo, ParseNodeSuperCall * pnodeSuperCall, BOOL fReturnValue, BOOL fEvaluateComponents);
  293. void EmitClassConstructorEndCode(FuncInfo *funcInfo);
  294. // TODO: home the 'this' argument
  295. void EmitLoadFormalIntoRegister(ParseNode *pnodeFormal, Js::RegSlot pos, FuncInfo *funcInfo);
  296. void HomeArguments(FuncInfo *funcInfo);
  297. void EnsureNoRedeclarations(ParseNodeBlock *pnodeBlock, FuncInfo *funcInfo);
  298. void DefineLabels(FuncInfo *funcInfo);
  299. void EmitProgram(ParseNodeProg *pnodeProg);
  300. void EmitScopeList(ParseNode *pnode, ParseNode *breakOnBodyScopeNode = nullptr);
  301. void EmitDefaultArgs(FuncInfo *funcInfo, ParseNodeFnc *pnode);
  302. void EmitOneFunction(ParseNodeFnc *pnodeFnc);
  303. void EmitGlobalFncDeclInit(Js::RegSlot rhsLocation, Js::PropertyId propertyId, FuncInfo * funcInfo);
  304. void EmitLocalPropInit(Js::RegSlot rhsLocation, Symbol *sym, FuncInfo *funcInfo);
  305. void EmitPropStore(Js::RegSlot rhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo, bool isLet = false, bool isConst = false, bool isFncDeclVar = false, bool skipUseBeforeDeclarationCheck = false);
  306. void EmitPropLoad(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo, bool skipUseBeforeDeclarationCheck = false);
  307. void EmitPropDelete(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo);
  308. void EmitPropTypeof(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo);
  309. void EmitTypeOfFld(FuncInfo * funcInfo, Js::PropertyId propertyId, Js::RegSlot value, Js::RegSlot instance, Js::OpCode op1, bool reuseLoc = false);
  310. bool ShouldLoadConstThis(FuncInfo* funcInfo);
  311. void EmitPropLoadThis(Js::RegSlot lhsLocation, ParseNodeSpecialName *pnode, FuncInfo *funcInfo, bool chkUndecl);
  312. void EmitPropStoreForSpecialSymbol(Js::RegSlot rhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo, bool init);
  313. void EmitLoadInstance(Symbol *sym, IdentPtr pid, Js::RegSlot *pThisLocation, Js::RegSlot *pTargetLocation, FuncInfo *funcInfo);
  314. void EmitGlobalBody(FuncInfo *funcInfo);
  315. void EmitFunctionBody(FuncInfo *funcInfo);
  316. void EmitAsmFunctionBody(FuncInfo *funcInfo);
  317. void EmitScopeObjectInit(FuncInfo *funcInfo);
  318. void EmitPatchableRootProperty(Js::OpCode opcode, Js::RegSlot regSlot, Js::PropertyId propertyId, bool isLoadMethod, bool isStore, FuncInfo *funcInfo);
  319. struct TryScopeRecord;
  320. JsUtil::DoublyLinkedList<TryScopeRecord> tryScopeRecordsList;
  321. void EmitLeaveOpCodesBeforeYield();
  322. void EmitTryBlockHeadersAfterYield();
  323. void InvalidateCachedOuterScopes(FuncInfo *funcInfo);
  324. bool InDynamicScope() const { return dynamicScopeCount != 0; }
  325. Scope * FindScopeForSym(Scope *symScope, Scope *scope, Js::PropertyId *envIndex, FuncInfo *funcInfo) const;
  326. static Js::OpCode GetStFldOpCode(bool isStrictMode, bool isRoot, bool isLetDecl, bool isConstDecl, bool isClassMemberInit)
  327. {
  328. return isClassMemberInit ? Js::OpCode::InitClassMember :
  329. isConstDecl ? (isRoot ? Js::OpCode::InitRootConstFld : Js::OpCode::InitConstFld) :
  330. isLetDecl ? (isRoot ? Js::OpCode::InitRootLetFld : Js::OpCode::InitLetFld) :
  331. isStrictMode ? (isRoot ? Js::OpCode::StRootFldStrict : Js::OpCode::StFldStrict) :
  332. isRoot ? Js::OpCode::StRootFld : Js::OpCode::StFld;
  333. }
  334. static Js::OpCode GetStFldOpCode(FuncInfo* funcInfo, bool isRoot, bool isLetDecl, bool isConstDecl, bool isClassMemberInit, bool forceStrictModeForClassComputedPropertyName = false);
  335. static Js::OpCode GetScopedStFldOpCode(bool isStrictMode, bool isConsoleScope = false)
  336. {
  337. return isStrictMode ?
  338. (isConsoleScope ? Js::OpCode::ConsoleScopedStFldStrict : Js::OpCode::ScopedStFldStrict) :
  339. (isConsoleScope ? Js::OpCode::ConsoleScopedStFld : Js::OpCode::ScopedStFld);
  340. }
  341. static Js::OpCode GetScopedStFldOpCode(FuncInfo* funcInfo, bool isConsoleScopeLetConst = false);
  342. static Js::OpCode GetStElemIOpCode(bool isStrictMode)
  343. {
  344. return isStrictMode ? Js::OpCode::StElemI_A_Strict : Js::OpCode::StElemI_A;
  345. }
  346. static Js::OpCode GetStElemIOpCode(FuncInfo* funcInfo);
  347. bool DoJitLoopBodies(FuncInfo *funcInfo) const;
  348. static void Generate(_In_ ParseNodeProg *pnode, uint32 grfscr, _In_ ByteCodeGenerator* byteCodeGenerator, __inout Js::ParseableFunctionInfo ** ppRootFunc, _In_ uint sourceIndex, _In_ bool forceNoNative, _In_ Parser* parser, Js::ScriptFunction ** functionRef);
  349. void Begin(
  350. _In_ ArenaAllocator *alloc,
  351. _In_ uint32 grfscr,
  352. _In_ Js::ParseableFunctionInfo* pRootFunc);
  353. void SetCurrentSourceIndex(uint sourceIndex) { this->sourceIndex = sourceIndex; }
  354. uint GetCurrentSourceIndex() { return sourceIndex; }
  355. static bool IsFalse(ParseNode* node);
  356. static bool IsThis(ParseNode* pnode);
  357. static bool IsSuper(ParseNode* pnode);
  358. void StartStatement(ParseNode* node);
  359. void EndStatement(ParseNode* node);
  360. void StartSubexpression(ParseNode* node);
  361. void EndSubexpression(ParseNode* node);
  362. // Debugger methods.
  363. bool IsInDebugMode() const;
  364. bool IsInNonDebugMode() const;
  365. bool ShouldTrackDebuggerMetadata() const;
  366. void TrackRegisterPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol *symbol, FuncInfo *funcInfo, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  367. void TrackActivationObjectPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol *symbol, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  368. void TrackSlotArrayPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol* symbol, Js::PropertyId propertyId, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  369. void TrackFunctionDeclarationPropertyForDebugger(Symbol *functionDeclarationSymbol, FuncInfo *funcInfoParent);
  370. void UpdateDebuggerPropertyInitializationOffset(Js::RegSlot location, Js::PropertyId propertyId, bool shouldConsumeRegister = true);
  371. void PopulateFormalsScope(uint beginOffset, FuncInfo *funcInfo, ParseNodeFnc *pnodeFnc);
  372. void InsertPropertyToDebuggerScope(FuncInfo* funcInfo, Js::DebuggerScope* debuggerScope, Symbol* sym);
  373. FuncInfo *FindEnclosingNonLambda();
  374. static FuncInfo* GetParentFuncInfo(FuncInfo* child);
  375. FuncInfo* GetEnclosingFuncInfo();
  376. bool CanStackNestedFunc(FuncInfo * funcInfo, bool trace = false);
  377. void CheckDeferParseHasMaybeEscapedNestedFunc();
  378. bool NeedObjectAsFunctionScope(FuncInfo * funcInfo, ParseNodeFnc * pnodeFnc) const;
  379. bool HasInterleavingDynamicScope(Symbol * sym) const;
  380. Js::FunctionBody *EnsureFakeGlobalFuncForUndefer(ParseNode *pnode);
  381. Js::FunctionBody *MakeGlobalFunctionBody(ParseNode *pnode);
  382. bool NeedScopeObjectForArguments(FuncInfo *funcInfo, ParseNodeFnc *pnodeFnc) const;
  383. void AddFuncInfoToFinalizationSet(FuncInfo *funcInfo);
  384. void FinalizeFuncInfos();
  385. void CheckFncDeclScopeSlot(ParseNodeFnc *pnodeFnc, FuncInfo *funcInfo);
  386. void EnsureFncDeclScopeSlot(ParseNodeFnc *pnodeFnc, FuncInfo *funcInfo);
  387. Js::OpCode GetStSlotOp(Scope *scope, int envIndex, Js::RegSlot scopeLocation, bool chkBlockVar, FuncInfo *funcInfo);
  388. Js::OpCode GetLdSlotOp(Scope *scope, int envIndex, Js::RegSlot scopeLocation, FuncInfo *funcInfo);
  389. Js::OpCode GetInitFldOp(Scope *scope, Js::RegSlot scopeLocation, FuncInfo *funcInfo, bool letDecl = false);
  390. void PushJumpCleanupForLoop(ParseNode* loopNode, uint loopId)
  391. {
  392. this->jumpCleanupList->Prepend({
  393. loopNode,
  394. loopId,
  395. Js::OpCode::Nop,
  396. 0,
  397. Js::Constants::NoRegister,
  398. Js::Constants::NoRegister
  399. });
  400. }
  401. void PushJumpCleanupForTry(
  402. Js::OpCode tryOp,
  403. Js::ByteCodeLabel label = 0,
  404. Js::RegSlot regSlot1 = Js::Constants::NoRegister,
  405. Js::RegSlot regSlot2 = Js::Constants::NoRegister)
  406. {
  407. this->jumpCleanupList->Prepend({nullptr, 0, tryOp, label, regSlot1, regSlot2});
  408. }
  409. void PopJumpCleanup() { this->jumpCleanupList->RemoveHead(); }
  410. bool HasJumpCleanup() { return !this->jumpCleanupList->Empty(); }
  411. void EmitJumpCleanup(ParseNode* target, FuncInfo* funcInfo);
  412. void ByteCodeGenerator::SetHasYield();
  413. bool ByteCodeGenerator::GetHasYield(ParseNode* node);
  414. void ByteCodeGenerator::PopTrackForYield(ParseNode* node);
  415. void ByteCodeGenerator::PushTrackForYield(ParseNode* node);
  416. private:
  417. bool NeedCheckBlockVar(Symbol* sym, Scope* scope, FuncInfo* funcInfo) const;
  418. Js::OpCode ToChkUndeclOp(Js::OpCode op) const;
  419. };
  420. template<class Fn> void ByteCodeGenerator::IterateBlockScopedVariables(ParseNodeBlock *pnodeBlock, Fn fn)
  421. {
  422. Assert(pnodeBlock->nop == knopBlock);
  423. for (auto lexvar = pnodeBlock->pnodeLexVars; lexvar; lexvar = lexvar->AsParseNodeVar()->pnodeNext)
  424. {
  425. fn(lexvar);
  426. }
  427. }
  428. struct ApplyCheck
  429. {
  430. bool matches;
  431. bool insideApplyCall;
  432. bool sawApply;
  433. };