From afa6c2f135cf3a1605ad22cb9f311e80765e6635 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Mon, 24 May 2021 15:36:15 +0200 Subject: [PATCH] Publish code via nibble map after it is copied to its final location --- src/coreclr/vm/codeman.cpp | 68 ++++++++++++--------------- src/coreclr/vm/codeman.h | 20 ++++---- src/coreclr/vm/i386/stublinkerx86.cpp | 3 +- src/coreclr/vm/jitinterface.cpp | 30 +++++++----- src/coreclr/vm/jitinterface.h | 13 ++++- 5 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 55730c6e13bdc..88264215fa015 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -2492,7 +2492,7 @@ HeapList* EEJitManager::NewCodeHeap(CodeHeapRequestInfo *pInfo, DomainCodeHeapLi void* EEJitManager::allocCodeRaw(CodeHeapRequestInfo *pInfo, size_t header, size_t blockSize, unsigned align, - HeapList ** ppCodeHeap, size_t* pAllocatedSize) + HeapList ** ppCodeHeap) { CONTRACT(void *) { THROWS; @@ -2501,12 +2501,7 @@ void* EEJitManager::allocCodeRaw(CodeHeapRequestInfo *pInfo, POSTCONDITION((RETVAL != NULL) || !pInfo->getThrowOnOutOfMemoryWithinRange()); } CONTRACT_END; - size_t allocatedSize = header+blockSize+(align-1)+pInfo->getReserveForJumpStubs(); - if (pAllocatedSize != NULL) - { - *pAllocatedSize = allocatedSize - (align - 1); - } - pInfo->setRequestSize(allocatedSize); + pInfo->setRequestSize(header+blockSize+(align-1)+pInfo->getReserveForJumpStubs()); void * mem = NULL; HeapList * pCodeHeap = NULL; @@ -2597,17 +2592,19 @@ void* EEJitManager::allocCodeRaw(CodeHeapRequestInfo *pInfo, RETURN(mem); } -void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag, CodeHeader** ppCodeHeader, CodeHeader** ppCodeHeaderRW, size_t* pAllocatedSize, BYTE** ppRealHeader +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 - ) + ) { CONTRACTL { THROWS; GC_NOTRIGGER; -// POSTCONDITION(CheckPointer(RETVAL)); } CONTRACTL_END; // @@ -2650,10 +2647,6 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo requestInfo.SetDynamicDomain(); } #endif - if (reserveForJumpStubs != 0) - { - __debugbreak(); - } requestInfo.setReserveForJumpStubs(reserveForJumpStubs); #if defined(USE_INDIRECT_CODEHEADER) @@ -2673,11 +2666,9 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo { CrstHolder ch(&m_CodeHeapCritSec); - HeapList *pCodeHeap = NULL; - - TADDR pCode = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), totalSize, alignment, &pCodeHeap, pAllocatedSize); - - _ASSERTE(pCodeHeap); + *ppCodeHeap = NULL; + TADDR pCode = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), totalSize, alignment, ppCodeHeap); + _ASSERTE(*ppCodeHeap); if (pMD->IsLCGMethod()) { @@ -2685,13 +2676,11 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo } _ASSERTE(IS_ALIGNED(pCode, alignment)); -//Maybe this is the problem! - // 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; - pCodeHdrRW = (CodeHeader *)new BYTE[*pAllocatedSize](); + + *pAllocatedSize = sizeof(CodeHeader) + totalSize + reserveForJumpStubs; + pCodeHdrRW = (CodeHeader *)new BYTE[*pAllocatedSize]; #ifdef USE_INDIRECT_CODEHEADER if (requestInfo.IsDynamicDomain()) @@ -2715,17 +2704,9 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo pCodeHdrRW->SetMethodDesc(pMD); #ifdef FEATURE_EH_FUNCLETS pCodeHdrRW->SetNumberOfUnwindInfos(nUnwindInfos); - *pModuleBase = pCodeHeap->GetModuleBase(); #endif - // This needs to happen elsewhere, - // if (requestInfo.IsDynamicDomain()) - // { - // // We are done setting the real code header members, so set it to the final executable mapping - // pCodeHdrRW->SetRealCodeHeader((BYTE*)pCode + ALIGN_UP(blockSize, sizeof(void*))); - // } - - NibbleMapSet(pCodeHeap, pCode, TRUE); +#ifdef USE_INDIRECT_CODEHEADER if (requestInfo.IsDynamicDomain()) { *ppRealHeader = (BYTE*)pCode + ALIGN_UP(blockSize, sizeof(void*)); @@ -2734,6 +2715,7 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo { *ppRealHeader = NULL; } +#endif // USE_INDIRECT_CODEHEADER } *ppCodeHeader = pCodeHdr; @@ -3012,7 +2994,7 @@ JumpStubBlockHeader * EEJitManager::allocJumpStubBlock(MethodDesc* pMD, DWORD n { CrstHolder ch(&m_CodeHeapCritSec); - mem = (TADDR) allocCodeRaw(&requestInfo, sizeof(TADDR), blockSize, CODE_SIZE_ALIGN, &pCodeHeap, NULL); + mem = (TADDR) allocCodeRaw(&requestInfo, sizeof(TADDR), blockSize, CODE_SIZE_ALIGN, &pCodeHeap); if (mem == NULL) { _ASSERTE(!throwOnOutOfMemoryWithinRange); @@ -3068,7 +3050,7 @@ void * EEJitManager::allocCodeFragmentBlock(size_t blockSize, unsigned alignment { CrstHolder ch(&m_CodeHeapCritSec); - mem = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), blockSize, alignment, &pCodeHeap, NULL); + mem = (TADDR) allocCodeRaw(&requestInfo, sizeof(CodeHeader), blockSize, alignment, &pCodeHeap); // CodeHeader comes immediately before the block CodeHeader * pCodeHdr = (CodeHeader *) (mem - sizeof(CodeHeader)); @@ -3878,6 +3860,18 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC } #if !defined(DACCESS_COMPILE) + +void EEJitManager::NibbleMapSetUnlocked(HeapList * pHp, TADDR pCode, BOOL bSet) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + CrstHolder ch(&m_CodeHeapCritSec); + NibbleMapSet(pHp, pCode, bSet); +} + void EEJitManager::NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet) { CONTRACTL { diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index f01b7feb8035e..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(); - void allocCode(MethodDesc* pFD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag, CodeHeader** ppCodeHeader, CodeHeader** ppCodeHeaderRW, size_t* pAllocatedSize, BYTE** ppRealHeader + 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); @@ -1054,7 +1058,7 @@ private : bool CanUseCodeHeap(CodeHeapRequestInfo *pInfo, HeapList *pCodeHeap); void* allocCodeRaw(CodeHeapRequestInfo *pInfo, size_t header, size_t blockSize, unsigned align, - HeapList ** ppCodeHeap, size_t* pAllocatedSize); + HeapList ** ppCodeHeap); DomainCodeHeapList *GetCodeHeapList(CodeHeapRequestInfo *pInfo, LoaderAllocator *pAllocator, BOOL fDynamicOnly = FALSE); DomainCodeHeapList *CreateCodeHeapList(CodeHeapRequestInfo *pInfo); diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index eba92f95b3084..8817bf1cc4fe4 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -5286,8 +5286,7 @@ void FixupPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator, int *(void**)GetBase() = (BYTE*)pMD - (iMethodDescChunkIndex * MethodDesc::ALIGNMENT); } - MethodDesc* pPrecodeMD = (MethodDesc*)GetMethodDesc(); - _ASSERTE((TADDR)pPrecodeMD == (TADDR)pMD); + _ASSERTE(GetMethodDesc() == (TADDR)pMD); PCODE target = (PCODE)GetEEFuncEntryPoint(PrecodeFixupThunk); #ifdef FIXUP_PRECODE_PREALLOCATE_DYNAMIC_METHOD_JUMP_STUBS diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 4bc1eb29e4627..c400618994efb 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11196,29 +11196,30 @@ void CEEJitInfo::BackoutJitData(EEJitManager * jitMgr) } /*********************************************************************/ -void CEEJitInfo::WriteCode() +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 -// memcpy((void*)m_CodeHeader->GetCodeStartAddress(), m_codeWriteBuffer, m_codeWriteBufferSize); memcpy(m_CodeHeader, m_CodeHeaderRW, m_codeWriteBufferSize); delete [] (BYTE*)m_CodeHeaderRW; m_CodeHeaderRW = NULL; - // delete [] m_codeWriteBuffer; - // m_codeWriteBuffer = NULL; - m_codeWriteBufferSize = 0; + // Now that the code header was written to the final location, publish the code via the nibble map + jitMgr->NibbleMapSetUnlocked(m_pCodeHeap, m_CodeHeader->GetCodeStartAddress(), TRUE); + m_pCodeHeap = NULL; #if defined(TARGET_AMD64) // Publish the new unwind information in a way that the ETW stack crawler can find @@ -11501,8 +11502,6 @@ void CEEJitInfo::allocUnwindInfo ( UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) &(m_theUnwindBlock[m_usedUnwindSize]); UNWIND_INFO * pUnwindInfoRW = (UNWIND_INFO *)((BYTE*)pUnwindInfo + m_writeableOffset); - uint32_t prevUsedUnwindSize = m_usedUnwindSize; - m_usedUnwindSize += unwindSize; reservePersonalityRoutineSpace(m_usedUnwindSize); @@ -12303,14 +12302,19 @@ void CEEJitInfo::allocMem (AllocMemArgs *pArgs) pArgs->hotCodeSize + pArgs->coldCodeSize, pArgs->roDataSize, totalSize.Value(), pArgs->flag, GetClrInstanceId()); } - m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), GetReserveForJumpStubs(), pArgs->flag, &m_CodeHeader, &m_CodeHeaderRW, &m_codeWriteBufferSize, &m_pRealCodeHeader + 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 - ); -// m_codeWriteBufferSize = totalSize.Value(); BYTE* current = (BYTE *)m_CodeHeader->GetCodeStartAddress(); m_writeableOffset = (BYTE *)m_CodeHeaderRW - (BYTE *)m_CodeHeader; @@ -13318,7 +13322,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, if (SUCCEEDED(res)) { - jitInfo.WriteCode(); + jitInfo.WriteCode(jitMgr); } else { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index da3e907b8b490..ac9f790e49b5f 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; @@ -711,8 +712,10 @@ class CEEJitInfo : public CEEInfo 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); @@ -814,8 +817,11 @@ class CEEJitInfo : public CEEInfo m_CodeHeader(NULL), m_CodeHeaderRW(NULL), m_codeWriteBufferSize(0), +#ifdef USE_INDIRECT_CODEHEADER m_pRealCodeHeader(NULL), +#endif m_writeableOffset(0), + m_pCodeHeap(NULL), m_ILHeader(header), #ifdef FEATURE_EH_FUNCLETS m_moduleBase(NULL), @@ -921,7 +927,7 @@ class CEEJitInfo : public CEEInfo void BackoutJitData(EEJitManager * jitMgr); - void WriteCode(); + void WriteCode(EEJitManager * jitMgr); void setPatchpointInfo(PatchpointInfo* patchpointInfo) override final; PatchpointInfo* getOSRInfo(unsigned* ilOffset) override final; @@ -950,8 +956,11 @@ protected : CodeHeader* m_CodeHeader; // descriptor for JITTED code CodeHeader* m_CodeHeaderRW; size_t m_codeWriteBufferSize; +#ifdef USE_INDIRECT_CODEHEADER BYTE* m_pRealCodeHeader; +#endif size_t m_writeableOffset; + 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