From 5b0d11199811433cf09f772a7ad9bab9a7cd1595 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 9 Apr 2024 18:22:47 +0200 Subject: [PATCH 01/14] Simplify "secret stub arg" handling between JIT and EE Fix #100662 --- src/coreclr/inc/corinfo.h | 1 + src/coreclr/inc/jiteeversionguid.h | 10 ++--- src/coreclr/jit/codegen.h | 1 + src/coreclr/jit/codegencommon.cpp | 37 ++++++++++++++----- src/coreclr/jit/compiler.cpp | 5 --- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/lclvars.cpp | 35 ------------------ src/coreclr/jit/lower.cpp | 11 ++++++ .../tools/Common/JitInterface/CorInfoTypes.cs | 1 + src/coreclr/vm/frames.h | 30 ++------------- src/coreclr/vm/jithelpers.cpp | 3 +- src/coreclr/vm/jitinterface.cpp | 1 + src/coreclr/vm/jitinterface.h | 2 +- 13 files changed, 53 insertions(+), 86 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 35f7d2f0bdf86..56ce0181def67 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -1761,6 +1761,7 @@ struct CORINFO_EE_INFO unsigned offsetOfCalleeSavedFP; unsigned offsetOfCallTarget; unsigned offsetOfReturnAddress; + unsigned offsetOfSecretStubArg; // This offset is used only for ARM unsigned offsetOfSPAfterProlog; } diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 0e9f6e2940bcb..6d038438b6127 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 3c216494-65f8-49e2-b69a-7f272193bcc6 */ - 0x3c216494, - 0x65f8, - 0x49e2, - {0xb6, 0x9a, 0x7f, 0x27, 0x21, 0x93, 0xbc, 0xc6} +constexpr GUID JITEEVersionIdentifier = { /* 589cc249-f57e-4ed2-a6ae-db386be96b84 */ + 0x589cc249, + 0xf57e, + 0x4ed2, + {0xa6, 0xae, 0xdb, 0x38, 0x6b, 0xe9, 0x6b, 0x84} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index b5b0d19402f0a..b9d4edcf3b32b 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -267,6 +267,7 @@ class CodeGen final : public CodeGenInterface var_types genParamStackStoreType(LclVarDsc* dsc, const ABIPassingSegment& seg); void genSpillOrAddRegisterParam(unsigned lclNum, class RegGraph* graph); + void genSpillOrAddSimpleRegisterParam(unsigned lclNum, regNumber sourceReg, class RegGraph* graph); void genEnregisterIncomingStackArgs(); #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) void genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 1edfb2ea124a7..335e0b4e7b9a8 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3141,6 +3141,22 @@ void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) } } +void CodeGen::genSpillOrAddSimpleRegisterParam(unsigned lclNum, regNumber sourceReg, RegGraph* graph) +{ + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + if (varDsc->lvOnFrame && (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)) + { + GetEmitter()->emitIns_S_R(ins_Store(varDsc->TypeGet()), emitActualTypeSize(varDsc), sourceReg, lclNum, 0); + } + + if (varDsc->lvIsInReg()) + { + RegNode* sourceRegNode = graph->GetOrAdd(sourceReg); + RegNode* destRegNode = graph->GetOrAdd(varDsc->GetRegNum()); + graph->AddEdge(sourceRegNode, destRegNode, TYP_I_IMPL, 0); + } +} + // ----------------------------------------------------------------------------- // genHomeRegisterParams: Move all register parameters to their initial // assigned location. @@ -3184,6 +3200,12 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) + { + GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, + compiler->lvaStubArgumentVar, 0); + } + return; } @@ -3216,6 +3238,11 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) + { + genSpillOrAddSimpleRegisterParam(compiler->lvaStubArgumentVar, REG_SECRET_STUB_PARAM, &graph); + } + DBEXEC(VERBOSE, graph.Dump()); regMaskTP busyRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; @@ -5406,16 +5433,6 @@ void CodeGen::genFnProlog() } #endif // TARGET_ARM - if (compiler->info.compPublishStubParam) - { - GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, - compiler->lvaStubArgumentVar, 0); - assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); - - // It's no longer live; clear it out so it can be used after this in the prolog - intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; - } - // // Zero out the frame as needed // diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c834a4f6f2781..0753a42335d48 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4591,11 +4591,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl assert(lvaStubArgumentVar == BAD_VAR_NUM); lvaStubArgumentVar = lvaGrabTempWithImplicitUse(false DEBUGARG("stub argument")); lvaGetDesc(lvaStubArgumentVar)->lvType = TYP_I_IMPL; - // TODO-CQ: there is no need to mark it as doNotEnreg. There are no stores for this local - // before codegen so liveness and LSRA mark it as "liveIn" and always allocate a stack slot for it. - // However, it would be better to process it like other argument locals and keep it in - // a reg for the whole method without spilling to the stack when possible. - lvaSetVarDoNotEnregister(lvaStubArgumentVar DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); } }; DoPhase(this, PHASE_PRE_IMPORT, preImportPhase); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 05b3e07ebf63d..e471f56c1bb87 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4238,7 +4238,7 @@ class Compiler return lvaGetDesc(lclNum)->lvInSsa; } - unsigned lvaStubArgumentVar; // variable representing the secret stub argument coming in EAX + unsigned lvaStubArgumentVar; // variable representing the secret stub argument unsigned lvaPSPSym; // variable representing the PSPSym diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 774eee3fe3cb2..6df228d89da25 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -7076,22 +7076,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() continue; } - // This should be low on the stack. Hence, it will be assigned later. - if (lclNum == lvaStubArgumentVar) - { -#ifdef JIT32_GCENCODER - noway_assert(codeGen->isFramePointerUsed()); -#endif - continue; - } - - // This should be low on the stack. Hence, it will be assigned later. - if (lclNum == lvaInlinedPInvokeFrameVar) - { - noway_assert(codeGen->isFramePointerUsed()); - continue; - } - if (varDsc->lvIsParam) { #ifdef TARGET_ARM64 @@ -7234,25 +7218,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() *------------------------------------------------------------------------- */ - // lvaInlinedPInvokeFrameVar and lvaStubArgumentVar need to be assigned last - // Important: The stack walker depends on lvaStubArgumentVar immediately - // following lvaInlinedPInvokeFrameVar in the frame. - - if (lvaStubArgumentVar != BAD_VAR_NUM) - { -#ifdef JIT32_GCENCODER - noway_assert(codeGen->isFramePointerUsed()); -#endif - stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaStubArgumentVar, lvaLclSize(lvaStubArgumentVar), stkOffs); - } - - if (lvaInlinedPInvokeFrameVar != BAD_VAR_NUM) - { - noway_assert(codeGen->isFramePointerUsed()); - stkOffs = - lvaAllocLocalAndSetVirtualOffset(lvaInlinedPInvokeFrameVar, lvaLclSize(lvaInlinedPInvokeFrameVar), stkOffs); - } - #ifdef JIT32_GCENCODER // JIT32 encoder cannot handle GS cookie at fp+0 since NO_GS_COOKIE == 0. // Add some padding if it is the last allocated local. diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 0427cf666a3bc..74ab73f2168e9 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5605,6 +5605,7 @@ void Lowering::InsertPInvokeMethodProlog() const LclVarDsc* inlinedPInvokeDsc = comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar); assert(inlinedPInvokeDsc->IsAddressExposed()); #endif // DEBUG + GenTree* frameAddr = new (comp, GT_LCL_ADDR) GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); @@ -5614,6 +5615,7 @@ void Lowering::InsertPInvokeMethodProlog() NewCallArg frameAddrArg = NewCallArg::Primitive(frameAddr).WellKnown(WellKnownArg::PInvokeFrame); call->gtArgs.PushBack(comp, frameAddrArg); + // for x86/arm32 don't pass the secretArg. #if !defined(TARGET_X86) && !defined(TARGET_ARM) NewCallArg stubParamArg = @@ -5669,6 +5671,15 @@ void Lowering::InsertPInvokeMethodProlog() DISPTREERANGE(firstBlockRange, storeFP); #endif // !defined(TARGET_ARM) + // InlinedCallFrame.m_StubSecretArg = stubSecretArg; + if (comp->info.compPublishStubParam) + { + GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); + GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + callFrameInfo.offsetOfSecretStubArg, value); + firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); + } + // -------------------------------------------------------- // On 32-bit targets, CORINFO_HELP_INIT_PINVOKE_FRAME initializes the PInvoke frame and then pushes it onto // the current thread's Frame stack. On 64-bit targets, it only initializes the PInvoke frame. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 2276c5cdc9a7c..5f914cbaea357 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -843,6 +843,7 @@ public struct InlinedCallFrameInfo public uint offsetOfCalleeSavedFP; public uint offsetOfCallTarget; public uint offsetOfReturnAddress; + public uint offsetOfSecretStubArg; public uint offsetOfSPAfterProlog; } public InlinedCallFrameInfo inlinedCallFrameInfo; diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index ea7eb1e194136..ab756163fc49f 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -730,7 +730,7 @@ class Frame : public FrameBase friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo); #endif #ifdef HOST_64BIT - friend Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg); + friend Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef FEATURE_EH_FUNCLETS friend class ExceptionTracker; @@ -2852,31 +2852,9 @@ class InlinedCallFrame : public Frame // method if the current InlinedCallFrame is inactive. PTR_MethodDesc GetActualInteropMethodDesc() { -#if defined(TARGET_X86) || defined(TARGET_ARM) - // Important: This code relies on the way JIT lays out frames. Keep it in sync - // with code:Compiler.lvaAssignFrameOffsets. - // - // | ... | - // +--------------------+ - // | lvaStubArgumentVar | <= filled with EAX in prolog | - // +--------------------+ | - // | | | - // | InlinedCallFrame | | - // | | <= m_pCrawl.pFrame | to lower addresses - // +--------------------+ V - // | ... | - // - // Extract the actual MethodDesc to report from the InlinedCallFrame. - TADDR addr = dac_cast(this) + sizeof(InlinedCallFrame); - return PTR_MethodDesc(*PTR_TADDR(addr)); -#elif defined(HOST_64BIT) - // On 64bit, the actual interop MethodDesc is saved off in a field off the InlinedCrawlFrame + // The actual interop MethodDesc is saved off in a field off the InlinedCrawlFrame // which is populated by the JIT. Refer to JIT_InitPInvokeFrame for details. return PTR_MethodDesc(m_StubSecretArg); -#else - _ASSERTE(!"NYI - Interop method reporting for this architecture!"); - return NULL; -#endif // defined(TARGET_X86) || defined(TARGET_ARM) } virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); @@ -2890,12 +2868,10 @@ class InlinedCallFrame : public Frame // See code:HasFunction. PTR_NDirectMethodDesc m_Datum; -#ifdef HOST_64BIT // IL stubs fill this field with the incoming secret argument when they erect // InlinedCallFrame so we know which interop method was invoked even if the frame // is not active at the moment. - PTR_VOID m_StubSecretArg; -#endif // HOST_64BIT + PTR_VOID m_StubSecretArg; // X86: ESP after pushing the outgoing arguments, and just before calling // out to unmanaged code. diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 3aae4a155fc77..e2e5890d837c5 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -6049,7 +6049,7 @@ HCIMPLEND /* Fills out portions of an InlinedCallFrame for JIT64 */ /* The idea here is to allocate and initialize the frame to only once, */ /* regardless of how many PInvokes there are in the method */ -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg) +Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame) { CONTRACTL { @@ -6063,7 +6063,6 @@ Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubS _ASSERTE(pFrame != pThread->GetFrame()); pFrame->Init(); - pFrame->m_StubSecretArg = StubSecretArg; pFrame->m_Next = pThread->GetFrame(); return pThread; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 1f1f1bcea1e9a..d212bdabb82bc 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10061,6 +10061,7 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) pInfo->offsetOfCalleeSavedFP = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCalleeSavedFP); pInfo->offsetOfCallTarget = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_Datum); pInfo->offsetOfReturnAddress = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallerReturnAddress); + pInfo->offsetOfSecretStubArg = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_StubSecretArg); #ifdef TARGET_ARM pInfo->offsetOfSPAfterProlog = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pSPAfterProlog); #endif // TARGET_ARM diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 7429352a47de6..1cf1460a009f8 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -1082,7 +1082,7 @@ EXTERN_C TypeHandle::CastResult STDCALL ObjIsInstanceOfCached(Object *pObject, T #ifdef HOST_64BIT class InlinedCallFrame; -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg); +Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef _DEBUG From e9469d7687f15cefdeda90b40b53364609c94c18 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 10 Apr 2024 12:30:43 +0200 Subject: [PATCH 02/14] Disallow enregistration for now --- src/coreclr/jit/codegencommon.cpp | 37 +++++++++---------------------- src/coreclr/jit/compiler.cpp | 5 +++++ src/coreclr/vm/frames.h | 4 ++-- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 335e0b4e7b9a8..1edfb2ea124a7 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3141,22 +3141,6 @@ void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) } } -void CodeGen::genSpillOrAddSimpleRegisterParam(unsigned lclNum, regNumber sourceReg, RegGraph* graph) -{ - LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); - if (varDsc->lvOnFrame && (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)) - { - GetEmitter()->emitIns_S_R(ins_Store(varDsc->TypeGet()), emitActualTypeSize(varDsc), sourceReg, lclNum, 0); - } - - if (varDsc->lvIsInReg()) - { - RegNode* sourceRegNode = graph->GetOrAdd(sourceReg); - RegNode* destRegNode = graph->GetOrAdd(varDsc->GetRegNum()); - graph->AddEdge(sourceRegNode, destRegNode, TYP_I_IMPL, 0); - } -} - // ----------------------------------------------------------------------------- // genHomeRegisterParams: Move all register parameters to their initial // assigned location. @@ -3200,12 +3184,6 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } - if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) - { - GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, - compiler->lvaStubArgumentVar, 0); - } - return; } @@ -3238,11 +3216,6 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } - if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) - { - genSpillOrAddSimpleRegisterParam(compiler->lvaStubArgumentVar, REG_SECRET_STUB_PARAM, &graph); - } - DBEXEC(VERBOSE, graph.Dump()); regMaskTP busyRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; @@ -5433,6 +5406,16 @@ void CodeGen::genFnProlog() } #endif // TARGET_ARM + if (compiler->info.compPublishStubParam) + { + GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, + compiler->lvaStubArgumentVar, 0); + assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); + + // It's no longer live; clear it out so it can be used after this in the prolog + intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; + } + // // Zero out the frame as needed // diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 0753a42335d48..c834a4f6f2781 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4591,6 +4591,11 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl assert(lvaStubArgumentVar == BAD_VAR_NUM); lvaStubArgumentVar = lvaGrabTempWithImplicitUse(false DEBUGARG("stub argument")); lvaGetDesc(lvaStubArgumentVar)->lvType = TYP_I_IMPL; + // TODO-CQ: there is no need to mark it as doNotEnreg. There are no stores for this local + // before codegen so liveness and LSRA mark it as "liveIn" and always allocate a stack slot for it. + // However, it would be better to process it like other argument locals and keep it in + // a reg for the whole method without spilling to the stack when possible. + lvaSetVarDoNotEnregister(lvaStubArgumentVar DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); } }; DoPhase(this, PHASE_PRE_IMPORT, preImportPhase); diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index ab756163fc49f..f7ad9633413ab 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -2852,8 +2852,8 @@ class InlinedCallFrame : public Frame // method if the current InlinedCallFrame is inactive. PTR_MethodDesc GetActualInteropMethodDesc() { - // The actual interop MethodDesc is saved off in a field off the InlinedCrawlFrame - // which is populated by the JIT. Refer to JIT_InitPInvokeFrame for details. + // The actual interop MethodDesc is saved off in a field in the InlinedCrawlFrame + // which is populated by the JIT in `InsertPInvokeMethodProlog`. return PTR_MethodDesc(m_StubSecretArg); } From 7959a4e89919d5a523ee6c4e7437cf2068a34bf2 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 10 Apr 2024 12:39:45 +0200 Subject: [PATCH 03/14] Fix offsets --- src/coreclr/jit/lower.cpp | 18 +++++++++--------- src/coreclr/vm/arm/asmconstants.h | 10 +++++----- src/coreclr/vm/i386/asmconstants.h | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 74ab73f2168e9..997d946a3f875 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5557,19 +5557,19 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // +08h +04h vptr for class InlinedCallFrame offsetOfFrameVptr method prolog // +10h +08h m_Next offsetOfFrameLink method prolog // +18h +0Ch m_Datum offsetOfCallTarget call site -// +20h n/a m_StubSecretArg not set by JIT -// +28h +10h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method +// +20h +10h m_StubSecretArg offsetOfSecretStubArg method prolog +// +28h +14h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method // prolog; // non-x86: method prolog (SP remains // constant in function, after prolog: no // localloc and PInvoke in same function) -// +30h +14h m_pCallerReturnAddress offsetOfReturnAddress call site -// +38h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT -// +1Ch m_pThread -// +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +20/24h JIT retval spill area (int) before call_gc ??? -// +24/28h JIT retval spill area (long) before call_gc ??? -// +28/2Ch Saved value of EBP method prolog ??? +// +30h +18h m_pCallerReturnAddress offsetOfReturnAddress call site +// +38h +1Ch m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT +// +20h m_pThread +// +24h m_pSPAfterProlog offsetOfSPAfterProlog arm only +// +24/28h JIT retval spill area (int) before call_gc ??? +// +28/2Ch JIT retval spill area (long) before call_gc ??? +// +2C/30h Saved value of EBP method prolog ??? // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 5c92427008bb4..7124a62025e1e 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -196,19 +196,19 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x08 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x0C +#define InlinedCallFrame__m_pCallSiteSP 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x10 +#define InlinedCallFrame__m_pCallerReturnAddress 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x14 +#define InlinedCallFrame__m_pCalleeSavedFP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x18 +#define InlinedCallFrame__m_pThread 0x1C ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) -#define InlinedCallFrame__m_pSPAfterProlog 0x1C +#define InlinedCallFrame__m_pSPAfterProlog 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pSPAfterProlog == offsetof(InlinedCallFrame, m_pSPAfterProlog)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index edafbdf72ae71..98940913abb2b 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -287,13 +287,13 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)); #define InlinedCallFrame__m_Datum 0x08 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)); -#define InlinedCallFrame__m_pCallSiteSP 0x0C +#define InlinedCallFrame__m_pCallSiteSP 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)); -#define InlinedCallFrame__m_pCallerReturnAddress 0x10 +#define InlinedCallFrame__m_pCallerReturnAddress 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)); -#define InlinedCallFrame__m_pCalleeSavedFP 0x14 +#define InlinedCallFrame__m_pCalleeSavedFP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); #ifdef FEATURE_STUBS_AS_IL From afcb375091d490ea9c04a42852e631ae99230b43 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 10 Apr 2024 12:41:23 +0200 Subject: [PATCH 04/14] Delete stub param --- src/coreclr/jit/codegen.h | 1 - src/coreclr/jit/gentree.cpp | 2 -- src/coreclr/jit/gentree.h | 1 - src/coreclr/jit/lower.cpp | 7 ------- src/coreclr/jit/morph.cpp | 2 -- 5 files changed, 13 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index b9d4edcf3b32b..b5b0d19402f0a 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -267,7 +267,6 @@ class CodeGen final : public CodeGenInterface var_types genParamStackStoreType(LclVarDsc* dsc, const ABIPassingSegment& seg); void genSpillOrAddRegisterParam(unsigned lclNum, class RegGraph* graph); - void genSpillOrAddSimpleRegisterParam(unsigned lclNum, regNumber sourceReg, class RegGraph* graph); void genEnregisterIncomingStackArgs(); #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) void genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 7e90d26a3d682..b0c3df37614fa 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -13133,8 +13133,6 @@ const char* Compiler::gtGetWellKnownArgNameForArgMsg(WellKnownArg arg) return "retbuf"; case WellKnownArg::PInvokeFrame: return "pinv frame"; - case WellKnownArg::SecretStubParam: - return "stub param"; case WellKnownArg::WrapperDelegateCell: return "wrap cell"; case WellKnownArg::ShiftLow: diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index d5dbad500c16d..cf5e1fdca4573 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4439,7 +4439,6 @@ enum class WellKnownArg : unsigned InstParam, RetBuffer, PInvokeFrame, - SecretStubParam, WrapperDelegateCell, ShiftLow, ShiftHigh, diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 997d946a3f875..58aac4f644f26 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5616,13 +5616,6 @@ void Lowering::InsertPInvokeMethodProlog() NewCallArg frameAddrArg = NewCallArg::Primitive(frameAddr).WellKnown(WellKnownArg::PInvokeFrame); call->gtArgs.PushBack(comp, frameAddrArg); -// for x86/arm32 don't pass the secretArg. -#if !defined(TARGET_X86) && !defined(TARGET_ARM) - NewCallArg stubParamArg = - NewCallArg::Primitive(PhysReg(REG_SECRET_STUB_PARAM)).WellKnown(WellKnownArg::SecretStubParam); - call->gtArgs.PushBack(comp, stubParamArg); -#endif - // some sanity checks on the frame list root vardsc const unsigned lclNum = comp->info.compLvFrameListRoot; const LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 8e9b07e8da6cc..216a05f4a0260 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -765,8 +765,6 @@ const char* getWellKnownArgName(WellKnownArg arg) return "RetBuffer"; case WellKnownArg::PInvokeFrame: return "PInvokeFrame"; - case WellKnownArg::SecretStubParam: - return "SecretStubParam"; case WellKnownArg::WrapperDelegateCell: return "WrapperDelegateCell"; case WellKnownArg::ShiftLow: From 6da2f44435f80f19934692cc7f2a2ba2f4e9ee4f Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 10 Apr 2024 16:32:07 +0200 Subject: [PATCH 05/14] Home stub argument correctly, clean up a bit --- src/coreclr/jit/codegencommon.cpp | 20 +++++------ src/coreclr/jit/lower.cpp | 56 +++++++++++++------------------ 2 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 1edfb2ea124a7..c7125f84021cc 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -5406,16 +5406,6 @@ void CodeGen::genFnProlog() } #endif // TARGET_ARM - if (compiler->info.compPublishStubParam) - { - GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, - compiler->lvaStubArgumentVar, 0); - assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); - - // It's no longer live; clear it out so it can be used after this in the prolog - intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; - } - // // Zero out the frame as needed // @@ -5509,6 +5499,16 @@ void CodeGen::genFnProlog() * Take care of register arguments first */ + if (compiler->info.compPublishStubParam) + { + GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, + compiler->lvaStubArgumentVar, 0); + assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); + + // It's no longer live; clear it out so it can be used after this in the prolog + intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; + } + #ifdef SWIFT_SUPPORT if (compiler->info.compCallConv == CorInfoCallConvExtension::Swift) { diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 58aac4f644f26..b1cd8b33e77c7 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5514,7 +5514,7 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) const CORINFO_EE_INFO* pInfo = comp->eeGetEEInfo(); const CORINFO_EE_INFO::InlinedCallFrameInfo& callFrameInfo = pInfo->inlinedCallFrameInfo; - GenTree* TCB = new (comp, GT_LCL_VAR) GenTreeLclVar(GT_LCL_VAR, TYP_I_IMPL, comp->info.compLvFrameListRoot); + GenTree* TCB = comp->gtNewLclVarNode(comp->info.compLvFrameListRoot, TYP_I_IMPL); // Thread->m_pFrame GenTree* addr = new (comp, GT_LEA) GenTreeAddrMode(TYP_I_IMPL, TCB, nullptr, 1, pInfo->offsetOfThreadFrame); @@ -5524,18 +5524,17 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) if (action == PushFrame) { // Thread->m_pFrame = &inlinedCallFrame; - data = new (comp, GT_LCL_ADDR) - GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + data = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); } else { assert(action == PopFrame); // Thread->m_pFrame = inlinedCallFrame.m_pNext; - data = new (comp, GT_LCL_FLD) GenTreeLclFld(GT_LCL_FLD, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, - pInfo->inlinedCallFrameInfo.offsetOfFrameLink); + data = comp->gtNewLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + pInfo->inlinedCallFrameInfo.offsetOfFrameLink); } - GenTree* storeInd = new (comp, GT_STOREIND) GenTreeStoreInd(TYP_I_IMPL, addr, data); + GenTree* storeInd = comp->gtNewStoreIndNode(TYP_I_IMPL, addr, data); return storeInd; } @@ -5600,20 +5599,16 @@ void Lowering::InsertPInvokeMethodProlog() const CORINFO_EE_INFO* pInfo = comp->eeGetEEInfo(); const CORINFO_EE_INFO::InlinedCallFrameInfo& callFrameInfo = pInfo->inlinedCallFrameInfo; -// First arg: &compiler->lvaInlinedPInvokeFrameVar + callFrameInfo.offsetOfFrameVptr -#if defined(DEBUG) - const LclVarDsc* inlinedPInvokeDsc = comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar); - assert(inlinedPInvokeDsc->IsAddressExposed()); -#endif // DEBUG + assert(comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar)->IsAddressExposed()); - GenTree* frameAddr = new (comp, GT_LCL_ADDR) - GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: - // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart, secretArg); - GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL); - + // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart); + GenTree* frameAddr = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); NewCallArg frameAddrArg = NewCallArg::Primitive(frameAddr).WellKnown(WellKnownArg::PInvokeFrame); + + GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL); call->gtArgs.PushBack(comp, frameAddrArg); // some sanity checks on the frame list root vardsc @@ -5622,16 +5617,22 @@ void Lowering::InsertPInvokeMethodProlog() noway_assert(!varDsc->lvIsParam); noway_assert(varDsc->lvType == TYP_I_IMPL); - GenTree* store = new (comp, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, TYP_I_IMPL, lclNum); - store->AsOp()->gtOp1 = call; - store->gtFlags |= GTF_VAR_DEF; - - GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); - + GenTree* store = comp->gtNewStoreLclVarNode(lclNum, call); comp->fgMorphTree(store); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); DISPTREERANGE(firstBlockRange, store); + // Store the stub secret arg if necessary. + // InlinedCallFrame.m_StubSecretArg = stubSecretArg; + if (comp->info.compPublishStubParam) + { + GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); + GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + callFrameInfo.offsetOfSecretStubArg, value); + firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); + DISPTREERANGE(firstBlockRange, store); + } + #if !defined(TARGET_X86) && !defined(TARGET_ARM) // For x86, this step is done at the call site (due to stack pointer not being static in the function). // For arm32, CallSiteSP is set up by the call to CORINFO_HELP_INIT_PINVOKE_FRAME. @@ -5642,7 +5643,6 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* spValue = PhysReg(REG_SPBASE); GenTreeLclFld* storeSP = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, callFrameInfo.offsetOfCallSiteSP, spValue); - assert(inlinedPInvokeDsc->lvDoNotEnregister); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeSP)); DISPTREERANGE(firstBlockRange, storeSP); @@ -5658,21 +5658,11 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* fpValue = PhysReg(REG_FPBASE); GenTreeLclFld* storeFP = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, callFrameInfo.offsetOfCalleeSavedFP, fpValue); - assert(inlinedPInvokeDsc->lvDoNotEnregister); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeFP)); DISPTREERANGE(firstBlockRange, storeFP); #endif // !defined(TARGET_ARM) - // InlinedCallFrame.m_StubSecretArg = stubSecretArg; - if (comp->info.compPublishStubParam) - { - GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); - GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, - callFrameInfo.offsetOfSecretStubArg, value); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); - } - // -------------------------------------------------------- // On 32-bit targets, CORINFO_HELP_INIT_PINVOKE_FRAME initializes the PInvoke frame and then pushes it onto // the current thread's Frame stack. On 64-bit targets, it only initializes the PInvoke frame. From fb3d473a4aee8767a4fce4f46cef7f3f6f6a9fc1 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 11 Apr 2024 11:39:41 +0200 Subject: [PATCH 06/14] Make stub arg dynamic --- src/coreclr/inc/corinfo.h | 3 +++ src/coreclr/jit/codegencommon.cpp | 7 ------- src/coreclr/jit/flowgraph.cpp | 4 +++- .../tools/Common/JitInterface/CorInfoImpl.cs | 3 ++- .../tools/Common/JitInterface/CorInfoTypes.cs | 3 +++ .../tools/Common/JitInterface/MemoryHelper.cs | 17 ----------------- .../ILCompiler.Compiler.csproj | 3 --- .../ILCompiler.ReadyToRun.csproj | 3 --- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 8 ++++---- .../ILCompiler.RyuJit/ILCompiler.RyuJit.csproj | 3 --- .../JitInterface/CorInfoImpl.RyuJit.cs | 8 ++++---- src/coreclr/vm/amd64/asmconstants.h | 8 ++++---- src/coreclr/vm/arm/asmconstants.h | 10 +++++----- src/coreclr/vm/arm64/asmconstants.h | 8 ++++---- src/coreclr/vm/frames.h | 12 ++++-------- src/coreclr/vm/i386/asmconstants.h | 6 +++--- src/coreclr/vm/jitinterface.cpp | 3 ++- src/coreclr/vm/loongarch64/asmconstants.h | 8 ++++---- src/coreclr/vm/riscv64/asmconstants.h | 8 ++++---- 19 files changed, 49 insertions(+), 76 deletions(-) delete mode 100644 src/coreclr/tools/Common/JitInterface/MemoryHelper.cs diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 56ce0181def67..06edf0bde3a47 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -1754,6 +1754,9 @@ struct CORINFO_EE_INFO // Size of the Frame structure unsigned size; + // Size of the Frame structure when it also contains the secret stub arg + unsigned sizeWithSecretStubArg; + unsigned offsetOfGSCookie; unsigned offsetOfFrameVptr; unsigned offsetOfFrameLink; diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index c7125f84021cc..46e46554b2913 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3681,13 +3681,6 @@ void CodeGen::genCheckUseBlockInit() { regMaskTP maskCalleeRegArgMask = intRegState.rsCalleeRegArgMaskLiveIn; - // If there is a secret stub param, don't count it, as it will no longer - // be live when we do block init. - if (compiler->info.compPublishStubParam) - { - maskCalleeRegArgMask &= ~RBM_SECRET_STUB_PARAM; - } - #ifdef TARGET_ARM // // On the Arm if we are using a block init to initialize, then we diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 600907981ad37..abd3db07fbf4a 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2437,7 +2437,9 @@ PhaseStatus Compiler::fgAddInternal() LclVarDsc* varDsc = lvaGetDesc(lvaInlinedPInvokeFrameVar); // Make room for the inlined frame. - lvaSetStruct(lvaInlinedPInvokeFrameVar, typGetBlkLayout(eeGetEEInfo()->inlinedCallFrameInfo.size), false); + const CORINFO_EE_INFO* eeInfo = eeGetEEInfo(); + unsigned frameSize = info.compPublishStubParam ? eeInfo->inlinedCallFrameInfo.sizeWithSecretStubArg : eeInfo->inlinedCallFrameInfo.size; + lvaSetStruct(lvaInlinedPInvokeFrameVar, typGetBlkLayout(frameSize), false); } // Do we need to insert a "JustMyCode" callback? diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 9366e1aa65b6d..a3ff6fe404594 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3278,12 +3278,13 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut) // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_EE_INFO* tmp = &pEEInfoOut) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_EE_INFO), 0xcc); #endif int pointerSize = this.PointerSize; pEEInfoOut.inlinedCallFrameInfo.size = (uint)SizeOfPInvokeTransitionFrame; + pEEInfoOut.inlinedCallFrameInfo.sizeWithSecretStubArg = (uint)SizeOfPInvokeTransitionFrame + (uint)pointerSize; pEEInfoOut.offsetOfDelegateInstance = (uint)pointerSize; // Delegate::_firstParameter pEEInfoOut.offsetOfDelegateFirstTarget = OffsetOfDelegateFirstTarget; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 5f914cbaea357..fcd97ba005448 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -836,6 +836,9 @@ public struct InlinedCallFrameInfo // Size of the Frame structure public uint size; + // Size of the Frame structure inside IL stubs that include secret stub arg in the frame + public uint sizeWithSecretStubArg; + public uint offsetOfGSCookie; public uint offsetOfFrameVptr; public uint offsetOfFrameLink; diff --git a/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs b/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs deleted file mode 100644 index ac009bcd17da1..0000000000000 --- a/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Internal.JitInterface -{ - internal static unsafe class MemoryHelper - { - public static void FillMemory(byte* dest, byte fill, int count) - { - for (; count > 0; count--) - { - *dest = fill; - dest++; - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 37c8c2108d917..7b4b101a3dbc7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -730,9 +730,6 @@ JitInterface\CorInfoTypes.VarInfo.cs - - JitInterface\MemoryHelper.cs - TypeSystem\TypesDebugInfoWriter\TypesDebugInfoWriter.cs diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 04fb0838bee7d..96e6df9805eb0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -332,9 +332,6 @@ JitInterface\JitConfigProvider.cs - - JitInterface\MemoryHelper.cs - JitInterface\UnboxingMethodDesc.cs diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index e1b1b359c0878..9c7ca0b7ecb86 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -934,7 +934,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_LOOKUP* tmp = &pLookup) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, sizeof(CORINFO_LOOKUP)); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_LOOKUP), 0xcc); #endif TypeDesc delegateTypeDesc = HandleToObject(delegateType); @@ -1660,7 +1660,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. - MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(pResult, (nuint)sizeof(CORINFO_FIELD_INFO), 0xcc); #endif Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET | @@ -1844,7 +1844,7 @@ private void ceeInfoGetCallInfo( #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. - MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(pResult, (nuint)sizeof(CORINFO_CALL_INFO), 0xcc); #endif pResult->codePointerOrStubLookup.lookupKind.needsRuntimeLookup = false; @@ -2645,7 +2645,7 @@ private void ceeInfoEmbedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_GENERICHANDLE_RESULT* tmp = &pResult) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_GENERICHANDLE_RESULT), 0xcc); #endif bool runtimeLookup = false; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj index e785f9b427190..3ddf3e46a13cb 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj @@ -73,9 +73,6 @@ JitInterface\CorInfoImpl.cs - - JitInterface\MemoryHelper.cs - JitInterface\UnboxingMethodDesc.cs diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 2be89e7374f59..1755ef4a162f8 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -363,7 +363,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_LOOKUP* tmp = &pLookup) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, sizeof(CORINFO_LOOKUP)); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_LOOKUP), 0xcc); #endif MethodDesc expectedTargetMethod = HandleToObject(pTargetMethod.hMethod); @@ -1190,7 +1190,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. - MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(pResult, (nuint)sizeof(CORINFO_CALL_INFO), 0xcc); #endif MethodDesc method = HandleToObject(pResolvedToken.hMethod); @@ -1698,7 +1698,7 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_GENERICHANDLE_RESULT* tmp = &pResult) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_GENERICHANDLE_RESULT), 0xcc); #endif ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid; object target = null; @@ -2057,7 +2057,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET #if DEBUG // In debug, write some bogus data to the struct to ensure we have filled everything // properly. - MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(pResult, (nuint)sizeof(CORINFO_FIELD_INFO), 0xcc); #endif Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET | diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 47cca560d7bb1..1c562a5f9fd57 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -504,19 +504,19 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__StringObject__m_StringLength ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)); -#define OFFSETOF__InlinedCallFrame__m_pCallSiteSP 0x20 +#define OFFSETOF__InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)); -#define OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)); -#define OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); -#define OFFSETOF__InlinedCallFrame__m_pThread 0x38 +#define OFFSETOF__InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)); diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 7124a62025e1e..5c92427008bb4 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -196,19 +196,19 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x08 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x10 +#define InlinedCallFrame__m_pCallSiteSP 0x0C ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x14 +#define InlinedCallFrame__m_pCallerReturnAddress 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x18 +#define InlinedCallFrame__m_pCalleeSavedFP 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x1C +#define InlinedCallFrame__m_pThread 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) -#define InlinedCallFrame__m_pSPAfterProlog 0x20 +#define InlinedCallFrame__m_pSPAfterProlog 0x1C ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pSPAfterProlog == offsetof(InlinedCallFrame, m_pSPAfterProlog)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index 262fa6860df73..8cf912a46003f 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -201,16 +201,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index f7ad9633413ab..47d8c4f33f562 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -2852,9 +2852,10 @@ class InlinedCallFrame : public Frame // method if the current InlinedCallFrame is inactive. PTR_MethodDesc GetActualInteropMethodDesc() { - // The actual interop MethodDesc is saved off in a field in the InlinedCrawlFrame - // which is populated by the JIT in `InsertPInvokeMethodProlog`. - return PTR_MethodDesc(m_StubSecretArg); + // The VM instructs the JIT to publish the secret stub arg at the end + // of the InlinedCallFrame structure when it exists. + TADDR addr = dac_cast(this) + sizeof(InlinedCallFrame); + return PTR_MethodDesc(*PTR_TADDR(addr)); } virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); @@ -2868,11 +2869,6 @@ class InlinedCallFrame : public Frame // See code:HasFunction. PTR_NDirectMethodDesc m_Datum; - // IL stubs fill this field with the incoming secret argument when they erect - // InlinedCallFrame so we know which interop method was invoked even if the frame - // is not active at the moment. - PTR_VOID m_StubSecretArg; - // X86: ESP after pushing the outgoing arguments, and just before calling // out to unmanaged code. // Other platforms: the field stays set throughout the declaring method. diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index 98940913abb2b..edafbdf72ae71 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -287,13 +287,13 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)); #define InlinedCallFrame__m_Datum 0x08 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)); -#define InlinedCallFrame__m_pCallSiteSP 0x10 +#define InlinedCallFrame__m_pCallSiteSP 0x0C ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)); -#define InlinedCallFrame__m_pCallerReturnAddress 0x14 +#define InlinedCallFrame__m_pCallerReturnAddress 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)); -#define InlinedCallFrame__m_pCalleeSavedFP 0x18 +#define InlinedCallFrame__m_pCalleeSavedFP 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); #ifdef FEATURE_STUBS_AS_IL diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index d212bdabb82bc..da3d93ea8b309 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10053,6 +10053,7 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) LIMITED_METHOD_CONTRACT; pInfo->size = sizeof(GSCookie) + sizeof(InlinedCallFrame); + pInfo->sizeWithSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame) + sizeof(PTR_VOID); pInfo->offsetOfGSCookie = 0; pInfo->offsetOfFrameVptr = sizeof(GSCookie); @@ -10061,7 +10062,7 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) pInfo->offsetOfCalleeSavedFP = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCalleeSavedFP); pInfo->offsetOfCallTarget = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_Datum); pInfo->offsetOfReturnAddress = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallerReturnAddress); - pInfo->offsetOfSecretStubArg = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_StubSecretArg); + pInfo->offsetOfSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame); #ifdef TARGET_ARM pInfo->offsetOfSPAfterProlog = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pSPAfterProlog); #endif // TARGET_ARM diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index 6828eec7505e1..8d53c8c3173a9 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -218,16 +218,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index 8076ee94f2130..d10d2d4dabc96 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -214,16 +214,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 From bf3eeb0fe8f5fa775864b92cdcb79ec1b44a2654 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 11 Apr 2024 13:04:25 +0200 Subject: [PATCH 07/14] Enregister stub arg --- src/coreclr/jit/codegen.h | 1 + src/coreclr/jit/codegencommon.cpp | 46 +++++++++++++++++++++------ src/coreclr/jit/compiler.cpp | 5 --- src/coreclr/jit/lsra.h | 2 ++ src/coreclr/jit/lsrabuild.cpp | 52 ++++++++++++++++++++----------- 5 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index b5b0d19402f0a..e94559fdb9a31 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -267,6 +267,7 @@ class CodeGen final : public CodeGenInterface var_types genParamStackStoreType(LclVarDsc* dsc, const ABIPassingSegment& seg); void genSpillOrAddRegisterParam(unsigned lclNum, class RegGraph* graph); + void genSpillOrAddNonStandardRegisterParam(unsigned lclNum, regNumber sourceReg, class RegGraph* graph); void genEnregisterIncomingStackArgs(); #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) void genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 46e46554b2913..d0dffea06d09b 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3141,6 +3141,31 @@ void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) } } +// ----------------------------------------------------------------------------- +// genSpillOrAddNonStandardRegisterParam: Handle a non-standard register parameter either +// by homing it to stack immediately, or by adding it to the register graph. +// +// Parameters: +// lclNum - Local that represents the non-standard parameter +// sourceReg - Register that the non-standard parameter is in on entry to the function +// graph - The register graph to add to +// +void CodeGen::genSpillOrAddNonStandardRegisterParam(unsigned lclNum, regNumber sourceReg, RegGraph* graph) +{ + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + if (varDsc->lvOnFrame && (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)) + { + GetEmitter()->emitIns_S_R(ins_Store(varDsc->TypeGet()), emitActualTypeSize(varDsc), sourceReg, lclNum, 0); + } + + if (varDsc->lvIsInReg()) + { + RegNode* sourceRegNode = graph->GetOrAdd(sourceReg); + RegNode* destRegNode = graph->GetOrAdd(varDsc->GetRegNum()); + graph->AddEdge(sourceRegNode, destRegNode, TYP_I_IMPL, 0); + } +} + // ----------------------------------------------------------------------------- // genHomeRegisterParams: Move all register parameters to their initial // assigned location. @@ -3184,6 +3209,12 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) + { + GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, + compiler->lvaStubArgumentVar, 0); + } + return; } @@ -3216,6 +3247,11 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } } + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) + { + genSpillOrAddNonStandardRegisterParam(compiler->lvaStubArgumentVar, REG_SECRET_STUB_PARAM, &graph); + } + DBEXEC(VERBOSE, graph.Dump()); regMaskTP busyRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; @@ -5492,16 +5528,6 @@ void CodeGen::genFnProlog() * Take care of register arguments first */ - if (compiler->info.compPublishStubParam) - { - GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, - compiler->lvaStubArgumentVar, 0); - assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); - - // It's no longer live; clear it out so it can be used after this in the prolog - intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; - } - #ifdef SWIFT_SUPPORT if (compiler->info.compCallConv == CorInfoCallConvExtension::Swift) { diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c834a4f6f2781..0753a42335d48 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4591,11 +4591,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl assert(lvaStubArgumentVar == BAD_VAR_NUM); lvaStubArgumentVar = lvaGrabTempWithImplicitUse(false DEBUGARG("stub argument")); lvaGetDesc(lvaStubArgumentVar)->lvType = TYP_I_IMPL; - // TODO-CQ: there is no need to mark it as doNotEnreg. There are no stores for this local - // before codegen so liveness and LSRA mark it as "liveIn" and always allocate a stack slot for it. - // However, it would be better to process it like other argument locals and keep it in - // a reg for the whole method without spilling to the stack when possible. - lvaSetVarDoNotEnregister(lvaStubArgumentVar DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); } }; DoPhase(this, PHASE_PRE_IMPORT, preImportPhase); diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 797c9d69c91d8..1132e98d1dd7d 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -644,6 +644,8 @@ class LinearScan : public LinearScanInterface template void buildIntervals(); + void buildInitialParamDef(const LclVarDsc* varDsc, regNumber paramReg); + // This is where the actual assignment is done for scenarios where // no local var enregistration is done. void allocateRegistersMinimal(); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 15726e201d8a5..2cba9659bb1ed 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2344,20 +2344,7 @@ void LinearScan::buildIntervals() if (isCandidateVar(argDsc)) { - Interval* interval = getIntervalForLocalVar(varIndex); - const var_types regType = argDsc->GetRegisterType(); - regMaskTP mask = allRegs(regType); - if (argDsc->lvIsRegArg && !stressInitialParamReg()) - { - // Set this interval as currently assigned to that register - regNumber inArgReg = argDsc->GetArgReg(); - assert(inArgReg < REG_COUNT); - mask = genRegMask(inArgReg); - assignPhysReg(inArgReg, interval); - INDEBUG(registersToDump |= getRegMask(inArgReg, interval->registerType)); - } - RefPosition* pos = newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, mask); - pos->setRegOptional(true); + buildInitialParamDef(argDsc, argDsc->lvIsRegArg ? argDsc->GetArgReg() : REG_NA); } else if (argDsc->lvPromoted) { @@ -2368,10 +2355,7 @@ void LinearScan::buildIntervals() if (fieldVarDsc->lvLRACandidate) { assert(fieldVarDsc->lvTracked); - Interval* interval = getIntervalForLocalVar(fieldVarDsc->lvVarIndex); - RefPosition* pos = - newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, allRegs(TypeGet(fieldVarDsc))); - pos->setRegOptional(true); + buildInitialParamDef(fieldVarDsc, REG_NA); } } } @@ -2418,6 +2402,12 @@ void LinearScan::buildIntervals() if (compiler->info.compPublishStubParam) { intRegState->rsCalleeRegArgMaskLiveIn |= RBM_SECRET_STUB_PARAM; + + LclVarDsc* stubParamDsc = compiler->lvaGetDesc(compiler->lvaStubArgumentVar); + if (isCandidateVar(stubParamDsc)) + { + buildInitialParamDef(stubParamDsc, REG_SECRET_STUB_PARAM); + } } #ifdef DEBUG @@ -2875,6 +2865,32 @@ void LinearScan::buildIntervals() #endif // DEBUG } +//------------------------------------------------------------------------ +// buildInitialParamDef: Build the initial definition for a parameter. +// +// Parameters: +// varDsc - LclVarDsc* for parameter +// paramReg - Register that parameter is in +// +void LinearScan::buildInitialParamDef(const LclVarDsc* varDsc, regNumber paramReg) +{ + assert(isCandidateVar(varDsc)); + + Interval* interval = getIntervalForLocalVar(varDsc->lvVarIndex); + const var_types regType = varDsc->GetRegisterType(); + regMaskTP mask = allRegs(regType); + if ((paramReg != REG_NA) && !stressInitialParamReg()) + { + // Set this interval as currently assigned to that register + assert(paramReg < REG_COUNT); + mask = genRegMask(paramReg); + assignPhysReg(paramReg, interval); + INDEBUG(registersToDump |= getRegMask(paramReg, interval->registerType)); + } + RefPosition* pos = newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, mask); + pos->setRegOptional(true); +} + #ifdef DEBUG //------------------------------------------------------------------------ From 47625a5f59b3fe00f303abbca6f2cd26d163f711 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 11 Apr 2024 13:17:00 +0200 Subject: [PATCH 08/14] Run jit-format, fix comment --- src/coreclr/jit/flowgraph.cpp | 3 ++- src/coreclr/jit/lower.cpp | 18 ++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index abd3db07fbf4a..1cc9c0b1b9d1b 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2438,7 +2438,8 @@ PhaseStatus Compiler::fgAddInternal() LclVarDsc* varDsc = lvaGetDesc(lvaInlinedPInvokeFrameVar); // Make room for the inlined frame. const CORINFO_EE_INFO* eeInfo = eeGetEEInfo(); - unsigned frameSize = info.compPublishStubParam ? eeInfo->inlinedCallFrameInfo.sizeWithSecretStubArg : eeInfo->inlinedCallFrameInfo.size; + unsigned frameSize = info.compPublishStubParam ? eeInfo->inlinedCallFrameInfo.sizeWithSecretStubArg + : eeInfo->inlinedCallFrameInfo.size; lvaSetStruct(lvaInlinedPInvokeFrameVar, typGetBlkLayout(frameSize), false); } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index b1cd8b33e77c7..80861e8fabde0 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5556,28 +5556,22 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // +08h +04h vptr for class InlinedCallFrame offsetOfFrameVptr method prolog // +10h +08h m_Next offsetOfFrameLink method prolog // +18h +0Ch m_Datum offsetOfCallTarget call site -// +20h +10h m_StubSecretArg offsetOfSecretStubArg method prolog -// +28h +14h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method +// +20h +10h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method // prolog; // non-x86: method prolog (SP remains // constant in function, after prolog: no // localloc and PInvoke in same function) -// +30h +18h m_pCallerReturnAddress offsetOfReturnAddress call site -// +38h +1Ch m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT -// +20h m_pThread -// +24h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +24/28h JIT retval spill area (int) before call_gc ??? -// +28/2Ch JIT retval spill area (long) before call_gc ??? -// +2C/30h Saved value of EBP method prolog ??? +// +28h +14h m_pCallerReturnAddress offsetOfReturnAddress call site +// +30h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT +// +38h +1Ch m_pThread +// +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only +// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs only // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* // the object. When we link the InlinedCallFrame onto the Frame chain, we must point at this location, // and not at the beginning of the InlinedCallFrame local, which is actually the GS cookie. // -// Return Value: -// none -// // See the usages for USE_PER_FRAME_PINVOKE_INIT for more information. void Lowering::InsertPInvokeMethodProlog() { From e0a2a9bfc2a8f4527290daf3073a21f38fb4ced8 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 15 Apr 2024 12:26:45 +0200 Subject: [PATCH 09/14] Address feedback --- eng/native/sanitizer-ignorelist.txt | 2 +- src/coreclr/jit/lower.cpp | 25 ++++++++++--------- .../tools/Common/JitInterface/CorInfoImpl.cs | 1 - src/coreclr/vm/frames.h | 2 +- src/coreclr/vm/jithelpers.cpp | 2 +- src/coreclr/vm/jitinterface.h | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/eng/native/sanitizer-ignorelist.txt b/eng/native/sanitizer-ignorelist.txt index ecc8bef9bf688..8e89d3ca960dc 100644 --- a/eng/native/sanitizer-ignorelist.txt +++ b/eng/native/sanitizer-ignorelist.txt @@ -10,5 +10,5 @@ fun:_ZN11CMiniMdBase19UsesAllocatedMemoryEP11CMiniColDef # 2 0x4e8051 in __ubsan_handle_dynamic_type_cache_miss # 3 0x7f02ce676cd8 in JIT_InitPInvokeFrame(InlinedCallFrame*, void*) /home/steveharter/git/dotnet_coreclr/vm/jithelpers.cpp:6491:9 # 4 0x7f0252bbceb2 () -fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFramePv +fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFrame diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 80861e8fabde0..b919c865c9459 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5565,7 +5565,7 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // +30h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT // +38h +1Ch m_pThread // +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs only +// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg only // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* @@ -5597,6 +5597,18 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); + // Store the stub secret arg if necessary. This has to be done before the call to the init helper below, + // which links the frame into the thread list on 32-bit platforms. + // InlinedCallFrame.m_StubSecretArg = stubSecretArg; + if (comp->info.compPublishStubParam) + { + GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); + GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + callFrameInfo.offsetOfSecretStubArg, value); + firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); + DISPTREERANGE(firstBlockRange, store); + } + // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart); GenTree* frameAddr = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); @@ -5616,17 +5628,6 @@ void Lowering::InsertPInvokeMethodProlog() firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); DISPTREERANGE(firstBlockRange, store); - // Store the stub secret arg if necessary. - // InlinedCallFrame.m_StubSecretArg = stubSecretArg; - if (comp->info.compPublishStubParam) - { - GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); - GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, - callFrameInfo.offsetOfSecretStubArg, value); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); - DISPTREERANGE(firstBlockRange, store); - } - #if !defined(TARGET_X86) && !defined(TARGET_ARM) // For x86, this step is done at the call site (due to stack pointer not being static in the function). // For arm32, CallSiteSP is set up by the call to CORINFO_HELP_INIT_PINVOKE_FRAME. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index a3ff6fe404594..9f2d6f28105c2 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3284,7 +3284,6 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut) int pointerSize = this.PointerSize; pEEInfoOut.inlinedCallFrameInfo.size = (uint)SizeOfPInvokeTransitionFrame; - pEEInfoOut.inlinedCallFrameInfo.sizeWithSecretStubArg = (uint)SizeOfPInvokeTransitionFrame + (uint)pointerSize; pEEInfoOut.offsetOfDelegateInstance = (uint)pointerSize; // Delegate::_firstParameter pEEInfoOut.offsetOfDelegateFirstTarget = OffsetOfDelegateFirstTarget; diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 47d8c4f33f562..bec433e552d8d 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -730,7 +730,7 @@ class Frame : public FrameBase friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo); #endif #ifdef HOST_64BIT - friend Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); + friend Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef FEATURE_EH_FUNCLETS friend class ExceptionTracker; diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index e2e5890d837c5..802af6f94a35f 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -6049,7 +6049,7 @@ HCIMPLEND /* Fills out portions of an InlinedCallFrame for JIT64 */ /* The idea here is to allocate and initialize the frame to only once, */ /* regardless of how many PInvokes there are in the method */ -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame) +Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame) { CONTRACTL { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 1cf1460a009f8..56d23c5971435 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -1082,7 +1082,7 @@ EXTERN_C TypeHandle::CastResult STDCALL ObjIsInstanceOfCached(Object *pObject, T #ifdef HOST_64BIT class InlinedCallFrame; -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); +Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef _DEBUG From 6c05297ed6a37d296d210869aeea753a4f74a613 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 15 Apr 2024 13:06:46 +0200 Subject: [PATCH 10/14] Fix formatting --- src/coreclr/jit/lower.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index b919c865c9459..7a5506eed93db 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5565,7 +5565,7 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // +30h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT // +38h +1Ch m_pThread // +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg only +// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* @@ -5597,8 +5597,9 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); - // Store the stub secret arg if necessary. This has to be done before the call to the init helper below, - // which links the frame into the thread list on 32-bit platforms. + // Store the stub secret arg if necessary. This has to be done before the + // call to the init helper below, which links the frame into the thread + // list on 32-bit platforms. // InlinedCallFrame.m_StubSecretArg = stubSecretArg; if (comp->info.compPublishStubParam) { From 1c23e377f33a05282af191573840b5dcfaefb283 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 15 Apr 2024 13:44:31 +0200 Subject: [PATCH 11/14] Update SPMI --- .../tools/superpmi/superpmi-shared/agnostic.h | 3 + .../superpmi-shared/methodcontext.cpp | 94 +++++++------------ 2 files changed, 37 insertions(+), 60 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 104a7ae1fabd3..71720ad00080c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -172,6 +172,7 @@ struct Agnostic_CORINFO_EE_INFO struct Agnostic_InlinedCallFrameInfo { DWORD size; + DWORD sizeWithSecretStubArg; DWORD offsetOfGSCookie; DWORD offsetOfFrameVptr; DWORD offsetOfFrameLink; @@ -179,6 +180,8 @@ struct Agnostic_CORINFO_EE_INFO DWORD offsetOfCalleeSavedFP; DWORD offsetOfCallTarget; DWORD offsetOfReturnAddress; + DWORD offsetOfSecretStubArg; + DWORD offsetOfSPAfterProlog; } inlinedCallFrameInfo; DWORD offsetOfThreadFrame; DWORD offsetOfGCState; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 7b0ddc8ded5ae..7eda52945a9cc 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -4305,6 +4305,7 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) Agnostic_CORINFO_EE_INFO value; value.inlinedCallFrameInfo.size = (DWORD)pEEInfoOut->inlinedCallFrameInfo.size; + value.inlinedCallFrameInfo.sizeWithSecretStubArg = (DWORD)pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg; value.inlinedCallFrameInfo.offsetOfGSCookie = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie; value.inlinedCallFrameInfo.offsetOfFrameVptr = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr; value.inlinedCallFrameInfo.offsetOfFrameLink = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink; @@ -4312,6 +4313,8 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) value.inlinedCallFrameInfo.offsetOfCalleeSavedFP = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP; value.inlinedCallFrameInfo.offsetOfCallTarget = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget; value.inlinedCallFrameInfo.offsetOfReturnAddress = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress; + value.inlinedCallFrameInfo.offsetOfSecretStubArg = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfSecretStubArg; + value.inlinedCallFrameInfo.offsetOfSPAfterProlog = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfSPAfterProlog; value.offsetOfThreadFrame = (DWORD)pEEInfoOut->offsetOfThreadFrame; value.offsetOfGCState = (DWORD)pEEInfoOut->offsetOfGCState; value.offsetOfDelegateInstance = (DWORD)pEEInfoOut->offsetOfDelegateInstance; @@ -4328,12 +4331,14 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) } void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& value) { - printf("GetEEInfo key %u, value icfi{sz-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u} " + printf("GetEEInfo key %u, value icfi{sz-%u sz-witharg-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u ossa-%u osap-%u} " "otf-%u ogcs-%u odi-%u odft-%u osdic-%u srpf-%u osps-%u muono-%u tabi-%u osType-%u", - key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.offsetOfGSCookie, + key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.sizeWithSecretStubArg, + value.inlinedCallFrameInfo.offsetOfGSCookie, value.inlinedCallFrameInfo.offsetOfFrameVptr, value.inlinedCallFrameInfo.offsetOfFrameLink, value.inlinedCallFrameInfo.offsetOfCallSiteSP, value.inlinedCallFrameInfo.offsetOfCalleeSavedFP, value.inlinedCallFrameInfo.offsetOfCallTarget, value.inlinedCallFrameInfo.offsetOfReturnAddress, + value.inlinedCallFrameInfo.offsetOfSecretStubArg, value.inlinedCallFrameInfo.offsetOfSPAfterProlog, value.offsetOfThreadFrame, value.offsetOfGCState, value.offsetOfDelegateInstance, value.offsetOfDelegateFirstTarget, value.offsetOfWrapperDelegateIndirectCell, value.sizeOfReversePInvokeFrame, value.osPageSize, value.maxUncheckedOffsetForNullObject, value.targetAbi, @@ -4341,64 +4346,33 @@ void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& valu } void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) { - Agnostic_CORINFO_EE_INFO value; - - int index = -1; - if (GetEEInfo != nullptr) - index = GetEEInfo->GetIndex((DWORD)0); - if (index >= 0) - { - value = GetEEInfo->Get(0); - DEBUG_REP(dmpGetEEInfo(0, value)); - - pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)value.inlinedCallFrameInfo.size; - pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = - (unsigned)value.inlinedCallFrameInfo.offsetOfCalleeSavedFP; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)value.inlinedCallFrameInfo.offsetOfCallTarget; - pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = - (unsigned)value.inlinedCallFrameInfo.offsetOfReturnAddress; - pEEInfoOut->offsetOfThreadFrame = (unsigned)value.offsetOfThreadFrame; - pEEInfoOut->offsetOfGCState = (unsigned)value.offsetOfGCState; - pEEInfoOut->offsetOfDelegateInstance = (unsigned)value.offsetOfDelegateInstance; - pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)value.offsetOfDelegateFirstTarget; - pEEInfoOut->offsetOfWrapperDelegateIndirectCell= (unsigned)value.offsetOfWrapperDelegateIndirectCell; - pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)value.sizeOfReversePInvokeFrame; - pEEInfoOut->osPageSize = (size_t)value.osPageSize; - pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)value.maxUncheckedOffsetForNullObject; - pEEInfoOut->targetAbi = (CORINFO_RUNTIME_ABI)value.targetAbi; - pEEInfoOut->osType = (CORINFO_OS)value.osType; - } - else - { - pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)0x40; - pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)0; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)0x8; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)0x10; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)0x28; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = (unsigned)0x38; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)0x18; - pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = (unsigned)0x30; - pEEInfoOut->offsetOfThreadFrame = (unsigned)0x10; - pEEInfoOut->offsetOfGCState = (unsigned)0xc; - pEEInfoOut->offsetOfDelegateInstance = (unsigned)0x8; - pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)0x18; - pEEInfoOut->offsetOfWrapperDelegateIndirectCell = (unsigned)0x40; - pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)0x8; - pEEInfoOut->osPageSize = (size_t)0x1000; - pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)((32 * 1024) - 1); - pEEInfoOut->targetAbi = CORINFO_CORECLR_ABI; -#ifdef TARGET_OSX - pEEInfoOut->osType = CORINFO_APPLE; -#elif defined(TARGET_UNIX) - pEEInfoOut->osType = CORINFO_UNIX; -#else - pEEInfoOut->osType = CORINFO_WINNT; -#endif - } + Agnostic_CORINFO_EE_INFO value = LookupByKeyOrMissNoMessage(GetEEInfo, 0); + + DEBUG_REP(dmpGetEEInfo(0, value)); + + pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)value.inlinedCallFrameInfo.size; + pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg = (unsigned)value.inlinedCallFrameInfo.sizeWithSecretStubArg; + pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie; + pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr; + pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = + (unsigned)value.inlinedCallFrameInfo.offsetOfCalleeSavedFP; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)value.inlinedCallFrameInfo.offsetOfCallTarget; + pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = + (unsigned)value.inlinedCallFrameInfo.offsetOfReturnAddress; + pEEInfoOut->inlinedCallFrameInfo.offsetOfSecretStubArg = (unsigned)value.inlinedCallFrameInfo.offsetOfSecretStubArg; + pEEInfoOut->inlinedCallFrameInfo.offsetOfSPAfterProlog = (unsigned)value.inlinedCallFrameInfo.offsetOfSPAfterProlog; + pEEInfoOut->offsetOfThreadFrame = (unsigned)value.offsetOfThreadFrame; + pEEInfoOut->offsetOfGCState = (unsigned)value.offsetOfGCState; + pEEInfoOut->offsetOfDelegateInstance = (unsigned)value.offsetOfDelegateInstance; + pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)value.offsetOfDelegateFirstTarget; + pEEInfoOut->offsetOfWrapperDelegateIndirectCell= (unsigned)value.offsetOfWrapperDelegateIndirectCell; + pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)value.sizeOfReversePInvokeFrame; + pEEInfoOut->osPageSize = (size_t)value.osPageSize; + pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)value.maxUncheckedOffsetForNullObject; + pEEInfoOut->targetAbi = (CORINFO_RUNTIME_ABI)value.targetAbi; + pEEInfoOut->osType = (CORINFO_OS)value.osType; } void MethodContext::recGetGSCookie(GSCookie* pCookieVal, GSCookie** ppCookieVal) From ac4dc794aee57b6dd8b16fa62375c9255cde78de Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 15 Apr 2024 22:58:31 +0200 Subject: [PATCH 12/14] New GUID --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 6d038438b6127..20ae636f572b0 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 589cc249-f57e-4ed2-a6ae-db386be96b84 */ - 0x589cc249, - 0xf57e, - 0x4ed2, - {0xa6, 0xae, 0xdb, 0x38, 0x6b, 0xe9, 0x6b, 0x84} +constexpr GUID JITEEVersionIdentifier = { /* 6496f552-af92-47da-bb0e-2299b4c21ca4 */ + 0x6496f552, + 0xaf92, + 0x47da, + {0xbb, 0x0e, 0x22, 0x99, 0xb4, 0xc2, 0x1c, 0xa4} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// From c93546d37d8f93a2062b72b1d95573c37e54c42f Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 30 Apr 2024 13:42:59 +0200 Subject: [PATCH 13/14] New JIT-EE GUID --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 20ae636f572b0..6a50f164b4fd4 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 6496f552-af92-47da-bb0e-2299b4c21ca4 */ - 0x6496f552, - 0xaf92, - 0x47da, - {0xbb, 0x0e, 0x22, 0x99, 0xb4, 0xc2, 0x1c, 0xa4} +constexpr GUID JITEEVersionIdentifier = { /* 805b30c6-0db4-4e31-9ae5-32eb6d6538fd */ + 0x805b30c6, + 0x0db4, + 0x4e31, + {0x9a, 0xe5, 0x32, 0xeb, 0x6d, 0x65, 0x38, 0xfd} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// From 133d48fc9af74fc8f871c98cad102696c11dd5cc Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 9 May 2024 00:15:58 +0200 Subject: [PATCH 14/14] New GUID --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 762656a3dbbcf..46b50f5410ce4 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 43854594-cd60-45df-a89f-5b7697586f46 */ - 0x43854594, - 0xcd60, - 0x45df, - {0xa8, 0x9f, 0x5b, 0x76, 0x97, 0x58, 0x6f, 0x46} +constexpr GUID JITEEVersionIdentifier = { /* 227e46fa-1be3-4770-b613-4a239e7c28aa */ + 0x227e46fa, + 0x1be3, + 0x4770, + {0xb6, 0x13, 0x4a, 0x23, 0x9e, 0x7c, 0x28, 0xaa} }; //////////////////////////////////////////////////////////////////////////////////////////////////////////