From d119fff0281c81038202e3db20ae8417648ea55f Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 11 May 2021 15:39:04 +0200 Subject: [PATCH 1/6] Modify JIT to support double mapped memory This change modifies JIT so that it can generate code into double mapped memory. The code is written into RW mapped memory, but the relative offsets are computed using the related RX locations. The change doesn't modify the runtime to provide double mapped memory yet, the JIT2EE interface allocMem returns the same addresses as RW and RX. The runtime changes will be part of follow-up PRs. However, it was already tested with the double mapping enabled locally. --- .../superpmi-shim-collector/icorjitinfo.cpp | 22 +++- .../superpmi-shim-counter/icorjitinfo.cpp | 16 ++- .../superpmi-shim-simple/icorjitinfo.cpp | 15 ++- .../ToolBox/superpmi/superpmi/icorjitinfo.cpp | 19 ++- src/coreclr/inc/corjit.h | 9 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 8 +- src/coreclr/inc/jiteeversionguid.h | 11 +- src/coreclr/jit/ICorJitInfo_API_names.h | 1 + src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 17 ++- src/coreclr/jit/emit.cpp | 47 ++++--- src/coreclr/jit/emit.h | 1 + src/coreclr/jit/emitarm.cpp | 14 +- src/coreclr/jit/emitarm.h | 4 +- src/coreclr/jit/emitarm64.cpp | 2 +- src/coreclr/jit/emitarm64.h | 2 +- src/coreclr/jit/emitxarch.cpp | 120 +++++++++--------- src/coreclr/jit/emitxarch.h | 2 + .../tools/Common/JitInterface/CorInfoBase.cs | 29 ++++- .../tools/Common/JitInterface/CorInfoImpl.cs | 13 +- .../ThunkGenerator/ThunkInput.txt | 5 +- .../tools/aot/jitinterface/jitinterface.h | 22 +++- src/coreclr/vm/jitinterface.cpp | 53 ++++++-- src/coreclr/vm/jitinterface.h | 20 +-- src/coreclr/zap/zapinfo.cpp | 14 +- 24 files changed, 319 insertions(+), 147 deletions(-) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index d8f08208102782..f153d2a7a1a8dd 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1934,18 +1934,27 @@ void interceptor_ICJI::allocMem(uint32_t hotCodeSize, /* IN */ uint32_t roDataSize, /* IN */ uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ - void** hotCodeBlock, /* OUT */ - void** coldCodeBlock, /* OUT */ - void** roDataBlock /* OUT */ + void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ + void ** coldCodeBlock, /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) { mc->cr->AddCall("allocMem"); - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, - coldCodeBlock, roDataBlock); + original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, + coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); } +void interceptor_ICJI::doneWritingCode() +{ + mc->cr->AddCall("doneWritingCode"); + original_ICorJitInfo->doneWritingCode(); +} + // Reserve memory for the method/funclet's unwind information. // Note that this must be called before allocMem. It should be // called once for the main method, once for every funclet, and @@ -2101,6 +2110,7 @@ void interceptor_ICJI::recordCallSite(uint32_t instrOffset, /* IN * // A relocation is recorded if we are pre-jitting. // A jump thunk may be inserted if we are jitting void interceptor_ICJI::recordRelocation(void* location, /* IN */ + void* locationRW, /* IN */ void* target, /* IN */ uint16_t fRelocType, /* IN */ uint16_t slotNum, /* IN */ @@ -2108,7 +2118,7 @@ void interceptor_ICJI::recordRelocation(void* location, /* IN */ ) { mc->cr->AddCall("recordRelocation"); - original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); mc->cr->recRecordRelocation(location, target, fRelocType, slotNum, addlDelta); } diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index f0fa56d661dfdf..e85781de8b3abb 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1256,11 +1256,14 @@ void interceptor_ICJI::allocMem( uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, + void** hotCodeBlockRW, void** coldCodeBlock, - void** roDataBlock) + void** coldCodeBlockRW, + void** roDataBlock, + void** roDataBlockRW) { mcs->AddCall("allocMem"); - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); + original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); } void interceptor_ICJI::reserveUnwindInfo( @@ -1363,13 +1366,14 @@ void interceptor_ICJI::recordCallSite( void interceptor_ICJI::recordRelocation( void* location, + void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) { mcs->AddCall("recordRelocation"); - original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); } uint16_t interceptor_ICJI::getRelocTypeHint( @@ -1393,3 +1397,9 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } +void interceptor_ICJI::doneWritingCode() +{ + mcs->AddCall("doneWritingCode"); + original_ICorJitInfo->doneWritingCode(); +} + diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index bf1184f71cf8ca..55610a74c5c5be 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1100,10 +1100,13 @@ void interceptor_ICJI::allocMem( uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, + void** hotCodeBlockRW, void** coldCodeBlock, - void** roDataBlock) + void** coldCodeBlockRW, + void** roDataBlock, + void** roDataBlockRW) { - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); + original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); } void interceptor_ICJI::reserveUnwindInfo( @@ -1195,12 +1198,13 @@ void interceptor_ICJI::recordCallSite( void interceptor_ICJI::recordRelocation( void* location, + void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) { - original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); } uint16_t interceptor_ICJI::getRelocTypeHint( @@ -1221,3 +1225,8 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } +void interceptor_ICJI::doneWritingCode() +{ + original_ICorJitInfo->doneWritingCode(); +} + diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp index b37de9e16e6ba5..33e4781764ad34 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1606,9 +1606,12 @@ void MyICJI::allocMem(uint32_t hotCodeSize, /* IN */ uint32_t roDataSize, /* IN */ uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ - void** hotCodeBlock, /* OUT */ - void** coldCodeBlock, /* OUT */ - void** roDataBlock /* OUT */ + void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ + void ** coldCodeBlock, /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) { jitInstance->mc->cr->AddCall("allocMem"); @@ -1666,6 +1669,10 @@ void MyICJI::allocMem(uint32_t hotCodeSize, /* IN */ else *roDataBlock = nullptr; + *hotCodeBlockRW = *hotCodeBlock; + *coldCodeBlockRW = *coldCodeBlock; + *roDataBlockRW = *roDataBlock; + jitInstance->mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); } @@ -1841,6 +1848,7 @@ void MyICJI::recordCallSite(uint32_t instrOffset, /* IN */ // A relocation is recorded if we are pre-jitting. // A jump thunk may be inserted if we are jitting void MyICJI::recordRelocation(void* location, /* IN */ + void* locationRW, /* IN */ void* target, /* IN */ uint16_t fRelocType, /* IN */ uint16_t slotNum, /* IN */ @@ -1869,3 +1877,8 @@ uint32_t MyICJI::getExpectedTargetArchitecture() DWORD result = jitInstance->mc->repGetExpectedTargetArchitecture(); return result; } + +void MyICJI::doneWritingCode() +{ + jitInstance->mc->cr->AddCall("doneWritingCode"); +} diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index aaf4dcb646f11a..3d7c017461744b 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -218,8 +218,11 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ void ** coldCodeBlock, /* OUT */ - void ** roDataBlock /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) = 0; // Reserve memory for the method/funclet's unwind information. @@ -430,6 +433,7 @@ class ICorJitInfo : public ICorDynamicInfo // A jump thunk may be inserted if we are jitting virtual void recordRelocation( void * location, /* IN */ + void * locationRW, /* IN */ void * target, /* IN */ uint16_t fRelocType, /* IN */ uint16_t slotNum = 0, /* IN */ @@ -452,6 +456,9 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a version number for the CORJIT_FLAGS value. */ ) = 0; + + // Notify the EE that JIT is done writing to the memory allocated for code + virtual void doneWritingCode() = 0; }; /**********************************************************************************/ diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index ae03ef525fe79d..7f8e5a78985cb1 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -641,8 +641,11 @@ void allocMem( uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, + void** hotCodeBlockRW, void** coldCodeBlock, - void** roDataBlock) override; + void** coldCodeBlockRW, + void** roDataBlock, + void** roDataBlockRW) override; void reserveUnwindInfo( bool isFunclet, @@ -700,6 +703,7 @@ void recordCallSite( void recordRelocation( void* location, + void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, @@ -714,6 +718,8 @@ uint32_t getJitFlags( CORJIT_FLAGS* flags, uint32_t sizeInBytes) override; +void doneWritingCode() override; + /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index b32d0edef000b8..1ae07e2b634430 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,13 +43,14 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 12234eca-dfc2-48bc-a320-6155cf25ce17 */ - 0x12234eca, - 0xdfc2, - 0x48bc, - {0xa3, 0x20, 0x61, 0x55, 0xcf, 0x25, 0xce, 0x17} +constexpr GUID JITEEVersionIdentifier = { /* 529be99f-ce88-426e-a099-7528a691226c */ + 0x529be99f, + 0xce88, + 0x426e, + { 0xa0, 0x99, 0x75, 0x28, 0xa6, 0x91, 0x22, 0x6c } }; + ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // END JITEEVersionIdentifier diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 5588f234a2c06e..f396182d9c996f 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -176,5 +176,6 @@ DEF_CLR_API(recordRelocation) DEF_CLR_API(getRelocTypeHint) DEF_CLR_API(getExpectedTargetArchitecture) DEF_CLR_API(getJitFlags) +DEF_CLR_API(doneWritingCode) #undef DEF_CLR_API diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 42109b1883be3c..7ce287d78ccb84 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1532,11 +1532,14 @@ void WrapICorJitInfo::allocMem( uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, + void** hotCodeBlockRW, void** coldCodeBlock, - void** roDataBlock) + void** coldCodeBlockRW, + void** roDataBlock, + void** roDataBlockRW) { API_ENTER(allocMem); - wrapHnd->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); + wrapHnd->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); API_LEAVE(allocMem); } @@ -1656,13 +1659,14 @@ void WrapICorJitInfo::recordCallSite( void WrapICorJitInfo::recordRelocation( void* location, + void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) { API_ENTER(recordRelocation); - wrapHnd->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + wrapHnd->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); API_LEAVE(recordRelocation); } @@ -1693,6 +1697,13 @@ uint32_t WrapICorJitInfo::getJitFlags( return temp; } +void WrapICorJitInfo::doneWritingCode() +{ + API_ENTER(doneWritingCode); + wrapHnd->doneWritingCode(); + API_LEAVE(doneWritingCode); +} + /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index b485b0f90cf214..5062743885aa37 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -5355,8 +5355,11 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, #endif BYTE* consBlock; + BYTE* consBlockRW; BYTE* codeBlock; + BYTE* codeBlockRW; BYTE* coldCodeBlock; + BYTE* coldCodeBlockRW; BYTE* cp; assert(emitCurIG == nullptr); @@ -5530,13 +5533,13 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); } emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0, - xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock); + xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; #else emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag, - (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock); + (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); #endif #ifdef DEBUG @@ -5762,6 +5765,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, /* Issue all instruction groups in order */ cp = codeBlock; + writeableOffset = codeBlockRW - codeBlock; #define DEFAULT_CODE_BUFFER_INIT 0xcc @@ -5779,6 +5783,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, assert(coldCodeBlock); cp = coldCodeBlock; + writeableOffset = coldCodeBlockRW - coldCodeBlock; #ifdef DEBUG if (emitComp->opts.disAsm || emitComp->verbose) { @@ -6065,11 +6070,11 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, // Patch Forward Short Jump CLANG_FORMAT_COMMENT_ANCHOR; #if defined(TARGET_XARCH) - *(BYTE*)adr -= (BYTE)adj; + *(BYTE*)(adr + writeableOffset) -= (BYTE)adj; #elif defined(TARGET_ARM) // The following works because the jump offset is in the low order bits of the instruction. // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps? - *(short int*)adr -= (short)adj; + *(short int*)(adr + writeableOffset) -= (short)adj; #elif defined(TARGET_ARM64) assert(!jmp->idAddr()->iiaHasInstrCount()); emitOutputLJ(NULL, adr, jmp); @@ -6082,7 +6087,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, // Patch Forward non-Short Jump CLANG_FORMAT_COMMENT_ANCHOR; #if defined(TARGET_XARCH) - *(int*)adr -= adj; + *(int*)(adr + writeableOffset) -= adj; #elif defined(TARGET_ARMARCH) assert(!jmp->idAddr()->iiaHasInstrCount()); emitOutputLJ(NULL, adr, jmp); @@ -6117,10 +6122,12 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, JITDUMP("Allocated method code size = %4u , actual size = %4u, unused size = %4u\n", emitTotalCodeSize, actualCodeSize, unusedSize); + BYTE* cpRW = cp + writeableOffset; for (unsigned i = 0; i < unusedSize; ++i) { - *cp++ = DEFAULT_CODE_BUFFER_INIT; + *cpRW++ = DEFAULT_CODE_BUFFER_INIT; } + cp = cpRW - writeableOffset; assert(emitTotalCodeSize == emitCurCodeOffs(cp)); // Total code size is sum of all IG->size and doesn't include padding in the last IG. @@ -6151,6 +6158,11 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, // Assign the real prolog size *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos); + // Ensure that any attempt to write code after this point will fail + writeableOffset = 0; + // Notify the EE that all code was written. It can switch off writeable code memory. + emitCmpHandle->doneWritingCode(); + /* Return the amount of code we've generated */ return actualCodeSize; @@ -6641,7 +6653,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0); size_t numElems = dscSize / TARGET_POINTER_SIZE; - target_size_t* bDst = (target_size_t*)dst; + target_size_t* bDst = (target_size_t*)(dst + writeableOffset); for (unsigned i = 0; i < numElems; i++) { BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i]; @@ -6670,7 +6682,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize); size_t numElems = dscSize / 4; - unsigned* uDst = (unsigned*)dst; + unsigned* uDst = (unsigned*)(dst + writeableOffset); insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB); for (unsigned i = 0; i < numElems; i++) @@ -6691,7 +6703,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) // Simple binary data: copy the bytes to the target assert(dsc->dsType == dataSection::data); - memcpy(dst, dsc->dsCont, dscSize); + memcpy(dst + writeableOffset, dsc->dsCont, dscSize); #ifdef DEBUG if (EMITVERBOSE) @@ -7395,7 +7407,8 @@ void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr) unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val) { - *castto(dst, unsigned char*) = (unsigned char)val; + BYTE* dstRW = dst + writeableOffset; + *castto(dst + writeableOffset, unsigned char*) = (unsigned char)val; #ifdef DEBUG #ifdef TARGET_AMD64 @@ -7414,7 +7427,8 @@ unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val) unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val) { - MISALIGNED_WR_I2(dst, (short)val); + BYTE* dstRW = dst + writeableOffset; + MISALIGNED_WR_I2(dstRW, (short)val); #ifdef DEBUG #ifdef TARGET_AMD64 @@ -7433,7 +7447,8 @@ unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val) unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val) { - MISALIGNED_WR_I4(dst, (int)val); + BYTE* dstRW = dst + writeableOffset; + MISALIGNED_WR_I4(dstRW, (int)val); #ifdef DEBUG #ifdef TARGET_AMD64 @@ -7452,10 +7467,11 @@ unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val) unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val) { + BYTE* dstRW = dst + writeableOffset; #if !defined(TARGET_64BIT) - MISALIGNED_WR_I4(dst, (int)val); + MISALIGNED_WR_I4(dstRW, (int)val); #else - MISALIGNED_WR_ST(dst, val); + MISALIGNED_WR_ST(dstRW, val); #endif return TARGET_POINTER_SIZE; @@ -8447,7 +8463,8 @@ void emitter::emitRecordRelocation(void* location, /* IN */ // late disassembly; maybe we'll need it? if (emitComp->info.compMatchedVM) { - emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + void* locationRW = (BYTE*)location + writeableOffset; + emitCmpHandle->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); } #if defined(LATE_DISASM) codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target); diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 6b57f4df2ef532..d11268c54b4257 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1621,6 +1621,7 @@ class emitter BYTE* emitCodeBlock; // Hot code block BYTE* emitColdCodeBlock; // Cold code block BYTE* emitConsBlock; // Read-only (constant) data block + size_t writeableOffset; // Offset applied to a code address to get memory location that can be written UNATIVE_OFFSET emitTotalHotCodeSize; UNATIVE_OFFSET emitTotalColdCodeSize; diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 58732c476d9e19..685c17f9293815 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -5094,7 +5094,7 @@ inline unsigned insEncodeImmT2_Mov(int imm) * Emit a Thumb-1 instruction (a 16-bit integer as code) */ -/*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code) +unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code) { unsigned short word1 = code & 0xffff; assert(word1 == code); @@ -5104,7 +5104,8 @@ inline unsigned insEncodeImmT2_Mov(int imm) assert(top5bits < 29); #endif - MISALIGNED_WR_I2(dst, word1); + BYTE* dstRW = dst + writeableOffset; + MISALIGNED_WR_I2(dstRW, word1); return sizeof(short); } @@ -5113,7 +5114,7 @@ inline unsigned insEncodeImmT2_Mov(int imm) * Emit a Thumb-2 instruction (two 16-bit integers as code) */ -/*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code) +unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code) { unsigned short word1 = (code >> 16) & 0xffff; unsigned short word2 = (code)&0xffff; @@ -5124,9 +5125,10 @@ inline unsigned insEncodeImmT2_Mov(int imm) assert(top5bits >= 29); #endif - MISALIGNED_WR_I2(dst, word1); - dst += 2; - MISALIGNED_WR_I2(dst, word2); + BYTE* dstRW = dst + writeableOffset; + MISALIGNED_WR_I2(dstRW, word1); + dstRW += 2; + MISALIGNED_WR_I2(dstRW, word2); return sizeof(short) * 2; } diff --git a/src/coreclr/jit/emitarm.h b/src/coreclr/jit/emitarm.h index e663a953e7a10b..27e5e9b1f6b7a7 100644 --- a/src/coreclr/jit/emitarm.h +++ b/src/coreclr/jit/emitarm.h @@ -20,8 +20,8 @@ BYTE* emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode); BYTE* emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* id); BYTE* emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id); -static unsigned emitOutput_Thumb1Instr(BYTE* dst, code_t code); -static unsigned emitOutput_Thumb2Instr(BYTE* dst, code_t code); +unsigned emitOutput_Thumb1Instr(BYTE* dst, code_t code); +unsigned emitOutput_Thumb2Instr(BYTE* dst, code_t code); /************************************************************************/ /* Debug-only routines to display instructions */ diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 3a37d7e893c35e..b92802941469f2 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -10253,7 +10253,7 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) { assert(sizeof(code_t) == 4); - *((code_t*)dst) = code; + *((code_t*)(dst + writeableOffset)) = code; return sizeof(code_t); } diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index 2ab236282623cc..841f10bf297fbc 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -101,7 +101,7 @@ emitter::code_t emitInsCode(instruction ins, insFormat fmt); void emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir); // Emit the 32-bit Arm64 instruction 'code' into the 'dst' buffer -static unsigned emitOutput_Instr(BYTE* dst, code_t code); +unsigned emitOutput_Instr(BYTE* dst, code_t code); // A helper method to return the natural scale for an EA 'size' static unsigned NaturalScale_helper(emitAttr size); diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 3af1528a314740..30a1360aec50e1 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -9270,7 +9270,7 @@ void emitter::emitDispIns( * Output nBytes bytes of NOP instructions */ -static BYTE* emitOutputNOP(BYTE* dst, size_t nBytes) +BYTE* emitter::emitOutputNOP(BYTE* dstRW, size_t nBytes) { assert(nBytes <= 15); @@ -9284,49 +9284,49 @@ static BYTE* emitOutputNOP(BYTE* dst, size_t nBytes) switch (nBytes) { case 15: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 14: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 13: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 12: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 11: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 10: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 9: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 8: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 7: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 6: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 5: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 4: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 3: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 2: - *dst++ = 0x90; + *dstRW++ = 0x90; FALLTHROUGH; case 1: - *dst++ = 0x90; + *dstRW++ = 0x90; break; case 0: break; @@ -9335,82 +9335,82 @@ static BYTE* emitOutputNOP(BYTE* dst, size_t nBytes) switch (nBytes) { case 2: - *dst++ = 0x66; + *dstRW++ = 0x66; FALLTHROUGH; case 1: - *dst++ = 0x90; + *dstRW++ = 0x90; break; case 0: break; case 3: - *dst++ = 0x0F; - *dst++ = 0x1F; - *dst++ = 0x00; + *dstRW++ = 0x0F; + *dstRW++ = 0x1F; + *dstRW++ = 0x00; break; case 4: - *dst++ = 0x0F; - *dst++ = 0x1F; - *dst++ = 0x40; - *dst++ = 0x00; + *dstRW++ = 0x0F; + *dstRW++ = 0x1F; + *dstRW++ = 0x40; + *dstRW++ = 0x00; break; case 6: - *dst++ = 0x66; + *dstRW++ = 0x66; FALLTHROUGH; case 5: - *dst++ = 0x0F; - *dst++ = 0x1F; - *dst++ = 0x44; - *dst++ = 0x00; - *dst++ = 0x00; + *dstRW++ = 0x0F; + *dstRW++ = 0x1F; + *dstRW++ = 0x44; + *dstRW++ = 0x00; + *dstRW++ = 0x00; break; case 7: - *dst++ = 0x0F; - *dst++ = 0x1F; - *dst++ = 0x80; - *dst++ = 0x00; - *dst++ = 0x00; - *dst++ = 0x00; - *dst++ = 0x00; + *dstRW++ = 0x0F; + *dstRW++ = 0x1F; + *dstRW++ = 0x80; + *dstRW++ = 0x00; + *dstRW++ = 0x00; + *dstRW++ = 0x00; + *dstRW++ = 0x00; break; case 15: // More than 3 prefixes is slower than just 2 NOPs - dst = emitOutputNOP(emitOutputNOP(dst, 7), 8); + dstRW = emitOutputNOP(emitOutputNOP(dstRW, 7), 8); break; case 14: // More than 3 prefixes is slower than just 2 NOPs - dst = emitOutputNOP(emitOutputNOP(dst, 7), 7); + dstRW = emitOutputNOP(emitOutputNOP(dstRW, 7), 7); break; case 13: // More than 3 prefixes is slower than just 2 NOPs - dst = emitOutputNOP(emitOutputNOP(dst, 5), 8); + dstRW = emitOutputNOP(emitOutputNOP(dstRW, 5), 8); break; case 12: // More than 3 prefixes is slower than just 2 NOPs - dst = emitOutputNOP(emitOutputNOP(dst, 4), 8); + dstRW = emitOutputNOP(emitOutputNOP(dstRW, 4), 8); break; case 11: - *dst++ = 0x66; + *dstRW++ = 0x66; FALLTHROUGH; case 10: - *dst++ = 0x66; + *dstRW++ = 0x66; FALLTHROUGH; case 9: - *dst++ = 0x66; + *dstRW++ = 0x66; FALLTHROUGH; case 8: - *dst++ = 0x0F; - *dst++ = 0x1F; - *dst++ = 0x84; - *dst++ = 0x00; - *dst++ = 0x00; - *dst++ = 0x00; - *dst++ = 0x00; - *dst++ = 0x00; + *dstRW++ = 0x0F; + *dstRW++ = 0x1F; + *dstRW++ = 0x84; + *dstRW++ = 0x00; + *dstRW++ = 0x00; + *dstRW++ = 0x00; + *dstRW++ = 0x00; + *dstRW++ = 0x00; break; } #endif // TARGET_AMD64 - return dst; + return dstRW; } //-------------------------------------------------------------------- @@ -9454,7 +9454,9 @@ BYTE* emitter::emitOutputAlign(insGroup* ig, instrDesc* id, BYTE* dst) emitComp->loopsAligned++; #endif - return emitOutputNOP(dst, paddingToAdd); + BYTE* dstRW = dst + writeableOffset; + dstRW = emitOutputNOP(dstRW, paddingToAdd); + return dstRW - writeableOffset; } /***************************************************************************** @@ -12775,7 +12777,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) if (ins == INS_nop) { - dst = emitOutputNOP(dst, id->idCodeSize()); + BYTE* dstRW = dst + writeableOffset; + dstRW = emitOutputNOP(dstRW, id->idCodeSize()); + dst = dstRW - writeableOffset; break; } @@ -13897,7 +13901,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } #endif - dst = emitOutputNOP(dst, diff); + BYTE* dstRW = dst + writeableOffset; + dstRW = emitOutputNOP(dstRW, diff); + dst = dstRW - writeableOffset; } assert((id->idCodeSize() - ((UNATIVE_OFFSET)(dst - *dp))) == 0); } diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index af8dffc3012084..fb22cb0e7de87b 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -240,6 +240,8 @@ ssize_t emitGetInsAmdCns(instrDesc* id, CnsVal* cv); void emitGetInsDcmCns(instrDesc* id, CnsVal* cv); ssize_t emitGetInsAmdAny(instrDesc* id); +BYTE* emitOutputNOP(BYTE* dstRW, size_t nBytes); + /************************************************************************/ /* Private helpers for instruction output */ /************************************************************************/ diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index d8b1857b943c2e..8cb1e49e0afa94 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2317,12 +2317,12 @@ static byte _notifyInstructionSetUsage(IntPtr thisHandle, IntPtr* ppException, I } [UnmanagedCallersOnly] - static void _allocMem(IntPtr thisHandle, IntPtr* ppException, uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock) + static void _allocMem(IntPtr thisHandle, IntPtr* ppException, uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW) { var _this = GetThis(thisHandle); try { - _this.allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, ref *hotCodeBlock, ref *coldCodeBlock, ref *roDataBlock); + _this.allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, ref *hotCodeBlock, ref *hotCodeBlockRW, ref *coldCodeBlock, ref *coldCodeBlockRW, ref *roDataBlock, ref *roDataBlockRW); } catch (Exception ex) { @@ -2490,12 +2490,12 @@ static void _recordCallSite(IntPtr thisHandle, IntPtr* ppException, uint instrOf } [UnmanagedCallersOnly] - static void _recordRelocation(IntPtr thisHandle, IntPtr* ppException, void* location, void* target, ushort fRelocType, ushort slotNum, int addlDelta) + static void _recordRelocation(IntPtr thisHandle, IntPtr* ppException, void* location, void* locationRW, void* target, ushort fRelocType, ushort slotNum, int addlDelta) { var _this = GetThis(thisHandle); try { - _this.recordRelocation(location, target, fRelocType, slotNum, addlDelta); + _this.recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); } catch (Exception ex) { @@ -2548,10 +2548,24 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_FLAGS* f } } + [UnmanagedCallersOnly] + static void _doneWritingCode(IntPtr thisHandle, IntPtr* ppException) + { + var _this = GetThis(thisHandle); + try + { + _this.doneWritingCode(); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + } + } + static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); callbacks[0] = (delegate* unmanaged)&_isJitIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2709,7 +2723,7 @@ static IntPtr GetUnmanagedCallbacks() callbacks[153] = (delegate* unmanaged)&_getTailCallHelpers; callbacks[154] = (delegate* unmanaged)&_convertPInvokeCalliToCall; callbacks[155] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[156] = (delegate* unmanaged)&_allocMem; + callbacks[156] = (delegate* unmanaged)&_allocMem; callbacks[157] = (delegate* unmanaged)&_reserveUnwindInfo; callbacks[158] = (delegate* unmanaged)&_allocUnwindInfo; callbacks[159] = (delegate* unmanaged)&_allocGCInfo; @@ -2721,10 +2735,11 @@ static IntPtr GetUnmanagedCallbacks() callbacks[165] = (delegate* unmanaged)&_getPgoInstrumentationResults; callbacks[166] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; callbacks[167] = (delegate* unmanaged)&_recordCallSite; - callbacks[168] = (delegate* unmanaged)&_recordRelocation; + callbacks[168] = (delegate* unmanaged)&_recordRelocation; callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; callbacks[171] = (delegate* unmanaged)&_getJitFlags; + callbacks[172] = (delegate* unmanaged)&_doneWritingCode; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 396769e2eb53e5..93f252118459ba 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3066,12 +3066,20 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI private byte[] _gcInfo; private CORINFO_EH_CLAUSE[] _ehClauses; - private void allocMem(uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, ref void* hotCodeBlock, ref void* coldCodeBlock, ref void* roDataBlock) + private void doneWritingCode() + { + } + + private void allocMem(uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, ref void* hotCodeBlock, ref void* hotCodeBlockRW, ref void* coldCodeBlock, ref void* coldCodeBlockRW, ref void* roDataBlock, ref void* roDataBlockRW) { hotCodeBlock = (void*)GetPin(_code = new byte[hotCodeSize]); + hotCodeBlockRW = hotCodeBlock; if (coldCodeSize != 0) + { coldCodeBlock = (void*)GetPin(_coldCode = new byte[coldCodeSize]); + coldCodeBlockRW = coldCodeBlock; + } _codeAlignment = -1; if ((flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) @@ -3105,6 +3113,7 @@ private void allocMem(uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint _roDataBlob = new MethodReadOnlyDataNode(MethodBeingCompiled); roDataBlock = (void*)GetPin(_roData); + roDataBlockRW = roDataBlock; } if (_numFrameInfos > 0) @@ -3280,7 +3289,7 @@ private static RelocType GetRelocType(TargetArchitecture targetArchitecture, ush }; } - private void recordRelocation(void* location, void* target, ushort fRelocType, ushort slotNum, int addlDelta) + private void recordRelocation(void* location, void* locationRW, void* target, ushort fRelocType, ushort slotNum, int addlDelta) { // slotNum is not used Debug.Assert(slotNum == 0); diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index c623119840327a..a39d22ae6fd75d 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -306,7 +306,7 @@ FUNCTIONS bool getTailCallHelpers(CORINFO_RESOLVED_TOKEN* callToken, CORINFO_SIG_INFO* sig, CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, CORINFO_TAILCALL_HELPERS* pResult); bool convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool mustConvert); bool notifyInstructionSetUsage(CORINFO_InstructionSet instructionSet,bool supportEnabled); - void allocMem( uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock ); + void allocMem( uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW ); void reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) void allocUnwindInfo(uint8_t* pHotCode, uint8_t* pColdCode, uint32_t startOffset, uint32_t endOffset, uint32_t unwindSize, uint8_t* pUnwindBlock, CorJitFuncKind funcKind) void* allocGCInfo(size_t size) @@ -318,8 +318,9 @@ FUNCTIONS JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData) JITINTERFACE_HRESULT allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData) void recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle) - void recordRelocation(void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) + void recordRelocation(void* location, void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) uint16_t getRelocTypeHint(void* target) uint32_t getExpectedTargetArchitecture() uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes) + void doneWritingCode() diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 3520b7f9484a0b..3d803fa1ca4c59 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -167,7 +167,7 @@ struct JitInterfaceCallbacks bool (* getTailCallHelpers)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* callToken, CORINFO_SIG_INFO* sig, CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, CORINFO_TAILCALL_HELPERS* pResult); bool (* convertPInvokeCalliToCall)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool mustConvert); bool (* notifyInstructionSetUsage)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_InstructionSet instructionSet, bool supportEnabled); - void (* allocMem)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock); + void (* allocMem)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW); void (* reserveUnwindInfo)(void * thisHandle, CorInfoExceptionClass** ppException, bool isFunclet, bool isColdCode, uint32_t unwindSize); void (* allocUnwindInfo)(void * thisHandle, CorInfoExceptionClass** ppException, uint8_t* pHotCode, uint8_t* pColdCode, uint32_t startOffset, uint32_t endOffset, uint32_t unwindSize, uint8_t* pUnwindBlock, CorJitFuncKind funcKind); void* (* allocGCInfo)(void * thisHandle, CorInfoExceptionClass** ppException, size_t size); @@ -179,10 +179,11 @@ struct JitInterfaceCallbacks JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData); JITINTERFACE_HRESULT (* allocPgoInstrumentationBySchema)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData); void (* recordCallSite)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle); - void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta); + void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta); uint16_t (* getRelocTypeHint)(void * thisHandle, CorInfoExceptionClass** ppException, void* target); uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException); uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes); + void (* doneWritingCode)(void * thisHandle, CorInfoExceptionClass** ppException); }; @@ -1701,11 +1702,14 @@ class JitInterfaceWrapper : public ICorJitInfo uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, + void** hotCodeBlockRW, void** coldCodeBlock, - void** roDataBlock) + void** coldCodeBlockRW, + void** roDataBlock, + void** roDataBlockRW) { CorInfoExceptionClass* pException = nullptr; - _callbacks->allocMem(_thisHandle, &pException, hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); + _callbacks->allocMem(_thisHandle, &pException, hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); if (pException != nullptr) throw pException; } @@ -1825,13 +1829,14 @@ class JitInterfaceWrapper : public ICorJitInfo virtual void recordRelocation( void* location, + void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) { CorInfoExceptionClass* pException = nullptr; - _callbacks->recordRelocation(_thisHandle, &pException, location, target, fRelocType, slotNum, addlDelta); + _callbacks->recordRelocation(_thisHandle, &pException, location, locationRW, target, fRelocType, slotNum, addlDelta); if (pException != nullptr) throw pException; } @@ -1861,4 +1866,11 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; return temp; } + + virtual void doneWritingCode() +{ + CorInfoExceptionClass* pException = nullptr; + _callbacks->doneWritingCode(_thisHandle, &pException); + if (pException != nullptr) throw pException; +} }; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index f629b76991001a..61cb01d019520e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11153,7 +11153,7 @@ void CEEJitInfo::BackoutJitData(EEJitManager * jitMgr) GC_TRIGGERS; } CONTRACTL_END; - CodeHeader* pCodeHeader = GetCodeHeader(); + CodeHeader* pCodeHeader = m_CodeHeader; if (pCodeHeader) jitMgr->RemoveJitData(pCodeHeader, m_GCinfo_len, m_EHinfo_len); } @@ -11276,7 +11276,7 @@ void CEEJitInfo::CompressDebugInfo() NULL, m_pMethodBeingCompiled->GetLoaderAllocator()->GetLowFrequencyHeap()); - GetCodeHeader()->SetDebugInfo(pDebugInfo); + m_CodeHeader->SetDebugInfo(pDebugInfo); } EX_CATCH { @@ -11551,6 +11551,7 @@ void CEEJitInfo::recordCallSite(uint32_t instrOffset, // A jump thunk may be inserted if we are jitting void CEEJitInfo::recordRelocation(void * location, + void * locationRW, void * target, WORD fRelocType, WORD slot, @@ -11571,7 +11572,7 @@ void CEEJitInfo::recordRelocation(void * location, { case IMAGE_REL_BASED_DIR64: // Write 64-bits into location - *((UINT64 *) ((BYTE *) location + slot)) = (UINT64) target; + *((UINT64 *) ((BYTE *) locationRW + slot)) = (UINT64) target; break; #ifdef TARGET_AMD64 @@ -11580,6 +11581,7 @@ void CEEJitInfo::recordRelocation(void * location, target = (BYTE *)target + addlDelta; INT32 * fixupLocation = (INT32 *) ((BYTE *) location + slot); + INT32 * fixupLocationRW = (INT32 *) ((BYTE *) locationRW + slot); BYTE * baseAddr = (BYTE *)fixupLocation + sizeof(INT32); delta = (INT64)((BYTE *)target - baseAddr); @@ -11625,7 +11627,7 @@ void CEEJitInfo::recordRelocation(void * location, DBG_ADDR(fixupLocation), DBG_ADDR(target), addlDelta, delta)); // Write the 32-bits pc-relative delta into location - *fixupLocation = (INT32) delta; + *fixupLocationRW = (INT32) delta; } break; #endif // TARGET_AMD64 @@ -11640,6 +11642,7 @@ void CEEJitInfo::recordRelocation(void * location, _ASSERTE((branchTarget & 0x3) == 0); // the low two bits must be zero PCODE fixupLocation = (PCODE) location; + PCODE fixupLocationRW = (PCODE) locationRW; _ASSERTE((fixupLocation & 0x3) == 0); // the low two bits must be zero delta = (INT64)(branchTarget - fixupLocation); @@ -11703,7 +11706,7 @@ void CEEJitInfo::recordRelocation(void * location, _ASSERTE(FitsInRel28(delta)); - PutArm64Rel28((UINT32*) fixupLocation, (INT32)delta); + PutArm64Rel28((UINT32*) fixupLocationRW, (INT32)delta); } break; @@ -11717,7 +11720,7 @@ void CEEJitInfo::recordRelocation(void * location, INT64 locationPage = (INT64)location & 0xFFFFFFFFFFFFF000LL; INT64 relPage = (INT64)(targetPage - locationPage); INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF; - PutArm64Rel21((UINT32 *)location, imm21); + PutArm64Rel21((UINT32 *)locationRW, imm21); } break; @@ -11728,7 +11731,7 @@ void CEEJitInfo::recordRelocation(void * location, // Write the 12 bits page offset into location. INT32 imm12 = (INT32)(SIZE_T)target & 0xFFFLL; - PutArm64Rel12((UINT32 *)location, imm12); + PutArm64Rel12((UINT32 *)locationRW, imm12); } break; @@ -12148,8 +12151,11 @@ void CEEJitInfo::allocMem ( uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ void ** coldCodeBlock, /* OUT */ - void ** roDataBlock /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) { CONTRACTL { @@ -12168,6 +12174,7 @@ void CEEJitInfo::allocMem ( ULONG codeSize = hotCodeSize; void **codeBlock = hotCodeBlock; + void **codeBlockRW = hotCodeBlockRW; S_SIZE_T totalSize = S_SIZE_T(codeSize); @@ -12249,17 +12256,20 @@ void CEEJitInfo::allocMem ( BYTE* current = (BYTE *)m_CodeHeader->GetCodeStartAddress(); *codeBlock = current; + *codeBlockRW = current; current += codeSize; if (roDataSize > 0) { current = (BYTE *)ALIGN_UP(current, roDataAlignment); *roDataBlock = current; + *roDataBlockRW = current; current += roDataSize; } else { *roDataBlock = NULL; + *roDataBlockRW = NULL; } #ifdef FEATURE_EH_FUNCLETS @@ -12413,6 +12423,21 @@ void CEEJitInfo::getEHinfo( EE_TO_JIT_TRANSITION(); } + +void CEEJitInfo::doneWritingCode() +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + JIT_TO_EE_TRANSITION(); + + EE_TO_JIT_TRANSITION(); +} + + #endif // CROSSGEN_COMPILE #if defined(CROSSGEN_COMPILE) @@ -14245,14 +14270,23 @@ void CEEInfo::allocMem ( uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ void ** coldCodeBlock, /* OUT */ - void ** roDataBlock /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) { LIMITED_METHOD_CONTRACT; UNREACHABLE(); // only called on derived class. } +void CEEInfo::doneWritingCode () +{ + LIMITED_METHOD_CONTRACT; + UNREACHABLE(); // only called on derived class. +} + void CEEInfo::reserveUnwindInfo ( bool isFunclet, /* IN */ bool isColdCode, /* IN */ @@ -14402,6 +14436,7 @@ void CEEInfo::recordCallSite( void CEEInfo::recordRelocation( void * location, /* IN */ + void * locationRW, /* IN */ void * target, /* IN */ WORD fRelocType, /* IN */ WORD slotNum, /* IN */ diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index bddc24fc4c3dfd..1ed3db99bf624d 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -643,8 +643,11 @@ class CEEJitInfo : public CEEInfo uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ void ** coldCodeBlock, /* OUT */ - void ** roDataBlock /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) override final; void reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) override final; @@ -673,6 +676,8 @@ class CEEJitInfo : public CEEInfo CORINFO_EH_CLAUSE* clause /* OUT */ ) override final; + void doneWritingCode() override final; + HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, /* IN */ PgoInstrumentationSchema* pSchema, /* IN/OUT */ @@ -695,6 +700,7 @@ class CEEJitInfo : public CEEInfo void recordRelocation( void *location, + void *locationRW, void *target, uint16_t fRelocType, uint16_t slot, @@ -704,18 +710,6 @@ class CEEJitInfo : public CEEInfo uint32_t getExpectedTargetArchitecture() override final; - CodeHeader* GetCodeHeader() - { - LIMITED_METHOD_CONTRACT; - return m_CodeHeader; - } - - void SetCodeHeader(CodeHeader* pValue) - { - LIMITED_METHOD_CONTRACT; - m_CodeHeader = pValue; - } - void ResetForJitRetry() { CONTRACTL { diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp index de7b6688ffde17..ddbf17921777dc 100644 --- a/src/coreclr/zap/zapinfo.cpp +++ b/src/coreclr/zap/zapinfo.cpp @@ -1145,8 +1145,11 @@ void ZapInfo::allocMem( uint32_t xcptnsCount, /* IN */ CorJitAllocMemFlag flag, /* IN */ void ** hotCodeBlock, /* OUT */ + void ** hotCodeBlockRW, /* OUT */ void ** coldCodeBlock, /* OUT */ - void ** roDataBlock /* OUT */ + void ** coldCodeBlockRW,/* OUT */ + void ** roDataBlock, /* OUT */ + void ** roDataBlockRW /* OUT */ ) { bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); @@ -1157,6 +1160,7 @@ void ZapInfo::allocMem( m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, hotCodeSize, align); *hotCodeBlock = m_pCode->GetData(); + *hotCodeBlockRW = m_pCode->GetData(); if (coldCodeSize != 0) { @@ -1164,6 +1168,7 @@ void ZapInfo::allocMem( m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, coldCodeSize, align); *coldCodeBlock = m_pColdCode->GetData(); + *coldCodeBlockRW = m_pColdCode->GetData(); } // @@ -1186,6 +1191,7 @@ void ZapInfo::allocMem( } m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, roDataSize, align); *roDataBlock = m_pROData->GetData(); + *roDataBlockRW = m_pROData->GetData(); } if (m_pImage->m_stats) @@ -2803,7 +2809,7 @@ void ZapInfo::recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO *callSig, CO return; } -void ZapInfo::recordRelocation(void *location, void *target, +void ZapInfo::recordRelocation(void *location, void *locationRW, void *target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) { // Factor slotNum into the location address @@ -4126,6 +4132,10 @@ bool ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig); } +void ZapInfo::doneWritingCode() +{ +} + LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void ** ppIndirection) { From d325732888beeb5983673f0ae1d2d36b7e675a54 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 11 May 2021 21:50:57 +0200 Subject: [PATCH 2/6] Apply JIT formatting patch --- src/coreclr/jit/emit.cpp | 10 ++++++---- src/coreclr/jit/emit.h | 8 ++++---- src/coreclr/jit/emitxarch.cpp | 10 +++++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 5062743885aa37..1287acc9a506ee 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -5533,13 +5533,15 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); } emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0, - xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); + xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, + (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; #else emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag, - (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); + (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, + (void**)&consBlock, (void**)&consBlockRW); #endif #ifdef DEBUG @@ -5764,7 +5766,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, #endif /* Issue all instruction groups in order */ - cp = codeBlock; + cp = codeBlock; writeableOffset = codeBlockRW - codeBlock; #define DEFAULT_CODE_BUFFER_INIT 0xcc @@ -5782,7 +5784,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, assert(emitCurCodeOffs(cp) == emitTotalHotCodeSize); assert(coldCodeBlock); - cp = coldCodeBlock; + cp = coldCodeBlock; writeableOffset = coldCodeBlockRW - coldCodeBlock; #ifdef DEBUG if (emitComp->opts.disAsm || emitComp->verbose) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index d11268c54b4257..666201fc98bf00 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1618,10 +1618,10 @@ class emitter bool emitIssuing; #endif - BYTE* emitCodeBlock; // Hot code block - BYTE* emitColdCodeBlock; // Cold code block - BYTE* emitConsBlock; // Read-only (constant) data block - size_t writeableOffset; // Offset applied to a code address to get memory location that can be written + BYTE* emitCodeBlock; // Hot code block + BYTE* emitColdCodeBlock; // Cold code block + BYTE* emitConsBlock; // Read-only (constant) data block + size_t writeableOffset; // Offset applied to a code address to get memory location that can be written UNATIVE_OFFSET emitTotalHotCodeSize; UNATIVE_OFFSET emitTotalColdCodeSize; diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 30a1360aec50e1..0b9a647a0ec7a2 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -9455,7 +9455,7 @@ BYTE* emitter::emitOutputAlign(insGroup* ig, instrDesc* id, BYTE* dst) #endif BYTE* dstRW = dst + writeableOffset; - dstRW = emitOutputNOP(dstRW, paddingToAdd); + dstRW = emitOutputNOP(dstRW, paddingToAdd); return dstRW - writeableOffset; } @@ -12778,8 +12778,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) if (ins == INS_nop) { BYTE* dstRW = dst + writeableOffset; - dstRW = emitOutputNOP(dstRW, id->idCodeSize()); - dst = dstRW - writeableOffset; + dstRW = emitOutputNOP(dstRW, id->idCodeSize()); + dst = dstRW - writeableOffset; break; } @@ -13902,8 +13902,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) #endif BYTE* dstRW = dst + writeableOffset; - dstRW = emitOutputNOP(dstRW, diff); - dst = dstRW - writeableOffset; + dstRW = emitOutputNOP(dstRW, diff); + dst = dstRW - writeableOffset; } assert((id->idCodeSize() - ((UNATIVE_OFFSET)(dst - *dp))) == 0); } From 26bdeefd28765e04b405b52a01cc9c28c7668460 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 12 May 2021 10:55:49 +0200 Subject: [PATCH 3/6] Reflect PR feedback * Change signature of allocMem to pass everything in a single structure * Extract code writing part of the emitEndCodeGen to a separate method and wrap the call to it in eeRunWithErrorTrap --- .../superpmi-shim-collector/icorjitinfo.cpp | 20 +- .../superpmi-shim-counter/icorjitinfo.cpp | 14 +- .../superpmi-shim-simple/icorjitinfo.cpp | 16 +- .../ToolBox/superpmi/superpmi/icorjitinfo.cpp | 55 +- src/coreclr/inc/corjit.h | 30 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 12 +- src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 14 +- src/coreclr/jit/emit.cpp | 562 +++++++++++------- src/coreclr/jit/emit.h | 9 + .../tools/Common/JitInterface/CorInfoBase.cs | 6 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 30 +- .../tools/Common/JitInterface/CorInfoTypes.cs | 19 + .../ThunkGenerator/ThunkInput.txt | 4 +- .../tools/aot/jitinterface/jitinterface.h | 20 +- src/coreclr/vm/jitinterface.cpp | 70 +-- src/coreclr/vm/jitinterface.h | 14 +- src/coreclr/zap/zapinfo.cpp | 62 +- 17 files changed, 487 insertions(+), 470 deletions(-) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index f153d2a7a1a8dd..c892fdd004beb8 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1929,24 +1929,12 @@ bool interceptor_ICJI::runWithErrorTrap(void (*function)(void*), void* param) } // get a block of memory for the code, readonly data, and read-write data -void interceptor_ICJI::allocMem(uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) +void interceptor_ICJI::allocMem(AllocMemArgs *pArgs) { mc->cr->AddCall("allocMem"); - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, - coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); - mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, - roDataBlock); + original_ICorJitInfo->allocMem(pArgs); + mc->cr->recAllocMem(pArgs->hotCodeSize, pArgs->coldCodeSize, pArgs->roDataSize, pArgs->xcptnsCount, pArgs->flag, &pArgs->hotCodeBlock, &pArgs->coldCodeBlock, + &pArgs->roDataBlock); } void interceptor_ICJI::doneWritingCode() diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index e85781de8b3abb..1eb7da0bd02501 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1250,20 +1250,10 @@ bool interceptor_ICJI::notifyInstructionSetUsage( } void interceptor_ICJI::allocMem( - uint32_t hotCodeSize, - uint32_t coldCodeSize, - uint32_t roDataSize, - uint32_t xcptnsCount, - CorJitAllocMemFlag flag, - void** hotCodeBlock, - void** hotCodeBlockRW, - void** coldCodeBlock, - void** coldCodeBlockRW, - void** roDataBlock, - void** roDataBlockRW) + AllocMemArgs* pArgs) { mcs->AddCall("allocMem"); - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); + original_ICorJitInfo->allocMem(pArgs); } void interceptor_ICJI::reserveUnwindInfo( diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 55610a74c5c5be..a46ad17ec157c8 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1094,19 +1094,9 @@ bool interceptor_ICJI::notifyInstructionSetUsage( } void interceptor_ICJI::allocMem( - uint32_t hotCodeSize, - uint32_t coldCodeSize, - uint32_t roDataSize, - uint32_t xcptnsCount, - CorJitAllocMemFlag flag, - void** hotCodeBlock, - void** hotCodeBlockRW, - void** coldCodeBlock, - void** coldCodeBlockRW, - void** roDataBlock, - void** roDataBlockRW) -{ - original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); + AllocMemArgs* pArgs) +{ + original_ICorJitInfo->allocMem(pArgs); } void interceptor_ICJI::reserveUnwindInfo( diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 33e4781764ad34..8aec03677c6059 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1601,57 +1601,46 @@ static void* ALIGN_UP_SPMI(void* val, size_t alignment) } // get a block of memory for the code, readonly data, and read-write data -void MyICJI::allocMem(uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) +void MyICJI::allocMem(AllocMemArgs* pArgs) { jitInstance->mc->cr->AddCall("allocMem"); // TODO-Cleanup: Could hot block size be ever 0? size_t codeAlignment = sizeof(void*); - size_t hotCodeAlignedSize = static_cast(hotCodeSize); + size_t hotCodeAlignedSize = static_cast(pArgs->hotCodeSize); - if ((flag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) + if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) { codeAlignment = 32; } - else if ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) + else if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) { codeAlignment = 16; } hotCodeAlignedSize = ALIGN_UP_SPMI(hotCodeAlignedSize, codeAlignment); hotCodeAlignedSize = hotCodeAlignedSize + (codeAlignment - sizeof(void*)); - *hotCodeBlock = jitInstance->mc->cr->allocateMemory(hotCodeAlignedSize); - *hotCodeBlock = ALIGN_UP_SPMI(*hotCodeBlock, codeAlignment); + pArgs->hotCodeBlock = jitInstance->mc->cr->allocateMemory(hotCodeAlignedSize); + pArgs->hotCodeBlock = ALIGN_UP_SPMI(pArgs->hotCodeBlock, codeAlignment); - if (coldCodeSize > 0) - *coldCodeBlock = jitInstance->mc->cr->allocateMemory(coldCodeSize); + if (pArgs->coldCodeSize > 0) + pArgs->coldCodeBlock = jitInstance->mc->cr->allocateMemory(pArgs->coldCodeSize); else - *coldCodeBlock = nullptr; + pArgs->coldCodeBlock = nullptr; - if (roDataSize > 0) + if (pArgs->roDataSize > 0) { size_t roDataAlignment = sizeof(void*); - size_t roDataAlignedSize = static_cast(roDataSize); + size_t roDataAlignedSize = static_cast(pArgs->roDataSize); - if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) + if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) { roDataAlignment = 32; } - else if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) + else if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) { roDataAlignment = 16; } - else if (roDataSize >= 8) + else if (pArgs->roDataSize >= 8) { roDataAlignment = 8; } @@ -1663,18 +1652,18 @@ void MyICJI::allocMem(uint32_t hotCodeSize, /* IN */ roDataAlignedSize = ALIGN_UP_SPMI(roDataAlignedSize, roDataAlignment); roDataAlignedSize = roDataAlignedSize + (roDataAlignment - sizeof(void*)); - *roDataBlock = jitInstance->mc->cr->allocateMemory(roDataAlignedSize); - *roDataBlock = ALIGN_UP_SPMI(*roDataBlock, roDataAlignment); + pArgs->roDataBlock = jitInstance->mc->cr->allocateMemory(roDataAlignedSize); + pArgs->roDataBlock = ALIGN_UP_SPMI(pArgs->roDataBlock, roDataAlignment); } else - *roDataBlock = nullptr; + pArgs->roDataBlock = nullptr; - *hotCodeBlockRW = *hotCodeBlock; - *coldCodeBlockRW = *coldCodeBlock; - *roDataBlockRW = *roDataBlock; + pArgs->hotCodeBlockRW = pArgs->hotCodeBlock; + pArgs->coldCodeBlockRW = pArgs->coldCodeBlock; + pArgs->roDataBlockRW = pArgs->roDataBlock; - jitInstance->mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, - coldCodeBlock, roDataBlock); + jitInstance->mc->cr->recAllocMem(pArgs->hotCodeSize, pArgs->coldCodeSize, pArgs->roDataSize, pArgs->xcptnsCount, pArgs->flag, &pArgs->hotCodeBlock, + &pArgs->coldCodeBlock, &pArgs->roDataBlock); } // Reserve memory for the method/funclet's unwind information. diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index 3d7c017461744b..dba1f6f22d2318 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -142,6 +142,24 @@ enum CheckedWriteBarrierKinds { CWBKind_AddrOfLocal, // Store through the address of a local (arguably a bug that this happens at all). }; +struct AllocMemArgs +{ + // Input arguments + uint32_t hotCodeSize; + uint32_t coldCodeSize; + uint32_t roDataSize; + uint32_t xcptnsCount; + CorJitAllocMemFlag flag; + + // Output arguments + void* hotCodeBlock; + void* hotCodeBlockRW; + void* coldCodeBlock; + void* coldCodeBlockRW; + void* roDataBlock; + void* roDataBlockRW; +}; + #include "corjithost.h" extern "C" void jitStartup(ICorJitHost* host); @@ -212,17 +230,7 @@ class ICorJitInfo : public ICorDynamicInfo public: // get a block of memory for the code, readonly data, and read-write data virtual void allocMem ( - uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ + AllocMemArgs *pArgs ) = 0; // Reserve memory for the method/funclet's unwind information. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 7f8e5a78985cb1..6ac767da49134f 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -635,17 +635,7 @@ bool notifyInstructionSetUsage( bool supportEnabled) override; void allocMem( - uint32_t hotCodeSize, - uint32_t coldCodeSize, - uint32_t roDataSize, - uint32_t xcptnsCount, - CorJitAllocMemFlag flag, - void** hotCodeBlock, - void** hotCodeBlockRW, - void** coldCodeBlock, - void** coldCodeBlockRW, - void** roDataBlock, - void** roDataBlockRW) override; + AllocMemArgs* pArgs) override; void reserveUnwindInfo( bool isFunclet, diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 7ce287d78ccb84..c51929c689d7d5 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1526,20 +1526,10 @@ bool WrapICorJitInfo::notifyInstructionSetUsage( } void WrapICorJitInfo::allocMem( - uint32_t hotCodeSize, - uint32_t coldCodeSize, - uint32_t roDataSize, - uint32_t xcptnsCount, - CorJitAllocMemFlag flag, - void** hotCodeBlock, - void** hotCodeBlockRW, - void** coldCodeBlock, - void** coldCodeBlockRW, - void** roDataBlock, - void** roDataBlockRW) + AllocMemArgs* pArgs) { API_ENTER(allocMem); - wrapHnd->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); + wrapHnd->allocMem(pArgs); API_LEAVE(allocMem); } diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 1287acc9a506ee..379cc65913d4bf 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -5314,19 +5314,18 @@ void emitter::emitComputeCodeSizes() } //------------------------------------------------------------------------ -// emitEndCodeGen: called at end of code generation to create code, data, and gc info +// writeCode: write code bytes into the specified blocks of memory // // Arguments: -// comp - compiler instance // contTrkPtrLcls - true if tracked stack pointers are contiguous on the stack -// fullInt - true if method has fully interruptible gc reporting -// fullPtrMap - true if gc reporting should use full register pointer map -// xcptnsCount - number of EH clauses to report for the method // prologSize [OUT] - prolog size in bytes // epilogSize [OUT] - epilog size in bytes (see notes) -// codeAddr [OUT] - address of the code buffer -// coldCodeAddr [OUT] - address of the cold code buffer (if any) -// consAddr [OUT] - address of the read only constant buffer (if any) +// codeBlock [IN] - executable memory address of the code buffer +// codeBlockRW [IN] - writeable memory address of the code buffer +// coldCodeBlock [IN] - executable memory address of the cold code buffer (if any) +// coldCodeBlockRW [IN] - writeable memory address of the cold code buffer (if any) +// consBlock [IN] - executable memory address of the read only constant buffer (if any) +// instrCount [OUT] - number of generated instructions (debug build only) // // Notes: // Currently, in methods with multiple epilogs, all epilogs must have the same @@ -5336,230 +5335,17 @@ void emitter::emitComputeCodeSizes() // Returns: // size of the method code, in bytes // -unsigned emitter::emitEndCodeGen(Compiler* comp, - bool contTrkPtrLcls, - bool fullyInt, - bool fullPtrMap, - unsigned xcptnsCount, - unsigned* prologSize, - unsigned* epilogSize, - void** codeAddr, - void** coldCodeAddr, - void** consAddr DEBUGARG(unsigned* instrCount)) +unsigned emitter::writeCode(bool contTrkPtrLcls, + unsigned* prologSize, + unsigned* epilogSize, + BYTE* codeBlock, + BYTE* codeBlockRW, + BYTE* coldCodeBlock, + BYTE* coldCodeBlockRW, + BYTE* consBlock DEBUGARG(unsigned* instrCount)) { -#ifdef DEBUG - if (emitComp->verbose) - { - printf("*************** In emitEndCodeGen()\n"); - } -#endif - - BYTE* consBlock; - BYTE* consBlockRW; - BYTE* codeBlock; - BYTE* codeBlockRW; - BYTE* coldCodeBlock; - BYTE* coldCodeBlockRW; BYTE* cp; - assert(emitCurIG == nullptr); - - emitCodeBlock = nullptr; - emitConsBlock = nullptr; - - emitOffsAdj = 0; - - /* Tell everyone whether we have fully interruptible code or not */ - - emitFullyInt = fullyInt; - emitFullGCinfo = fullPtrMap; - -#ifndef UNIX_X86_ABI - emitFullArgInfo = !emitHasFramePtr; -#else - emitFullArgInfo = fullPtrMap; -#endif - -#if EMITTER_STATS - GCrefsTable.record(emitGCrFrameOffsCnt); - emitSizeTable.record(static_cast(emitSizeMethod)); - stkDepthTable.record(emitMaxStackDepth); -#endif // EMITTER_STATS - - // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0. - emitSimpleStkUsed = true; - u1.emitSimpleStkMask = 0; - u1.emitSimpleByrefStkMask = 0; - -#if EMIT_TRACK_STACK_DEPTH - /* Convert max. stack depth from # of bytes to # of entries */ - - unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int); - JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth, - maxStackDepthIn4ByteElements); - emitMaxStackDepth = maxStackDepthIn4ByteElements; - - /* Should we use the simple stack */ - - if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo) - { - /* We won't use the "simple" argument table */ - - emitSimpleStkUsed = false; - - /* Allocate the argument tracking table */ - - if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl)) - { - u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl; - } - else - { - u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth)); - } - - u2.emitArgTrackTop = u2.emitArgTrackTab; - u2.emitGcArgTrackCnt = 0; - } -#endif - - if (emitEpilogCnt == 0) - { - /* No epilogs, make sure the epilog size is set to 0 */ - - emitEpilogSize = 0; - -#ifdef TARGET_XARCH - emitExitSeqSize = 0; -#endif // TARGET_XARCH - } - - /* Return the size of the epilog to the caller */ - - *epilogSize = emitEpilogSize; - -#ifdef TARGET_XARCH - *epilogSize += emitExitSeqSize; -#endif // TARGET_XARCH - -#ifdef DEBUG - if (EMIT_INSTLIST_VERBOSE) - { - printf("\nInstruction list before instruction issue:\n\n"); - emitDispIGlist(true); - } - - emitCheckIGoffsets(); -#endif - - /* Allocate the code block (and optionally the data blocks) */ - - // If we're doing procedure splitting and we found cold blocks, then - // allocate hot and cold buffers. Otherwise only allocate a hot - // buffer. - - coldCodeBlock = nullptr; - - CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; - -#ifdef TARGET_X86 - // - // These are the heuristics we use to decide whether or not to force the - // code to be 16-byte aligned. - // - // 1. For ngen code with IBC data, use 16-byte alignment if the method - // has been called more than ScenarioHotWeight times. - // 2. For JITed code and ngen code without IBC data, use 16-byte alignment - // when the code is 16 bytes or smaller. We align small getters/setters - // because of they are penalized heavily on certain hardware when not 16-byte - // aligned (VSWhidbey #373938). To minimize size impact of this optimization, - // we do not align large methods because of the penalty is amortized for them. - // - if (emitComp->fgHaveProfileData()) - { - const float scenarioHotWeight = 256.0f; - if (emitComp->fgCalledCount > (scenarioHotWeight * emitComp->fgProfileRunsCount())) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; - } - } - else - { - if (emitTotalHotCodeSize <= 16) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; - } - } -#endif - -#ifdef TARGET_XARCH - // For x64/x86, align methods that are "optimizations enabled" to 32 byte boundaries if - // they are larger than 16 bytes and contain a loop. - // - if (emitComp->opts.OptimizationEnabled() && !emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && - (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; - } -#endif - - // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes - // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem - assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); - - if (emitConsDsc.alignment == 16) - { - allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); - } - else if (emitConsDsc.alignment == 32) - { - allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); - } - -#ifdef TARGET_ARM64 - // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. - // This way allows us to use a single `ldr` to access such data like float constant/jmp table. - if (emitTotalColdCodeSize > 0) - { - // JIT data might be far away from the cold code. - NYI_ARM64("Need to handle fix-up to data from cold code."); - } - - UNATIVE_OFFSET roDataAlignmentDelta = 0; - if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) - { - UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. - roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; - assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); - } - emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0, - xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, - (void**)&coldCodeBlockRW, (void**)&consBlock, (void**)&consBlockRW); - - consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; - -#else - emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag, - (void**)&codeBlock, (void**)&codeBlockRW, (void**)&coldCodeBlock, (void**)&coldCodeBlockRW, - (void**)&consBlock, (void**)&consBlockRW); -#endif - -#ifdef DEBUG - if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) - { - assert(((size_t)codeBlock & 31) == 0); - } -#endif - - // if (emitConsDsc.dsdOffs) - // printf("Cons=%08X\n", consBlock); - - /* Give the block addresses to the caller and other functions here */ - - *codeAddr = emitCodeBlock = codeBlock; - *coldCodeAddr = emitColdCodeBlock = coldCodeBlock; - *consAddr = emitConsBlock = consBlock; - /* Nothing has been pushed on the stack */ CLANG_FORMAT_COMMENT_ANCHOR; @@ -6160,14 +5946,328 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, // Assign the real prolog size *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos); + return actualCodeSize; +} + +//------------------------------------------------------------------------ +// emitEndCodeGen: called at end of code generation to create code, data, and gc info +// +// Arguments: +// comp - compiler instance +// contTrkPtrLcls - true if tracked stack pointers are contiguous on the stack +// fullInt - true if method has fully interruptible gc reporting +// fullPtrMap - true if gc reporting should use full register pointer map +// xcptnsCount - number of EH clauses to report for the method +// prologSize [OUT] - prolog size in bytes +// epilogSize [OUT] - epilog size in bytes (see notes) +// codeAddr [OUT] - address of the code buffer +// coldCodeAddr [OUT] - address of the cold code buffer (if any) +// consAddr [OUT] - address of the read only constant buffer (if any) +// +// Notes: +// Currently, in methods with multiple epilogs, all epilogs must have the same +// size. epilogSize is the size of just one of these epilogs, not the cumulative +// size of all of the method's epilogs. +// +// Returns: +// size of the method code, in bytes +// +unsigned emitter::emitEndCodeGen(Compiler* comp, + bool contTrkPtrLcls, + bool fullyInt, + bool fullPtrMap, + unsigned xcptnsCount, + unsigned* prologSize, + unsigned* epilogSize, + void** codeAddr, + void** coldCodeAddr, + void** consAddr DEBUGARG(unsigned* instrCount)) +{ +#ifdef DEBUG + if (emitComp->verbose) + { + printf("*************** In emitEndCodeGen()\n"); + } +#endif + + BYTE* consBlock; + BYTE* consBlockRW; + BYTE* codeBlock; + BYTE* codeBlockRW; + BYTE* coldCodeBlock; + BYTE* coldCodeBlockRW; + + assert(emitCurIG == nullptr); + + emitCodeBlock = nullptr; + emitConsBlock = nullptr; + + emitOffsAdj = 0; + + /* Tell everyone whether we have fully interruptible code or not */ + + emitFullyInt = fullyInt; + emitFullGCinfo = fullPtrMap; + +#ifndef UNIX_X86_ABI + emitFullArgInfo = !emitHasFramePtr; +#else + emitFullArgInfo = fullPtrMap; +#endif + +#if EMITTER_STATS + GCrefsTable.record(emitGCrFrameOffsCnt); + emitSizeTable.record(static_cast(emitSizeMethod)); + stkDepthTable.record(emitMaxStackDepth); +#endif // EMITTER_STATS + + // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0. + emitSimpleStkUsed = true; + u1.emitSimpleStkMask = 0; + u1.emitSimpleByrefStkMask = 0; + +#if EMIT_TRACK_STACK_DEPTH + /* Convert max. stack depth from # of bytes to # of entries */ + + unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int); + JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth, + maxStackDepthIn4ByteElements); + emitMaxStackDepth = maxStackDepthIn4ByteElements; + + /* Should we use the simple stack */ + + if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo) + { + /* We won't use the "simple" argument table */ + + emitSimpleStkUsed = false; + + /* Allocate the argument tracking table */ + + if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl)) + { + u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl; + } + else + { + u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth)); + } + + u2.emitArgTrackTop = u2.emitArgTrackTab; + u2.emitGcArgTrackCnt = 0; + } +#endif + + if (emitEpilogCnt == 0) + { + /* No epilogs, make sure the epilog size is set to 0 */ + + emitEpilogSize = 0; + +#ifdef TARGET_XARCH + emitExitSeqSize = 0; +#endif // TARGET_XARCH + } + + /* Return the size of the epilog to the caller */ + + *epilogSize = emitEpilogSize; + +#ifdef TARGET_XARCH + *epilogSize += emitExitSeqSize; +#endif // TARGET_XARCH + +#ifdef DEBUG + if (EMIT_INSTLIST_VERBOSE) + { + printf("\nInstruction list before instruction issue:\n\n"); + emitDispIGlist(true); + } + + emitCheckIGoffsets(); +#endif + + /* Allocate the code block (and optionally the data blocks) */ + + // If we're doing procedure splitting and we found cold blocks, then + // allocate hot and cold buffers. Otherwise only allocate a hot + // buffer. + + coldCodeBlock = nullptr; + + CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; + +#ifdef TARGET_X86 + // + // These are the heuristics we use to decide whether or not to force the + // code to be 16-byte aligned. + // + // 1. For ngen code with IBC data, use 16-byte alignment if the method + // has been called more than ScenarioHotWeight times. + // 2. For JITed code and ngen code without IBC data, use 16-byte alignment + // when the code is 16 bytes or smaller. We align small getters/setters + // because of they are penalized heavily on certain hardware when not 16-byte + // aligned (VSWhidbey #373938). To minimize size impact of this optimization, + // we do not align large methods because of the penalty is amortized for them. + // + if (emitComp->fgHaveProfileData()) + { + const float scenarioHotWeight = 256.0f; + if (emitComp->fgCalledCount > (scenarioHotWeight * emitComp->fgProfileRunsCount())) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; + } + } + else + { + if (emitTotalHotCodeSize <= 16) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; + } + } +#endif + +#ifdef TARGET_XARCH + // For x64/x86, align methods that are "optimizations enabled" to 32 byte boundaries if + // they are larger than 16 bytes and contain a loop. + // + if (emitComp->opts.OptimizationEnabled() && !emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && + (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; + } +#endif + + // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes + // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem + assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); + + if (emitConsDsc.alignment == 16) + { + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); + } + else if (emitConsDsc.alignment == 32) + { + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); + } + + AllocMemArgs args; + memset(&args, 0, sizeof(args)); + +#ifdef TARGET_ARM64 + // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // This way allows us to use a single `ldr` to access such data like float constant/jmp table. + if (emitTotalColdCodeSize > 0) + { + // JIT data might be far away from the cold code. + NYI_ARM64("Need to handle fix-up to data from cold code."); + } + + UNATIVE_OFFSET roDataAlignmentDelta = 0; + if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) + { + UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. + roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; + assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); + } + + args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; + args.coldCodeSize = emitTotalColdCodeSize; + args.roDataSize = 0; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; + + emitCmpHandle->allocMem(&args); + + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; + coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; + + consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; + consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta; + +#else + + args.hotCodeSize = emitTotalHotCodeSize; + args.coldCodeSize = emitTotalColdCodeSize; + args.roDataSize = emitConsDsc.dsdOffs; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; + + emitCmpHandle->allocMem(&args); + + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; + coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; + consBlock = (BYTE*)args.roDataBlock; + consBlockRW = (BYTE*)args.roDataBlockRW; + +#endif + +#ifdef DEBUG + if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) + { + assert(((size_t)codeBlock & 31) == 0); + } +#endif + + // if (emitConsDsc.dsdOffs) + // printf("Cons=%08X\n", consBlock); + + /* Give the block addresses to the caller and other functions here */ + + *codeAddr = emitCodeBlock = codeBlock; + *coldCodeAddr = emitColdCodeBlock = coldCodeBlock; + *consAddr = emitConsBlock = consBlock; + + struct Param + { + emitter* pThis; + unsigned actualCodeSize; + bool contTrkPtrLcls; + unsigned* prologSize; + unsigned* epilogSize; + BYTE* codeBlock; + BYTE* codeBlockRW; + BYTE* coldCodeBlock; + BYTE* coldCodeBlockRW; + BYTE* consBlock; + INDEBUG(unsigned* instrCount;) + } param; + + param.pThis = this; + param.contTrkPtrLcls = contTrkPtrLcls; + param.prologSize = prologSize; + param.epilogSize = epilogSize; + param.codeBlock = codeBlock; + param.codeBlockRW = codeBlockRW; + param.coldCodeBlock = coldCodeBlock; + param.coldCodeBlockRW = coldCodeBlockRW; + param.consBlock = consBlock; +#ifdef DEBUG + param.instrCount = instrCount; +#endif + + bool success = comp->eeRunWithErrorTrap( + [](Param* pParam) { + pParam->actualCodeSize = pParam->pThis->writeCode(pParam->contTrkPtrLcls, pParam->prologSize, pParam->epilogSize, pParam->codeBlock, pParam->codeBlockRW, pParam->coldCodeBlock, pParam->coldCodeBlockRW, pParam->consBlock DEBUGARG(pParam->instrCount)); + }, ¶m); + // Ensure that any attempt to write code after this point will fail writeableOffset = 0; - // Notify the EE that all code was written. It can switch off writeable code memory. + // Notify the EE that all code writing is done. It can switch off writeable code memory. emitCmpHandle->doneWritingCode(); + if (!success) + { + fatal(CORJIT_INTERNALERROR); + } + /* Return the amount of code we've generated */ - return actualCodeSize; + return param.actualCodeSize; } // See specification comment at the declaration. diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 666201fc98bf00..8a2ef877a3fce3 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1732,6 +1732,15 @@ class emitter void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins); void spillIntArgRegsToShadowSlots(); + unsigned writeCode(bool contTrkPtrLcls, + unsigned* prologSize, + unsigned* epilogSize, + BYTE* codeBlock, + BYTE* codeBlockRW, + BYTE* coldCodeBlock, + BYTE* coldCodeBlockRW, + BYTE* consBlock DEBUGARG(unsigned* instrCount)); + /************************************************************************/ /* The logic that creates and keeps track of instruction groups */ /************************************************************************/ diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 8cb1e49e0afa94..1e01f81b814260 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2317,12 +2317,12 @@ static byte _notifyInstructionSetUsage(IntPtr thisHandle, IntPtr* ppException, I } [UnmanagedCallersOnly] - static void _allocMem(IntPtr thisHandle, IntPtr* ppException, uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW) + static void _allocMem(IntPtr thisHandle, IntPtr* ppException, AllocMemArgs* pArgs) { var _this = GetThis(thisHandle); try { - _this.allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, ref *hotCodeBlock, ref *hotCodeBlockRW, ref *coldCodeBlock, ref *coldCodeBlockRW, ref *roDataBlock, ref *roDataBlockRW); + _this.allocMem(ref *pArgs); } catch (Exception ex) { @@ -2723,7 +2723,7 @@ static IntPtr GetUnmanagedCallbacks() callbacks[153] = (delegate* unmanaged)&_getTailCallHelpers; callbacks[154] = (delegate* unmanaged)&_convertPInvokeCalliToCall; callbacks[155] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[156] = (delegate* unmanaged)&_allocMem; + callbacks[156] = (delegate* unmanaged)&_allocMem; callbacks[157] = (delegate* unmanaged)&_reserveUnwindInfo; callbacks[158] = (delegate* unmanaged)&_allocUnwindInfo; callbacks[159] = (delegate* unmanaged)&_allocGCInfo; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 93f252118459ba..8cbbf0e638e172 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3070,50 +3070,50 @@ private void doneWritingCode() { } - private void allocMem(uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, ref void* hotCodeBlock, ref void* hotCodeBlockRW, ref void* coldCodeBlock, ref void* coldCodeBlockRW, ref void* roDataBlock, ref void* roDataBlockRW) + private void allocMem(ref AllocMemArgs args) { - hotCodeBlock = (void*)GetPin(_code = new byte[hotCodeSize]); - hotCodeBlockRW = hotCodeBlock; + args.hotCodeBlock = (void*)GetPin(_code = new byte[args.hotCodeSize]); + args.hotCodeBlockRW = args.hotCodeBlock; - if (coldCodeSize != 0) + if (args.coldCodeSize != 0) { - coldCodeBlock = (void*)GetPin(_coldCode = new byte[coldCodeSize]); - coldCodeBlockRW = coldCodeBlock; + args.coldCodeBlock = (void*)GetPin(_coldCode = new byte[args.coldCodeSize]); + args.coldCodeBlockRW = args.coldCodeBlock; } _codeAlignment = -1; - if ((flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) + if ((args.flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) { _codeAlignment = 32; } - else if ((flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) + else if ((args.flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) { _codeAlignment = 16; } - if (roDataSize != 0) + if (args.roDataSize != 0) { _roDataAlignment = 8; - if ((flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) + if ((args.flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) { _roDataAlignment = 32; } - else if ((flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) + else if ((args.flag & CorJitAllocMemFlag.CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) { _roDataAlignment = 16; } - else if (roDataSize < 8) + else if (args.roDataSize < 8) { _roDataAlignment = PointerSize; } - _roData = new byte[roDataSize]; + _roData = new byte[args.roDataSize]; _roDataBlob = new MethodReadOnlyDataNode(MethodBeingCompiled); - roDataBlock = (void*)GetPin(_roData); - roDataBlockRW = roDataBlock; + args.roDataBlock = (void*)GetPin(_roData); + args.roDataBlockRW = args.roDataBlock; } if (_numFrameInfos > 0) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index e787a52dc3fc1a..84f1ba7a4ddac7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -313,6 +313,25 @@ public struct PgoInstrumentationSchema public int Other; } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct AllocMemArgs + { + // Input arguments + public uint hotCodeSize; + public uint coldCodeSize; + public uint roDataSize; + public uint xcptnsCount; + public CorJitAllocMemFlag flag; + + // Output arguments + public void* hotCodeBlock; + public void* hotCodeBlockRW; + public void* coldCodeBlock; + public void* coldCodeBlockRW; + public void* roDataBlock; + public void* roDataBlockRW; + } + // Flags computed by a runtime compiler public enum CorInfoMethodRuntimeFlags { diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index a39d22ae6fd75d..97c9bd441d14ca 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -101,6 +101,8 @@ CORINFO_JUST_MY_CODE_HANDLE**,ref CORINFO_JUST_MY_CODE_HANDLE_* ICorJitInfo::PgoInstrumentationSchema**,ref PgoInstrumentationSchema* ICorJitInfo::PgoInstrumentationSchema*,PgoInstrumentationSchema* +AllocMemArgs*, ref AllocMemArgs + ; Enums CorInfoClassId CorInfoHelpFunc @@ -306,7 +308,7 @@ FUNCTIONS bool getTailCallHelpers(CORINFO_RESOLVED_TOKEN* callToken, CORINFO_SIG_INFO* sig, CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, CORINFO_TAILCALL_HELPERS* pResult); bool convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool mustConvert); bool notifyInstructionSetUsage(CORINFO_InstructionSet instructionSet,bool supportEnabled); - void allocMem( uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW ); + void allocMem(AllocMemArgs* pArgs); void reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) void allocUnwindInfo(uint8_t* pHotCode, uint8_t* pColdCode, uint32_t startOffset, uint32_t endOffset, uint32_t unwindSize, uint8_t* pUnwindBlock, CorJitFuncKind funcKind) void* allocGCInfo(size_t size) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 3d803fa1ca4c59..9e5d3aaafc9335 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -167,7 +167,7 @@ struct JitInterfaceCallbacks bool (* getTailCallHelpers)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* callToken, CORINFO_SIG_INFO* sig, CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, CORINFO_TAILCALL_HELPERS* pResult); bool (* convertPInvokeCalliToCall)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool mustConvert); bool (* notifyInstructionSetUsage)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_InstructionSet instructionSet, bool supportEnabled); - void (* allocMem)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t hotCodeSize, uint32_t coldCodeSize, uint32_t roDataSize, uint32_t xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** hotCodeBlockRW, void** coldCodeBlock, void** coldCodeBlockRW, void** roDataBlock, void** roDataBlockRW); + void (* allocMem)(void * thisHandle, CorInfoExceptionClass** ppException, AllocMemArgs* pArgs); void (* reserveUnwindInfo)(void * thisHandle, CorInfoExceptionClass** ppException, bool isFunclet, bool isColdCode, uint32_t unwindSize); void (* allocUnwindInfo)(void * thisHandle, CorInfoExceptionClass** ppException, uint8_t* pHotCode, uint8_t* pColdCode, uint32_t startOffset, uint32_t endOffset, uint32_t unwindSize, uint8_t* pUnwindBlock, CorJitFuncKind funcKind); void* (* allocGCInfo)(void * thisHandle, CorInfoExceptionClass** ppException, size_t size); @@ -1696,20 +1696,10 @@ class JitInterfaceWrapper : public ICorJitInfo } virtual void allocMem( - uint32_t hotCodeSize, - uint32_t coldCodeSize, - uint32_t roDataSize, - uint32_t xcptnsCount, - CorJitAllocMemFlag flag, - void** hotCodeBlock, - void** hotCodeBlockRW, - void** coldCodeBlock, - void** coldCodeBlockRW, - void** roDataBlock, - void** roDataBlockRW) -{ - CorInfoExceptionClass* pException = nullptr; - _callbacks->allocMem(_thisHandle, &pException, hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, hotCodeBlockRW, coldCodeBlock, coldCodeBlockRW, roDataBlock, roDataBlockRW); + AllocMemArgs* pArgs) +{ + CorInfoExceptionClass* pException = nullptr; + _callbacks->allocMem(_thisHandle, &pException, pArgs); if (pException != nullptr) throw pException; } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 61cb01d019520e..b2005c737095d7 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12144,19 +12144,7 @@ HRESULT CEEJitInfo::getPgoInstrumentationResults( return hr; } -void CEEJitInfo::allocMem ( - uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) +void CEEJitInfo::allocMem (AllocMemArgs *pArgs) { CONTRACTL { THROWS; @@ -12166,40 +12154,40 @@ void CEEJitInfo::allocMem ( JIT_TO_EE_TRANSITION(); - _ASSERTE(coldCodeSize == 0); - if (coldCodeBlock) + _ASSERTE(pArgs->coldCodeSize == 0); + if (pArgs->coldCodeBlock) { - *coldCodeBlock = NULL; + pArgs->coldCodeBlock = NULL; } - ULONG codeSize = hotCodeSize; - void **codeBlock = hotCodeBlock; - void **codeBlockRW = hotCodeBlockRW; + ULONG codeSize = pArgs->hotCodeSize; + void **codeBlock = &pArgs->hotCodeBlock; + void **codeBlockRW = &pArgs->hotCodeBlockRW; S_SIZE_T totalSize = S_SIZE_T(codeSize); size_t roDataAlignment = sizeof(void*); - if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN)!= 0) + if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN)!= 0) { roDataAlignment = 32; } - else if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN)!= 0) + else if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN)!= 0) { roDataAlignment = 16; } - else if (roDataSize >= 8) + else if (pArgs->roDataSize >= 8) { roDataAlignment = 8; } - if (roDataSize > 0) + if (pArgs->roDataSize > 0) { size_t codeAlignment = sizeof(void*); - if ((flag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) + if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) { codeAlignment = 32; } - else if ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) + else if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) { codeAlignment = 16; } @@ -12209,7 +12197,7 @@ void CEEJitInfo::allocMem ( // Add padding to align read-only data. totalSize += (roDataAlignment - codeAlignment); } - totalSize += roDataSize; + totalSize += pArgs->roDataSize; } #ifdef FEATURE_EH_FUNCLETS @@ -12243,10 +12231,10 @@ void CEEJitInfo::allocMem ( } FireEtwMethodJitMemoryAllocatedForCode(ullMethodIdentifier, ullModuleID, - hotCodeSize + coldCodeSize, roDataSize, totalSize.Value(), flag, GetClrInstanceId()); + pArgs->hotCodeSize + pArgs->coldCodeSize, pArgs->roDataSize, totalSize.Value(), pArgs->flag, GetClrInstanceId()); } - m_CodeHeader = m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), GetReserveForJumpStubs(), flag + m_CodeHeader = m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), GetReserveForJumpStubs(), pArgs->flag #ifdef FEATURE_EH_FUNCLETS , m_totalUnwindInfos , &m_moduleBase @@ -12259,17 +12247,17 @@ void CEEJitInfo::allocMem ( *codeBlockRW = current; current += codeSize; - if (roDataSize > 0) + if (pArgs->roDataSize > 0) { current = (BYTE *)ALIGN_UP(current, roDataAlignment); - *roDataBlock = current; - *roDataBlockRW = current; - current += roDataSize; + pArgs->roDataBlock = current; + pArgs->roDataBlockRW = current; + current += pArgs->roDataSize; } else { - *roDataBlock = NULL; - *roDataBlockRW = NULL; + pArgs->roDataBlock = NULL; + pArgs->roDataBlockRW = NULL; } #ifdef FEATURE_EH_FUNCLETS @@ -14263,19 +14251,7 @@ bool CEEInfo::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, return false; } -void CEEInfo::allocMem ( - uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) +void CEEInfo::allocMem (AllocMemArgs *pArgs) { LIMITED_METHOD_CONTRACT; UNREACHABLE(); // only called on derived class. diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 1ed3db99bf624d..6ccceb0bf8a9b0 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -636,19 +636,7 @@ class CEEJitInfo : public CEEInfo public: // ICorJitInfo stuff - void allocMem ( - uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) override final; + void allocMem (AllocMemArgs *pArgs) override final; void reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) override final; diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp index ddbf17921777dc..9b74518376b6dd 100644 --- a/src/coreclr/zap/zapinfo.cpp +++ b/src/coreclr/zap/zapinfo.cpp @@ -1138,50 +1138,38 @@ HRESULT ZapInfo::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, return pgoResults->m_hr; } -void ZapInfo::allocMem( - uint32_t hotCodeSize, /* IN */ - uint32_t coldCodeSize, /* IN */ - uint32_t roDataSize, /* IN */ - uint32_t xcptnsCount, /* IN */ - CorJitAllocMemFlag flag, /* IN */ - void ** hotCodeBlock, /* OUT */ - void ** hotCodeBlockRW, /* OUT */ - void ** coldCodeBlock, /* OUT */ - void ** coldCodeBlockRW,/* OUT */ - void ** roDataBlock, /* OUT */ - void ** roDataBlockRW /* OUT */ - ) +void ZapInfo::allocMem(AllocMemArgs *pArgs) { bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); UINT align = DEFAULT_CODE_ALIGN; - if ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16); + if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16); - m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, hotCodeSize, align); - *hotCodeBlock = m_pCode->GetData(); - *hotCodeBlockRW = m_pCode->GetData(); + m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->hotCodeSize, align); + pArgs->hotCodeBlock = m_pCode->GetData(); + pArgs->hotCodeBlockRW = m_pCode->GetData(); - if (coldCodeSize != 0) + if (pArgs->coldCodeSize != 0) { align = sizeof(DWORD); - m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, coldCodeSize, align); - *coldCodeBlock = m_pColdCode->GetData(); - *coldCodeBlockRW = m_pColdCode->GetData(); + m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->coldCodeSize, align); + pArgs->coldCodeBlock = m_pColdCode->GetData(); + pArgs->coldCodeBlockRW = m_pColdCode->GetData(); } // // Allocate data // - if (roDataSize > 0) + if (pArgs->roDataSize > 0) { - if (flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) + if (pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) { align = 16; } - else if (optForSize || (roDataSize < 8)) + else if (optForSize || (pArgs->roDataSize < 8)) { align = TARGET_POINTER_SIZE; } @@ -1189,36 +1177,36 @@ void ZapInfo::allocMem( { align = 8; } - m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, roDataSize, align); - *roDataBlock = m_pROData->GetData(); - *roDataBlockRW = m_pROData->GetData(); + m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, pArgs->roDataSize, align); + pArgs->roDataBlock = m_pROData->GetData(); + pArgs->roDataBlockRW = m_pROData->GetData(); } if (m_pImage->m_stats) { - m_pImage->m_stats->m_nativeCodeSize += hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSize += coldCodeSize; - m_pImage->m_stats->m_nativeRODataSize += roDataSize; + m_pImage->m_stats->m_nativeCodeSize += pArgs->hotCodeSize; + m_pImage->m_stats->m_nativeColdCodeSize += pArgs->coldCodeSize; + m_pImage->m_stats->m_nativeRODataSize += pArgs->roDataSize; BOOL haveProfileData = CurrentMethodHasProfileData(); if (haveProfileData) { - m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods += hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += coldCodeSize; + m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods += pArgs->hotCodeSize; + m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += pArgs->coldCodeSize; } - if (coldCodeSize) + if (pArgs->coldCodeSize) { m_pImage->m_stats->m_NumHotColdAllocations++; - m_pImage->m_stats->m_nativeCodeSizeInSplitMethods += hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += coldCodeSize; + m_pImage->m_stats->m_nativeCodeSizeInSplitMethods += pArgs->hotCodeSize; + m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += pArgs->coldCodeSize; if (haveProfileData) { - m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods += hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += coldCodeSize; + m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods += pArgs->hotCodeSize; + m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += pArgs->coldCodeSize; } } else From 2fb29339c45d48142e065f6f9dab3771b5aa7afa Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 12 May 2021 12:51:15 +0200 Subject: [PATCH 4/6] Reflect PR feedback and apply formatting patch --- src/coreclr/jit/emit.cpp | 106 ++++++++++++++++++---------------- src/coreclr/jit/emit.h | 10 ++-- src/coreclr/jit/emitarm64.cpp | 5 +- src/coreclr/jit/emitxarch.cpp | 2 +- src/coreclr/jit/emitxarch.h | 2 - 5 files changed, 65 insertions(+), 60 deletions(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 379cc65913d4bf..b5973650c27ee7 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -5335,13 +5335,13 @@ void emitter::emitComputeCodeSizes() // Returns: // size of the method code, in bytes // -unsigned emitter::writeCode(bool contTrkPtrLcls, +unsigned emitter::writeCode(bool contTrkPtrLcls, unsigned* prologSize, unsigned* epilogSize, - BYTE* codeBlock, - BYTE* codeBlockRW, - BYTE* coldCodeBlock, - BYTE* coldCodeBlockRW, + BYTE* codeBlock, + BYTE* codeBlockRW, + BYTE* coldCodeBlock, + BYTE* coldCodeBlockRW, BYTE* consBlock DEBUGARG(unsigned* instrCount)) { BYTE* cp; @@ -5996,7 +5996,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, BYTE* codeBlockRW; BYTE* coldCodeBlock; BYTE* coldCodeBlockRW; - + assert(emitCurIG == nullptr); emitCodeBlock = nullptr; @@ -6171,38 +6171,38 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); } - args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; + args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; args.coldCodeSize = emitTotalColdCodeSize; - args.roDataSize = 0; - args.xcptnsCount = xcptnsCount; - args.flag = allocMemFlag; + args.roDataSize = 0; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; emitCmpHandle->allocMem(&args); - codeBlock = (BYTE*)args.hotCodeBlock; - codeBlockRW = (BYTE*)args.hotCodeBlockRW; - coldCodeBlock = (BYTE*)args.coldCodeBlock; + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; - consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; + consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta; #else - args.hotCodeSize = emitTotalHotCodeSize; + args.hotCodeSize = emitTotalHotCodeSize; args.coldCodeSize = emitTotalColdCodeSize; - args.roDataSize = emitConsDsc.dsdOffs; - args.xcptnsCount = xcptnsCount; - args.flag = allocMemFlag; + args.roDataSize = emitConsDsc.dsdOffs; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; emitCmpHandle->allocMem(&args); - codeBlock = (BYTE*)args.hotCodeBlock; - codeBlockRW = (BYTE*)args.hotCodeBlockRW; - coldCodeBlock = (BYTE*)args.coldCodeBlock; + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; - consBlock = (BYTE*)args.roDataBlock; - consBlockRW = (BYTE*)args.roDataBlockRW; + consBlock = (BYTE*)args.roDataBlock; + consBlockRW = (BYTE*)args.roDataBlockRW; #endif @@ -6224,36 +6224,40 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, struct Param { - emitter* pThis; - unsigned actualCodeSize; - bool contTrkPtrLcls; + emitter* pThis; + unsigned actualCodeSize; + bool contTrkPtrLcls; unsigned* prologSize; unsigned* epilogSize; - BYTE* codeBlock; - BYTE* codeBlockRW; - BYTE* coldCodeBlock; - BYTE* coldCodeBlockRW; - BYTE* consBlock; + BYTE* codeBlock; + BYTE* codeBlockRW; + BYTE* coldCodeBlock; + BYTE* coldCodeBlockRW; + BYTE* consBlock; INDEBUG(unsigned* instrCount;) } param; - param.pThis = this; - param.contTrkPtrLcls = contTrkPtrLcls; - param.prologSize = prologSize; - param.epilogSize = epilogSize; - param.codeBlock = codeBlock; - param.codeBlockRW = codeBlockRW; - param.coldCodeBlock = coldCodeBlock; + param.pThis = this; + param.contTrkPtrLcls = contTrkPtrLcls; + param.prologSize = prologSize; + param.epilogSize = epilogSize; + param.codeBlock = codeBlock; + param.codeBlockRW = codeBlockRW; + param.coldCodeBlock = coldCodeBlock; param.coldCodeBlockRW = coldCodeBlockRW; - param.consBlock = consBlock; + param.consBlock = consBlock; #ifdef DEBUG param.instrCount = instrCount; #endif bool success = comp->eeRunWithErrorTrap( [](Param* pParam) { - pParam->actualCodeSize = pParam->pThis->writeCode(pParam->contTrkPtrLcls, pParam->prologSize, pParam->epilogSize, pParam->codeBlock, pParam->codeBlockRW, pParam->coldCodeBlock, pParam->coldCodeBlockRW, pParam->consBlock DEBUGARG(pParam->instrCount)); - }, ¶m); + pParam->actualCodeSize = + pParam->pThis->writeCode(pParam->contTrkPtrLcls, pParam->prologSize, pParam->epilogSize, + pParam->codeBlock, pParam->codeBlockRW, pParam->coldCodeBlock, + pParam->coldCodeBlockRW, pParam->consBlock DEBUGARG(pParam->instrCount)); + }, + ¶m); // Ensure that any attempt to write code after this point will fail writeableOffset = 0; @@ -6748,6 +6752,8 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) { size_t dscSize = dsc->dsSize; + BYTE *dstRW = dst + writeableOffset; + // absolute label table if (dsc->dsType == dataSection::blockAbsoluteAddr) { @@ -6755,7 +6761,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0); size_t numElems = dscSize / TARGET_POINTER_SIZE; - target_size_t* bDst = (target_size_t*)(dst + writeableOffset); + target_size_t* bDstRW = (target_size_t*)dstRW; for (unsigned i = 0; i < numElems; i++) { BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i]; @@ -6769,13 +6775,13 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) #ifdef TARGET_ARM target = (BYTE*)((size_t)target | 1); // Or in thumb bit #endif - bDst[i] = (target_size_t)(size_t)target; + bDstRW[i] = (target_size_t)(size_t)target; if (emitComp->opts.compReloc) { - emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW); + emitRecordRelocation(&(bDstRW[i]), target, IMAGE_REL_BASED_HIGHLOW); } - JITDUMP(" " FMT_BB ": 0x%p\n", block->bbNum, bDst[i]); + JITDUMP(" " FMT_BB ": 0x%p\n", block->bbNum, bDstRW[i]); } } // relative label table @@ -6784,7 +6790,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize); size_t numElems = dscSize / 4; - unsigned* uDst = (unsigned*)(dst + writeableOffset); + unsigned* uDstRW = (unsigned*)dstRW; insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB); for (unsigned i = 0; i < numElems; i++) @@ -6795,9 +6801,9 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) insGroup* lab = (insGroup*)emitCodeGetCookie(block); assert(FitsIn(lab->igOffs - labFirst->igOffs)); - uDst[i] = lab->igOffs - labFirst->igOffs; + uDstRW[i] = lab->igOffs - labFirst->igOffs; - JITDUMP(" " FMT_BB ": 0x%x\n", block->bbNum, uDst[i]); + JITDUMP(" " FMT_BB ": 0x%x\n", block->bbNum, uDstRW[i]); } } else @@ -6805,7 +6811,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) // Simple binary data: copy the bytes to the target assert(dsc->dsType == dataSection::data); - memcpy(dst + writeableOffset, dsc->dsCont, dscSize); + memcpy(dstRW, dsc->dsCont, dscSize); #ifdef DEBUG if (EMITVERBOSE) @@ -7510,7 +7516,7 @@ void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr) unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val) { BYTE* dstRW = dst + writeableOffset; - *castto(dst + writeableOffset, unsigned char*) = (unsigned char)val; + *castto(dstRW, unsigned char*) = (unsigned char)val; #ifdef DEBUG #ifdef TARGET_AMD64 diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 8a2ef877a3fce3..c55c3521a3c8db 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1732,13 +1732,13 @@ class emitter void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins); void spillIntArgRegsToShadowSlots(); - unsigned writeCode(bool contTrkPtrLcls, + unsigned writeCode(bool contTrkPtrLcls, unsigned* prologSize, unsigned* epilogSize, - BYTE* codeBlock, - BYTE* codeBlockRW, - BYTE* coldCodeBlock, - BYTE* coldCodeBlockRW, + BYTE* codeBlock, + BYTE* codeBlockRW, + BYTE* coldCodeBlock, + BYTE* coldCodeBlockRW, BYTE* consBlock DEBUGARG(unsigned* instrCount)); /************************************************************************/ diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index b92802941469f2..825794bbc38d5f 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -10250,10 +10250,11 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t * Emit a 32-bit Arm64 instruction */ -/*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) +unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) { assert(sizeof(code_t) == 4); - *((code_t*)(dst + writeableOffset)) = code; + BYTE* dstRW = dst + writeableOffset; + *((code_t*)dstRW) = code; return sizeof(code_t); } diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 0b9a647a0ec7a2..516c976fe009ae 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -9270,7 +9270,7 @@ void emitter::emitDispIns( * Output nBytes bytes of NOP instructions */ -BYTE* emitter::emitOutputNOP(BYTE* dstRW, size_t nBytes) +static BYTE* emitOutputNOP(BYTE* dstRW, size_t nBytes) { assert(nBytes <= 15); diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index fb22cb0e7de87b..af8dffc3012084 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -240,8 +240,6 @@ ssize_t emitGetInsAmdCns(instrDesc* id, CnsVal* cv); void emitGetInsDcmCns(instrDesc* id, CnsVal* cv); ssize_t emitGetInsAmdAny(instrDesc* id); -BYTE* emitOutputNOP(BYTE* dstRW, size_t nBytes); - /************************************************************************/ /* Private helpers for instruction output */ /************************************************************************/ From f11ea73378e7921ed0be07d4d088e59c5c8bf2d0 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 12 May 2021 14:08:47 +0200 Subject: [PATCH 5/6] Yet another formatting patch --- src/coreclr/jit/emit.cpp | 6 +++--- src/coreclr/jit/emitarm64.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index b5973650c27ee7..4331e52ca49928 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -6752,7 +6752,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) { size_t dscSize = dsc->dsSize; - BYTE *dstRW = dst + writeableOffset; + BYTE* dstRW = dst + writeableOffset; // absolute label table if (dsc->dsType == dataSection::blockAbsoluteAddr) @@ -6761,7 +6761,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0); size_t numElems = dscSize / TARGET_POINTER_SIZE; - target_size_t* bDstRW = (target_size_t*)dstRW; + target_size_t* bDstRW = (target_size_t*)dstRW; for (unsigned i = 0; i < numElems; i++) { BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i]; @@ -6790,7 +6790,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize); size_t numElems = dscSize / 4; - unsigned* uDstRW = (unsigned*)dstRW; + unsigned* uDstRW = (unsigned*)dstRW; insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB); for (unsigned i = 0; i < numElems; i++) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 825794bbc38d5f..3badba90a0c032 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -10253,7 +10253,7 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code) { assert(sizeof(code_t) == 4); - BYTE* dstRW = dst + writeableOffset; + BYTE* dstRW = dst + writeableOffset; *((code_t*)dstRW) = code; return sizeof(code_t); From e608b7517925c3bb7290ad40664d7356361638e2 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 12 May 2021 18:15:29 +0200 Subject: [PATCH 6/6] Remove the doneWritingCode This change reverts the addition of the doneWritingCode as it seems using a scrach buffer to write the code and then creating the target writeable mapping only for memcpy of the code to that would be beneficial. I want to explore that and this JIT change doesn't do anything in the doneWritingCode yet. The change to extract part of the emitEndCodeGen into a separate writeCode method was reverted too. --- .../superpmi-shim-collector/icorjitinfo.cpp | 6 - .../superpmi-shim-counter/icorjitinfo.cpp | 6 - .../superpmi-shim-simple/icorjitinfo.cpp | 5 - .../ToolBox/superpmi/superpmi/icorjitinfo.cpp | 5 - src/coreclr/inc/corjit.h | 3 - src/coreclr/inc/icorjitinfoimpl_generated.h | 2 - src/coreclr/jit/ICorJitInfo_API_names.h | 1 - src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 7 - src/coreclr/jit/emit.cpp | 596 ++++++++---------- src/coreclr/jit/emit.h | 9 - .../tools/Common/JitInterface/CorInfoBase.cs | 17 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 4 - .../ThunkGenerator/ThunkInput.txt | 1 - .../tools/aot/jitinterface/jitinterface.h | 8 - src/coreclr/vm/jitinterface.cpp | 19 - src/coreclr/vm/jitinterface.h | 2 - src/coreclr/zap/zapinfo.cpp | 4 - 17 files changed, 258 insertions(+), 437 deletions(-) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index c892fdd004beb8..d7a3b48fdacf53 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1937,12 +1937,6 @@ void interceptor_ICJI::allocMem(AllocMemArgs *pArgs) &pArgs->roDataBlock); } -void interceptor_ICJI::doneWritingCode() -{ - mc->cr->AddCall("doneWritingCode"); - original_ICorJitInfo->doneWritingCode(); -} - // Reserve memory for the method/funclet's unwind information. // Note that this must be called before allocMem. It should be // called once for the main method, once for every funclet, and diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 1eb7da0bd02501..46ab7cb8489156 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1387,9 +1387,3 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } -void interceptor_ICJI::doneWritingCode() -{ - mcs->AddCall("doneWritingCode"); - original_ICorJitInfo->doneWritingCode(); -} - diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index a46ad17ec157c8..1ab397077f06c2 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1215,8 +1215,3 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } -void interceptor_ICJI::doneWritingCode() -{ - original_ICorJitInfo->doneWritingCode(); -} - diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 8aec03677c6059..ce20edd00be1d3 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1866,8 +1866,3 @@ uint32_t MyICJI::getExpectedTargetArchitecture() DWORD result = jitInstance->mc->repGetExpectedTargetArchitecture(); return result; } - -void MyICJI::doneWritingCode() -{ - jitInstance->mc->cr->AddCall("doneWritingCode"); -} diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index dba1f6f22d2318..51fe431bbb8be5 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -464,9 +464,6 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a version number for the CORJIT_FLAGS value. */ ) = 0; - - // Notify the EE that JIT is done writing to the memory allocated for code - virtual void doneWritingCode() = 0; }; /**********************************************************************************/ diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 6ac767da49134f..ebd9813e2c4fd8 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -708,8 +708,6 @@ uint32_t getJitFlags( CORJIT_FLAGS* flags, uint32_t sizeInBytes) override; -void doneWritingCode() override; - /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index f396182d9c996f..5588f234a2c06e 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -176,6 +176,5 @@ DEF_CLR_API(recordRelocation) DEF_CLR_API(getRelocTypeHint) DEF_CLR_API(getExpectedTargetArchitecture) DEF_CLR_API(getJitFlags) -DEF_CLR_API(doneWritingCode) #undef DEF_CLR_API diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index c51929c689d7d5..33f33056ff639f 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1687,13 +1687,6 @@ uint32_t WrapICorJitInfo::getJitFlags( return temp; } -void WrapICorJitInfo::doneWritingCode() -{ - API_ENTER(doneWritingCode); - wrapHnd->doneWritingCode(); - API_LEAVE(doneWritingCode); -} - /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 4331e52ca49928..7490a2e8de1d30 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -5314,18 +5314,19 @@ void emitter::emitComputeCodeSizes() } //------------------------------------------------------------------------ -// writeCode: write code bytes into the specified blocks of memory +// emitEndCodeGen: called at end of code generation to create code, data, and gc info // // Arguments: +// comp - compiler instance // contTrkPtrLcls - true if tracked stack pointers are contiguous on the stack +// fullInt - true if method has fully interruptible gc reporting +// fullPtrMap - true if gc reporting should use full register pointer map +// xcptnsCount - number of EH clauses to report for the method // prologSize [OUT] - prolog size in bytes // epilogSize [OUT] - epilog size in bytes (see notes) -// codeBlock [IN] - executable memory address of the code buffer -// codeBlockRW [IN] - writeable memory address of the code buffer -// coldCodeBlock [IN] - executable memory address of the cold code buffer (if any) -// coldCodeBlockRW [IN] - writeable memory address of the cold code buffer (if any) -// consBlock [IN] - executable memory address of the read only constant buffer (if any) -// instrCount [OUT] - number of generated instructions (debug build only) +// codeAddr [OUT] - address of the code buffer +// coldCodeAddr [OUT] - address of the cold code buffer (if any) +// consAddr [OUT] - address of the read only constant buffer (if any) // // Notes: // Currently, in methods with multiple epilogs, all epilogs must have the same @@ -5335,17 +5336,257 @@ void emitter::emitComputeCodeSizes() // Returns: // size of the method code, in bytes // -unsigned emitter::writeCode(bool contTrkPtrLcls, - unsigned* prologSize, - unsigned* epilogSize, - BYTE* codeBlock, - BYTE* codeBlockRW, - BYTE* coldCodeBlock, - BYTE* coldCodeBlockRW, - BYTE* consBlock DEBUGARG(unsigned* instrCount)) +unsigned emitter::emitEndCodeGen(Compiler* comp, + bool contTrkPtrLcls, + bool fullyInt, + bool fullPtrMap, + unsigned xcptnsCount, + unsigned* prologSize, + unsigned* epilogSize, + void** codeAddr, + void** coldCodeAddr, + void** consAddr DEBUGARG(unsigned* instrCount)) { +#ifdef DEBUG + if (emitComp->verbose) + { + printf("*************** In emitEndCodeGen()\n"); + } +#endif + + BYTE* consBlock; + BYTE* consBlockRW; + BYTE* codeBlock; + BYTE* codeBlockRW; + BYTE* coldCodeBlock; + BYTE* coldCodeBlockRW; BYTE* cp; + assert(emitCurIG == nullptr); + + emitCodeBlock = nullptr; + emitConsBlock = nullptr; + + emitOffsAdj = 0; + + /* Tell everyone whether we have fully interruptible code or not */ + + emitFullyInt = fullyInt; + emitFullGCinfo = fullPtrMap; + +#ifndef UNIX_X86_ABI + emitFullArgInfo = !emitHasFramePtr; +#else + emitFullArgInfo = fullPtrMap; +#endif + +#if EMITTER_STATS + GCrefsTable.record(emitGCrFrameOffsCnt); + emitSizeTable.record(static_cast(emitSizeMethod)); + stkDepthTable.record(emitMaxStackDepth); +#endif // EMITTER_STATS + + // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0. + emitSimpleStkUsed = true; + u1.emitSimpleStkMask = 0; + u1.emitSimpleByrefStkMask = 0; + +#if EMIT_TRACK_STACK_DEPTH + /* Convert max. stack depth from # of bytes to # of entries */ + + unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int); + JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth, + maxStackDepthIn4ByteElements); + emitMaxStackDepth = maxStackDepthIn4ByteElements; + + /* Should we use the simple stack */ + + if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo) + { + /* We won't use the "simple" argument table */ + + emitSimpleStkUsed = false; + + /* Allocate the argument tracking table */ + + if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl)) + { + u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl; + } + else + { + u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth)); + } + + u2.emitArgTrackTop = u2.emitArgTrackTab; + u2.emitGcArgTrackCnt = 0; + } +#endif + + if (emitEpilogCnt == 0) + { + /* No epilogs, make sure the epilog size is set to 0 */ + + emitEpilogSize = 0; + +#ifdef TARGET_XARCH + emitExitSeqSize = 0; +#endif // TARGET_XARCH + } + + /* Return the size of the epilog to the caller */ + + *epilogSize = emitEpilogSize; + +#ifdef TARGET_XARCH + *epilogSize += emitExitSeqSize; +#endif // TARGET_XARCH + +#ifdef DEBUG + if (EMIT_INSTLIST_VERBOSE) + { + printf("\nInstruction list before instruction issue:\n\n"); + emitDispIGlist(true); + } + + emitCheckIGoffsets(); +#endif + + /* Allocate the code block (and optionally the data blocks) */ + + // If we're doing procedure splitting and we found cold blocks, then + // allocate hot and cold buffers. Otherwise only allocate a hot + // buffer. + + coldCodeBlock = nullptr; + + CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; + +#ifdef TARGET_X86 + // + // These are the heuristics we use to decide whether or not to force the + // code to be 16-byte aligned. + // + // 1. For ngen code with IBC data, use 16-byte alignment if the method + // has been called more than ScenarioHotWeight times. + // 2. For JITed code and ngen code without IBC data, use 16-byte alignment + // when the code is 16 bytes or smaller. We align small getters/setters + // because of they are penalized heavily on certain hardware when not 16-byte + // aligned (VSWhidbey #373938). To minimize size impact of this optimization, + // we do not align large methods because of the penalty is amortized for them. + // + if (emitComp->fgHaveProfileData()) + { + const float scenarioHotWeight = 256.0f; + if (emitComp->fgCalledCount > (scenarioHotWeight * emitComp->fgProfileRunsCount())) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; + } + } + else + { + if (emitTotalHotCodeSize <= 16) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; + } + } +#endif + +#ifdef TARGET_XARCH + // For x64/x86, align methods that are "optimizations enabled" to 32 byte boundaries if + // they are larger than 16 bytes and contain a loop. + // + if (emitComp->opts.OptimizationEnabled() && !emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && + (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) + { + allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; + } +#endif + + // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes + // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem + assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); + + if (emitConsDsc.alignment == 16) + { + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); + } + else if (emitConsDsc.alignment == 32) + { + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); + } + + AllocMemArgs args; + memset(&args, 0, sizeof(args)); + +#ifdef TARGET_ARM64 + // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // This way allows us to use a single `ldr` to access such data like float constant/jmp table. + if (emitTotalColdCodeSize > 0) + { + // JIT data might be far away from the cold code. + NYI_ARM64("Need to handle fix-up to data from cold code."); + } + + UNATIVE_OFFSET roDataAlignmentDelta = 0; + if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) + { + UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. + roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; + assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); + } + + args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; + args.coldCodeSize = emitTotalColdCodeSize; + args.roDataSize = 0; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; + + emitCmpHandle->allocMem(&args); + + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; + coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; + + consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; + consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta; + +#else + + args.hotCodeSize = emitTotalHotCodeSize; + args.coldCodeSize = emitTotalColdCodeSize; + args.roDataSize = emitConsDsc.dsdOffs; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; + + emitCmpHandle->allocMem(&args); + + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; + coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; + consBlock = (BYTE*)args.roDataBlock; + consBlockRW = (BYTE*)args.roDataBlockRW; + +#endif + +#ifdef DEBUG + if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) + { + assert(((size_t)codeBlock & 31) == 0); + } +#endif + + // if (emitConsDsc.dsdOffs) + // printf("Cons=%08X\n", consBlock); + + /* Give the block addresses to the caller and other functions here */ + + *codeAddr = emitCodeBlock = codeBlock; + *coldCodeAddr = emitColdCodeBlock = coldCodeBlock; + *consAddr = emitConsBlock = consBlock; + /* Nothing has been pushed on the stack */ CLANG_FORMAT_COMMENT_ANCHOR; @@ -5946,332 +6187,9 @@ unsigned emitter::writeCode(bool contTrkPtrLcls, // Assign the real prolog size *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos); - return actualCodeSize; -} - -//------------------------------------------------------------------------ -// emitEndCodeGen: called at end of code generation to create code, data, and gc info -// -// Arguments: -// comp - compiler instance -// contTrkPtrLcls - true if tracked stack pointers are contiguous on the stack -// fullInt - true if method has fully interruptible gc reporting -// fullPtrMap - true if gc reporting should use full register pointer map -// xcptnsCount - number of EH clauses to report for the method -// prologSize [OUT] - prolog size in bytes -// epilogSize [OUT] - epilog size in bytes (see notes) -// codeAddr [OUT] - address of the code buffer -// coldCodeAddr [OUT] - address of the cold code buffer (if any) -// consAddr [OUT] - address of the read only constant buffer (if any) -// -// Notes: -// Currently, in methods with multiple epilogs, all epilogs must have the same -// size. epilogSize is the size of just one of these epilogs, not the cumulative -// size of all of the method's epilogs. -// -// Returns: -// size of the method code, in bytes -// -unsigned emitter::emitEndCodeGen(Compiler* comp, - bool contTrkPtrLcls, - bool fullyInt, - bool fullPtrMap, - unsigned xcptnsCount, - unsigned* prologSize, - unsigned* epilogSize, - void** codeAddr, - void** coldCodeAddr, - void** consAddr DEBUGARG(unsigned* instrCount)) -{ -#ifdef DEBUG - if (emitComp->verbose) - { - printf("*************** In emitEndCodeGen()\n"); - } -#endif - - BYTE* consBlock; - BYTE* consBlockRW; - BYTE* codeBlock; - BYTE* codeBlockRW; - BYTE* coldCodeBlock; - BYTE* coldCodeBlockRW; - - assert(emitCurIG == nullptr); - - emitCodeBlock = nullptr; - emitConsBlock = nullptr; - - emitOffsAdj = 0; - - /* Tell everyone whether we have fully interruptible code or not */ - - emitFullyInt = fullyInt; - emitFullGCinfo = fullPtrMap; - -#ifndef UNIX_X86_ABI - emitFullArgInfo = !emitHasFramePtr; -#else - emitFullArgInfo = fullPtrMap; -#endif - -#if EMITTER_STATS - GCrefsTable.record(emitGCrFrameOffsCnt); - emitSizeTable.record(static_cast(emitSizeMethod)); - stkDepthTable.record(emitMaxStackDepth); -#endif // EMITTER_STATS - - // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0. - emitSimpleStkUsed = true; - u1.emitSimpleStkMask = 0; - u1.emitSimpleByrefStkMask = 0; - -#if EMIT_TRACK_STACK_DEPTH - /* Convert max. stack depth from # of bytes to # of entries */ - - unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int); - JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth, - maxStackDepthIn4ByteElements); - emitMaxStackDepth = maxStackDepthIn4ByteElements; - - /* Should we use the simple stack */ - - if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo) - { - /* We won't use the "simple" argument table */ - - emitSimpleStkUsed = false; - - /* Allocate the argument tracking table */ - - if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl)) - { - u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl; - } - else - { - u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth)); - } - - u2.emitArgTrackTop = u2.emitArgTrackTab; - u2.emitGcArgTrackCnt = 0; - } -#endif - - if (emitEpilogCnt == 0) - { - /* No epilogs, make sure the epilog size is set to 0 */ - - emitEpilogSize = 0; - -#ifdef TARGET_XARCH - emitExitSeqSize = 0; -#endif // TARGET_XARCH - } - - /* Return the size of the epilog to the caller */ - - *epilogSize = emitEpilogSize; - -#ifdef TARGET_XARCH - *epilogSize += emitExitSeqSize; -#endif // TARGET_XARCH - -#ifdef DEBUG - if (EMIT_INSTLIST_VERBOSE) - { - printf("\nInstruction list before instruction issue:\n\n"); - emitDispIGlist(true); - } - - emitCheckIGoffsets(); -#endif - - /* Allocate the code block (and optionally the data blocks) */ - - // If we're doing procedure splitting and we found cold blocks, then - // allocate hot and cold buffers. Otherwise only allocate a hot - // buffer. - - coldCodeBlock = nullptr; - - CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; - -#ifdef TARGET_X86 - // - // These are the heuristics we use to decide whether or not to force the - // code to be 16-byte aligned. - // - // 1. For ngen code with IBC data, use 16-byte alignment if the method - // has been called more than ScenarioHotWeight times. - // 2. For JITed code and ngen code without IBC data, use 16-byte alignment - // when the code is 16 bytes or smaller. We align small getters/setters - // because of they are penalized heavily on certain hardware when not 16-byte - // aligned (VSWhidbey #373938). To minimize size impact of this optimization, - // we do not align large methods because of the penalty is amortized for them. - // - if (emitComp->fgHaveProfileData()) - { - const float scenarioHotWeight = 256.0f; - if (emitComp->fgCalledCount > (scenarioHotWeight * emitComp->fgProfileRunsCount())) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; - } - } - else - { - if (emitTotalHotCodeSize <= 16) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; - } - } -#endif - -#ifdef TARGET_XARCH - // For x64/x86, align methods that are "optimizations enabled" to 32 byte boundaries if - // they are larger than 16 bytes and contain a loop. - // - if (emitComp->opts.OptimizationEnabled() && !emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && - (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) - { - allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; - } -#endif - - // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes - // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem - assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); - - if (emitConsDsc.alignment == 16) - { - allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); - } - else if (emitConsDsc.alignment == 32) - { - allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); - } - - AllocMemArgs args; - memset(&args, 0, sizeof(args)); - -#ifdef TARGET_ARM64 - // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. - // This way allows us to use a single `ldr` to access such data like float constant/jmp table. - if (emitTotalColdCodeSize > 0) - { - // JIT data might be far away from the cold code. - NYI_ARM64("Need to handle fix-up to data from cold code."); - } - - UNATIVE_OFFSET roDataAlignmentDelta = 0; - if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) - { - UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. - roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; - assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); - } - - args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; - args.coldCodeSize = emitTotalColdCodeSize; - args.roDataSize = 0; - args.xcptnsCount = xcptnsCount; - args.flag = allocMemFlag; - - emitCmpHandle->allocMem(&args); - - codeBlock = (BYTE*)args.hotCodeBlock; - codeBlockRW = (BYTE*)args.hotCodeBlockRW; - coldCodeBlock = (BYTE*)args.coldCodeBlock; - coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; - - consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; - consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta; - -#else - - args.hotCodeSize = emitTotalHotCodeSize; - args.coldCodeSize = emitTotalColdCodeSize; - args.roDataSize = emitConsDsc.dsdOffs; - args.xcptnsCount = xcptnsCount; - args.flag = allocMemFlag; - - emitCmpHandle->allocMem(&args); - - codeBlock = (BYTE*)args.hotCodeBlock; - codeBlockRW = (BYTE*)args.hotCodeBlockRW; - coldCodeBlock = (BYTE*)args.coldCodeBlock; - coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; - consBlock = (BYTE*)args.roDataBlock; - consBlockRW = (BYTE*)args.roDataBlockRW; - -#endif - -#ifdef DEBUG - if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) - { - assert(((size_t)codeBlock & 31) == 0); - } -#endif - - // if (emitConsDsc.dsdOffs) - // printf("Cons=%08X\n", consBlock); - - /* Give the block addresses to the caller and other functions here */ - - *codeAddr = emitCodeBlock = codeBlock; - *coldCodeAddr = emitColdCodeBlock = coldCodeBlock; - *consAddr = emitConsBlock = consBlock; - - struct Param - { - emitter* pThis; - unsigned actualCodeSize; - bool contTrkPtrLcls; - unsigned* prologSize; - unsigned* epilogSize; - BYTE* codeBlock; - BYTE* codeBlockRW; - BYTE* coldCodeBlock; - BYTE* coldCodeBlockRW; - BYTE* consBlock; - INDEBUG(unsigned* instrCount;) - } param; - - param.pThis = this; - param.contTrkPtrLcls = contTrkPtrLcls; - param.prologSize = prologSize; - param.epilogSize = epilogSize; - param.codeBlock = codeBlock; - param.codeBlockRW = codeBlockRW; - param.coldCodeBlock = coldCodeBlock; - param.coldCodeBlockRW = coldCodeBlockRW; - param.consBlock = consBlock; -#ifdef DEBUG - param.instrCount = instrCount; -#endif - - bool success = comp->eeRunWithErrorTrap( - [](Param* pParam) { - pParam->actualCodeSize = - pParam->pThis->writeCode(pParam->contTrkPtrLcls, pParam->prologSize, pParam->epilogSize, - pParam->codeBlock, pParam->codeBlockRW, pParam->coldCodeBlock, - pParam->coldCodeBlockRW, pParam->consBlock DEBUGARG(pParam->instrCount)); - }, - ¶m); - - // Ensure that any attempt to write code after this point will fail - writeableOffset = 0; - // Notify the EE that all code writing is done. It can switch off writeable code memory. - emitCmpHandle->doneWritingCode(); - - if (!success) - { - fatal(CORJIT_INTERNALERROR); - } - /* Return the amount of code we've generated */ - return param.actualCodeSize; + return actualCodeSize; } // See specification comment at the declaration. diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index c55c3521a3c8db..666201fc98bf00 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1732,15 +1732,6 @@ class emitter void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins); void spillIntArgRegsToShadowSlots(); - unsigned writeCode(bool contTrkPtrLcls, - unsigned* prologSize, - unsigned* epilogSize, - BYTE* codeBlock, - BYTE* codeBlockRW, - BYTE* coldCodeBlock, - BYTE* coldCodeBlockRW, - BYTE* consBlock DEBUGARG(unsigned* instrCount)); - /************************************************************************/ /* The logic that creates and keeps track of instruction groups */ /************************************************************************/ diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 1e01f81b814260..7125dfc59b9042 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2548,24 +2548,10 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_FLAGS* f } } - [UnmanagedCallersOnly] - static void _doneWritingCode(IntPtr thisHandle, IntPtr* ppException) - { - var _this = GetThis(thisHandle); - try - { - _this.doneWritingCode(); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - } - } - static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); callbacks[0] = (delegate* unmanaged)&_isJitIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2739,7 +2725,6 @@ static IntPtr GetUnmanagedCallbacks() callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; callbacks[171] = (delegate* unmanaged)&_getJitFlags; - callbacks[172] = (delegate* unmanaged)&_doneWritingCode; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 8cbbf0e638e172..65137fad8c029d 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3066,10 +3066,6 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI private byte[] _gcInfo; private CORINFO_EH_CLAUSE[] _ehClauses; - private void doneWritingCode() - { - } - private void allocMem(ref AllocMemArgs args) { args.hotCodeBlock = (void*)GetPin(_code = new byte[args.hotCodeSize]); diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 97c9bd441d14ca..18ac90d0b459ed 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -324,5 +324,4 @@ FUNCTIONS uint16_t getRelocTypeHint(void* target) uint32_t getExpectedTargetArchitecture() uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes) - void doneWritingCode() diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 9e5d3aaafc9335..78daddda066b57 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -183,7 +183,6 @@ struct JitInterfaceCallbacks uint16_t (* getRelocTypeHint)(void * thisHandle, CorInfoExceptionClass** ppException, void* target); uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException); uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes); - void (* doneWritingCode)(void * thisHandle, CorInfoExceptionClass** ppException); }; @@ -1856,11 +1855,4 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; return temp; } - - virtual void doneWritingCode() -{ - CorInfoExceptionClass* pException = nullptr; - _callbacks->doneWritingCode(_thisHandle, &pException); - if (pException != nullptr) throw pException; -} }; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index b2005c737095d7..14e1c153c116ab 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12412,19 +12412,6 @@ void CEEJitInfo::getEHinfo( EE_TO_JIT_TRANSITION(); } -void CEEJitInfo::doneWritingCode() -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - JIT_TO_EE_TRANSITION(); - - EE_TO_JIT_TRANSITION(); -} - #endif // CROSSGEN_COMPILE @@ -14257,12 +14244,6 @@ void CEEInfo::allocMem (AllocMemArgs *pArgs) UNREACHABLE(); // only called on derived class. } -void CEEInfo::doneWritingCode () -{ - LIMITED_METHOD_CONTRACT; - UNREACHABLE(); // only called on derived class. -} - void CEEInfo::reserveUnwindInfo ( bool isFunclet, /* IN */ bool isColdCode, /* IN */ diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 6ccceb0bf8a9b0..9a68805e02453a 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -664,8 +664,6 @@ class CEEJitInfo : public CEEInfo CORINFO_EH_CLAUSE* clause /* OUT */ ) override final; - void doneWritingCode() override final; - HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, /* IN */ PgoInstrumentationSchema* pSchema, /* IN/OUT */ diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp index 9b74518376b6dd..11a27f7d1a2ebe 100644 --- a/src/coreclr/zap/zapinfo.cpp +++ b/src/coreclr/zap/zapinfo.cpp @@ -4120,10 +4120,6 @@ bool ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig); } -void ZapInfo::doneWritingCode() -{ -} - LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void ** ppIndirection) {