From 66018468c742b1c9bc51278a6679864637bff4e7 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Mon, 27 Oct 2025 15:42:18 +0100 Subject: [PATCH 1/5] Don't use shuffle thunks on Apple mobile --- src/coreclr/inc/switches.h | 5 ++-- src/coreclr/vm/arm64/cgencpu.h | 3 +++ src/coreclr/vm/arm64/stubs.cpp | 33 +++++++++++++++++++++++++++ src/coreclr/vm/comdelegate.cpp | 12 ++++------ src/coreclr/vm/i386/stublinkerx86.cpp | 6 ++--- src/coreclr/vm/i386/stublinkerx86.h | 4 ++-- src/coreclr/vm/prestub.cpp | 16 ++++++------- 7 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 93f6a13980f4ce..5c6f82a89b3915 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -165,8 +165,9 @@ #define CHAIN_LOOKUP #endif // FEATURE_VIRTUAL_STUB_DISPATCH -#if !defined(FEATURE_PORTABLE_ENTRYPOINTS) && !defined(TARGET_X86) -#define FEATURE_PORTABLE_SHUFFLE_THUNKS +// FEATURE_SHUFFLE_THUNKS depends on CPUSTUBLINKER that is de-facto JIT +#if defined(FEATURE_JIT) && !defined(TARGET_X86) +#define FEATURE_SHUFFLE_THUNKS #endif #if defined(TARGET_UNIX) || !defined(TARGET_X86) diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index aa668e54a99a2a..95e0e289640723 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -513,6 +513,9 @@ class StubLinkerCPU : public StubLinker void EmitLoadStoreRegImm(DWORD flags, IntReg Xt, IntReg Xn, int offset=0, int log2Size = 3); void EmitLoadStoreRegImm(DWORD flags, VecReg Vt, IntReg Xn, int offset=0); +#if !defined(FEATURE_SHUFFLE_THUNKS) + void EmitUnboxMethodStub(MethodDesc* pRealMD); +#endif // !defined(FEATURE_SHUFFLE_THUNKS) void EmitRet(IntReg reg); }; diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index 3f1a5dc78f7cc3..ace964e0f6965a 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -1382,5 +1382,38 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, #endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif // FEATURE_READYTORUN +#if !defined(FEATURE_SHUFFLE_THUNKS) +// +// This method unboxes the THIS pointer and then calls pRealMD +// If it's shared code for a method in a generic value class, then also extract the vtable pointer +// 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) +{ + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(!pUnboxMD->IsStatic()); + } + CONTRACTL_END; + +#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL + _ASSERTE(!pUnboxMD->RequiresInstMethodTableArg()); +#else + if (pUnboxMD->RequiresInstMethodTableArg()) + { + EmitComputedInstantiatingMethodStub(pUnboxMD, NULL, NULL); + return; + } +#endif + + // + // unboxing a value class simply means adding sizeof(void*) to the THIS pointer + // + EmitAddImm(IntReg(0), IntReg(0), sizeof(void*)); + EmitCallManagedMethod(pUnboxMD, TRUE); +} +#endif // !defined(FEATURE_SHUFFLE_THUNKS) #endif // #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 9e4e9f519eaa32..92224150bbd844 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -31,7 +31,7 @@ #ifndef DACCESS_COMPILE -#if defined(TARGET_X86) +#if !defined(FEATURE_SHUFFLE_THUNKS) // Return an encoded shuffle entry describing a general register or stack offset that needs to be shuffled. static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0) @@ -56,9 +56,7 @@ static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0) return static_cast(ofs); } -#endif - -#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS +#else // !defined(FEATURE_SHUFFLE_THUNKS) // Iterator for extracting shuffle entries for argument desribed by an ArgLocDesc. // Used when calculating shuffle array entries in GenerateShuffleArray below. @@ -633,18 +631,18 @@ BOOL GenerateShuffleArrayPortable(MethodDesc* pMethodSrc, MethodDesc *pMethodDst return TRUE; } -#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS +#endif // !defined(FEATURE_SHUFFLE_THUNKS) #ifndef FEATURE_PORTABLE_ENTRYPOINTS BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray * pShuffleEntryArray) { STANDARD_VM_CONTRACT; -#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifdef FEATURE_SHUFFLE_THUNKS // Portable default implementation if (!GenerateShuffleArrayPortable(pInvoke, pTargetMeth, pShuffleEntryArray, ShuffleComputationType::DelegateShuffleThunk)) return FALSE; -#elif defined(TARGET_X86) +#elif defined(TARGET_X86) || defined(TARGET_ARM64) || defined(TARGET_AMD64) ShuffleEntry entry; ZeroMemory(&entry, sizeof(entry)); diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 349685369b6285..5c357eab0c7bbc 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -374,7 +374,7 @@ VOID StubLinkerCPU::X64EmitMovXmmXmm(X86Reg destXmmreg, X86Reg srcXmmReg) Emit8(REX_PREFIX_BASE | rex); Emit16(0x280F); - Emit8(static_cast(0300 | (destXmmreg << 3) | srcXmmReg)); + Emit8(static_cast(0300 | (destXmmreg << 3) | srcXmmReg)); } //--------------------------------------------------------------- @@ -846,7 +846,7 @@ static const X86Reg c_argRegs[] = { }; #endif -#ifdef TARGET_X86 +#if !defined(FEATURE_SHUFFLE_THUNKS) // This method unboxes the THIS pointer and then calls pRealMD // If it's shared code for a method in a generic value class, then also extract the vtable pointer // and pass it as an extra argument. Thus this stub generator really covers both @@ -877,7 +877,7 @@ VOID StubLinkerCPU::EmitUnboxMethodStub(MethodDesc* pUnboxMD) X86EmitAddReg(THIS_kREG, sizeof(void*)); EmitTailJumpToMethod(pUnboxMD); } -#endif //TARGET_X86 +#endif // !defined(FEATURE_SHUFFLE_THUNKS) #if defined(FEATURE_SHARE_GENERIC_CODE) && defined(TARGET_AMD64) VOID StubLinkerCPU::EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg) diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 9547cab0746e11..9043eb7a909dfe 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -197,9 +197,9 @@ class StubLinkerCPU : public StubLinker #endif } -#ifdef TARGET_X86 +#if !defined(FEATURE_SHUFFLE_THUNKS) VOID EmitUnboxMethodStub(MethodDesc* pRealMD); -#endif // TARGET_X86 +#endif // !defined(FEATURE_SHUFFLE_THUNKS) VOID EmitTailJumpToMethod(MethodDesc *pMD); #ifdef TARGET_AMD64 VOID EmitLoadMethodAddressIntoAX(MethodDesc *pMD); diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 3193129948340a..155af20ac329f2 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -1710,7 +1710,7 @@ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) _ASSERTE(pUnboxedMD != NULL && pUnboxedMD != pMD); -#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifdef FEATURE_SHUFFLE_THUNKS StackSArray portableShuffle; BOOL usePortableShuffle = FALSE; if (!pUnboxedMD->RequiresInstMethodTableArg()) @@ -1746,24 +1746,24 @@ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) pstub = CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); #else // !FEATURE_PORTABLE_ENTRYPOINTS #ifdef FEATURE_INSTANTIATINGSTUB_AS_IL -#ifndef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifndef FEATURE_SHUFFLE_THUNKS if (pUnboxedMD->RequiresInstMethodTableArg()) -#endif // !FEATURE_PORTABLE_SHUFFLE_THUNKS +#endif // !FEATURE_SHUFFLE_THUNKS { _ASSERTE(pUnboxedMD->RequiresInstMethodTableArg()); pstub = CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); } -#ifndef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifndef FEATURE_SHUFFLE_THUNKS else -#endif // !FEATURE_PORTABLE_SHUFFLE_THUNKS +#endif // !FEATURE_SHUFFLE_THUNKS #endif // FEATURE_INSTANTIATINGSTUB_AS_IL -#ifndef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifndef FEATURE_SHUFFLE_THUNKS { CPUSTUBLINKER sl; sl.EmitUnboxMethodStub(pUnboxedMD); pstub = sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "UnboxingStub"); } -#endif // !FEATURE_PORTABLE_SHUFFLE_THUNKS +#endif // !FEATURE_SHUFFLE_THUNKS #endif // FEATURE_PORTABLE_ENTRYPOINTS } RETURN pstub; @@ -1806,7 +1806,7 @@ Stub * MakeInstantiatingStubWorker(MethodDesc *pMD) } Stub *pstub = NULL; -#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS +#ifdef FEATURE_SHUFFLE_THUNKS StackSArray portableShuffle; if (GenerateShuffleArrayPortable(pMD, pSharedMD, &portableShuffle, ShuffleComputationType::InstantiatingStub)) { From 6020809f2d846106d05084a8a1322310251adaf0 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Mon, 27 Oct 2025 17:42:54 +0100 Subject: [PATCH 2/5] Separate x86 and arm64/amd64 shuffle thunk paths --- src/coreclr/vm/arm64/cgencpu.h | 2 -- src/coreclr/vm/comdelegate.cpp | 19 ++++++++++++------- src/coreclr/vm/i386/stublinkerx86.h | 2 -- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 95e0e289640723..ed396771ab2049 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -513,9 +513,7 @@ class StubLinkerCPU : public StubLinker void EmitLoadStoreRegImm(DWORD flags, IntReg Xt, IntReg Xn, int offset=0, int log2Size = 3); void EmitLoadStoreRegImm(DWORD flags, VecReg Vt, IntReg Xn, int offset=0); -#if !defined(FEATURE_SHUFFLE_THUNKS) void EmitUnboxMethodStub(MethodDesc* pRealMD); -#endif // !defined(FEATURE_SHUFFLE_THUNKS) void EmitRet(IntReg reg); }; diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 92224150bbd844..34f78f92fb2811 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -31,7 +31,7 @@ #ifndef DACCESS_COMPILE -#if !defined(FEATURE_SHUFFLE_THUNKS) +#if defined(TARGET_X86) // Return an encoded shuffle entry describing a general register or stack offset that needs to be shuffled. static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0) @@ -56,7 +56,9 @@ static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0) return static_cast(ofs); } -#else // !defined(FEATURE_SHUFFLE_THUNKS) +#endif // defined(TARGET_X86) + +#if defined(FEATURE_SHUFFLE_THUNKS) // Iterator for extracting shuffle entries for argument desribed by an ArgLocDesc. // Used when calculating shuffle array entries in GenerateShuffleArray below. @@ -642,7 +644,7 @@ BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray(stackSizeDelta); pShuffleEntryArray->Append(entry); +#elif defined(TARGET_ARM64) || defined(TARGET_AMD64) + // Fall back to IL-based shuffle thunks + return FALSE; #else #error Unsupported architecture #endif @@ -827,7 +832,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); @@ -887,7 +892,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) { @@ -931,12 +936,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) diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 9043eb7a909dfe..82013d73aeed0c 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -197,9 +197,7 @@ class StubLinkerCPU : public StubLinker #endif } -#if !defined(FEATURE_SHUFFLE_THUNKS) VOID EmitUnboxMethodStub(MethodDesc* pRealMD); -#endif // !defined(FEATURE_SHUFFLE_THUNKS) VOID EmitTailJumpToMethod(MethodDesc *pMD); #ifdef TARGET_AMD64 VOID EmitLoadMethodAddressIntoAX(MethodDesc *pMD); From f626c881ea87a6128720917193abab247303f7e4 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 28 Oct 2025 22:51:32 -0700 Subject: [PATCH 3/5] Cleanup ifdefs --- src/coreclr/inc/switches.h | 8 +- src/coreclr/vm/arm64/cgencpu.h | 3 - src/coreclr/vm/arm64/stubs.cpp | 33 ------ src/coreclr/vm/comdelegate.cpp | 15 +-- src/coreclr/vm/dllimport.h | 4 - src/coreclr/vm/i386/stublinkerx86.cpp | 163 +++++++++++++------------- src/coreclr/vm/i386/stublinkerx86.h | 10 +- src/coreclr/vm/ilstubcache.cpp | 4 - src/coreclr/vm/loongarch64/cgencpu.h | 3 - src/coreclr/vm/method.hpp | 6 - src/coreclr/vm/prestub.cpp | 75 ++++-------- src/coreclr/vm/riscv64/cgencpu.h | 2 - 12 files changed, 117 insertions(+), 209 deletions(-) diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 5c6f82a89b3915..9d6f7083f53fa4 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -165,13 +165,9 @@ #define CHAIN_LOOKUP #endif // FEATURE_VIRTUAL_STUB_DISPATCH -// FEATURE_SHUFFLE_THUNKS depends on CPUSTUBLINKER that is de-facto JIT +// FEATURE_PORTABLE_SHUFFLE_THUNKS depends on CPUSTUBLINKER that is de-facto JIT #if defined(FEATURE_JIT) && !defined(TARGET_X86) -#define FEATURE_SHUFFLE_THUNKS -#endif - -#if defined(TARGET_UNIX) || !defined(TARGET_X86) -#define FEATURE_INSTANTIATINGSTUB_AS_IL +#define FEATURE_PORTABLE_SHUFFLE_THUNKS #endif // If this is uncommented, leaves a file "StubLog_.log" with statistics on the behavior diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index ed396771ab2049..467821e938489d 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -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); @@ -513,7 +511,6 @@ class StubLinkerCPU : public StubLinker void EmitLoadStoreRegImm(DWORD flags, IntReg Xt, IntReg Xn, int offset=0, int log2Size = 3); void EmitLoadStoreRegImm(DWORD flags, VecReg Vt, IntReg Xn, int offset=0); - void EmitUnboxMethodStub(MethodDesc* pRealMD); void EmitRet(IntReg reg); }; diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index ace964e0f6965a..3f1a5dc78f7cc3 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -1382,38 +1382,5 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, #endif // FEATURE_STUBPRECODE_DYNAMIC_HELPERS #endif // FEATURE_READYTORUN -#if !defined(FEATURE_SHUFFLE_THUNKS) -// -// This method unboxes the THIS pointer and then calls pRealMD -// If it's shared code for a method in a generic value class, then also extract the vtable pointer -// 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) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(!pUnboxMD->IsStatic()); - } - CONTRACTL_END; - -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL - _ASSERTE(!pUnboxMD->RequiresInstMethodTableArg()); -#else - if (pUnboxMD->RequiresInstMethodTableArg()) - { - EmitComputedInstantiatingMethodStub(pUnboxMD, NULL, NULL); - return; - } -#endif - - // - // unboxing a value class simply means adding sizeof(void*) to the THIS pointer - // - EmitAddImm(IntReg(0), IntReg(0), sizeof(void*)); - EmitCallManagedMethod(pUnboxMD, TRUE); -} -#endif // !defined(FEATURE_SHUFFLE_THUNKS) #endif // #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 34f78f92fb2811..fc554fc45e8b6c 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -58,7 +58,7 @@ static UINT16 ShuffleOfs(INT ofs, UINT stackSizeDelta = 0) } #endif // defined(TARGET_X86) -#if defined(FEATURE_SHUFFLE_THUNKS) +#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS // Iterator for extracting shuffle entries for argument desribed by an ArgLocDesc. // Used when calculating shuffle array entries in GenerateShuffleArray below. @@ -633,14 +633,14 @@ BOOL GenerateShuffleArrayPortable(MethodDesc* pMethodSrc, MethodDesc *pMethodDst return TRUE; } -#endif // !defined(FEATURE_SHUFFLE_THUNKS) +#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 * pShuffleEntryArray) { STANDARD_VM_CONTRACT; -#ifdef FEATURE_SHUFFLE_THUNKS +#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS // Portable default implementation if (!GenerateShuffleArrayPortable(pInvoke, pTargetMeth, pShuffleEntryArray, ShuffleComputationType::DelegateShuffleThunk)) return FALSE; @@ -728,9 +728,6 @@ BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray(stackSizeDelta); pShuffleEntryArray->Append(entry); -#elif defined(TARGET_ARM64) || defined(TARGET_AMD64) - // Fall back to IL-based shuffle thunks - return FALSE; #else #error Unsupported architecture #endif @@ -778,7 +775,7 @@ BOOL GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArrayGetStubHeap()); #endif } diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index ee60abdfc62b1e..2a20d4ee85a0f4 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -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, @@ -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); } diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 5c357eab0c7bbc..32a8c15f5fcdcd 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -846,13 +846,13 @@ static const X86Reg c_argRegs[] = { }; #endif -#if !defined(FEATURE_SHUFFLE_THUNKS) +#ifdef TARGET_X86 // This method unboxes the THIS pointer and then calls pRealMD // If it's shared code for a method in a generic value class, then also extract the vtable pointer // 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 { @@ -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 // !defined(FEATURE_SHUFFLE_THUNKS) +#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; @@ -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) @@ -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; diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 82013d73aeed0c..9c5592b3d915e5 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -197,16 +197,18 @@ class StubLinkerCPU : public StubLinker #endif } - VOID EmitUnboxMethodStub(MethodDesc* pRealMD); +#ifdef TARGET_X86 + 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. diff --git a/src/coreclr/vm/ilstubcache.cpp b/src/coreclr/vm/ilstubcache.cpp index 13f6891133f56a..dbd771eeaadb69 100644 --- a/src/coreclr/vm/ilstubcache.cpp +++ b/src/coreclr/vm/ilstubcache.cpp @@ -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"; @@ -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); @@ -254,7 +251,6 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa pMD->SetILStubType(DynamicMethodDesc::StubInstantiating); } else -#endif if (SF_IsTailCallStoreArgsStub(dwStubFlags)) { pMD->SetILStubType(DynamicMethodDesc::StubTailCallStoreArgs); diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index 608c9ec356a7c5..81dcff68ed91f2 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -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); diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 076bdfa8ee8ca1..7ee163d8c67bc3 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2765,10 +2765,8 @@ class DynamicMethodDesc : public StoredSigMethodDesc StubArrayOp, StubMulticastDelegate, StubWrapperDelegate, -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL StubUnboxingIL, StubInstantiating, -#endif StubTailCallStoreArgs, StubTailCallCallTarget, @@ -2897,10 +2895,8 @@ class DynamicMethodDesc : public StoredSigMethodDesc bool isStepThrough = false; -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL ILStubType type = GetILStubType(); isStepThrough = type == StubUnboxingIL || type == StubInstantiating; -#endif // FEATURE_INSTANTIATINGSTUB_AS_IL return isStepThrough; } @@ -2960,14 +2956,12 @@ class DynamicMethodDesc : public StoredSigMethodDesc _ASSERTE(IsILStub()); return GetILStubType() == DynamicMethodDesc::StubWrapperDelegate; } -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL bool IsUnboxingILStub() const { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); return GetILStubType() == DynamicMethodDesc::StubUnboxingIL; } -#endif bool IsDelegateShuffleThunk() const { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 155af20ac329f2..c58b4c2f687d62 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -1469,15 +1469,12 @@ void MethodDesc::CreateDerivedTargetSigWithExtraParams(MetaSig& msig, SigBuilder #endif // TARGET_X86 } -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL - Stub * CreateUnboxingILStubForValueTypeMethods(MethodDesc* pTargetMD) { CONTRACT(Stub*) { - THROWS; - GC_TRIGGERS; + STANDARD_VM_CHECK; POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; @@ -1582,8 +1579,7 @@ Stub * CreateInstantiatingILStub(MethodDesc* pTargetMD, void* pHiddenArg) CONTRACT(Stub*) { - THROWS; - GC_TRIGGERS; + STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pHiddenArg)); POSTCONDITION(CheckPointer(RETVAL)); } @@ -1689,15 +1685,13 @@ Stub * CreateInstantiatingILStub(MethodDesc* pTargetMD, void* pHiddenArg) RETURN Stub::NewStub(JitILStub(pStubMD)); } -#endif /* Make a stub that for a value class method that expects a BOXed this pointer */ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) { CONTRACT(Stub*) { - THROWS; - GC_TRIGGERS; + STANDARD_VM_CHECK; POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; @@ -1710,7 +1704,7 @@ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) _ASSERTE(pUnboxedMD != NULL && pUnboxedMD != pMD); -#ifdef FEATURE_SHUFFLE_THUNKS +#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS StackSArray portableShuffle; BOOL usePortableShuffle = FALSE; if (!pUnboxedMD->RequiresInstMethodTableArg()) @@ -1737,36 +1731,17 @@ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) sl.EmitComputedInstantiatingMethodStub(pUnboxedMD, &portableShuffle[0], NULL); - pstub = sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_INSTANTIATING_METHOD, "UnboxingStub"); + RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_INSTANTIATING_METHOD, "UnboxingStub"); } - else -#endif +#elif defined(TARGET_X86) + CPUSTUBLINKER sl; + if (sl.EmitUnboxMethodStub(pUnboxedMD)) { -#ifdef FEATURE_PORTABLE_ENTRYPOINTS - pstub = CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); -#else // !FEATURE_PORTABLE_ENTRYPOINTS -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL -#ifndef FEATURE_SHUFFLE_THUNKS - if (pUnboxedMD->RequiresInstMethodTableArg()) -#endif // !FEATURE_SHUFFLE_THUNKS - { - _ASSERTE(pUnboxedMD->RequiresInstMethodTableArg()); - pstub = CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); - } -#ifndef FEATURE_SHUFFLE_THUNKS - else -#endif // !FEATURE_SHUFFLE_THUNKS -#endif // FEATURE_INSTANTIATINGSTUB_AS_IL -#ifndef FEATURE_SHUFFLE_THUNKS - { - CPUSTUBLINKER sl; - sl.EmitUnboxMethodStub(pUnboxedMD); - pstub = sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "UnboxingStub"); - } -#endif // !FEATURE_SHUFFLE_THUNKS -#endif // FEATURE_PORTABLE_ENTRYPOINTS + RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "UnboxingStub"); } - RETURN pstub; +#endif + + RETURN CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); } #if defined(FEATURE_SHARE_GENERIC_CODE) @@ -1774,8 +1749,7 @@ Stub * MakeInstantiatingStubWorker(MethodDesc *pMD) { CONTRACT(Stub*) { - THROWS; - GC_TRIGGERS; + STANDARD_VM_CHECK; PRECONDITION(pMD->IsInstantiatingStub()); PRECONDITION(!pMD->RequiresInstArg()); PRECONDITION(!pMD->IsSharedByGenericMethodInstantiations()); @@ -1804,9 +1778,8 @@ Stub * MakeInstantiatingStubWorker(MethodDesc *pMD) // It's a per-instantiation static method extraArg = pMD->GetMethodTable(); } - Stub *pstub = NULL; -#ifdef FEATURE_SHUFFLE_THUNKS +#ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS StackSArray portableShuffle; if (GenerateShuffleArrayPortable(pMD, pSharedMD, &portableShuffle, ShuffleComputationType::InstantiatingStub)) { @@ -1814,23 +1787,17 @@ Stub * MakeInstantiatingStubWorker(MethodDesc *pMD) _ASSERTE(pSharedMD != NULL && pSharedMD != pMD); sl.EmitComputedInstantiatingMethodStub(pSharedMD, &portableShuffle[0], extraArg); - pstub = sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_INSTANTIATING_METHOD, "InstantiatingStub"); + RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_INSTANTIATING_METHOD, "InstantiatingStub"); } - else -#endif +#elif defined(TARGET_X86) + CPUSTUBLINKER sl; + if (sl.EmitInstantiatingMethodStub(pSharedMD, extraArg)) { -#ifdef FEATURE_INSTANTIATINGSTUB_AS_IL - pstub = CreateInstantiatingILStub(pSharedMD, extraArg); -#else - CPUSTUBLINKER sl; - _ASSERTE(pSharedMD != NULL && pSharedMD != pMD); - sl.EmitInstantiatingMethodStub(pSharedMD, extraArg); - - pstub = sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "InstantiatingStub"); -#endif + RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "InstantiatingStub"); } +#endif - RETURN pstub; + RETURN CreateInstantiatingILStub(pSharedMD, extraArg); } #endif // defined(FEATURE_SHARE_GENERIC_CODE) diff --git a/src/coreclr/vm/riscv64/cgencpu.h b/src/coreclr/vm/riscv64/cgencpu.h index f4c10a3d0e7c04..241d171817ebec 100644 --- a/src/coreclr/vm/riscv64/cgencpu.h +++ b/src/coreclr/vm/riscv64/cgencpu.h @@ -392,9 +392,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); From c5ee0bbaf3ee5a0c2c0a9ec142ff678c5876765f Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 28 Oct 2025 23:02:53 -0700 Subject: [PATCH 4/5] More simplification --- src/coreclr/vm/comdelegate.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index fc554fc45e8b6c..da3ba5c4c4f94d 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -829,7 +829,6 @@ LoaderHeap *DelegateEEClass::GetStubHeap() return GetInvokeMethod()->GetLoaderAllocator()->GetStubHeap(); } -#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); @@ -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 || TARGET_ARM64 || TARGET_AMD64 static PCODE SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMeth) { @@ -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 rShuffleEntryArray; if (GenerateShuffleArray(pMD, pTargetMeth, &rShuffleEntryArray)) @@ -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(TARGET_ARM64) || defined(TARGET_AMD64) || defined(FEATURE_PORTABLE_ENTRYPOINTS) pShuffleThunk = CreateILDelegateShuffleThunk(pMD, isInstRetBuff); -#else - _ASSERTE(FALSE); - return (PCODE)NULL; -#endif // TARGET_RISCV64 || TARGET_LOONGARCH64 || TARGET_ARM64 || TARGET_AMD64 } if (!pShuffleThunk) From d32e3397ae63bba85e11a05c2b9b95df11affa55 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 28 Oct 2025 23:10:34 -0700 Subject: [PATCH 5/5] Nits --- src/coreclr/vm/i386/stublinkerx86.cpp | 6 +++--- src/coreclr/vm/prestub.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 32a8c15f5fcdcd..3c37645e2cd66b 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -895,7 +895,7 @@ bool StubLinkerCPU::EmitInstantiatingMethodStub(MethodDesc* pMD, void* extra) #ifdef UNIX_X86_ABI // Unix x86 ABI requires stack alignment return false; -#else +#else // UNIX_X86_ABI MetaSig msig(pMD); ArgIterator argit(&msig); @@ -946,9 +946,9 @@ bool StubLinkerCPU::EmitInstantiatingMethodStub(MethodDesc* pMD, void* extra) EmitTailJumpToMethod(pMD); return true; -#endif +#endif // UNIX_X86_ABI } -#endif //TARGET_X86 +#endif // TARGET_X86 #ifdef FEATURE_PORTABLE_SHUFFLE_THUNKS VOID StubLinkerCPU::EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg) diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index c58b4c2f687d62..4eed9884cffb69 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -1739,7 +1739,7 @@ Stub * MakeUnboxingStubWorker(MethodDesc *pMD) { RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "UnboxingStub"); } -#endif +#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS || TARGET_X86 RETURN CreateUnboxingILStubForValueTypeMethods(pUnboxedMD); } @@ -1795,7 +1795,7 @@ Stub * MakeInstantiatingStubWorker(MethodDesc *pMD) { RETURN sl.Link(pMD->GetLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_NONE, "InstantiatingStub"); } -#endif +#endif // FEATURE_PORTABLE_SHUFFLE_THUNKS || TARGET_X86 RETURN CreateInstantiatingILStub(pSharedMD, extraArg); }