Skip to content

Commit

Permalink
Simplify "secret stub arg" handling between JIT and EE
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobbotsch committed Apr 9, 2024
1 parent 0764864 commit 7e08baf
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 72 deletions.
1 change: 1 addition & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
37 changes: 27 additions & 10 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
//
Expand Down
5 changes: 0 additions & 5 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 0 additions & 21 deletions src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7076,15 +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)
{
Expand Down Expand Up @@ -7234,18 +7225,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());
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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 =
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 3 additions & 27 deletions src/coreclr/vm/frames.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<TADDR>(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);
Expand All @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 7e08baf

Please sign in to comment.