ByteCodeGenerator.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. #if defined(_M_ARM32_OR_ARM64) || defined(_M_X64)
  6. const int32 AstBytecodeRatioEstimate = 4;
  7. #else
  8. const int32 AstBytecodeRatioEstimate = 5;
  9. #endif
  10. class ByteCodeGenerator
  11. {
  12. private:
  13. Js::ScriptContext* scriptContext;
  14. ArenaAllocator *alloc;
  15. uint32 flags;
  16. Js::PropertyRecordList* propertyRecords;
  17. SList<FuncInfo*> *funcInfoStack;
  18. ParseNode *currentBlock;
  19. ParseNode *currentTopStatement;
  20. Scope *currentScope;
  21. Scope *globalScope; // the global members will be in this scope
  22. Js::ScopeInfo* parentScopeInfo;
  23. Js::ByteCodeWriter m_writer;
  24. // pointer to the root function wrapper that will be invoked by the caller
  25. Js::ParseableFunctionInfo * pRootFunc;
  26. SList<FuncInfo*> * funcInfosToFinalize;
  27. int32 maxAstSize;
  28. uint16 envDepth;
  29. uint sourceIndex;
  30. uint dynamicScopeCount;
  31. uint loopDepth;
  32. uint16 m_callSiteId;
  33. bool isBinding;
  34. bool trackEnvDepth;
  35. bool funcEscapes;
  36. bool inPrologue;
  37. bool inDestructuredPattern;
  38. Parser* parser; // currently active parser (used for AST transformation)
  39. Js::Utf8SourceInfo *m_utf8SourceInfo;
  40. // The stack walker won't be able to find the current function being defer parse, pass in
  41. // The address so we can patch it up if it is a stack function and we need to box it.
  42. Js::ScriptFunction ** functionRef;
  43. public:
  44. // This points to the current function body which can be reused when parsing a subtree (called due to deferred parsing logic).
  45. Js::FunctionBody * pCurrentFunction;
  46. bool InDestructuredPattern() const { return inDestructuredPattern; }
  47. void SetInDestructuredPattern(bool in) { inDestructuredPattern = in; }
  48. bool InPrologue() const { return inPrologue; }
  49. void SetInPrologue(bool val) { inPrologue = val; }
  50. Parser* GetParser() { return parser; }
  51. Js::ParseableFunctionInfo * GetRootFunc(){return pRootFunc;}
  52. void SetRootFuncInfo(FuncInfo* funcInfo);
  53. // Treat the return value register like a constant register so that the byte code writer maps it to the bottom
  54. // of the register range.
  55. static const Js::RegSlot ReturnRegister = REGSLOT_TO_CONSTREG(Js::FunctionBody::ReturnValueRegSlot);
  56. static const Js::RegSlot RootObjectRegister = REGSLOT_TO_CONSTREG(Js::FunctionBody::RootObjectRegSlot);
  57. static const unsigned int DefaultArraySize = 0; // This __must__ be '0' so that "(new Array()).length == 0"
  58. static const unsigned int MinArgumentsForCallOptimization = 16;
  59. bool forceNoNative;
  60. ByteCodeGenerator(Js::ScriptContext* scriptContext, Js::ScopeInfo* parentScopeInfo);
  61. #if DBG_DUMP
  62. bool Trace() const
  63. {
  64. return Js::Configuration::Global.flags.Trace.IsEnabled(Js::ByteCodePhase);
  65. }
  66. #else
  67. bool Trace() const
  68. {
  69. return false;
  70. }
  71. #endif
  72. Js::ScriptContext* GetScriptContext() { return scriptContext; }
  73. Scope *GetCurrentScope() const { return currentScope; }
  74. void SetCurrentBlock(ParseNode *pnode) { currentBlock = pnode; }
  75. ParseNode *GetCurrentBlock() const { return currentBlock; }
  76. void SetCurrentTopStatement(ParseNode *pnode) { currentTopStatement = pnode; }
  77. ParseNode *GetCurrentTopStatement() const { return currentTopStatement; }
  78. Js::ModuleID GetModuleID() const
  79. {
  80. return m_utf8SourceInfo->GetSrcInfo()->moduleID;
  81. }
  82. void SetFlags(uint32 grfscr)
  83. {
  84. flags = grfscr;
  85. }
  86. uint32 GetFlags(void)
  87. {
  88. return flags;
  89. }
  90. bool IsConsoleScopeEval(void)
  91. {
  92. return (flags & fscrConsoleScopeEval) == fscrConsoleScopeEval;
  93. }
  94. bool IsModuleCode()
  95. {
  96. return (flags & fscrIsModuleCode) == fscrIsModuleCode;
  97. }
  98. bool IsBinding() const {
  99. return isBinding;
  100. }
  101. Js::ByteCodeWriter *Writer() {
  102. return &m_writer;
  103. }
  104. ArenaAllocator *GetAllocator() {
  105. return alloc;
  106. }
  107. Js::PropertyRecordList* EnsurePropertyRecordList()
  108. {
  109. if (this->propertyRecords == nullptr)
  110. {
  111. Recycler* recycler = this->scriptContext->GetRecycler();
  112. this->propertyRecords = RecyclerNew(recycler, Js::PropertyRecordList, recycler);
  113. }
  114. return this->propertyRecords;
  115. }
  116. bool IsEvalWithNoParentScopeInfo()
  117. {
  118. return (flags & fscrEvalCode) && !HasParentScopeInfo();
  119. }
  120. Js::ProfileId GetNextCallSiteId(Js::OpCode op)
  121. {
  122. if (m_writer.ShouldIncrementCallSiteId(op))
  123. {
  124. if (m_callSiteId != Js::Constants::NoProfileId)
  125. {
  126. return m_callSiteId++;
  127. }
  128. }
  129. return m_callSiteId;
  130. }
  131. Js::RegSlot NextVarRegister();
  132. Js::RegSlot NextConstRegister();
  133. FuncInfo *TopFuncInfo() const;
  134. void EnterLoop();
  135. void ExitLoop() { loopDepth--; }
  136. BOOL IsInLoop() const { return loopDepth > 0; }
  137. // TODO: per-function register assignment for env and global symbols
  138. void AssignRegister(Symbol *sym);
  139. void AddTargetStmt(ParseNode *pnodeStmt);
  140. Js::RegSlot AssignNullConstRegister();
  141. Js::RegSlot AssignUndefinedConstRegister();
  142. Js::RegSlot AssignTrueConstRegister();
  143. Js::RegSlot AssignFalseConstRegister();
  144. Js::RegSlot AssignThisRegister();
  145. Js::RegSlot AssignNewTargetRegister();
  146. void SetNeedEnvRegister();
  147. void AssignFrameObjRegister();
  148. void AssignFrameSlotsRegister();
  149. void AssignParamSlotsRegister();
  150. void AssignFrameDisplayRegister();
  151. void ProcessCapturedSym(Symbol *sym);
  152. void ProcessScopeWithCapturedSym(Scope *scope);
  153. void InitScopeSlotArray(FuncInfo * funcInfo);
  154. void FinalizeRegisters(FuncInfo * funcInfo, Js::FunctionBody * byteCodeFunction);
  155. void SetClosureRegisters(FuncInfo * funcInfo, Js::FunctionBody * byteCodeFunction);
  156. void EnsureSpecialScopeSlots(FuncInfo* funcInfo, Scope* scope);
  157. void SetHasTry(bool has);
  158. void SetHasFinally(bool has);
  159. void SetNumberOfInArgs(Js::ArgSlot argCount);
  160. Js::RegSlot EnregisterConstant(unsigned int constant);
  161. Js::RegSlot EnregisterStringConstant(IdentPtr pid);
  162. Js::RegSlot EnregisterDoubleConstant(double d);
  163. Js::RegSlot EnregisterStringTemplateCallsiteConstant(ParseNode* pnode);
  164. static Js::JavascriptArray* BuildArrayFromStringList(ParseNode* stringNodeList, uint arrayLength, Js::ScriptContext* scriptContext);
  165. bool HasParentScopeInfo() const
  166. {
  167. return this->parentScopeInfo != nullptr;
  168. }
  169. Js::RegSlot EmitLdObjProto(Js::OpCode op, Js::RegSlot objReg, FuncInfo *funcInfo)
  170. {
  171. // LdHomeObjProto protoReg, objReg
  172. // LdFuncObjProto protoReg, objReg
  173. Js::RegSlot protoReg = funcInfo->AcquireTmpRegister();
  174. this->Writer()->Reg2(op, protoReg, objReg);
  175. funcInfo->ReleaseTmpRegister(protoReg);
  176. return protoReg;
  177. }
  178. void RestoreScopeInfo(Js::ScopeInfo *scopeInfo, FuncInfo * func);
  179. void RestoreOneScope(Js::ScopeInfo * scopeInfo, FuncInfo * func);
  180. FuncInfo *StartBindGlobalStatements(ParseNode *pnode);
  181. void AssignPropertyId(Symbol *sym, Js::ParseableFunctionInfo* functionInfo);
  182. void AssignPropertyId(IdentPtr pid);
  183. void ProcessCapturedSyms(ParseNode *pnodeFnc);
  184. void RecordAllIntConstants(FuncInfo * funcInfo);
  185. void RecordAllStrConstants(FuncInfo * funcInfo);
  186. void RecordAllStringTemplateCallsiteConstants(FuncInfo* funcInfo);
  187. // For now, this just assigns field ids for the current script.
  188. // Later, we will combine this information with the global field ID map.
  189. // This temporary code will not work if a global member is accessed both with and without a LHS.
  190. void AssignPropertyIds(Js::ParseableFunctionInfo* functionInfo);
  191. void MapCacheIdsToPropertyIds(FuncInfo *funcInfo);
  192. void MapReferencedPropertyIds(FuncInfo *funcInfo);
  193. FuncInfo *StartBindFunction(const char16 *name, uint nameLength, uint shortNameOffset, bool* pfuncExprWithName, ParseNode *pnode, Js::ParseableFunctionInfo * reuseNestedFunc);
  194. void EndBindFunction(bool funcExprWithName);
  195. void StartBindCatch(ParseNode *pnode);
  196. // Block scopes related functions
  197. template<class Fn> void IterateBlockScopedVariables(ParseNode *pnodeBlock, Fn fn);
  198. void InitBlockScopedContent(ParseNode *pnodeBlock, Js::DebuggerScope *debuggerScope, FuncInfo *funcInfo);
  199. Js::DebuggerScope* RecordStartScopeObject(ParseNode *pnodeBlock, Js::DiagExtraScopesType scopeType, Js::RegSlot scopeLocation = Js::Constants::NoRegister, int* index = nullptr);
  200. void RecordEndScopeObject(ParseNode *pnodeBlock);
  201. void EndBindCatch();
  202. void StartEmitFunction(ParseNode *pnodeFnc);
  203. void EndEmitFunction(ParseNode *pnodeFnc);
  204. void StartEmitBlock(ParseNode *pnodeBlock);
  205. void EndEmitBlock(ParseNode *pnodeBlock);
  206. void StartEmitCatch(ParseNode *pnodeCatch);
  207. void EndEmitCatch(ParseNode *pnodeCatch);
  208. void StartEmitWith(ParseNode *pnodeWith);
  209. void EndEmitWith(ParseNode *pnodeWith);
  210. void EnsureFncScopeSlots(ParseNode *pnode, FuncInfo *funcInfo);
  211. void EnsureLetConstScopeSlots(ParseNode *pnodeBlock, FuncInfo *funcInfo);
  212. bool EnsureSymbolModuleSlots(Symbol* sym, FuncInfo* funcInfo);
  213. void EmitAssignmentToDefaultModuleExport(ParseNode* pnode, FuncInfo* funcInfo);
  214. void EmitModuleExportAccess(Symbol* sym, Js::OpCode opcode, Js::RegSlot location, FuncInfo* funcInfo);
  215. void PushScope(Scope *innerScope);
  216. void PopScope();
  217. void PushBlock(ParseNode *pnode);
  218. void PopBlock();
  219. void PushFuncInfo(char16 const * location, FuncInfo* funcInfo);
  220. void PopFuncInfo(char16 const * location);
  221. Js::RegSlot PrependLocalScopes(Js::RegSlot evalEnv, Js::RegSlot tempLoc, FuncInfo *funcInfo);
  222. Symbol *FindSymbol(Symbol **symRef, IdentPtr pid, bool forReference = false);
  223. Symbol *AddSymbolToScope(Scope *scope, const char16 *key, int keyLength, ParseNode *varDecl, SymbolType symbolType);
  224. Symbol *AddSymbolToFunctionScope(const char16 *key, int keyLength, ParseNode *varDecl, SymbolType symbolType);
  225. void FuncEscapes(Scope *scope);
  226. void EmitTopLevelStatement(ParseNode *stmt, FuncInfo *funcInfo, BOOL fReturnValue);
  227. void EmitInvertedLoop(ParseNode* outerLoop,ParseNode* invertedLoop,FuncInfo* funcInfo);
  228. void DefineFunctions(FuncInfo *funcInfoParent);
  229. Js::RegSlot DefineOneFunction(ParseNode *pnodeFnc, FuncInfo *funcInfoParent, bool generateAssignment=true, Js::RegSlot regEnv = Js::Constants::NoRegister, Js::RegSlot frameDisplayTemp = Js::Constants::NoRegister);
  230. void DefineCachedFunctions(FuncInfo *funcInfoParent);
  231. void DefineUncachedFunctions(FuncInfo *funcInfoParent);
  232. void DefineUserVars(FuncInfo *funcInfo);
  233. void InitBlockScopedNonTemps(ParseNode *pnode, FuncInfo *funcInfo);
  234. // temporarily load all constants and special registers in a single block
  235. void LoadAllConstants(FuncInfo *funcInfo);
  236. void LoadHeapArguments(FuncInfo *funcInfo);
  237. void LoadUncachedHeapArguments(FuncInfo *funcInfo);
  238. void LoadCachedHeapArguments(FuncInfo *funcInfo);
  239. void LoadThisObject(FuncInfo *funcInfo, bool thisLoadedFromParams = false);
  240. void EmitThis(FuncInfo *funcInfo, Js::RegSlot fromRegister);
  241. void LoadNewTargetObject(FuncInfo *funcInfo);
  242. void GetEnclosingNonLambdaScope(FuncInfo *funcInfo, Scope * &scope, Js::PropertyId &envIndex);
  243. void EmitInternalScopedSlotLoad(FuncInfo *funcInfo, Js::RegSlot slot, Js::RegSlot symbolRegister, bool chkUndecl = false);
  244. void EmitInternalScopedSlotLoad(FuncInfo *funcInfo, Scope *scope, Js::PropertyId envIndex, Js::RegSlot slot, Js::RegSlot symbolRegister, bool chkUndecl = false);
  245. void EmitInternalScopedSlotStore(FuncInfo *funcInfo, Js::RegSlot slot, Js::RegSlot symbolRegister);
  246. void EmitInternalScopeObjInit(FuncInfo *funcInfo, Scope *scope, Js::RegSlot valueLocation, Js::PropertyId propertyId);
  247. void EmitSuperCall(FuncInfo* funcInfo, ParseNode* pnode, BOOL fReturnValue);
  248. void EmitScopeSlotLoadThis(FuncInfo *funcInfo, Js::RegSlot regLoc, bool chkUndecl = true);
  249. void EmitScopeSlotStoreThis(FuncInfo *funcInfo, Js::RegSlot regLoc, bool chkUndecl = false);
  250. void EmitClassConstructorEndCode(FuncInfo *funcInfo);
  251. void EmitBaseClassConstructorThisObject(FuncInfo *funcInfo);
  252. // TODO: home the 'this' argument
  253. void EmitLoadFormalIntoRegister(ParseNode *pnodeFormal, Js::RegSlot pos, FuncInfo *funcInfo);
  254. void HomeArguments(FuncInfo *funcInfo);
  255. void EnsureNoRedeclarations(ParseNode *pnodeBlock, FuncInfo *funcInfo);
  256. void DefineLabels(FuncInfo *funcInfo);
  257. void EmitProgram(ParseNode *pnodeProg);
  258. void EmitScopeList(ParseNode *pnode, ParseNode *breakOnBodyScopeNode = nullptr);
  259. void EmitDefaultArgs(FuncInfo *funcInfo, ParseNode *pnode);
  260. void EmitOneFunction(ParseNode *pnode);
  261. void EmitGlobalFncDeclInit(Js::RegSlot rhsLocation, Js::PropertyId propertyId, FuncInfo * funcInfo);
  262. void EmitLocalPropInit(Js::RegSlot rhsLocation, Symbol *sym, FuncInfo *funcInfo);
  263. void EmitPropStore(Js::RegSlot rhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo, bool isLet = false, bool isConst = false, bool isFncDeclVar = false);
  264. void EmitPropLoad(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo);
  265. void EmitPropDelete(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo);
  266. void EmitPropTypeof(Js::RegSlot lhsLocation, Symbol *sym, IdentPtr pid, FuncInfo *funcInfo);
  267. void EmitTypeOfFld(FuncInfo * funcInfo, Js::PropertyId propertyId, Js::RegSlot value, Js::RegSlot instance, Js::OpCode op1);
  268. void EmitLoadInstance(Symbol *sym, IdentPtr pid, Js::RegSlot *pThisLocation, Js::RegSlot *pTargetLocation, FuncInfo *funcInfo);
  269. void EmitGlobalBody(FuncInfo *funcInfo);
  270. void EmitFunctionBody(FuncInfo *funcInfo);
  271. void EmitAsmFunctionBody(FuncInfo *funcInfo);
  272. void EmitScopeObjectInit(FuncInfo *funcInfo);
  273. void EmitPatchableRootProperty(Js::OpCode opcode, Js::RegSlot regSlot, Js::PropertyId propertyId, bool isLoadMethod, bool isStore, FuncInfo *funcInfo);
  274. struct TryScopeRecord;
  275. JsUtil::DoublyLinkedList<TryScopeRecord> tryScopeRecordsList;
  276. void EmitLeaveOpCodesBeforeYield();
  277. void EmitTryBlockHeadersAfterYield();
  278. void InvalidateCachedOuterScopes(FuncInfo *funcInfo);
  279. bool InDynamicScope() const { return dynamicScopeCount != 0; }
  280. Scope * FindScopeForSym(Scope *symScope, Scope *scope, Js::PropertyId *envIndex, FuncInfo *funcInfo) const;
  281. static Js::OpCode GetStFldOpCode(bool isStrictMode, bool isRoot, bool isLetDecl, bool isConstDecl, bool isClassMemberInit)
  282. {
  283. return isClassMemberInit ? Js::OpCode::InitClassMember :
  284. isConstDecl ? (isRoot ? Js::OpCode::InitRootConstFld : Js::OpCode::InitConstFld) :
  285. isLetDecl ? (isRoot ? Js::OpCode::InitRootLetFld : Js::OpCode::InitLetFld) :
  286. isStrictMode ? (isRoot ? Js::OpCode::StRootFldStrict : Js::OpCode::StFldStrict) :
  287. isRoot ? Js::OpCode::StRootFld : Js::OpCode::StFld;
  288. }
  289. static Js::OpCode GetStFldOpCode(FuncInfo* funcInfo, bool isRoot, bool isLetDecl, bool isConstDecl, bool isClassMemberInit);
  290. static Js::OpCode GetScopedStFldOpCode(bool isStrictMode, bool isConsoleScope = false)
  291. {
  292. return isStrictMode ?
  293. (isConsoleScope ? Js::OpCode::ConsoleScopedStFldStrict : Js::OpCode::ScopedStFldStrict) :
  294. (isConsoleScope ? Js::OpCode::ConsoleScopedStFld : Js::OpCode::ScopedStFld);
  295. }
  296. static Js::OpCode GetScopedStFldOpCode(FuncInfo* funcInfo, bool isConsoleScopeLetConst = false);
  297. static Js::OpCode GetStElemIOpCode(bool isStrictMode)
  298. {
  299. return isStrictMode ? Js::OpCode::StElemI_A_Strict : Js::OpCode::StElemI_A;
  300. }
  301. static Js::OpCode GetStElemIOpCode(FuncInfo* funcInfo);
  302. bool DoJitLoopBodies(FuncInfo *funcInfo) const;
  303. static void Generate(__in ParseNode *pnode, uint32 grfscr, __in ByteCodeGenerator* byteCodeGenerator, __inout Js::ParseableFunctionInfo ** ppRootFunc, __in uint sourceIndex, __in bool forceNoNative, __in Parser* parser, Js::ScriptFunction ** functionRef);
  304. void Begin(
  305. __in ArenaAllocator *alloc,
  306. __in uint32 grfscr,
  307. __in Js::ParseableFunctionInfo* pRootFunc);
  308. void SetCurrentSourceIndex(uint sourceIndex) { this->sourceIndex = sourceIndex; }
  309. uint GetCurrentSourceIndex() { return sourceIndex; }
  310. static bool IsFalse(ParseNode* node);
  311. void StartStatement(ParseNode* node);
  312. void EndStatement(ParseNode* node);
  313. void StartSubexpression(ParseNode* node);
  314. void EndSubexpression(ParseNode* node);
  315. bool IsES6DestructuringEnabled() const;
  316. bool IsES6ForLoopSemanticsEnabled() const;
  317. // Debugger methods.
  318. bool IsInDebugMode() const;
  319. bool IsInNonDebugMode() const;
  320. bool ShouldTrackDebuggerMetadata() const;
  321. void TrackRegisterPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol *symbol, FuncInfo *funcInfo, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  322. void TrackActivationObjectPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol *symbol, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  323. void TrackSlotArrayPropertyForDebugger(Js::DebuggerScope *debuggerScope, Symbol* symbol, Js::PropertyId propertyId, Js::DebuggerScopePropertyFlags flags = Js::DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  324. void TrackFunctionDeclarationPropertyForDebugger(Symbol *functionDeclarationSymbol, FuncInfo *funcInfoParent);
  325. void UpdateDebuggerPropertyInitializationOffset(Js::RegSlot location, Js::PropertyId propertyId, bool shouldConsumeRegister = true);
  326. void PopulateFormalsScope(uint beginOffset, FuncInfo *funcInfo, ParseNode *pnode);
  327. void InsertPropertyToDebuggerScope(FuncInfo* funcInfo, Js::DebuggerScope* debuggerScope, Symbol* sym);
  328. FuncInfo *FindEnclosingNonLambda();
  329. bool CanStackNestedFunc(FuncInfo * funcInfo, bool trace = false);
  330. void CheckDeferParseHasMaybeEscapedNestedFunc();
  331. bool NeedObjectAsFunctionScope(FuncInfo * funcInfo, ParseNode * pnodeFnc) const;
  332. bool HasInterleavingDynamicScope(Symbol * sym) const;
  333. void MarkThisUsedInLambda();
  334. void EmitInitCapturedThis(FuncInfo* funcInfo, Scope* scope);
  335. void EmitInitCapturedNewTarget(FuncInfo* funcInfo, Scope* scope);
  336. Js::FunctionBody *EnsureFakeGlobalFuncForUndefer(ParseNode *pnode);
  337. Js::FunctionBody *MakeGlobalFunctionBody(ParseNode *pnode);
  338. static bool NeedScopeObjectForArguments(FuncInfo *funcInfo, ParseNode *pnodeFnc);
  339. void AddFuncInfoToFinalizationSet(FuncInfo *funcInfo);
  340. void FinalizeFuncInfos();
  341. Js::OpCode GetStSlotOp(Scope *scope, int envIndex, Js::RegSlot scopeLocation, bool chkBlockVar, FuncInfo *funcInfo);
  342. Js::OpCode GetLdSlotOp(Scope *scope, int envIndex, Js::RegSlot scopeLocation, FuncInfo *funcInfo);
  343. Js::OpCode GetInitFldOp(Scope *scope, Js::RegSlot scopeLocation, FuncInfo *funcInfo, bool letDecl = false);
  344. private:
  345. bool NeedCheckBlockVar(Symbol* sym, Scope* scope, FuncInfo* funcInfo) const;
  346. Js::OpCode ToChkUndeclOp(Js::OpCode op) const;
  347. };
  348. template<class Fn> void ByteCodeGenerator::IterateBlockScopedVariables(ParseNode *pnodeBlock, Fn fn)
  349. {
  350. Assert(pnodeBlock->nop == knopBlock);
  351. for (auto lexvar = pnodeBlock->sxBlock.pnodeLexVars; lexvar; lexvar = lexvar->sxVar.pnodeNext)
  352. {
  353. fn(lexvar);
  354. }
  355. }
  356. struct ApplyCheck {
  357. bool matches;
  358. bool insideApplyCall;
  359. bool sawApply;
  360. };