Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
16 changes: 8 additions & 8 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,7 @@ LoaderHeap *DelegateEEClass::GetStubHeap()
return GetInvokeMethod()->GetLoaderAllocator()->GetStubHeap();
}

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

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

static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth)
{
Expand Down Expand Up @@ -933,12 +933,12 @@ static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth)
else
#endif // !FEATURE_PORTABLE_ENTRYPOINTS
{
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) || defined(FEATURE_PORTABLE_ENTRYPOINTS)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) || defined(TARGET_ARM64) || defined(TARGET_AMD64) || defined(FEATURE_PORTABLE_ENTRYPOINTS)
pShuffleThunk = CreateILDelegateShuffleThunk(pMD, isInstRetBuff);
#else
_ASSERTE(FALSE);
return (PCODE)NULL;
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64 || TARGET_ARM64 || TARGET_AMD64
}

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
161 changes: 81 additions & 80 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
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
}
#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