Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/coreclr/inc/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,11 @@
#define CHAIN_LOOKUP
#endif // FEATURE_VIRTUAL_STUB_DISPATCH

#if !defined(FEATURE_PORTABLE_ENTRYPOINTS) && !defined(TARGET_X86)
// FEATURE_PORTABLE_SHUFFLE_THUNKS depends on CPUSTUBLINKER that is de-facto JIT
#if defined(FEATURE_JIT) && !defined(TARGET_X86)
#define FEATURE_PORTABLE_SHUFFLE_THUNKS
#endif

#if defined(TARGET_UNIX) || !defined(TARGET_X86)
#define FEATURE_INSTANTIATINGSTUB_AS_IL
#endif

// If this is uncommented, leaves a file "StubLog_<pid>.log" with statistics on the behavior
// of stub-based interface dispatch.
//#define STUB_LOGGING
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/arm64/cgencpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,7 @@ class StubLinkerCPU : public StubLinker

void EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray);

#if defined(FEATURE_SHARE_GENERIC_CODE)
void EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg);
#endif // FEATURE_SHARE_GENERIC_CODE

void EmitMovConstant(IntReg target, UINT64 constant);
void EmitJumpRegister(IntReg regTarget);
Expand Down
19 changes: 6 additions & 13 deletions src/coreclr/vm/comdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0)

return static_cast<UINT16>(ofs);
}
#endif
#endif // defined(TARGET_X86)

#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS

Expand Down Expand Up @@ -635,7 +635,7 @@ BOOL GenerateShuffleArrayPortable(MethodDesc* pMethodSrc, MethodDesc *pMethodDst
}
#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS

#ifndef FEATURE_PORTABLE_ENTRYPOINTS
#if defined(FEATURE_PORTABLE_SHUFFLE_THUNKS) || defined(TARGET_X86)
BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray<ShuffleEntry> * pShuffleEntryArray)
{
STANDARD_VM_CONTRACT;
Expand Down Expand Up @@ -775,7 +775,7 @@ BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray<S
return TRUE;
}
static ShuffleThunkCache* s_pShuffleThunkCache = NULL;
#endif // !FEATURE_PORTABLE_ENTRYPOINTS
#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS || TARGET_X86

// One time init.
void COMDelegate::Init()
Expand All @@ -787,7 +787,7 @@ void COMDelegate::Init()
MODE_ANY;
}
CONTRACTL_END;
#ifndef FEATURE_PORTABLE_ENTRYPOINTS
#if defined(FEATURE_PORTABLE_SHUFFLE_THUNKS) || defined(TARGET_X86)
s_pShuffleThunkCache = new ShuffleThunkCache(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap());
#endif
}
Expand Down Expand Up @@ -829,7 +829,6 @@ LoaderHeap *DelegateEEClass::GetStubHeap()
return GetInvokeMethod()->GetLoaderAllocator()->GetStubHeap();
}

#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) || defined(FEATURE_PORTABLE_ENTRYPOINTS)
static Stub* CreateILDelegateShuffleThunk(MethodDesc* pDelegateMD, bool callTargetWithThis)
{
SigTypeContext typeContext(pDelegateMD);
Expand Down Expand Up @@ -889,7 +888,6 @@ static Stub* CreateILDelegateShuffleThunk(MethodDesc* pDelegateMD, bool callTarg

return Stub::NewStub(JitILStub(pStubMD), NEWSTUB_FL_SHUFFLE_THUNK);
}
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64

static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth)
{
Expand All @@ -915,7 +913,7 @@ static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth)

MethodDesc *pMD = pClass->GetInvokeMethod();

#ifndef FEATURE_PORTABLE_ENTRYPOINTS
#if defined(FEATURE_PORTABLE_SHUFFLE_THUNKS) || defined(TARGET_X86)
// We haven't already setup a shuffle thunk, go do it now (which will cache the result automatically).
StackSArray<ShuffleEntry> rShuffleEntryArray;
if (GenerateShuffleArray(pMD, pTargetMeth, &rShuffleEntryArray))
Expand All @@ -931,14 +929,9 @@ static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth)
pShuffleThunk = pShuffleThunkCache->Canonicalize((const BYTE *)&rShuffleEntryArray[0], "DelegateShuffleThunk");
}
else
#endif // !FEATURE_PORTABLE_ENTRYPOINTS
#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS || TARGET_X86
{
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) || defined(FEATURE_PORTABLE_ENTRYPOINTS)
pShuffleThunk = CreateILDelegateShuffleThunk(pMD, isInstRetBuff);
#else
_ASSERTE(FALSE);
return (PCODE)NULL;
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64
}

