ByteCodeWriter.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. namespace Js
  7. {
  8. struct ByteCodeWriter
  9. {
  10. protected:
  11. struct DataChunk
  12. {
  13. private:
  14. byte* currentByte;
  15. byte* buffer;
  16. uint byteSize;
  17. public:
  18. DataChunk* nextChunk;
  19. DataChunk(ArenaAllocator* allocator, uint initSize) :
  20. nextChunk(nullptr),
  21. byteSize(initSize)
  22. {
  23. buffer = AnewArray(allocator, byte, initSize);
  24. currentByte = buffer;
  25. }
  26. inline uint GetSize()
  27. {
  28. return byteSize;
  29. }
  30. inline const byte* GetBuffer()
  31. {
  32. return buffer;
  33. }
  34. inline void Reset()
  35. {
  36. currentByte = buffer;
  37. }
  38. inline uint RemainingBytes()
  39. {
  40. Assert(byteSize >= GetCurrentOffset());
  41. return byteSize - GetCurrentOffset();
  42. }
  43. inline uint GetCurrentOffset()
  44. {
  45. Assert(currentByte >= buffer);
  46. return (uint) (currentByte - buffer);
  47. }
  48. inline void SetCurrentOffset(uint offset)
  49. {
  50. currentByte = buffer + offset;
  51. }
  52. // This does not do check if there is enough space for the copy to succeed.
  53. inline void WriteUnsafe(__in_bcount(byteSize) const void* data, __in uint byteSize)
  54. {
  55. AssertMsg(RemainingBytes() >= byteSize, "We do not have enough room");
  56. js_memcpy_s(currentByte, this->RemainingBytes(), data, byteSize);
  57. currentByte += byteSize;
  58. }
  59. };
  60. // This is a linked list of data chunks. It is designed to be allocated
  61. // once and re-used. After a call to Reset(), this data structure can be reused to
  62. // store more data.
  63. struct Data
  64. {
  65. private:
  66. ArenaAllocator* tempAllocator;
  67. DataChunk* head; // First chunk to be written to
  68. DataChunk* current; // The current chunk being written to
  69. uint currentOffset; // The global offset of last byte written to in the linked data structure
  70. bool fixedGrowthPolicy;
  71. void Write(__in_bcount(byteSize) const void* data, __in uint byteSize);
  72. _NOINLINE void SlowWrite(__in_bcount(byteSize) const void* data, __in uint byteSize);
  73. void AddChunk(uint byteSize);
  74. public:
  75. Data(bool fixedGrowthPolicy = false) : head(nullptr),
  76. current(nullptr),
  77. tempAllocator(nullptr),
  78. currentOffset(0),
  79. fixedGrowthPolicy(fixedGrowthPolicy)
  80. {
  81. }
  82. void Create(uint initSize, ArenaAllocator* tmpAlloc);
  83. inline uint GetCurrentOffset() const { return currentOffset; }
  84. inline DataChunk * GetCurrentChunk() const { return &(*current); }
  85. void SetCurrent(uint offset, DataChunk* currChunk);
  86. void Copy(Recycler* alloc, ByteBlock ** finalBlock);
  87. void Encode(OpCode op, ByteCodeWriter* writer) { EncodeT<Js::SmallLayout>(op, writer); }
  88. void Encode(OpCode op, const void * rawData, int byteSize, ByteCodeWriter* writer) { EncodeT<Js::SmallLayout>(op, rawData, byteSize, writer); }
  89. void Encode(const void * rawData, int byteSize);
  90. template <LayoutSize layoutSize> void EncodeOpCode(uint16 op, ByteCodeWriter* writer);
  91. template <> void EncodeOpCode<SmallLayout>(uint16 op, ByteCodeWriter* writer);
  92. // EncodeT functions return the global offset where the opcode has been encoded
  93. template <LayoutSize layoutSize> uint EncodeT(OpCode op, ByteCodeWriter* writer);
  94. template <LayoutSize layoutSize> uint EncodeT(OpCode op, const void * rawData, int byteSize, ByteCodeWriter* writer);
  95. // asm.js encoding
  96. void Encode(OpCodeAsmJs op, ByteCodeWriter* writer){ EncodeT<Js::SmallLayout>(op, writer, /*isPatching*/false); }
  97. void Encode(OpCodeAsmJs op, const void * rawData, int byteSize, ByteCodeWriter* writer, bool isPatching = false){ EncodeT<Js::SmallLayout>(op, rawData, byteSize, writer, isPatching); }
  98. template <LayoutSize layoutSize> uint EncodeT(OpCodeAsmJs op, ByteCodeWriter* writer, bool isPatching);
  99. template <LayoutSize layoutSize> uint EncodeT(OpCodeAsmJs op, const void * rawData, int byteSize, ByteCodeWriter* writer, bool isPatching = false);
  100. void Reset();
  101. };
  102. struct LoopHeaderData {
  103. uint startOffset;
  104. uint endOffset;
  105. bool isNested;
  106. LoopHeaderData() {}
  107. LoopHeaderData(uint startOffset, uint endOffset, bool isNested) : startOffset(startOffset), endOffset(endOffset), isNested(isNested){}
  108. };
  109. JsUtil::List<uint, ArenaAllocator> * m_labelOffsets; // Label offsets, once defined
  110. struct JumpInfo
  111. {
  112. ByteCodeLabel labelId;
  113. uint patchOffset;
  114. };
  115. #ifdef BYTECODE_BRANCH_ISLAND
  116. bool useBranchIsland;
  117. JsUtil::List<JumpInfo, ArenaAllocator> * m_longJumpOffsets;
  118. Js::OpCode lastOpcode;
  119. bool inEnsureLongBranch;
  120. uint firstUnknownJumpInfo;
  121. int nextBranchIslandOffset;
  122. // Size of emitting a jump around byte code instruction
  123. static const uint JumpAroundSize;
  124. // Size of emitting a long jump byte code instruction
  125. static const uint LongBranchSize;
  126. #endif
  127. JsUtil::List<JumpInfo, ArenaAllocator> * m_jumpOffsets; // Offsets to replace "ByteCodeLabel" with actual destination
  128. JsUtil::List<LoopHeaderData, ArenaAllocator> * m_loopHeaders; // Start/End offsets for loops
  129. SListBase<size_t> rootObjectLoadInlineCacheOffsets; // load inline cache offsets
  130. SListBase<size_t> rootObjectStoreInlineCacheOffsets; // load inline cache offsets
  131. SListBase<size_t> rootObjectLoadMethodInlineCacheOffsets;
  132. FunctionBody* m_functionWrite; // Function being written
  133. Data m_byteCodeData; // Accumulated byte-code
  134. Data m_auxiliaryData; // Optional accumulated auxiliary data
  135. Data m_auxContextData; // Optional accumulated auxiliary ScriptContext specific data
  136. uint m_beginCodeSpan; // Debug Info for where in bytecode the current statement starts. (Statements do not nest.)
  137. ParseNode* m_pMatchingNode; // Parse node for statement we are tracking debugInfo for.
  138. // This ref count mechanism ensures that nested Start/End Statement with matching parse node will not mess-up the upper Start/End balance.
  139. // This count will be incremented/decremented when the nested Start/End has the same m_pMatchingNode.
  140. int m_matchingNodeRefCount;
  141. struct SubexpressionNode
  142. {
  143. ParseNode* node;
  144. int beginCodeSpan;
  145. SubexpressionNode() {}
  146. SubexpressionNode(ParseNode* node, int beginCodeSpan) : node(node), beginCodeSpan(beginCodeSpan) {}
  147. };
  148. JsUtil::Stack<SubexpressionNode> * m_subexpressionNodesStack; // Parse nodes for Subexpressions not participating in debug-stepping actions
  149. SmallSpanSequenceIter spanIter;
  150. int m_loopNest;
  151. uint m_byteCodeCount;
  152. uint m_byteCodeWithoutLDACount; // Number of total bytecodes except LD_A and LdUndef
  153. uint m_byteCodeInLoopCount;
  154. uint32 m_tmpRegCount;
  155. bool m_doJitLoopBodies;
  156. bool m_hasLoop;
  157. bool m_isInDebugMode;
  158. bool m_doInterruptProbe;
  159. public:
  160. struct CacheIdUnit {
  161. uint cacheId;
  162. bool isRootObjectCache;
  163. CacheIdUnit() {}
  164. CacheIdUnit(uint cacheId, bool isRootObjectCache = false) : cacheId(cacheId), isRootObjectCache(isRootObjectCache) {}
  165. };
  166. protected:
  167. // A map of, bytecode register in which the function to be called is, to the inline cache index associated with the load of the function.
  168. typedef JsUtil::BaseDictionary<Js::RegSlot, CacheIdUnit, ArenaAllocator, PrimeSizePolicy> CallRegToLdFldCacheIndexMap;
  169. CallRegToLdFldCacheIndexMap* callRegToLdFldCacheIndexMap;
  170. // Debugger fields.
  171. Js::DebuggerScope* m_currentDebuggerScope;
  172. #if DBG
  173. bool isInitialized;
  174. bool isInUse;
  175. #endif
  176. void IncreaseByteCodeCount();
  177. void AddJumpOffset(Js::OpCode op, ByteCodeLabel labelId, uint fieldByteOffset);
  178. RegSlot ConsumeReg(RegSlot reg);
  179. void CheckOpen();
  180. void CheckLabel(ByteCodeLabel labelID);
  181. inline void CheckOp(OpCode op, OpLayoutType layoutType);
  182. inline void CheckReg(RegSlot registerID);
  183. bool DoDynamicProfileOpcode(Phase tag, bool noHeuristics = false) const;
  184. template <typename T>
  185. void PatchJumpOffset(JsUtil::List<JumpInfo, ArenaAllocator> * jumpOffsets, byte * byteBuffer, uint byteCount);
  186. #ifdef BYTECODE_BRANCH_ISLAND
  187. static int32 GetBranchLimit();
  188. void AddLongJumpOffset(ByteCodeLabel labelId, uint fieldByteOffset);
  189. void EnsureLongBranch(Js::OpCode op);
  190. void UpdateNextBranchIslandOffset(uint firstUnknownJumpInfo, uint firstUnknownJumpOffset);
  191. #endif
  192. // Debugger methods.
  193. void PushDebuggerScope(Js::DebuggerScope* debuggerScope);
  194. void PopDebuggerScope();
  195. public:
  196. ByteCodeWriter() : m_byteCodeCount(/*fixedGrowthPolicy=*/ true), m_currentDebuggerScope(nullptr) {}
  197. #if DBG
  198. ~ByteCodeWriter() { Assert(!isInUse); }
  199. #endif
  200. void Create();
  201. void InitData(ArenaAllocator* alloc, int32 initCodeBufferSize);
  202. void Begin(FunctionBody* functionWrite, ArenaAllocator* alloc, bool doJitLoopBodies, bool hasLoop, bool inDebugMode);
  203. #ifdef LOG_BYTECODE_AST_RATIO
  204. void End(int32 currentAstSize, int32 maxAstSize);
  205. #else
  206. void End();
  207. #endif
  208. void Reset();
  209. void AllocateLoopHeaders();
  210. #if DBG_DUMP
  211. uint ByteCodeDataSize();
  212. uint AuxiliaryDataSize();
  213. uint AuxiliaryContextDataSize();
  214. #endif
  215. void Empty(OpCode op);
  216. void Reg1(OpCode op, RegSlot R0);
  217. void Reg2(OpCode op, RegSlot R0, RegSlot R1);
  218. void Reg3(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2);
  219. void Reg3C(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, uint cacheId);
  220. void Reg4(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, RegSlot R3);
  221. void Reg1Unsigned1(OpCode op, RegSlot R0, uint C1);
  222. void Reg2B1(OpCode op, RegSlot R0, RegSlot R1, uint8 B3);
  223. void Reg3B1(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, uint8 B3);
  224. void Reg5(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, RegSlot R3, RegSlot R4);
  225. void ArgIn0(RegSlot arg);
  226. template <bool isVar>
  227. void ArgOut(ArgSlot arg, RegSlot reg, ProfileId callSiteId, bool emitProfiledArgout);
  228. void ArgOutEnv(ArgSlot arg);
  229. #ifdef BYTECODE_BRANCH_ISLAND
  230. void BrLong(OpCode op, ByteCodeLabel labelID);
  231. #endif
  232. void Br(ByteCodeLabel labelID);
  233. void Br(OpCode op, ByteCodeLabel labelID);
  234. void BrReg1(OpCode op, ByteCodeLabel labelID, RegSlot R1);
  235. void BrReg1Unsigned1(OpCode op, ByteCodeLabel labelID, RegSlot R1, uint C1);
  236. void BrS(OpCode op, ByteCodeLabel labelID, byte val);
  237. void BrReg2(OpCode op, ByteCodeLabel labelID, RegSlot R1, RegSlot R2);
  238. void BrProperty(OpCode op, ByteCodeLabel labelID, RegSlot R1, PropertyIdIndexType propertyIdIndex);
  239. void BrLocalProperty(OpCode op, ByteCodeLabel labelID, PropertyIdIndexType propertyIdIndex);
  240. void BrEnvProperty(OpCode op, ByteCodeLabel labelID, PropertyIdIndexType propertyIdIndex, int32 slotIndex);
  241. void StartCall(OpCode op, ArgSlot ArgCount);
  242. void CallI(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, ProfileId callSiteId, CallFlags callFlags = CallFlags_None);
  243. void CallIExtended(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, CallIExtendedOptions options, const void *buffer, uint byteCount, ProfileId callSiteId, CallFlags callFlags = CallFlags_None);
  244. void RemoveEntryForRegSlotFromCacheIdMap(RegSlot functionRegister);
  245. void Element(OpCode op, RegSlot value, RegSlot instance, RegSlot element, bool instanceAtReturnRegOK = false);
  246. void ElementUnsigned1(OpCode op, RegSlot value, RegSlot instance, uint32 element);
  247. void Property(OpCode op, RegSlot Value, RegSlot Instance, PropertyIdIndexType propertyIdIndex);
  248. void ScopedProperty(OpCode op, RegSlot Value, PropertyIdIndexType propertyIdIndex);
  249. void Slot(OpCode op, RegSlot value, RegSlot instance, uint32 slotId);
  250. void Slot(OpCode op, RegSlot value, RegSlot instance, uint32 slotId, ProfileId profileId);
  251. void SlotI1(OpCode op, RegSlot value, uint32 slotId1);
  252. void SlotI1(OpCode op, RegSlot value, uint32 slotId1, ProfileId profileId);
  253. void SlotI2(OpCode op, RegSlot value, uint32 slotId1, uint32 slotId2);
  254. void SlotI2(OpCode op, RegSlot value, uint32 slotId1, uint32 slotId2, ProfileId profileId);
  255. void ElementU(OpCode op, RegSlot instance, PropertyIdIndexType propertyIdIndex);
  256. void ElementScopedU(OpCode op, PropertyIdIndexType propertyIdIndex);
  257. void ElementRootU(OpCode op, PropertyIdIndexType propertyIdIndex);
  258. void ElementP(OpCode op, RegSlot value, uint cacheId, bool isCtor = false, bool registerCacheIdForCall = true);
  259. void ElementPIndexed(OpCode op, RegSlot value, uint cacheId, uint32 scopeIndex);
  260. void PatchableRootProperty(OpCode op, RegSlot value, uint cacheId, bool isLoadMethod, bool isStore, bool registerCacheIdForCall = true);
  261. void PatchableProperty(OpCode op, RegSlot value, RegSlot instance, uint cacheId, bool isCtor = false, bool registerCacheIdForCall = true);
  262. void PatchablePropertyWithThisPtr(OpCode op, RegSlot value, RegSlot instance, RegSlot thisInstance, uint cacheId, bool isCtor = false, bool registerCacheIdForCall = true);
  263. void ScopedProperty2(OpCode op, RegSlot Value, PropertyIdIndexType propertyIdIndex, RegSlot R2);
  264. void W1(OpCode op, unsigned short C1);
  265. void Reg2Int1(OpCode op, RegSlot R0, RegSlot R1, int C1);
  266. void Unsigned1(OpCode op, uint C1);
  267. void Num3(OpCode op, RegSlot C0, RegSlot C1, RegSlot C2);
  268. template <typename SizePolicy> bool TryWriteReg1(OpCode op, RegSlot R0);
  269. template <typename SizePolicy> bool TryWriteReg2(OpCode op, RegSlot R0, RegSlot R1);
  270. template <typename SizePolicy> bool TryWriteReg3(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2);
  271. template <typename SizePolicy> bool TryWriteReg3C(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, CacheId cacheId);
  272. template <typename SizePolicy> bool TryWriteReg4(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, RegSlot R3);
  273. template <typename SizePolicy> bool TryWriteReg2B1(OpCode op, RegSlot R0, RegSlot R1, uint8 B2);
  274. template <typename SizePolicy> bool TryWriteReg3B1(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, uint8 B3);
  275. template <typename SizePolicy> bool TryWriteReg5(OpCode op, RegSlot R0, RegSlot R1, RegSlot R2, RegSlot R3, RegSlot R4);
  276. template <typename SizePolicy> bool TryWriteUnsigned1(OpCode op, uint C1);
  277. template <typename SizePolicy> bool TryWriteArg(OpCode op, ArgSlot arg, RegSlot reg);
  278. template <typename SizePolicy> bool TryWriteArgNoSrc(OpCode op, ArgSlot arg);
  279. template <typename SizePolicy> bool TryWriteBrReg1(OpCode op, ByteCodeLabel labelID, RegSlot R1);
  280. template <typename SizePolicy> bool TryWriteBrReg1Unsigned1(OpCode op, ByteCodeLabel labelID, RegSlot R1, uint C2);
  281. template <typename SizePolicy> bool TryWriteBrReg2(OpCode op, ByteCodeLabel labelID, RegSlot R1, RegSlot R2);
  282. template <typename SizePolicy> bool TryWriteCallI(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount);
  283. template <typename SizePolicy> bool TryWriteCallIFlags(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, CallFlags callFlags);
  284. template <typename SizePolicy> bool TryWriteCallIWithICIndex(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, uint32 inlineCacheIndex, bool isRootLoad);
  285. template <typename SizePolicy> bool TryWriteCallIFlagsWithICIndex(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, uint32 inlineCacheIndex, bool isRootLoad, CallFlags callFlags);
  286. template <typename SizePolicy> bool TryWriteCallIExtended(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, CallIExtendedOptions options, uint32 spreadArgsOffset);
  287. template <typename SizePolicy> bool TryWriteCallIExtendedWithICIndex(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, InlineCacheIndex inlineCacheIndex, bool isRootLoad, CallIExtendedOptions options, uint32 spreadArgsOffset);
  288. template <typename SizePolicy> bool TryWriteCallIExtendedFlags(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, CallIExtendedOptions options, uint32 spreadArgsOffset, CallFlags callFlags);
  289. template <typename SizePolicy> bool TryWriteCallIExtendedFlagsWithICIndex(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, InlineCacheIndex inlineCacheIndex, bool isRootLoad, CallIExtendedOptions options, uint32 spreadArgsOffset, CallFlags callFlags);
  290. template <typename SizePolicy> bool TryWriteElementI(OpCode op, RegSlot Value, RegSlot Instance, RegSlot Element);
  291. template <typename SizePolicy> bool TryWriteElementUnsigned1(OpCode op, RegSlot Value, RegSlot Instance, uint32 Element);
  292. template <typename SizePolicy> bool TryWriteElementC(OpCode op, RegSlot value, RegSlot instance, PropertyIdIndexType propertyIdIndex);
  293. template <typename SizePolicy> bool TryWriteElementScopedC(OpCode op, RegSlot value, PropertyIdIndexType propertyIdIndex);
  294. template <typename SizePolicy> bool TryWriteElementSlot(OpCode op, RegSlot value, RegSlot instance, uint32 slotId);
  295. template <typename SizePolicy> bool TryWriteElementSlotI1(OpCode op, RegSlot value, uint32 slotId);
  296. template <typename SizePolicy> bool TryWriteElementSlotI2(OpCode op, RegSlot value, uint32 slotId1, uint32 slotId2);
  297. template <typename SizePolicy> bool TryWriteElementSlotI3(OpCode op, RegSlot value, RegSlot instance, uint32 slotId, RegSlot homeObj);
  298. template <typename SizePolicy> bool TryWriteElementU(OpCode op, RegSlot instance, PropertyIdIndexType index);
  299. template <typename SizePolicy> bool TryWriteElementScopedU(OpCode op, PropertyIdIndexType index);
  300. template <typename SizePolicy> bool TryWriteElementRootU(OpCode op, PropertyIdIndexType index);
  301. template <typename SizePolicy> bool TryWriteElementRootCP(OpCode op, RegSlot value, uint cacheId, bool isLoadMethod, bool isStore);
  302. template <typename SizePolicy> bool TryWriteElementP(OpCode op, RegSlot value, CacheId cacheId);
  303. template <typename SizePolicy> bool TryWriteElementPIndexed(OpCode op, RegSlot value, uint32 scopeIndex, CacheId cacheId);
  304. template <typename SizePolicy> bool TryWriteElementCP(OpCode op, RegSlot value, RegSlot instance, CacheId cacheId);
  305. template <typename SizePolicy> bool TryWriteElementScopedC2(OpCode op, RegSlot value, PropertyIdIndexType propertyIdIndex, RegSlot instance2);
  306. template <typename SizePolicy> bool TryWriteElementC2(OpCode op, RegSlot value, RegSlot instance, PropertyIdIndexType propertyIdIndex, RegSlot instance2);
  307. template <typename SizePolicy> bool TryWriteClass(OpCode op, RegSlot constructor, RegSlot extends);
  308. template <typename SizePolicy> bool TryWriteReg1Unsigned1(OpCode op, RegSlot R0, uint C1);
  309. template <typename SizePolicy> bool TryWriteReg2Int1(OpCode op, RegSlot R0, RegSlot R1, int C1);
  310. void AuxiliaryContext(OpCode op, RegSlot destinationRegister, const void* buffer, int byteCount, Js::RegSlot C1);
  311. int Auxiliary(OpCode op, RegSlot destinationRegister, const void* buffer, int byteCount, int size);
  312. void Auxiliary(OpCode op, RegSlot destinationRegister, uint byteOffset, int size);
  313. int AuxNoReg(OpCode op, const void* buffer, int byteCount, int size);
  314. void AuxNoReg(OpCode op, uint byteOffset, int size);
  315. int Reg2Aux(OpCode op, RegSlot R0, RegSlot R1, const void* buffer, int byteCount, int size);
  316. void Reg2Aux(OpCode op, RegSlot R0, RegSlot R1, uint byteOffset, int size);
  317. uint InsertAuxiliaryData(const void* buffer, uint byteCount);
  318. void InitClass(RegSlot constructor, RegSlot extends = Js::Constants::NoRegister);
  319. void NewFunction(RegSlot destinationRegister, uint index, bool isGenerator, RegSlot homeObjLocation);
  320. void NewInnerFunction(RegSlot destinationRegister, uint index, RegSlot environmentRegister, bool isGenerator, RegSlot homeObjLocation);
  321. ByteCodeLabel DefineLabel();
  322. void MarkLabel(ByteCodeLabel labelID);
  323. void StartStatement(ParseNode* node, uint32 tmpRegCount);
  324. void EndStatement(ParseNode* node);
  325. void StartSubexpression(ParseNode* node);
  326. void EndSubexpression(ParseNode* node);
  327. void RecordFrameDisplayRegister(RegSlot slot);
  328. void RecordObjectRegister(RegSlot slot);
  329. uint GetCurrentOffset() const { return (uint)m_byteCodeData.GetCurrentOffset(); }
  330. DataChunk * GetCurrentChunk() const { return m_byteCodeData.GetCurrentChunk(); }
  331. void SetCurrent(uint offset, DataChunk * chunk) { m_byteCodeData.SetCurrent(offset, chunk); }
  332. bool ShouldIncrementCallSiteId(OpCode op);
  333. inline void SetCallSiteCount(Js::ProfileId callSiteId) { this->m_functionWrite->SetProfiledCallSiteCount(callSiteId); }
  334. // Debugger methods.
  335. DebuggerScope* RecordStartScopeObject(DiagExtraScopesType scopeType, RegSlot scopeLocation = Js::Constants::NoRegister, int* index = nullptr);
  336. void AddPropertyToDebuggerScope(DebuggerScope* debuggerScope, RegSlot location, Js::PropertyId propertyId, bool shouldConsumeRegister = true, DebuggerScopePropertyFlags flags = DebuggerScopePropertyFlags_None, bool isFunctionDeclaration = false);
  337. void RecordEndScopeObject();
  338. DebuggerScope* GetCurrentDebuggerScope() const { return m_currentDebuggerScope; }
  339. void UpdateDebuggerPropertyInitializationOffset(Js::DebuggerScope* currentDebuggerScope, Js::RegSlot location, Js::PropertyId propertyId, bool shouldConsumeRegister = true, int byteCodeOffset = Constants::InvalidOffset, bool isFunctionDeclaration = false);
  340. FunctionBody* GetFunctionWrite() const { return m_functionWrite; }
  341. void RecordStatementAdjustment(FunctionBody::StatementAdjustmentType type);
  342. void RecordCrossFrameEntryExitRecord(bool isEnterBlock);
  343. void RecordForInOrOfCollectionScope();
  344. uint EnterLoop(Js::ByteCodeLabel loopEntrance);
  345. void ExitLoop(uint loopId);
  346. bool DoJitLoopBodies() const { return m_doJitLoopBodies; }
  347. bool DoInterruptProbes() const { return m_doInterruptProbe; }
  348. static bool DoProfileCallOp(OpCode op)
  349. {
  350. return op >= OpCode::CallI && op <= OpCode::CallIExtendedFlags;
  351. }
  352. bool DoProfileNewScObjectOp(OpCode op)
  353. {
  354. return
  355. !PHASE_OFF(InlineConstructorsPhase, m_functionWrite) &&
  356. (op == OpCode::NewScObject || op == OpCode::NewScObjectSpread);
  357. }
  358. bool DoProfileNewScObjArrayOp(OpCode op)
  359. {
  360. return
  361. !PHASE_OFF(NativeArrayPhase, m_functionWrite) &&
  362. !m_functionWrite->IsInDebugMode() &&
  363. (op == OpCode::NewScObjArray || op == OpCode::NewScObjArraySpread);
  364. }
  365. bool DoProfileNewScArrayOp(OpCode op)
  366. {
  367. return
  368. !PHASE_OFF(NativeArrayPhase, m_functionWrite) &&
  369. !PHASE_OFF(NativeNewScArrayPhase, m_functionWrite) &&
  370. !m_functionWrite->IsInDebugMode() &&
  371. (op == OpCode::NewScIntArray || op == OpCode::NewScFltArray || op == OpCode::NewScArray);
  372. }
  373. uint GetTotalSize()
  374. {
  375. return m_byteCodeData.GetCurrentOffset() + m_auxiliaryData.GetCurrentOffset() + m_auxContextData.GetCurrentOffset();
  376. }
  377. #if DBG
  378. bool IsInitialized() const { return isInitialized; }
  379. bool IsInUse() const { return isInUse; }
  380. #endif
  381. };
  382. }
  383. namespace JsUtil
  384. {
  385. template <>
  386. class ValueEntry<Js::ByteCodeWriter::CacheIdUnit>: public BaseValueEntry<Js::ByteCodeWriter::CacheIdUnit>
  387. {
  388. public:
  389. void Clear()
  390. {
  391. this->value = 0;
  392. }
  393. };
  394. };