JITOutput.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. #include "Backend.h"
  6. JITOutput::JITOutput(JITOutputIDL * outputData) :
  7. m_outputData(outputData),
  8. m_inProcAlloc(nullptr),
  9. m_func(nullptr)
  10. {
  11. }
  12. void
  13. JITOutput::SetHasJITStackClosure()
  14. {
  15. m_outputData->hasJittedStackClosure = true;
  16. }
  17. void
  18. JITOutput::SetVarSlotsOffset(int32 offset)
  19. {
  20. m_outputData->localVarSlotsOffset = offset;
  21. }
  22. void
  23. JITOutput::SetVarChangedOffset(int32 offset)
  24. {
  25. m_outputData->localVarChangedOffset = offset;
  26. }
  27. void
  28. JITOutput::SetHasBailoutInstr(bool val)
  29. {
  30. m_outputData->hasBailoutInstr = val;
  31. }
  32. void
  33. JITOutput::SetArgUsedForBranch(uint8 param)
  34. {
  35. Assert(param > 0);
  36. Assert(param < Js::Constants::MaximumArgumentCountForConstantArgumentInlining);
  37. m_outputData->argUsedForBranch |= (1 << (param - 1));
  38. }
  39. void
  40. JITOutput::SetFrameHeight(uint val)
  41. {
  42. m_outputData->frameHeight = val;
  43. }
  44. void
  45. JITOutput::RecordThrowMap(Js::ThrowMapEntry * throwMap, uint mapCount)
  46. {
  47. m_outputData->throwMapOffset = NativeCodeData::GetDataTotalOffset(throwMap);
  48. m_outputData->throwMapCount = mapCount;
  49. }
  50. bool
  51. JITOutput::IsTrackCompoundedIntOverflowDisabled() const
  52. {
  53. return m_outputData->disableTrackCompoundedIntOverflow != FALSE;
  54. }
  55. bool
  56. JITOutput::IsArrayCheckHoistDisabled() const
  57. {
  58. return m_outputData->disableArrayCheckHoist != FALSE;
  59. }
  60. bool
  61. JITOutput::IsStackArgOptDisabled() const
  62. {
  63. return m_outputData->disableStackArgOpt != FALSE;
  64. }
  65. bool
  66. JITOutput::IsSwitchOptDisabled() const
  67. {
  68. return m_outputData->disableSwitchOpt != FALSE;
  69. }
  70. bool
  71. JITOutput::IsAggressiveIntTypeSpecDisabled() const
  72. {
  73. return m_outputData->disableAggressiveIntTypeSpec != FALSE;
  74. }
  75. uint16
  76. JITOutput::GetArgUsedForBranch() const
  77. {
  78. return m_outputData->argUsedForBranch;
  79. }
  80. intptr_t
  81. JITOutput::GetCodeAddress() const
  82. {
  83. return (intptr_t)m_outputData->codeAddress;
  84. }
  85. void
  86. JITOutput::SetCodeAddress(intptr_t addr)
  87. {
  88. m_outputData->codeAddress = addr;
  89. }
  90. size_t
  91. JITOutput::GetCodeSize() const
  92. {
  93. return (size_t)m_outputData->codeSize;
  94. }
  95. ushort
  96. JITOutput::GetPdataCount() const
  97. {
  98. return m_outputData->pdataCount;
  99. }
  100. ushort
  101. JITOutput::GetXdataSize() const
  102. {
  103. return m_outputData->xdataSize;
  104. }
  105. EmitBufferAllocation<VirtualAllocWrapper, PreReservedVirtualAllocWrapper> *
  106. JITOutput::RecordInProcNativeCodeSize(Func *func, uint32 bytes, ushort pdataCount, ushort xdataSize)
  107. {
  108. m_func = func;
  109. #if defined(_M_ARM32_OR_ARM64)
  110. bool canAllocInPreReservedHeapPageSegment = false;
  111. #else
  112. bool canAllocInPreReservedHeapPageSegment = m_func->CanAllocInPreReservedHeapPageSegment();
  113. #endif
  114. BYTE *buffer = nullptr;
  115. m_inProcAlloc = m_func->GetInProcCodeGenAllocators()->emitBufferManager.AllocateBuffer(bytes, &buffer, pdataCount, xdataSize, canAllocInPreReservedHeapPageSegment, true);
  116. if (buffer == nullptr)
  117. {
  118. Js::Throw::OutOfMemory();
  119. }
  120. m_outputData->codeAddress = (intptr_t)buffer;
  121. m_outputData->codeSize = bytes;
  122. m_outputData->pdataCount = pdataCount;
  123. m_outputData->xdataSize = xdataSize;
  124. m_outputData->isInPrereservedRegion = m_inProcAlloc->inPrereservedRegion;
  125. return m_inProcAlloc;
  126. }
  127. #if ENABLE_OOP_NATIVE_CODEGEN
  128. EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> *
  129. JITOutput::RecordOOPNativeCodeSize(Func *func, uint32 bytes, ushort pdataCount, ushort xdataSize)
  130. {
  131. m_func = func;
  132. #if defined(_M_ARM32_OR_ARM64)
  133. bool canAllocInPreReservedHeapPageSegment = false;
  134. #else
  135. bool canAllocInPreReservedHeapPageSegment = m_func->CanAllocInPreReservedHeapPageSegment();
  136. #endif
  137. BYTE *buffer = nullptr;
  138. m_oopAlloc = m_func->GetOOPCodeGenAllocators()->emitBufferManager.AllocateBuffer(bytes, &buffer, pdataCount, xdataSize, canAllocInPreReservedHeapPageSegment, true);
  139. if (buffer == nullptr)
  140. {
  141. Js::Throw::OutOfMemory();
  142. }
  143. m_outputData->codeAddress = (intptr_t)buffer;
  144. m_outputData->codeSize = bytes;
  145. m_outputData->pdataCount = pdataCount;
  146. m_outputData->xdataSize = xdataSize;
  147. m_outputData->isInPrereservedRegion = m_oopAlloc->inPrereservedRegion;
  148. return m_oopAlloc;
  149. }
  150. #endif
  151. void
  152. JITOutput::RecordNativeCode(const BYTE* sourceBuffer, BYTE* localCodeAddress)
  153. {
  154. #if ENABLE_OOP_NATIVE_CODEGEN
  155. if (JITManager::GetJITManager()->IsJITServer())
  156. {
  157. RecordNativeCode(sourceBuffer, localCodeAddress, m_oopAlloc, m_func->GetOOPCodeGenAllocators());
  158. }
  159. else
  160. #endif
  161. {
  162. RecordNativeCode(sourceBuffer, localCodeAddress, m_inProcAlloc, m_func->GetInProcCodeGenAllocators());
  163. }
  164. }
  165. template <typename TEmitBufferAllocation, typename TCodeGenAllocators>
  166. void
  167. JITOutput::RecordNativeCode(const BYTE* sourceBuffer, BYTE* localCodeAddress, TEmitBufferAllocation allocation, TCodeGenAllocators codeGenAllocators)
  168. {
  169. Assert(m_outputData->codeAddress == (intptr_t)allocation->allocation->address);
  170. if (!codeGenAllocators->emitBufferManager.CommitBuffer(allocation, localCodeAddress, m_outputData->codeSize, sourceBuffer))
  171. {
  172. Js::Throw::OutOfMemory();
  173. }
  174. #if DBG_DUMP
  175. if (m_func->IsLoopBody())
  176. {
  177. codeGenAllocators->emitBufferManager.totalBytesLoopBody += m_outputData->codeSize;
  178. }
  179. #endif
  180. }
  181. void
  182. JITOutput::RecordInlineeFrameOffsetsInfo(unsigned int offsetsArrayOffset, unsigned int offsetsArrayCount)
  183. {
  184. m_outputData->inlineeFrameOffsetArrayOffset = offsetsArrayOffset;
  185. m_outputData->inlineeFrameOffsetArrayCount = offsetsArrayCount;
  186. }
  187. #if _M_X64
  188. void
  189. JITOutput::RecordUnwindInfo(BYTE *unwindInfo, size_t size, BYTE * xdataAddr, BYTE* localXdataAddr)
  190. {
  191. Assert(XDATA_SIZE >= size);
  192. memcpy_s(localXdataAddr, XDATA_SIZE, unwindInfo, size);
  193. m_outputData->xdataAddr = (intptr_t)xdataAddr;
  194. }
  195. #elif _M_ARM
  196. size_t
  197. JITOutput::RecordUnwindInfo(size_t offset, BYTE *unwindInfo, size_t size, BYTE * xdataAddr)
  198. {
  199. BYTE *xdataFinal = xdataAddr + offset;
  200. Assert(xdataFinal);
  201. Assert(((DWORD)xdataFinal & 0x3) == 0); // 4 byte aligned
  202. memcpy_s(xdataFinal, size, unwindInfo, size);
  203. return (size_t)xdataFinal;
  204. }
  205. void
  206. JITOutput::RecordXData(BYTE * xdata)
  207. {
  208. m_outputData->xdataOffset = NativeCodeData::GetDataTotalOffset(xdata);
  209. }
  210. #endif
  211. void
  212. JITOutput::FinalizeNativeCode()
  213. {
  214. #if ENABLE_OOP_NATIVE_CODEGEN
  215. if (JITManager::GetJITManager()->IsJITServer())
  216. {
  217. m_func->GetOOPCodeGenAllocators()->emitBufferManager.CompletePreviousAllocation(m_oopAlloc);
  218. #if defined(_CONTROL_FLOW_GUARD)
  219. #if _M_IX86 || _M_X64
  220. if (!m_func->IsLoopBody() && CONFIG_FLAG(UseJITTrampoline))
  221. {
  222. m_outputData->thunkAddress = m_func->GetOOPThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
  223. }
  224. #endif
  225. #endif
  226. }
  227. else
  228. #endif
  229. {
  230. m_func->GetInProcCodeGenAllocators()->emitBufferManager.CompletePreviousAllocation(m_inProcAlloc);
  231. m_func->GetInProcJITEntryPointInfo()->SetInProcJITNativeCodeData(m_func->GetNativeCodeDataAllocator()->Finalize());
  232. m_func->GetInProcJITEntryPointInfo()->GetJitTransferData()->SetRawData(m_func->GetTransferDataAllocator()->Finalize());
  233. #if !FLOATVAR
  234. CodeGenNumberChunk * numberChunks = m_func->GetNumberAllocator()->Finalize();
  235. m_func->GetInProcJITEntryPointInfo()->SetNumberChunks(numberChunks);
  236. #endif
  237. #if defined(_CONTROL_FLOW_GUARD)
  238. #if _M_IX86 || _M_X64
  239. if (!m_func->IsLoopBody() && CONFIG_FLAG(UseJITTrampoline))
  240. {
  241. m_outputData->thunkAddress = m_func->GetInProcThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
  242. }
  243. #endif
  244. #endif
  245. }
  246. if (!m_outputData->thunkAddress && CONFIG_FLAG(OOPCFGRegistration))
  247. {
  248. m_func->GetThreadContextInfo()->SetValidCallTargetForCFG((PVOID)m_outputData->codeAddress);
  249. }
  250. }
  251. JITOutputIDL *
  252. JITOutput::GetOutputData()
  253. {
  254. return m_outputData;
  255. }