if (!pShuffleThunk)
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/vm/dllimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,8 @@ enum ILStubTypes
ILSTUB_ARRAYOP_SET = 0x80000002,
ILSTUB_ARRAYOP_ADDRESS = 0x80000003,
ILSTUB_MULTICASTDELEGATE_INVOKE = 0x80000004,
#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL
ILSTUB_UNBOXINGILSTUB = 0x80000005,
ILSTUB_INSTANTIATINGSTUB = 0x80000006,
#endif // FEATURE_INSTANTIATINGSTUB_AS_IL
ILSTUB_WRAPPERDELEGATE_INVOKE = 0x80000007,
ILSTUB_TAILCALL_STOREARGS = 0x80000008,
ILSTUB_TAILCALL_CALLTARGET = 0x80000009,
Expand Down Expand Up @@ -231,10 +229,8 @@ inline bool SF_IsMulticastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CON
inline bool SF_IsDelegateInvokeMethod (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_DELEGATE_INVOKE_METHOD); }

inline bool SF_IsWrapperDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_WRAPPERDELEGATE_INVOKE); }
#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL
inline bool SF_IsUnboxingILStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_UNBOXINGILSTUB); }
inline bool SF_IsInstantiatingStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_INSTANTIATINGSTUB); }
#endif // FEATURE_INSTANTIATINGSTUB_AS_IL
inline bool SF_IsTailCallStoreArgsStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_TAILCALL_STOREARGS); }
inline bool SF_IsTailCallCallTargetStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_TAILCALL_CALLTARGET); }
inline bool SF_IsDelegateShuffleThunk (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_DELEGATE_SHUFFLE_THUNK); }
Expand Down
163 changes: 82 additions & 81 deletions src/coreclr/vm/i386/stublinkerx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ VOID StubLinkerCPU::X64EmitMovXmmXmm(X86Reg destXmmreg, X86Reg srcXmmReg)
Emit8(REX_PREFIX_BASE | rex);

Emit16(0x280F);
Emit8(static_cast<UINT8>(0300 | (destXmmreg << 3) | srcXmmReg));
Emit8(static_cast<UINT8>(0300 | (destXmmreg << 3) | srcXmmReg));
}

