JITOutput.cpp 8.8 KB

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