Skip to content

Commit

Permalink
Publish code via nibble map after it is copied to its final location
Browse files Browse the repository at this point in the history
  • Loading branch information
janvorli committed May 24, 2021
1 parent 951b9f1 commit afa6c2f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 62 deletions.
68 changes: 31 additions & 37 deletions src/coreclr/vm/codeman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

//
Expand Down Expand Up @@ -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)
Expand All @@ -2673,25 +2666,21 @@ 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())
{
pMD->AsDynamicMethodDesc()->GetLCGMethodResolver()->m_recordCodePointer = (void*) pCode;
}

_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())
Expand All @@ -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*));
Expand All @@ -2734,6 +2715,7 @@ void EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, size_t reserveFo
{
*ppRealHeader = NULL;
}
#endif // USE_INDIRECT_CODEHEADER
}

*ppCodeHeader = pCodeHdr;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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 {
Expand Down
20 changes: 12 additions & 8 deletions src/coreclr/vm/codeman.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -497,7 +497,7 @@ typedef struct _HeapList
void SetNext(PTR_HeapList next)
{ hpNext = next; }

} HeapList;
};

//-----------------------------------------------------------------------------
// Implementation of the standard CodeHeap.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/vm/i386/stublinkerx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 17 additions & 13 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -13318,7 +13322,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config,

if (SUCCEEDED(res))
{
jitInfo.WriteCode();
jitInfo.WriteCode(jitMgr);
}
else
{
Expand Down
13 changes: 11 additions & 2 deletions src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ class CEEInfo : public ICorJitInfo
/*********************************************************************/

class EEJitManager;
struct HeapList;
struct _hpCodeHdr;
typedef struct _hpCodeHdr CodeHeader;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit afa6c2f

Please sign in to comment.