//---------------------------------------------------------------
Expand Down Expand Up @@ -852,7 +852,7 @@ static const X86Reg c_argRegs[] = {
// and pass it as an extra argument. Thus this stub generator really covers both
// - Unboxing, non-instantiating stubs
// - Unboxing, method-table-instantiating stubs
VOID StubLinkerCPU::EmitUnboxMethodStub(MethodDesc* pUnboxMD)
bool StubLinkerCPU::EmitUnboxMethodStub(MethodDesc* pUnboxMD)
{
CONTRACTL
{
Expand All @@ -861,25 +861,96 @@ VOID StubLinkerCPU::EmitUnboxMethodStub(MethodDesc* pUnboxMD)
}
CONTRACTL_END;

#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL
_ASSERTE(!pUnboxMD->RequiresInstMethodTableArg());
#else
if (pUnboxMD->RequiresInstMethodTableArg())
{
EmitInstantiatingMethodStub(pUnboxMD, NULL);
return;
return EmitInstantiatingMethodStub(pUnboxMD, NULL);
}
#endif

//
// unboxing a value class simply means adding sizeof(void*) to the THIS pointer
//
X86EmitAddReg(THIS_kREG, sizeof(void*));
EmitTailJumpToMethod(pUnboxMD);
return true;
}

// The stub generated by this method passes an extra dictionary argument before jumping to
// shared-instantiation generic code.
//
// pMD is either
// * An InstantiatedMethodDesc for a generic method whose code is shared across instantiations.
// In this case, the extra argument is the InstantiatedMethodDesc for the instantiation-specific stub itself.
// or * A MethodDesc for a static method in a generic class whose code is shared across instantiations.
// In this case, the extra argument is the MethodTable pointer of the instantiated type.
// or * A MethodDesc for unboxing stub. In this case, the extra argument is null.
bool StubLinkerCPU::EmitInstantiatingMethodStub(MethodDesc* pMD, void* extra)
{
CONTRACTL
{
STANDARD_VM_CHECK;
PRECONDITION(pMD->RequiresInstArg());
}
CONTRACTL_END;

#ifdef UNIX_X86_ABI
// Unix x86 ABI requires stack alignment
return false;
#else // UNIX_X86_ABI
MetaSig msig(pMD);
ArgIterator argit(&msig);

int paramTypeArgOffset = argit.GetParamTypeArgOffset();

// It's on the stack
if (TransitionBlock::IsStackArgumentOffset(paramTypeArgOffset))
{
// Pop return address into AX
X86EmitPopReg(kEAX);

if (extra != NULL)
{
// Push extra dictionary argument
X86EmitPushImmPtr(extra);
}
else
{
// Push the vtable pointer from "this"
X86EmitIndexPush(THIS_kREG, 0);
}

// Put return address back
X86EmitPushReg(kEAX);
}
// It's in a register
else
{
X86Reg paramReg = GetX86ArgumentRegisterFromOffset(paramTypeArgOffset - TransitionBlock::GetOffsetOfArgumentRegisters());

if (extra != NULL)
{
X86EmitRegLoad(paramReg, (UINT_PTR)extra);
}
else
{
// Just extract the vtable pointer from "this"
X86EmitIndexRegLoad(paramReg, THIS_kREG);
}
}

if (extra == NULL)
{
// Unboxing stub case.
X86EmitAddReg(THIS_kREG, sizeof(void*));
}

EmitTailJumpToMethod(pMD);

return true;
#endif // UNIX_X86_ABI
}
#endif //TARGET_X86
#endif // TARGET_X86

#if defined(FEATURE_SHARE_GENERIC_CODE) && defined(TARGET_AMD64)
#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS
VOID StubLinkerCPU::EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg)
{
STANDARD_VM_CONTRACT;
Expand Down Expand Up @@ -939,7 +1010,7 @@ VOID StubLinkerCPU::EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, s
EmitTailJumpToMethod(pSharedMD);
SetTargetMethod(pSharedMD);
}
#endif // defined(FEATURE_SHARE_GENERIC_CODE) && defined(TARGET_AMD64)
#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS

#ifdef TARGET_AMD64
VOID StubLinkerCPU::EmitLoadMethodAddressIntoAX(MethodDesc *pMD)
Expand Down Expand Up @@ -984,76 +1055,6 @@ VOID StubLinkerCPU::EmitTailJumpToMethod(MethodDesc *pMD)
#endif
}

#if defined(FEATURE_SHARE_GENERIC_CODE) && !defined(FEATURE_INSTANTIATINGSTUB_AS_IL) && defined(TARGET_X86)
// The stub generated by this method passes an extra dictionary argument before jumping to
// shared-instantiation generic code.
//
// pMD is either
// * An InstantiatedMethodDesc for a generic method whose code is shared across instantiations.
// In this case, the extra argument is the InstantiatedMethodDesc for the instantiation-specific stub itself.
// or * A MethodDesc for a static method in a generic class whose code is shared across instantiations.
// In this case, the extra argument is the MethodTable pointer of the instantiated type.
// or * A MethodDesc for unboxing stub. In this case, the extra argument is null.
VOID StubLinkerCPU::EmitInstantiatingMethodStub(MethodDesc* pMD, void* extra)
{
CONTRACTL
{
STANDARD_VM_CHECK;
PRECONDITION(pMD->RequiresInstArg());
}
CONTRACTL_END;

MetaSig msig(pMD);
ArgIterator argit(&msig);

int paramTypeArgOffset = argit.GetParamTypeArgOffset();

// It's on the stack
if (TransitionBlock::IsStackArgumentOffset(paramTypeArgOffset))
{
// Pop return address into AX
X86EmitPopReg(kEAX);

if (extra != NULL)
{
// Push extra dictionary argument
X86EmitPushImmPtr(extra);
}
else
{
// Push the vtable pointer from "this"
X86EmitIndexPush(THIS_kREG, 0);
}

// Put return address back
X86EmitPushReg(kEAX);
}
// It's in a register
else
{
X86Reg paramReg = GetX86ArgumentRegisterFromOffset(paramTypeArgOffset - TransitionBlock::GetOffsetOfArgumentRegisters());

if (extra != NULL)
{
X86EmitRegLoad(paramReg, (UINT_PTR)extra);
}
else
{
// Just extract the vtable pointer from "this"
X86EmitIndexRegLoad(paramReg, THIS_kREG);
}
}

if (extra == NULL)
{
// Unboxing stub case.
X86EmitAddReg(THIS_kREG, sizeof(void*));
}

EmitTailJumpToMethod(pMD);
}
#endif // defined(FEATURE_SHARE_GENERIC_CODE) && !defined(FEATURE_INSTANTIATINGSTUB_AS_IL) && defined(TARGET_X86)

VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray)
{
STANDARD_VM_CONTRACT;
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/vm/i386/stublinkerx86.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,17 @@ class StubLinkerCPU : public StubLinker
}

#ifdef TARGET_X86
VOID EmitUnboxMethodStub(MethodDesc* pRealMD);
bool EmitUnboxMethodStub(MethodDesc* pRealMD);
bool EmitInstantiatingMethodStub(MethodDesc* pSharedMD, void* extra);
#endif // TARGET_X86
VOID EmitTailJumpToMethod(MethodDesc *pMD);
#ifdef TARGET_AMD64
VOID EmitLoadMethodAddressIntoAX(MethodDesc *pMD);
#endif

#if defined(FEATURE_SHARE_GENERIC_CODE)
VOID EmitInstantiatingMethodStub(MethodDesc* pSharedMD, void* extra);
#endif // FEATURE_SHARE_GENERIC_CODE
#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS
VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg);
#endif

//===========================================================================
// Emits code to adjust for a static delegate target.
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/vm/ilstubcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,8 @@ namespace
case DynamicMethodDesc::StubArrayOp: return "IL_STUB_Array";
case DynamicMethodDesc::StubMulticastDelegate: return "IL_STUB_MulticastDelegate_Invoke";
case DynamicMethodDesc::StubDelegateInvokeMethod: return "IL_STUB_Delegate_Invoke";
#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL
case DynamicMethodDesc::StubUnboxingIL: return "IL_STUB_UnboxingStub";
case DynamicMethodDesc::StubInstantiating: return "IL_STUB_InstantiatingStub";
#endif
case DynamicMethodDesc::StubWrapperDelegate: return "IL_STUB_WrapperDelegate_Invoke";
case DynamicMethodDesc::StubTailCallStoreArgs: return "IL_STUB_StoreTailCallArgs";
case DynamicMethodDesc::StubTailCallCallTarget: return "IL_STUB_CallTailCallTarget";
Expand Down Expand Up @@ -243,7 +241,6 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
pMD->SetILStubType(DynamicMethodDesc::StubWrapperDelegate);
}
else
#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL
if (SF_IsUnboxingILStub(dwStubFlags))
{
pMD->SetILStubType(DynamicMethodDesc::StubUnboxingIL);
Expand All @@ -254,7 +251,6 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
pMD->SetILStubType(DynamicMethodDesc::StubInstantiating);
}
else
#endif
if (SF_IsTailCallStoreArgsStub(dwStubFlags))
{
pMD->SetILStubType(DynamicMethodDesc::StubTailCallStoreArgs);
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/loongarch64/cgencpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,7 @@ class StubLinkerCPU : public StubLinker
void EmitCallLabel(CodeLabel *target, BOOL fTailCall, BOOL fIndirect);

void EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray);

#if defined(FEATURE_SHARE_GENERIC_CODE)
void EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg);
#endif // FEATURE_SHARE_GENERIC_CODE

void EmitMovConstant(IntReg Rd, UINT64 constant);
void EmitJumpRegister(IntReg regTarget);
Expand Down
Loading
Loading