IRBuilder.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. ///---------------------------------------------------------------------------
  7. ///
  8. /// class IRBuilder
  9. ///
  10. /// To generate IR from the Jn bytecodes.
  11. ///
  12. ///---------------------------------------------------------------------------
  13. class BranchReloc
  14. {
  15. public:
  16. BranchReloc(IR::BranchInstr * instr, uint32 branchOffset, uint32 offs)
  17. : branchInstr(instr), branchOffset(branchOffset), offset(offs), isNotBackEdge(false)
  18. { }
  19. private:
  20. IR::BranchInstr * branchInstr;
  21. uint32 offset;
  22. bool isNotBackEdge;
  23. uint32 branchOffset;
  24. public:
  25. IR::BranchInstr * GetBranchInstr()
  26. {
  27. return this->branchInstr;
  28. }
  29. uint32 GetOffset() const
  30. {
  31. return this->offset;
  32. }
  33. uint32 GetBranchOffset() const
  34. {
  35. return this->branchOffset;
  36. }
  37. bool IsNotBackEdge() const
  38. {
  39. return this->isNotBackEdge;
  40. }
  41. void SetNotBackEdge()
  42. {
  43. this->isNotBackEdge = true;
  44. }
  45. };
  46. class IRBuilder
  47. {
  48. friend struct IRBuilderSwitchAdapter;
  49. public:
  50. IRBuilder(Func * func)
  51. : m_func(func)
  52. , m_argsOnStack(0)
  53. , m_loopBodyRetIPSym(nullptr)
  54. , m_ldSlots(nullptr)
  55. , m_loopCounterSym(nullptr)
  56. , callTreeHasSomeProfileInfo(false)
  57. , finallyBlockLevel(0)
  58. , m_saveLoopImplicitCallFlags(nullptr)
  59. , handlerOffsetStack(nullptr)
  60. , m_switchAdapter(this)
  61. , m_switchBuilder(&m_switchAdapter)
  62. , m_stackFuncPtrSym(nullptr)
  63. , m_loopBodyForInEnumeratorArrayOpnd(nullptr)
  64. , m_paramScopeDone(false)
  65. #if DBG
  66. , m_callsOnStack(0)
  67. , m_usedAsTemp(nullptr)
  68. #endif
  69. #ifdef BAILOUT_INJECTION
  70. , seenLdStackArgPtr(false)
  71. , expectApplyArg(false)
  72. , seenProfiledBeginSwitch(false)
  73. #endif
  74. #ifdef BYTECODE_BRANCH_ISLAND
  75. , longBranchMap(nullptr)
  76. #endif
  77. {
  78. auto loopCount = func->GetJITFunctionBody()->GetLoopCount();
  79. if (loopCount > 0) {
  80. #if DBG
  81. m_saveLoopImplicitCallFlags = AnewArrayZ(func->m_alloc, IR::Opnd*, loopCount);
  82. #else
  83. m_saveLoopImplicitCallFlags = AnewArray(func->m_alloc, IR::Opnd*, loopCount);
  84. #endif
  85. }
  86. // Note: use original byte code without debugging probes, so that we don't jit BPs inserted by the user.
  87. func->m_workItem->InitializeReader(&m_jnReader, &m_statementReader, func->m_alloc);
  88. };
  89. ~IRBuilder()
  90. {
  91. Assert(m_func->GetJITFunctionBody()->GetLoopCount() == 0 || m_saveLoopImplicitCallFlags);
  92. if (m_saveLoopImplicitCallFlags)
  93. {
  94. AdeleteArray(m_func->m_alloc, m_func->GetJITFunctionBody()->GetLoopCount(), m_saveLoopImplicitCallFlags);
  95. }
  96. }
  97. void Build();
  98. void InsertLabels();
  99. IR::LabelInstr * CreateLabel(IR::BranchInstr * branchInstr, uint& offset);
  100. private:
  101. void InsertInstr(IR::Instr *instr, IR::Instr* insertBeforeInstr);
  102. void AddInstr(IR::Instr *instr, uint32 offset);
  103. BranchReloc * AddBranchInstr(IR::BranchInstr *instr, uint32 offset, uint32 targetOffset);
  104. #ifdef BYTECODE_BRANCH_ISLAND
  105. void ConsumeBranchIsland();
  106. void EnsureConsumeBranchIsland();
  107. uint ResolveVirtualLongBranch(IR::BranchInstr * branchInstr, uint offset);
  108. #endif
  109. BranchReloc * CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset);
  110. void BuildGeneratorPreamble();
  111. void LoadNativeCodeData();
  112. void BuildConstantLoads();
  113. void BuildImplicitArgIns();
  114. #define LAYOUT_TYPE(layout) \
  115. void Build##layout(Js::OpCode newOpcode, uint32 offset);
  116. #define LAYOUT_TYPE_WMS(layout) \
  117. template <typename SizePolicy> void Build##layout(Js::OpCode newOpcode, uint32 offset);
  118. #include "ByteCode/LayoutTypes.h"
  119. void BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0);
  120. void BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, uint32 nextOffset);
  121. void BuildProfiledReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex = Js::Constants::NoInlineCacheIndex);
  122. void BuildProfiledReg2WithICIndex(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex);
  123. void BuildReg3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
  124. Js::RegSlot src2RegSlot, Js::ProfileId profileId);
  125. void BuildReg3C(Js::OpCode newOpCode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
  126. Js::RegSlot src2RegSlot, Js::CacheId inlineCacheIndex);
  127. void BuildReg4(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
  128. Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot);
  129. void BuildReg2B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, byte index);
  130. void BuildReg3B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
  131. Js::RegSlot src2RegSlot, uint8 index);
  132. void BuildReg5(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
  133. Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot, Js::RegSlot src4RegSlot);
  134. void BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 C1);
  135. void BuildReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, int32 C1);
  136. void BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, int32 C1, Js::ProfileId profileId);
  137. void BuildReg2Int1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, int32 value);
  138. void BuildElementC(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldRegSlot, Js::RegSlot regSlot,
  139. Js::PropertyIdIndexType propertyIdIndex);
  140. void BuildElementScopedC(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot,
  141. Js::PropertyIdIndexType propertyIdIndex);
  142. void BuildElementSlot(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldRegSlot, Js::RegSlot regSlot,
  143. int32 slotId, Js::ProfileId profileId);
  144. void BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot,
  145. int32 slotId, Js::ProfileId profileId);
  146. void BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot,
  147. int32 slotId1, int32 slotId2, Js::ProfileId profileId);
  148. void BuildArgIn0(uint32 offset, Js::RegSlot R0);
  149. void BuildArg(Js::OpCode newOpcode, uint32 offset, Js::ArgSlot argument, Js::RegSlot srcRegSlot);
  150. void BuildArgIn(uint32 offset, Js::RegSlot dstRegSlot, uint16 argument);
  151. void BuildArgInRest();
  152. void BuildElementP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot, Js::CacheId inlineCacheIndex);
  153. void BuildElementCP(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instance, Js::RegSlot regSlot, Js::CacheId inlineCacheIndex);
  154. void BuildElementC2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instanceSlot, Js::RegSlot instance2Slot,
  155. Js::RegSlot regSlot, Js::PropertyIdIndexType propertyIdIndex);
  156. void BuildElementScopedC2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instance2Slot,
  157. Js::RegSlot regSlot, Js::PropertyIdIndexType propertyIdIndex);
  158. void BuildElementU(Js::OpCode newOpcode, uint32 offset, Js::RegSlot instance, Js::PropertyIdIndexType propertyIdIndex);
  159. void BuildElementI(Js::OpCode newOpcode, uint32 offset, Js::RegSlot baseRegSlot, Js::RegSlot indexRegSlot,
  160. Js::RegSlot regSlot, Js::ProfileId profileId);
  161. void BuildElementUnsigned1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot baseRegSlot, uint32 index, Js::RegSlot regSlot);
  162. IR::Instr * BuildCallI_Helper(Js::OpCode newOpcode, uint32 offset, Js::RegSlot Return, Js::RegSlot Function, Js::ArgSlot ArgCount,
  163. Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex = Js::Constants::NoInlineCacheIndex);
  164. IR::Instr * BuildProfiledCallI(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  165. Js::ArgSlot argCount, Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex = Js::Constants::NoInlineCacheIndex);
  166. IR::Instr * BuildProfiledCallIExtended(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  167. Js::ArgSlot argCount, Js::ProfileId profileId, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  168. IR::Instr * BuildProfiledCallIWithICIndex(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  169. Js::ArgSlot argCount, Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex);
  170. void BuildProfiledCallIExtendedFlags(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  171. Js::ArgSlot argCount, Js::ProfileId profileId, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  172. void BuildProfiledCallIExtendedWithICIndex(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  173. Js::ArgSlot argCount, Js::ProfileId profileId, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  174. void BuildProfiledCallIExtendedFlagsWithICIndex(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  175. Js::ArgSlot argCount, Js::ProfileId profileId, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  176. void BuildProfiled2CallI(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  177. Js::ArgSlot argCount, Js::ProfileId profileId, Js::ProfileId profileId2);
  178. void BuildProfiled2CallIExtended(Js::OpCode opcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  179. Js::ArgSlot argCount, Js::ProfileId profileId, Js::ProfileId profileId2, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  180. void BuildLdSpreadIndices(uint32 offset, uint32 spreadAuxOffset);
  181. IR::Instr * BuildCallIExtended(Js::OpCode newOpcode, uint32 offset, Js::RegSlot returnValue, Js::RegSlot function,
  182. Js::ArgSlot argCount, Js::CallIExtendedOptions options, uint32 spreadAuxOffset);
  183. void BuildCallCommon(IR::Instr *instr, StackSym *symDst, Js::ArgSlot argCount);
  184. void BuildRegexFromPattern(Js::RegSlot dstRegSlot, uint32 patternIndex, uint32 offset);
  185. void BuildClass(Js::OpCode newOpcode, uint32 offset, Js::RegSlot constructor, Js::RegSlot extends);
  186. void BuildBrReg1(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot srcRegSlot);
  187. void BuildBrReg2(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot);
  188. void BuildBrBReturn(Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset);
  189. IR::IndirOpnd * BuildIndirOpnd(IR::RegOpnd *baseReg, IR::RegOpnd *indexReg);
  190. IR::IndirOpnd * BuildIndirOpnd(IR::RegOpnd *baseReg, uint32 offset);
  191. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  192. IR::IndirOpnd * BuildIndirOpnd(IR::RegOpnd *baseReg, uint32 offset, const char16 *desc);
  193. #endif
  194. IR::SymOpnd * BuildFieldOpnd(Js::OpCode newOpCode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex = -1);
  195. PropertySym * BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, uint inlineCacheIndex, PropertyKind propertyKind);
  196. SymID BuildSrcStackSymID(Js::RegSlot regSlot);
  197. IR::RegOpnd * BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type = TyVar, bool isCatchObjectSym = false);
  198. IR::RegOpnd * BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type = TyVar);
  199. IR::AddrOpnd * BuildAuxArrayOpnd(AuxArrayValue auxArrayType, uint32 auxArrayOffset);
  200. IR::Opnd * BuildAuxObjectLiteralTypeRefOpnd(int objectId);
  201. IR::Opnd * BuildForInEnumeratorOpnd(uint forInLoopLevel);
  202. IR::RegOpnd * EnsureLoopBodyForInEnumeratorArrayOpnd();
  203. private:
  204. uint AddStatementBoundary(uint statementIndex, uint offset);
  205. void CheckBuiltIn(PropertySym * propertySym, Js::BuiltinFunction *puBuiltInIndex);
  206. bool IsFloatFunctionCallsite(Js::BuiltinFunction index, size_t argc);
  207. IR::Instr * BuildProfiledFieldLoad(Js::OpCode loadOp, IR::RegOpnd *dstOpnd, IR::SymOpnd *srcOpnd, Js::CacheId inlineCacheIndex, bool *pUnprofiled);
  208. IR::Instr * BuildProfiledSlotLoad(Js::OpCode loadOp, IR::RegOpnd *dstOpnd, IR::SymOpnd *srcOpnd, Js::ProfileId profileId, bool *pUnprofiled);
  209. SymID GetMappedTemp(Js::RegSlot reg)
  210. {
  211. AssertMsg(this->RegIsTemp(reg), "Processing non-temp reg as a temp?");
  212. AssertMsg(this->tempMap, "Processing non-temp reg without a temp map?");
  213. Js::RegSlot tempIndex = reg - this->firstTemp;
  214. AssertOrFailFast(tempIndex < m_func->GetJITFunctionBody()->GetTempCount());
  215. return this->tempMap[tempIndex];
  216. }
  217. void SetMappedTemp(Js::RegSlot reg, SymID tempId)
  218. {
  219. AssertMsg(this->RegIsTemp(reg), "Processing non-temp reg as a temp?");
  220. AssertMsg(this->tempMap, "Processing non-temp reg without a temp map?");
  221. Js::RegSlot tempIndex = reg - this->firstTemp;
  222. AssertOrFailFast(tempIndex < m_func->GetJITFunctionBody()->GetTempCount());
  223. this->tempMap[tempIndex] = tempId;
  224. }
  225. BOOL GetTempUsed(Js::RegSlot reg)
  226. {
  227. AssertMsg(this->RegIsTemp(reg), "Processing non-temp reg as a temp?");
  228. AssertMsg(this->fbvTempUsed, "Processing non-temp reg without a used BV?");
  229. Js::RegSlot tempIndex = reg - this->firstTemp;
  230. AssertOrFailFast(tempIndex < m_func->GetJITFunctionBody()->GetTempCount());
  231. return this->fbvTempUsed->Test(tempIndex);
  232. }
  233. void SetTempUsed(Js::RegSlot reg, BOOL used)
  234. {
  235. AssertMsg(this->RegIsTemp(reg), "Processing non-temp reg as a temp?");
  236. AssertMsg(this->fbvTempUsed, "Processing non-temp reg without a used BV?");
  237. Js::RegSlot tempIndex = reg - this->firstTemp;
  238. AssertOrFailFast(tempIndex < m_func->GetJITFunctionBody()->GetTempCount());
  239. if (used)
  240. {
  241. this->fbvTempUsed->Set(tempIndex);
  242. }
  243. else
  244. {
  245. this->fbvTempUsed->Clear(tempIndex);
  246. }
  247. }
  248. BOOL RegIsTemp(Js::RegSlot reg)
  249. {
  250. return reg >= this->firstTemp;
  251. }
  252. BOOL RegIsConstant(Js::RegSlot reg)
  253. {
  254. return reg > 0 && reg < m_func->GetJITFunctionBody()->GetConstCount();
  255. }
  256. bool IsParamScopeDone() const { return m_paramScopeDone; }
  257. void SetParamScopeDone(bool done = true) { m_paramScopeDone = done; }
  258. Js::RegSlot InnerScopeIndexToRegSlot(uint32) const;
  259. Js::RegSlot GetEnvReg() const;
  260. Js::RegSlot GetEnvRegForEvalCode() const;
  261. Js::RegSlot GetEnvRegForInnerFrameDisplay() const;
  262. void AddEnvOpndForInnerFrameDisplay(IR::Instr *instr, uint offset);
  263. bool DoSlotArrayCheck(IR::SymOpnd *fieldOpnd, bool doDynamicCheck);
  264. void EmitClosureRangeChecks();
  265. void DoClosureRegCheck(Js::RegSlot reg);
  266. void BuildInitCachedScope(int auxOffset, int offset);
  267. void GenerateLoopBodySlotAccesses(uint offset);
  268. void GenerateLoopBodyStSlots(SymID loopParamSymId, uint offset);
  269. IR::Instr * GenerateLoopBodyStSlot(Js::RegSlot regSlot, uint offset = Js::Constants::NoByteCodeOffset);
  270. bool IsLoopBody() const;
  271. bool IsLoopBodyInTry() const;
  272. uint GetLoopBodyExitInstrOffset() const;
  273. IR::SymOpnd * BuildLoopBodySlotOpnd(SymID symId);
  274. void EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym = false);
  275. void SetLoopBodyStSlot(SymID symID, bool isCatchObjectSym);
  276. bool IsLoopBodyOuterOffset(uint offset) const;
  277. bool IsLoopBodyReturnIPInstr(IR::Instr * instr) const;
  278. IR::Opnd * InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset);
  279. IR::Instr * CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset);
  280. StackSym * EnsureStackFuncPtrSym();
  281. void InsertBailOutForDebugger(uint offset, IR::BailOutKind kind, IR::Instr* insertBeforeInstr = nullptr);
  282. void InsertBailOnNoProfile(uint offset);
  283. void InsertBailOnNoProfile(IR::Instr *const insertBeforeInstr);
  284. bool DoBailOnNoProfile();
  285. void InsertIncrLoopBodyLoopCounter(IR::LabelInstr *loopTopLabelInstr);
  286. void InsertInitLoopBodyLoopCounter(uint loopNum);
  287. void InsertDoneLoopBodyLoopCounter(uint32 lastOffset);
  288. IR::RegOpnd * InsertConvPrimStr(IR::RegOpnd * srcOpnd, uint offset, bool forcePreOpBailOutIfNeeded);
  289. #ifdef BAILOUT_INJECTION
  290. void InjectBailOut(uint offset);
  291. void CheckBailOutInjection(Js::OpCode opcode);
  292. bool seenLdStackArgPtr;
  293. bool expectApplyArg;
  294. bool seenProfiledBeginSwitch;
  295. #endif
  296. JitArenaAllocator * m_tempAlloc;
  297. JitArenaAllocator * m_funcAlloc;
  298. Func * m_func;
  299. IR::Instr * m_lastInstr;
  300. IR::Instr ** m_offsetToInstruction;
  301. uint32 m_functionStartOffset;
  302. Js::ByteCodeReader m_jnReader;
  303. Js::StatementReader<Js::FunctionBody::ArenaStatementMapList> m_statementReader;
  304. SList<IR::Instr *> *m_argStack;
  305. SList<BranchReloc*> *branchRelocList;
  306. typedef Pair<uint, bool> handlerStackElementType;
  307. SList<handlerStackElementType> *handlerOffsetStack;
  308. SymID * tempMap;
  309. BVFixed * fbvTempUsed;
  310. Js::RegSlot firstTemp;
  311. IRBuilderSwitchAdapter m_switchAdapter;
  312. SwitchIRBuilder m_switchBuilder;
  313. BVFixed * m_ldSlots;
  314. BVFixed * m_stSlots;
  315. #if DBG
  316. BVFixed * m_usedAsTemp;
  317. #endif
  318. StackSym * m_loopBodyRetIPSym;
  319. StackSym* m_loopCounterSym;
  320. StackSym * m_stackFuncPtrSym;
  321. bool m_paramScopeDone;
  322. bool callTreeHasSomeProfileInfo;
  323. uint finallyBlockLevel;
  324. // Keep track of how many args we have on the stack whenever
  325. // we make a call so that the max stack used over all calls can be
  326. // used to estimate how much stack we should probe for at the
  327. // beginning of a JITted function.
  328. #if DBG
  329. uint32 m_offsetToInstructionCount;
  330. uint32 m_callsOnStack;
  331. #endif
  332. uint32 m_argsOnStack;
  333. Js::PropertyId m_loopBodyLocalsStartSlot;
  334. IR::Opnd** m_saveLoopImplicitCallFlags;
  335. IR::RegOpnd * m_loopBodyForInEnumeratorArrayOpnd;
  336. #ifdef BYTECODE_BRANCH_ISLAND
  337. typedef JsUtil::BaseDictionary<uint32, uint32, JitArenaAllocator> LongBranchMap;
  338. LongBranchMap * longBranchMap;
  339. static IR::Instr * const VirtualLongBranchInstr;
  340. #endif
  341. };