From dc5a1c8f221ff3c38d61021e517719ac1aa24356 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 26 May 2021 17:19:57 +0200 Subject: [PATCH] JIT into scratch buffer (#53173) * Generate JITted code into a scratch buffer Copy it to the final location after the JITing is done. * Put also the code header and real code header into the buffer * Disable the scratch buffer usage until we enable W^X --- src/coreclr/vm/codeman.cpp | 86 ++++++++++++++-------- src/coreclr/vm/codeman.h | 18 +++-- src/coreclr/vm/jitinterface.cpp | 123 +++++++++++++++++++++----------- src/coreclr/vm/jitinterface.h | 32 +++++++++ 4 files changed, 182 insertions(+), 77 deletions(-) diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index e47b3206761d4..1898a791903f6 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -2592,18 +2592,20 @@ void* EEJitManager::allocCodeRaw(CodeHeapRequestInfo *pInfo, RETURN(mem); } -CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag +void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag, CodeHeader** ppCodeHeader, CodeHeader** ppCodeHeaderRW, + size_t* pAllocatedSize, HeapList** ppCodeHeap +#ifdef USE_INDIRECT_CODEHEADER + , BYTE** ppRealHeader +#endif #ifdef FEATURE_EH_FUNCLETS - , UINT nUnwindInfos - , TADDR * pModuleBase + , UINT nUnwindInfos #endif - ) + ) { - CONTRACT(CodeHeader *) { + CONTRACTL { THROWS; GC_NOTRIGGER; - POSTCONDITION(CheckPointer(RETVAL)); - } CONTRACT_END; + } CONTRACTL_END; // // Alignment @@ -2636,6 +2638,7 @@ CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t re SIZE_T totalSize = blockSize; CodeHeader * pCodeHdr = NULL; + CodeHeader * pCodeHdrRW = NULL; CodeHeapRequestInfo requestInfo(pMD); #if defined(FEATURE_JIT_PITCHING) @@ -2663,11 +2666,9 @@ CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t re { CrstHolder ch(&m_CodeHeapCritSec); - HeapList *pCodeHeap = NULL; - - TADDR pCode = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), totalSize, alignment, &pCodeHeap); - - _ASSERTE(pCodeHeap); + *ppCodeHeap = NULL; + TADDR pCode = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), totalSize, alignment, ppCodeHeap); + _ASSERTE(*ppCodeHeap); if (pMD->IsLCGMethod()) { @@ -2676,16 +2677,20 @@ CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t re _ASSERTE(IS_ALIGNED(pCode, alignment)); - // Initialize the CodeHeader *BEFORE* we publish this code range via the nibble - // map so that we don't have to harden readers against uninitialized data. - // However because we hold the lock, this initialization should be fast and cheap! - pCodeHdr = ((CodeHeader *)pCode) - 1; + *pAllocatedSize = sizeof(CodeHeader) + totalSize; +#ifdef FEATURE_WXORX + pCodeHdrRW = (CodeHeader *)new BYTE[*pAllocatedSize]; +#else + pCodeHdrRW = pCodeHdr; +#endif + #ifdef USE_INDIRECT_CODEHEADER if (requestInfo.IsDynamicDomain()) { - pCodeHdr->SetRealCodeHeader((BYTE*)pCode + ALIGN_UP(blockSize, sizeof(void*))); + // Set the real code header to the writeable mapping so that we can set its members via the CodeHeader methods below + pCodeHdrRW->SetRealCodeHeader((BYTE *)(pCodeHdrRW + 1) + ALIGN_UP(blockSize, sizeof(void*))); } else { @@ -2693,23 +2698,32 @@ CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t re // // allocate the real header in the low frequency heap BYTE* pRealHeader = (BYTE*)(void*)pMD->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(realHeaderSize)); - pCodeHdr->SetRealCodeHeader(pRealHeader); + pCodeHdrRW->SetRealCodeHeader(pRealHeader); } #endif - pCodeHdr->SetDebugInfo(NULL); - pCodeHdr->SetEHInfo(NULL); - pCodeHdr->SetGCInfo(NULL); - pCodeHdr->SetMethodDesc(pMD); + pCodeHdrRW->SetDebugInfo(NULL); + pCodeHdrRW->SetEHInfo(NULL); + pCodeHdrRW->SetGCInfo(NULL); + pCodeHdrRW->SetMethodDesc(pMD); #ifdef FEATURE_EH_FUNCLETS - pCodeHdr->SetNumberOfUnwindInfos(nUnwindInfos); - *pModuleBase = pCodeHeap->GetModuleBase(); + pCodeHdrRW->SetNumberOfUnwindInfos(nUnwindInfos); #endif - NibbleMapSet(pCodeHeap, pCode, TRUE); +#ifdef USE_INDIRECT_CODEHEADER + if (requestInfo.IsDynamicDomain()) + { + *ppRealHeader = (BYTE*)pCode + ALIGN_UP(blockSize, sizeof(void*)); + } + else + { + *ppRealHeader = NULL; + } +#endif // USE_INDIRECT_CODEHEADER } - RETURN(pCodeHdr); + *ppCodeHeader = pCodeHdr; + *ppCodeHeaderRW = pCodeHdrRW; } EEJitManager::DomainCodeHeapList *EEJitManager::GetCodeHeapList(CodeHeapRequestInfo *pInfo, LoaderAllocator *pAllocator, BOOL fDynamicOnly) @@ -2995,7 +3009,7 @@ JumpStubBlockHeader * EEJitManager::allocJumpStubBlock(MethodDesc* pMD, DWORD n CodeHeader * pCodeHdr = (CodeHeader *) (mem - sizeof(CodeHeader)); pCodeHdr->SetStubCodeBlockKind(STUB_CODE_BLOCK_JUMPSTUB); - NibbleMapSet(pCodeHeap, mem, TRUE); + NibbleMapSetUnlocked(pCodeHeap, mem, TRUE); pBlock = (JumpStubBlockHeader *)mem; @@ -3046,7 +3060,7 @@ void * EEJitManager::allocCodeFragmentBlock(size_t blockSize, unsigned alignment CodeHeader * pCodeHdr = (CodeHeader *) (mem - sizeof(CodeHeader)); pCodeHdr->SetStubCodeBlockKind(kind); - NibbleMapSet(pCodeHeap, mem, TRUE); + NibbleMapSetUnlocked(pCodeHeap, mem, TRUE); // Record the jump stub reservation pCodeHeap->reserveForJumpStubs += requestInfo.getReserveForJumpStubs(); @@ -3224,7 +3238,7 @@ void EEJitManager::RemoveJitData (CodeHeader * pCHdr, size_t GCinfo_len, size_t if (pHp == NULL) return; - NibbleMapSet(pHp, (TADDR)(pCHdr + 1), FALSE); + NibbleMapSetUnlocked(pHp, (TADDR)(pCHdr + 1), FALSE); } // Backout the GCInfo @@ -3386,7 +3400,7 @@ void EEJitManager::FreeCodeMemory(HostCodeHeap *pCodeHeap, void * codeStart) // so pCodeHeap can only be a HostCodeHeap. // clean up the NibbleMap - NibbleMapSet(pCodeHeap->m_pHeapList, (TADDR)codeStart, FALSE); + NibbleMapSetUnlocked(pCodeHeap->m_pHeapList, (TADDR)codeStart, FALSE); // The caller of this method doesn't call HostCodeHeap->FreeMemForCode // directly because the operation should be protected by m_CodeHeapCritSec. @@ -3850,6 +3864,7 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC } #if !defined(DACCESS_COMPILE) + void EEJitManager::NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet) { CONTRACTL { @@ -3857,6 +3872,17 @@ void EEJitManager::NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet) GC_NOTRIGGER; } CONTRACTL_END; + CrstHolder ch(&m_CodeHeapCritSec); + NibbleMapSetUnlocked(pHp, pCode, bSet); +} + +void EEJitManager::NibbleMapSetUnlocked(HeapList * pHp, TADDR pCode, BOOL bSet) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + // Currently all callers to this method ensure EEJitManager::m_CodeHeapCritSec // is held. _ASSERTE(m_CodeHeapCritSec.OwnedByCurrentThread()); diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 85a857b09d726..e5b9e6fb2205b 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -461,9 +461,9 @@ class CodeHeap // The number of code heaps at which we increase the size of new code heaps. #define CODE_HEAP_SIZE_INCREASE_THRESHOLD 5 -typedef DPTR(struct _HeapList) PTR_HeapList; +typedef DPTR(struct HeapList) PTR_HeapList; -typedef struct _HeapList +struct HeapList { PTR_HeapList hpNext; @@ -497,7 +497,7 @@ typedef struct _HeapList void SetNext(PTR_HeapList next) { hpNext = next; } -} HeapList; +}; //----------------------------------------------------------------------------- // Implementation of the standard CodeHeap. @@ -974,12 +974,15 @@ class EEJitManager : public IJitManager BOOL LoadJIT(); - CodeHeader* allocCode(MethodDesc* pFD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag + void allocCode(MethodDesc* pFD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag, CodeHeader** ppCodeHeader, CodeHeader** ppCodeHeaderRW, + size_t* pAllocatedSize, HeapList** ppCodeHeap +#ifdef USE_INDIRECT_CODEHEADER + , BYTE** ppRealHeader +#endif #ifdef FEATURE_EH_FUNCLETS - , UINT nUnwindInfos - , TADDR * pModuleBase + , UINT nUnwindInfos #endif - ); + ); BYTE * allocGCInfo(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize); EE_ILEXCEPTION* allocEHInfo(CodeHeader* pCodeHeader, unsigned numClauses, size_t * pAllocationSize); JumpStubBlockHeader* allocJumpStubBlock(MethodDesc* pMD, DWORD numJumps, @@ -1024,6 +1027,7 @@ class EEJitManager : public IJitManager #ifndef DACCESS_COMPILE // Heap Management functions void NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet); + void NibbleMapSetUnlocked(HeapList * pHp, TADDR pCode, BOOL bSet); #endif // !DACCESS_COMPILE static TADDR FindMethodCode(RangeSection * pRangeSection, PCODE currentPC); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e98a43973ce75..857d6473ab850 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11195,6 +11195,40 @@ void CEEJitInfo::BackoutJitData(EEJitManager * jitMgr) jitMgr->RemoveJitData(pCodeHeader, m_GCinfo_len, m_EHinfo_len); } +/*********************************************************************/ +void CEEJitInfo::WriteCode(EEJitManager * jitMgr) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + } CONTRACTL_END; + +#ifdef USE_INDIRECT_CODEHEADER + if (m_pRealCodeHeader != NULL) + { + // Restore the read only version of the real code header + m_CodeHeaderRW->SetRealCodeHeader(m_pRealCodeHeader); + m_pRealCodeHeader = NULL; + } +#endif // USE_INDIRECT_CODEHEADER + + if (m_CodeHeaderRW != m_CodeHeader) + { + memcpy(m_CodeHeader, m_CodeHeaderRW, m_codeWriteBufferSize); + } + + // Now that the code header was written to the final location, publish the code via the nibble map + jitMgr->NibbleMapSet(m_pCodeHeap, m_CodeHeader->GetCodeStartAddress(), TRUE); + +#if defined(TARGET_AMD64) + // Publish the new unwind information in a way that the ETW stack crawler can find + _ASSERTE(m_usedUnwindInfos == m_totalUnwindInfos); + UnwindInfoTable::PublishUnwindInfoForMethod(m_moduleBase, m_CodeHeader->GetUnwindInfo(0), m_totalUnwindInfos); +#endif // defined(TARGET_AMD64) + +} + + /*********************************************************************/ // Route jit information to the Jit Debug store. void CEEJitInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, uint32_t cMap, @@ -11313,7 +11347,7 @@ void CEEJitInfo::CompressDebugInfo() NULL, m_pMethodBeingCompiled->GetLoaderAllocator()->GetLowFrequencyHeap()); - m_CodeHeader->SetDebugInfo(pDebugInfo); + m_CodeHeaderRW->SetDebugInfo(pDebugInfo); } EX_CATCH { @@ -11457,13 +11491,18 @@ void CEEJitInfo::allocUnwindInfo ( _ASSERTE(m_usedUnwindInfos > 0); } - PT_RUNTIME_FUNCTION pRuntimeFunction = m_CodeHeader->GetUnwindInfo(m_usedUnwindInfos); + PT_RUNTIME_FUNCTION pRuntimeFunction = m_CodeHeaderRW->GetUnwindInfo(m_usedUnwindInfos); + m_usedUnwindInfos++; // Make sure that the RUNTIME_FUNCTION is aligned on a DWORD sized boundary _ASSERTE(IS_ALIGNED(pRuntimeFunction, sizeof(DWORD))); + + size_t writeableOffset = (BYTE *)m_CodeHeaderRW - (BYTE *)m_CodeHeader; UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) &(m_theUnwindBlock[m_usedUnwindSize]); + UNWIND_INFO * pUnwindInfoRW = (UNWIND_INFO *)((BYTE*)pUnwindInfo + writeableOffset); + m_usedUnwindSize += unwindSize; reservePersonalityRoutineSpace(m_usedUnwindSize); @@ -11522,15 +11561,14 @@ void CEEJitInfo::allocUnwindInfo ( for (ULONG iUnwindInfo = 0; iUnwindInfo < m_usedUnwindInfos - 1; iUnwindInfo++) { - PT_RUNTIME_FUNCTION pOtherFunction = m_CodeHeader->GetUnwindInfo(iUnwindInfo); - _ASSERTE(( RUNTIME_FUNCTION__BeginAddress(pOtherFunction) >= RUNTIME_FUNCTION__EndAddress(pRuntimeFunction, baseAddress) - || RUNTIME_FUNCTION__EndAddress(pOtherFunction, baseAddress) <= RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction))); + PT_RUNTIME_FUNCTION pOtherFunction = m_CodeHeaderRW->GetUnwindInfo(iUnwindInfo); + _ASSERTE(( RUNTIME_FUNCTION__BeginAddress(pOtherFunction) >= RUNTIME_FUNCTION__EndAddress(pRuntimeFunction, baseAddress + writeableOffset) + || RUNTIME_FUNCTION__EndAddress(pOtherFunction, baseAddress + writeableOffset) <= RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction))); } } #endif // _DEBUG - /* Copy the UnwindBlock */ - memcpy(pUnwindInfo, pUnwindBlock, unwindSize); + memcpy(pUnwindInfoRW, pUnwindBlock, unwindSize); #if defined(TARGET_X86) @@ -11538,33 +11576,27 @@ void CEEJitInfo::allocUnwindInfo ( #elif defined(TARGET_AMD64) - pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; + pUnwindInfoRW->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; - ULONG * pPersonalityRoutine = (ULONG*)ALIGN_UP(&(pUnwindInfo->UnwindCode[pUnwindInfo->CountOfUnwindCodes]), sizeof(ULONG)); - *pPersonalityRoutine = ExecutionManager::GetCLRPersonalityRoutineValue(); + ULONG * pPersonalityRoutineRW = (ULONG*)ALIGN_UP(&(pUnwindInfoRW->UnwindCode[pUnwindInfoRW->CountOfUnwindCodes]), sizeof(ULONG)); + *pPersonalityRoutineRW = ExecutionManager::GetCLRPersonalityRoutineValue(); #elif defined(TARGET_ARM64) - *(LONG *)pUnwindInfo |= (1 << 20); // X bit + *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit - ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); - *pPersonalityRoutine = ExecutionManager::GetCLRPersonalityRoutineValue(); + ULONG * pPersonalityRoutineRW = (ULONG*)((BYTE *)pUnwindInfoRW + ALIGN_UP(unwindSize, sizeof(ULONG))); + *pPersonalityRoutineRW = ExecutionManager::GetCLRPersonalityRoutineValue(); #elif defined(TARGET_ARM) - *(LONG *)pUnwindInfo |= (1 << 20); // X bit + *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit - ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); - *pPersonalityRoutine = (TADDR)ProcessCLRException - baseAddress; + ULONG * pPersonalityRoutineRW = (ULONG*)((BYTE *)pUnwindInfoRW + ALIGN_UP(unwindSize, sizeof(ULONG))); + *pPersonalityRoutineRW = (TADDR)ProcessCLRException - baseAddress; #endif -#if defined(TARGET_AMD64) - // Publish the new unwind information in a way that the ETW stack crawler can find - if (m_usedUnwindInfos == m_totalUnwindInfos) - UnwindInfoTable::PublishUnwindInfoForMethod(baseAddress, m_CodeHeader->GetUnwindInfo(0), m_totalUnwindInfos); -#endif // defined(TARGET_AMD64) - EE_TO_JIT_TRANSITION(); #else // FEATURE_EH_FUNCLETS LIMITED_METHOD_CONTRACT; @@ -11685,7 +11717,7 @@ void CEEJitInfo::recordRelocation(void * location, delta = (INT64)(branchTarget - fixupLocation); _ASSERTE((delta & 0x3) == 0); // the low two bits must be zero - UINT32 branchInstr = *((UINT32*) fixupLocation); + UINT32 branchInstr = *((UINT32*) fixupLocationRW); branchInstr &= 0xFC000000; // keep bits 31-26 _ASSERTE((branchInstr & 0x7FFFFFFF) == 0x14000000); // Must be B or BL @@ -12271,24 +12303,31 @@ void CEEJitInfo::allocMem (AllocMemArgs *pArgs) pArgs->hotCodeSize + pArgs->coldCodeSize, pArgs->roDataSize, totalSize.Value(), pArgs->flag, GetClrInstanceId()); } - m_CodeHeader = m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), GetReserveForJumpStubs(), pArgs->flag + m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), GetReserveForJumpStubs(), pArgs->flag, &m_CodeHeader, &m_CodeHeaderRW, &m_codeWriteBufferSize, &m_pCodeHeap +#ifdef USE_INDIRECT_CODEHEADER + , &m_pRealCodeHeader +#endif +#ifdef FEATURE_EH_FUNCLETS + , m_totalUnwindInfos +#endif + ); + #ifdef FEATURE_EH_FUNCLETS - , m_totalUnwindInfos - , &m_moduleBase + m_moduleBase = m_pCodeHeap->GetModuleBase(); #endif - ); BYTE* current = (BYTE *)m_CodeHeader->GetCodeStartAddress(); + size_t writeableOffset = (BYTE *)m_CodeHeaderRW - (BYTE *)m_CodeHeader; *codeBlock = current; - *codeBlockRW = current; + *codeBlockRW = current + writeableOffset; current += codeSize; if (pArgs->roDataSize > 0) { current = (BYTE *)ALIGN_UP(current, roDataAlignment); pArgs->roDataBlock = current; - pArgs->roDataBlockRW = current; + pArgs->roDataBlockRW = current + writeableOffset; current += pArgs->roDataSize; } else @@ -12326,8 +12365,8 @@ void * CEEJitInfo::allocGCInfo (size_t size) JIT_TO_EE_TRANSITION(); - _ASSERTE(m_CodeHeader != 0); - _ASSERTE(m_CodeHeader->GetGCInfo() == 0); + _ASSERTE(m_CodeHeaderRW != 0); + _ASSERTE(m_CodeHeaderRW->GetGCInfo() == 0); #ifdef HOST_64BIT if (size & 0xFFFFFFFF80000000LL) @@ -12336,13 +12375,13 @@ void * CEEJitInfo::allocGCInfo (size_t size) } #endif // HOST_64BIT - block = m_jitManager->allocGCInfo(m_CodeHeader,(DWORD)size, &m_GCinfo_len); + block = m_jitManager->allocGCInfo(m_CodeHeaderRW,(DWORD)size, &m_GCinfo_len); if (!block) { COMPlusThrowHR(CORJIT_OUTOFMEM); } - _ASSERTE(m_CodeHeader->GetGCInfo() != 0 && block == m_CodeHeader->GetGCInfo()); + _ASSERTE(m_CodeHeaderRW->GetGCInfo() != 0 && block == m_CodeHeaderRW->GetGCInfo()); EE_TO_JIT_TRANSITION(); @@ -12362,14 +12401,14 @@ void CEEJitInfo::setEHcount ( JIT_TO_EE_TRANSITION(); _ASSERTE(cEH != 0); - _ASSERTE(m_CodeHeader != 0); - _ASSERTE(m_CodeHeader->GetEHInfo() == 0); + _ASSERTE(m_CodeHeaderRW != 0); + _ASSERTE(m_CodeHeaderRW->GetEHInfo() == 0); EE_ILEXCEPTION* ret; - ret = m_jitManager->allocEHInfo(m_CodeHeader,cEH, &m_EHinfo_len); + ret = m_jitManager->allocEHInfo(m_CodeHeaderRW,cEH, &m_EHinfo_len); _ASSERTE(ret); // allocEHInfo throws if there's not enough memory - _ASSERTE(m_CodeHeader->GetEHInfo() != 0 && m_CodeHeader->GetEHInfo()->EHCount() == cEH); + _ASSERTE(m_CodeHeaderRW->GetEHInfo() != 0 && m_CodeHeaderRW->GetEHInfo()->EHCount() == cEH); EE_TO_JIT_TRANSITION(); } @@ -12388,9 +12427,9 @@ void CEEJitInfo::setEHinfo ( JIT_TO_EE_TRANSITION(); // Fix make the Code Manager EH clauses EH_INFO+ - _ASSERTE(m_CodeHeader->GetEHInfo() != 0 && EHnumber < m_CodeHeader->GetEHInfo()->EHCount()); + _ASSERTE(m_CodeHeaderRW->GetEHInfo() != 0 && EHnumber < m_CodeHeaderRW->GetEHInfo()->EHCount()); - EE_ILEXCEPTION_CLAUSE* pEHClause = m_CodeHeader->GetEHInfo()->EHClause(EHnumber); + EE_ILEXCEPTION_CLAUSE* pEHClause = m_CodeHeaderRW->GetEHInfo()->EHClause(EHnumber); pEHClause->TryStartPC = clause->TryOffset; pEHClause->TryEndPC = clause->TryLength; @@ -13282,7 +13321,11 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, LOG((LF_JIT, LL_INFO10000, "Done Jitting method %s::%s %s }\n",cls,name, ftn->m_pszDebugMethodSignature)); - if (!SUCCEEDED(res)) + if (SUCCEEDED(res)) + { + jitInfo.WriteCode(jitMgr); + } + else { jitInfo.BackoutJitData(jitMgr); ThrowExceptionForJit(res); diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 56cb5befac401..8b6c5053c821b 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -626,6 +626,7 @@ class CEEInfo : public ICorJitInfo /*********************************************************************/ class EEJitManager; +struct HeapList; struct _hpCodeHdr; typedef struct _hpCodeHdr CodeHeader; @@ -704,7 +705,19 @@ class CEEJitInfo : public CEEInfo GC_NOTRIGGER; } CONTRACTL_END; + if (m_CodeHeaderRW != m_CodeHeader) + { + delete [] (BYTE*)m_CodeHeaderRW; + } + m_CodeHeader = NULL; + m_CodeHeaderRW = NULL; + + m_codeWriteBufferSize = 0; +#ifdef USE_INDIRECT_CODEHEADER + m_pRealCodeHeader = NULL; +#endif + m_pCodeHeap = NULL; if (m_pOffsetMapping != NULL) delete [] ((BYTE*) m_pOffsetMapping); @@ -804,6 +817,12 @@ class CEEJitInfo : public CEEInfo : CEEInfo(fd, fVerifyOnly, allowInlining), m_jitManager(jm), m_CodeHeader(NULL), + m_CodeHeaderRW(NULL), + m_codeWriteBufferSize(0), +#ifdef USE_INDIRECT_CODEHEADER + m_pRealCodeHeader(NULL), +#endif + m_pCodeHeap(NULL), m_ILHeader(header), #ifdef FEATURE_EH_FUNCLETS m_moduleBase(NULL), @@ -852,6 +871,11 @@ class CEEJitInfo : public CEEInfo MODE_ANY; } CONTRACTL_END; + if (m_CodeHeaderRW != m_CodeHeader) + { + delete [] (BYTE*)m_CodeHeaderRW; + } + if (m_pOffsetMapping != NULL) delete [] ((BYTE*) m_pOffsetMapping); @@ -909,6 +933,8 @@ class CEEJitInfo : public CEEInfo void BackoutJitData(EEJitManager * jitMgr); + void WriteCode(EEJitManager * jitMgr); + void setPatchpointInfo(PatchpointInfo* patchpointInfo) override final; PatchpointInfo* getOSRInfo(unsigned* ilOffset) override final; @@ -934,6 +960,12 @@ protected : EEJitManager* m_jitManager; // responsible for allocating memory CodeHeader* m_CodeHeader; // descriptor for JITTED code + CodeHeader* m_CodeHeaderRW; + size_t m_codeWriteBufferSize; +#ifdef USE_INDIRECT_CODEHEADER + BYTE* m_pRealCodeHeader; +#endif + HeapList* m_pCodeHeap; COR_ILMETHOD_DECODER * m_ILHeader; // the code header as exist in the file #ifdef FEATURE_EH_FUNCLETS TADDR m_moduleBase; // Base for unwind Infos