From c06cc3fbd21fd4c2cd34e871d63eb215f0bd7985 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 21:03:28 +0800 Subject: [PATCH 01/27] Use direct SinglecastDelegateInvokeStub on windows x86 --- src/coreclr/vm/comdelegate.cpp | 21 -------------- src/coreclr/vm/i386/asmconstants.h | 3 -- src/coreclr/vm/i386/asmhelpers.asm | 17 +++++++++++ src/coreclr/vm/i386/cgencpu.h | 2 -- src/coreclr/vm/i386/jithelp.asm | 2 -- src/coreclr/vm/i386/stublinkerx86.cpp | 41 --------------------------- src/coreclr/vm/i386/stublinkerx86.h | 10 ------- src/coreclr/vm/jithelpers.cpp | 13 --------- src/coreclr/vm/jitinterface.h | 1 - 9 files changed, 17 insertions(+), 93 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index b9ff707e60947..d5edfdf7da3cf 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1894,28 +1894,7 @@ PCODE COMDelegate::TheDelegateInvokeStub() } CONTRACT_END; -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) - static PCODE s_pInvokeStub; - - if (s_pInvokeStub == NULL) - { - CPUSTUBLINKER sl; - sl.EmitDelegateInvoke(); - // Process-wide singleton stub that never unloads - Stub *pCandidate = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_MULTICAST); - - if (InterlockedCompareExchangeT(&s_pInvokeStub, pCandidate->GetEntryPoint(), NULL) != NULL) - { - // if we are here someone managed to set the stub before us so we release the current - ExecutableWriterHolder candidateWriterHolder(pCandidate, sizeof(Stub)); - candidateWriterHolder.GetRW()->DecRef(); - } - } - - RETURN s_pInvokeStub; -#else RETURN GetEEFuncEntryPoint(SinglecastDelegateInvokeStub); -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL } // Get the cpu stub for a delegate invoke. diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index 8c8fec685e0f8..2ce218ab50525 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -283,7 +283,6 @@ ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(Inlin #define InlinedCallFrame__m_pCalleeSavedFP 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); -#ifdef FEATURE_STUBS_AS_IL // DelegateObject from src/vm/object.h #define DelegateObject___target 0x04 // offset 0 is m_pMethTab of base class Object #define DelegateObject___methodBase 0x08 @@ -299,8 +298,6 @@ ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtrAux == offsetof(DelegateObje ASMCONSTANTS_C_ASSERT(DelegateObject___invocationList == offsetof(DelegateObject, _invocationList)); ASMCONSTANTS_C_ASSERT(DelegateObject___invocationCount == offsetof(DelegateObject, _invocationCount)); -#endif - // ResolveCacheElem from src/vm/virtualcallstub.h #define ResolveCacheElem__pMT 0x00 #define ResolveCacheElem__token 0x04 diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 07f6e8b955d03..7634b07db50b1 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -915,6 +915,23 @@ _ProfileTailcallNaked@4 proc public retn 4 _ProfileTailcallNaked@4 endp +_SinglecastDelegateInvokeStub@0 proc public + + test ecx, ecx + jz NullObject + + + mov eax, [ecx + DelegateObject___methodPtr] + mov ecx, [ecx + DelegateObject___target] ; replace "this" pointer + + jmp eax + +NullObject: + mov ecx, CORINFO_NullReferenceException_ASM + jmp @JIT_InternalThrow@4 + +_SinglecastDelegateInvokeStub@0 endp + ;========================================================================== ; Invoked for vararg forward P/Invoke calls as a stub. ; Except for secret return buffer, arguments come on the stack so EDX is available as scratch. diff --git a/src/coreclr/vm/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index e99b8f542b590..236475226b4be 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -34,9 +34,7 @@ class BaseDomain; // CPU-dependent functions Stub * GenerateInitPInvokeFrameHelper(); -#ifdef FEATURE_STUBS_AS_IL EXTERN_C void SinglecastDelegateInvokeStub(); -#endif // FEATURE_STUBS_AS_IL #define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) diff --git a/src/coreclr/vm/i386/jithelp.asm b/src/coreclr/vm/i386/jithelp.asm index c2011190abc3f..536f55e4f5809 100644 --- a/src/coreclr/vm/i386/jithelp.asm +++ b/src/coreclr/vm/i386/jithelp.asm @@ -36,7 +36,6 @@ JIT_LLsh TEXTEQU <_JIT_LLsh@0> JIT_LRsh TEXTEQU <_JIT_LRsh@0> JIT_LRsz TEXTEQU <_JIT_LRsz@0> JIT_LMul TEXTEQU <@JIT_LMul@16> -JIT_InternalThrowFromHelper TEXTEQU <@JIT_InternalThrowFromHelper@4> JIT_WriteBarrierReg_PreGrow TEXTEQU <_JIT_WriteBarrierReg_PreGrow@0> JIT_WriteBarrierReg_PostGrow TEXTEQU <_JIT_WriteBarrierReg_PostGrow@0> JIT_TailCall TEXTEQU <_JIT_TailCall@0> @@ -53,7 +52,6 @@ EXTERN g_card_table:DWORD ifdef _DEBUG EXTERN WriteBarrierAssert:PROC endif ; _DEBUG -EXTERN JIT_InternalThrowFromHelper:PROC ifdef FEATURE_HIJACK EXTERN JIT_TailCallHelper:PROC endif diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index cfe9eec74af2e..6d63043a1ab1f 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -3584,47 +3584,6 @@ VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray) } -#if !defined(FEATURE_STUBS_AS_IL) - -#ifdef TARGET_X86 -//=========================================================================== -// Emits code for MulticastDelegate.Invoke() -VOID StubLinkerCPU::EmitDelegateInvoke() -{ - STANDARD_VM_CONTRACT; - - CodeLabel *pNullLabel = NewCodeLabel(); - - // test THISREG, THISREG - X86EmitR2ROp(0x85, THIS_kREG, THIS_kREG); - - // jz null - X86EmitCondJump(pNullLabel, X86CondCode::kJZ); - - // mov SCRATCHREG, [THISREG + Delegate.FP] ; Save target stub in register - X86EmitIndexRegLoad(SCRATCH_REGISTER_X86REG, THIS_kREG, DelegateObject::GetOffsetOfMethodPtr()); - - // mov THISREG, [THISREG + Delegate.OR] ; replace "this" pointer - X86EmitIndexRegLoad(THIS_kREG, THIS_kREG, DelegateObject::GetOffsetOfTarget()); - - // jmp SCRATCHREG - Emit16(0xe0ff | (SCRATCH_REGISTER_X86REG<<8)); - - // Do a null throw - EmitLabel(pNullLabel); - - // mov ECX, CORINFO_NullReferenceException - Emit8(0xb8+kECX); - Emit32(CORINFO_NullReferenceException); - - X86EmitCall(NewExternalCodeLabel(GetEEFuncEntryPoint(JIT_InternalThrowFromHelper)), 0); - - X86EmitReturn(0); -} -#endif // TARGET_X86 - -#endif // !FEATURE_STUBS_AS_IL - #if !defined(FEATURE_STUBS_AS_IL) //=========================================================================== // Emits code to break into debugger diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 031ca2f9b0aa3..500d87f6b2532 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -374,16 +374,6 @@ class StubLinkerCPU : public StubLinker BOOL bShouldProfile); #endif // FEATURE_COMINTEROP && TARGET_X86 -#ifndef FEATURE_STUBS_AS_IL - -#ifdef TARGET_X86 - //=========================================================================== - // Emits code for Delegate.Invoke() any delegate type - VOID EmitDelegateInvoke(); -#endif // TARGET_X86 - -#endif // !FEATURE_STUBS_AS_IL - //=========================================================================== // Emits code to adjust for a static delegate target. VOID EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 1bfeaf2b03928..ca062d92631bb 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -3923,19 +3923,6 @@ HCIMPL1(void, JIT_InternalThrow, unsigned exceptNum) } HCIMPLEND -/*********************************************************************/ -HCIMPL1(void*, JIT_InternalThrowFromHelper, unsigned exceptNum) -{ - FCALL_CONTRACT; - - FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_NOPOLL(Frame::FRAME_ATTR_CAPTURE_DEPTH_2|Frame::FRAME_ATTR_EXACT_DEPTH); - COMPlusThrow(MapCorInfoExceptionToRuntimeExceptionKind(exceptNum)); - HELPER_METHOD_FRAME_END(); - return NULL; -} -HCIMPLEND - #ifndef STATUS_STACK_BUFFER_OVERRUN // Not defined yet in CESDK includes # define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS)0xC0000409L) #endif diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 68617d39305bd..cd11551a3292f 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -252,7 +252,6 @@ extern "C" FCDECL2(VOID, JIT_WriteBarrier_Callable, Object **dst, Object *ref); #define WriteBarrier_Helper JIT_WriteBarrier_Callable extern "C" FCDECL1(void, JIT_InternalThrow, unsigned exceptNum); -extern "C" FCDECL1(void*, JIT_InternalThrowFromHelper, unsigned exceptNum); #ifdef TARGET_AMD64 From 48452029ef66ac1d2354b894ada952c7aaf9d88b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 21:29:48 +0800 Subject: [PATCH 02/27] Cleanup ifdefs --- src/coreclr/vm/dllimportcallback.h | 4 ++-- src/coreclr/vm/i386/asmhelpers.S | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/coreclr/vm/dllimportcallback.h b/src/coreclr/vm/dllimportcallback.h index ac2f2e93cdfd0..82e6fae2e781e 100644 --- a/src/coreclr/vm/dllimportcallback.h +++ b/src/coreclr/vm/dllimportcallback.h @@ -398,9 +398,9 @@ class UMEntryThunkCache AppDomain *m_pDomain; }; -#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL) +#ifndef FEATURE_EH_FUNCLETS EXCEPTION_HANDLER_DECL(FastNExportExceptHandler); -#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL +#endif FEATURE_EH_FUNCLETS extern "C" void TheUMEntryPrestub(void); extern "C" PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk); diff --git a/src/coreclr/vm/i386/asmhelpers.S b/src/coreclr/vm/i386/asmhelpers.S index 54f58fd75bb62..3a093d3b43bf2 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -737,10 +737,6 @@ NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler jmp eax // continue on into the method NESTED_END ResolveWorkerAsmStub, _TEXT -#ifdef FEATURE_STUBS_AS_IL -// ========================================================================== -// void SinglecastDelegateInvokeStub(); -// LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT test ecx, ecx @@ -756,7 +752,6 @@ LOCAL_LABEL(NullObject): jmp C_FUNC(JIT_InternalThrow) LEAF_END SinglecastDelegateInvokeStub, _TEXT -#endif // FEATURE_STUBS_AS_IL // ======================================================================================= // void ResolveWorkerChainLookupAsmStub(); From faf25e7b271f115b85e4e8f9458b928351f7d7a4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 21:34:51 +0800 Subject: [PATCH 03/27] EmitDebugBreak is unused --- src/coreclr/vm/i386/stublinkerx86.cpp | 9 --------- src/coreclr/vm/i386/stublinkerx86.h | 6 ------ 2 files changed, 15 deletions(-) diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 6d63043a1ab1f..ffb46062cc089 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -3585,15 +3585,6 @@ VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray) #if !defined(FEATURE_STUBS_AS_IL) -//=========================================================================== -// Emits code to break into debugger -VOID StubLinkerCPU::EmitDebugBreak() -{ - STANDARD_VM_CONTRACT; - - // int3 - Emit8(0xCC); -} #if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 500d87f6b2532..443f3c6685213 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -379,12 +379,6 @@ class StubLinkerCPU : public StubLinker VOID EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray); -#ifndef FEATURE_STUBS_AS_IL - //=========================================================================== - // Emits code to break into debugger - VOID EmitDebugBreak(); -#endif // !FEATURE_STUBS_AS_IL - #if defined(_DEBUG) && !defined(TARGET_UNIX) //=========================================================================== // Emits code to log JITHelper access From 09fcf2b56f46394759ac5bcef891dd40a9097458 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 21:47:58 +0800 Subject: [PATCH 04/27] endif format --- src/coreclr/vm/dllimportcallback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/dllimportcallback.h b/src/coreclr/vm/dllimportcallback.h index 82e6fae2e781e..0d142b2510a68 100644 --- a/src/coreclr/vm/dllimportcallback.h +++ b/src/coreclr/vm/dllimportcallback.h @@ -400,7 +400,7 @@ class UMEntryThunkCache #ifndef FEATURE_EH_FUNCLETS EXCEPTION_HANDLER_DECL(FastNExportExceptHandler); -#endif FEATURE_EH_FUNCLETS +#endif // FEATURE_EH_FUNCLETS extern "C" void TheUMEntryPrestub(void); extern "C" PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk); From 19057f9d138612aec6e9110ce07daf997c129787 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 21:52:40 +0800 Subject: [PATCH 05/27] Restore comment --- src/coreclr/vm/i386/asmhelpers.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/coreclr/vm/i386/asmhelpers.S b/src/coreclr/vm/i386/asmhelpers.S index 3a093d3b43bf2..50c90b2d6fa82 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -737,6 +737,9 @@ NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler jmp eax // continue on into the method NESTED_END ResolveWorkerAsmStub, _TEXT +// ========================================================================== +// void SinglecastDelegateInvokeStub(); +// LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT test ecx, ecx From 157325ba27d2b9a34e0544b5acde6c403cbae0f8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 11 Jul 2024 22:32:14 +0800 Subject: [PATCH 06/27] Fix JIT_InternalThrowFromHelper reference --- src/coreclr/vm/amd64/AsmHelpers.asm | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index 39bee849fa19e..eac31fc24c3d8 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -565,9 +565,6 @@ NESTED_ENTRY ProfileTailcallNaked, _TEXT ret NESTED_END ProfileTailcallNaked, _TEXT - -extern JIT_InternalThrowFromHelper:proc - LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT test rcx, rcx From c98be47e1a41728baa7335cddb0d335ff14242a4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 16 Jul 2024 00:03:06 +0800 Subject: [PATCH 07/27] Use IL stub for Delegate.Invoke --- src/coreclr/debug/ee/frameinfo.cpp | 1 + src/coreclr/vm/class.h | 1 + src/coreclr/vm/comdelegate.cpp | 61 +++++++++++++++++++++++------- src/coreclr/vm/comdelegate.h | 3 -- src/coreclr/vm/dllimport.h | 2 + src/coreclr/vm/ilstubcache.cpp | 6 +++ src/coreclr/vm/method.hpp | 8 ++++ 7 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/coreclr/debug/ee/frameinfo.cpp b/src/coreclr/debug/ee/frameinfo.cpp index 48e0d2d56c146..59945c30c08bc 100644 --- a/src/coreclr/debug/ee/frameinfo.cpp +++ b/src/coreclr/debug/ee/frameinfo.cpp @@ -1563,6 +1563,7 @@ StackWalkAction DebuggerWalkStackProc(CrawlFrame *pCF, void *data) _ASSERTE(md->IsDynamicMethod()); DynamicMethodDesc* dMD = md->AsDynamicMethodDesc(); use |= dMD->IsMulticastStub(); + use |= dMD->IsSinglecastStub(); use |= dMD->GetILStubType() == DynamicMethodDesc::StubTailCallCallTarget; if (use) diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 74c66714555f3..6f45869c9e5e7 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -1893,6 +1893,7 @@ class DelegateEEClass : public EEClass PTR_Stub m_pStaticCallStub; PTR_Stub m_pInstRetBuffCallStub; PTR_MethodDesc m_pInvokeMethod; + PTR_Stub m_pSingleCastInvokeStub; PTR_Stub m_pMultiCastInvokeStub; PTR_Stub m_pWrapperDelegateInvokeStub; UMThunkMarshInfo* m_pUMThunkMarshInfo; diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index d5edfdf7da3cf..c299e23e43a6f 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1885,18 +1885,6 @@ BOOL COMDelegate::IsTrueMulticastDelegate(OBJECTREF delegate) return isMulticast; } -PCODE COMDelegate::TheDelegateInvokeStub() -{ - CONTRACT(PCODE) - { - STANDARD_VM_CHECK; - POSTCONDITION(RETVAL != NULL); - } - CONTRACT_END; - - RETURN GetEEFuncEntryPoint(SinglecastDelegateInvokeStub); -} - // Get the cpu stub for a delegate invoke. PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) { @@ -1920,7 +1908,54 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) if (*pMD->GetSig() != (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_DEFAULT)) COMPlusThrow(kInvalidProgramException); - ret = COMDelegate::TheDelegateInvokeStub(); + Stub *pStub = pClass->m_pMultiCastInvokeStub; + if (pStub == NULL) + { + MetaSig sig(pMD); + + BOOL fReturnVal = !sig.IsReturnTypeVoid(); + + SigTypeContext emptyContext; + ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, (ILStubLinkerFlags)(ILSTUB_LINKER_FLAG_STUB_HAS_THIS | ILSTUB_LINKER_FLAG_TARGET_HAS_THIS)); + + ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); + + // Load the target object + pCode->EmitLoadThis(); + pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__TARGET))); + + // Load the arguments + for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) + pCode->EmitLDARG(paramCount); + + // Load the method pointer + pCode->EmitLoadThis(); + pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__METHOD_PTR))); + + PCCOR_SIGNATURE pSig; + DWORD cbSig; + pMD->GetSig(&pSig,&cbSig); + + // call the delegate + pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs(), fReturnVal); + + // return + pCode->EmitRET(); + + MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), + pMD->GetMethodTable(), + ILSTUB_MULTICASTDELEGATE_INVOKE, + pMD->GetModule(), + pSig, cbSig, + NULL, + &sl); + + pStub = Stub::NewStub(JitILStub(pStubMD)); + + InterlockedCompareExchangeT(&pClass->m_pSingleCastInvokeStub, pStub, NULL); + } + + ret = pStub->GetEntryPoint(); } else { diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index dd5948f02bb98..55a2fa0c55727 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -79,9 +79,6 @@ class COMDelegate // Get the cpu stub for a delegate invoke. static PCODE GetInvokeMethodStub(EEImplMethodDesc* pMD); - // get the one single delegate invoke stub - static PCODE TheDelegateInvokeStub(); - static MethodDesc * __fastcall GetMethodDesc(OBJECTREF obj); static OBJECTREF GetTargetObject(OBJECTREF obj); diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index f5e2c058fb1a1..619c9111a0129 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -203,6 +203,7 @@ enum ILStubTypes ILSTUB_TAILCALL_STOREARGS = 0x80000008, ILSTUB_TAILCALL_CALLTARGET = 0x80000009, ILSTUB_STATIC_VIRTUAL_DISPATCH_STUB = 0x8000000A, + ILSTUB_SINGLECASTDELEGATE_INVOKE = 0x8000000B, }; #ifdef FEATURE_COMINTEROP @@ -230,6 +231,7 @@ inline bool SF_IsArrayOpStub (DWORD dwStubFlags) { LIMITED_METHOD_CONT (dwStubFlags == ILSTUB_ARRAYOP_ADDRESS)); } inline bool SF_IsMulticastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_MULTICASTDELEGATE_INVOKE); } +inline bool SF_IsSinglecastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_SINGLECASTDELEGATE_INVOKE); } inline bool SF_IsWrapperDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_WRAPPERDELEGATE_INVOKE); } #ifdef FEATURE_INSTANTIATINGSTUB_AS_IL diff --git a/src/coreclr/vm/ilstubcache.cpp b/src/coreclr/vm/ilstubcache.cpp index 65afb93865dcd..6601bb4c53aa1 100644 --- a/src/coreclr/vm/ilstubcache.cpp +++ b/src/coreclr/vm/ilstubcache.cpp @@ -148,6 +148,7 @@ namespace case DynamicMethodDesc::StubStructMarshalInterop: return "IL_STUB_StructMarshal"; case DynamicMethodDesc::StubArrayOp: return "IL_STUB_Array"; case DynamicMethodDesc::StubMulticastDelegate: return "IL_STUB_MulticastDelegate_Invoke"; + case DynamicMethodDesc::StubSinglecastDelegate: return "IL_STUB_SinglecastDelegate_Invoke"; #ifdef FEATURE_INSTANTIATINGSTUB_AS_IL case DynamicMethodDesc::StubUnboxingIL: return "IL_STUB_UnboxingStub"; case DynamicMethodDesc::StubInstantiating: return "IL_STUB_InstantiatingStub"; @@ -242,6 +243,11 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa pMD->SetILStubType(DynamicMethodDesc::StubMulticastDelegate); } else + if (SF_IsSinglecastDelegateStub(dwStubFlags)) + { + pMD->SetILStubType(DynamicMethodDesc::StubSinglecastDelegate); + } + else if (SF_IsWrapperDelegateStub(dwStubFlags)) { pMD->SetILStubType(DynamicMethodDesc::StubWrapperDelegate); diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 7c229b146a538..a77299c09de1c 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2444,6 +2444,8 @@ class DynamicMethodDesc : public StoredSigMethodDesc StubVirtualStaticMethodDispatch, + StubSinglecastDelegate, + StubLast }; @@ -2591,6 +2593,12 @@ class DynamicMethodDesc : public StoredSigMethodDesc _ASSERTE(IsILStub()); return GetILStubType() == DynamicMethodDesc::StubMulticastDelegate; } + bool IsSinglecastStub() const + { + LIMITED_METHOD_DAC_CONTRACT; + _ASSERTE(IsILStub()); + return GetILStubType() == DynamicMethodDesc::StubSinglecastDelegate; + } bool IsWrapperDelegateStub() const { LIMITED_METHOD_DAC_CONTRACT; From 72fd2d69c99e0bd339189ea8abe0f3dce798bafd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 16 Jul 2024 01:43:14 +0800 Subject: [PATCH 08/27] Remove SinglecastDelegateInvokeStub in asm --- src/coreclr/vm/amd64/AsmHelpers.asm | 17 ---------- src/coreclr/vm/amd64/asmconstants.h | 6 ---- src/coreclr/vm/amd64/cgencpu.h | 1 - src/coreclr/vm/amd64/unixasmhelpers.S | 17 ---------- src/coreclr/vm/arm/asmconstants.h | 6 ---- src/coreclr/vm/arm/asmhelpers.S | 16 ---------- src/coreclr/vm/arm/cgencpu.h | 2 -- src/coreclr/vm/arm64/asmconstants.h | 6 ---- src/coreclr/vm/arm64/asmhelpers.S | 16 ---------- src/coreclr/vm/arm64/asmhelpers.asm | 16 ---------- src/coreclr/vm/arm64/cgencpu.h | 2 -- src/coreclr/vm/i386/asmconstants.h | 15 --------- src/coreclr/vm/i386/asmhelpers.S | 19 ----------- src/coreclr/vm/i386/asmhelpers.asm | 17 ---------- src/coreclr/vm/i386/cgencpu.h | 2 -- src/coreclr/vm/loongarch64/asmconstants.h | 6 ---- src/coreclr/vm/loongarch64/asmhelpers.S | 13 -------- src/coreclr/vm/loongarch64/cgencpu.h | 2 -- src/coreclr/vm/riscv64/asmconstants.h | 6 ---- src/coreclr/vm/riscv64/asmhelpers.S | 13 -------- src/coreclr/vm/riscv64/cgencpu.h | 2 -- src/coreclr/vm/stubmgr.cpp | 39 ++++++----------------- 22 files changed, 10 insertions(+), 229 deletions(-) diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index eac31fc24c3d8..af3b24773e3e9 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -565,23 +565,6 @@ NESTED_ENTRY ProfileTailcallNaked, _TEXT ret NESTED_END ProfileTailcallNaked, _TEXT -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - - test rcx, rcx - jz NullObject - - - mov rax, [rcx + OFFSETOF__DelegateObject___methodPtr] - mov rcx, [rcx + OFFSETOF__DelegateObject___target] ; replace "this" pointer - - jmp rax - -NullObject: - mov rcx, CORINFO_NullReferenceException_ASM - jmp JIT_InternalThrow - -LEAF_END SinglecastDelegateInvokeStub, _TEXT - ifdef FEATURE_TIERED_COMPILATION extern OnCallCountThresholdReached:proc diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 524e1fd40b7ae..69f4f72e83843 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -124,12 +124,6 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadExceptionState__m_pCurrentTracker -#define OFFSETOF__DelegateObject___methodPtr 0x18 -ASMCONSTANT_OFFSETOF_ASSERT(DelegateObject, _methodPtr); - -#define OFFSETOF__DelegateObject___target 0x08 -ASMCONSTANT_OFFSETOF_ASSERT(DelegateObject, _target); - #define OFFSETOF__MethodTable__m_dwFlags 0x00 ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodTable__m_dwFlags == offsetof(MethodTable, m_dwFlags)); diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index 75d31ea1a4ad0..24d0d81e82b4e 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -34,7 +34,6 @@ class ComCallMethodDesc; // // functions implemented in AMD64 assembly // -EXTERN_C void SinglecastDelegateInvokeStub(); #define COMMETHOD_PREPAD 16 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) #define COMMETHOD_CALL_PRESTUB_SIZE 6 // 32-bit indirect relative call diff --git a/src/coreclr/vm/amd64/unixasmhelpers.S b/src/coreclr/vm/amd64/unixasmhelpers.S index 77fe1384dcd9e..7e404a2a09cf6 100644 --- a/src/coreclr/vm/amd64/unixasmhelpers.S +++ b/src/coreclr/vm/amd64/unixasmhelpers.S @@ -182,23 +182,6 @@ NESTED_END OnHijackTripThread, _TEXT #endif // FEATURE_HIJACK -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - - test rdi, rdi - jz NullObject - - - mov rax, [rdi + OFFSETOF__DelegateObject___methodPtr] - mov rdi, [rdi + OFFSETOF__DelegateObject___target] // replace "this" pointer - - jmp rax - -NullObject: - mov rdi, CORINFO_NullReferenceException_ASM - jmp C_FUNC(JIT_InternalThrow) - -LEAF_END SinglecastDelegateInvokeStub, _TEXT - #ifdef FEATURE_TIERED_COMPILATION NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 1a65e1e45351d..3eee96811bfd4 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -64,12 +64,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureSp == offsetof(LazyMachState, capture #define LazyMachState_captureIp (LazyMachState_captureSp+4) ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, captureIp)) -#define DelegateObject___methodPtr 0x0c -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr)); - -#define DelegateObject___target 0x04 -ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target)); - #define MethodTable__m_BaseSize 0x04 ASMCONSTANTS_C_ASSERT(MethodTable__m_BaseSize == offsetof(MethodTable, m_BaseSize)); diff --git a/src/coreclr/vm/arm/asmhelpers.S b/src/coreclr/vm/arm/asmhelpers.S index 81d92b7a107f0..cd0c707b4c911 100644 --- a/src/coreclr/vm/arm/asmhelpers.S +++ b/src/coreclr/vm/arm/asmhelpers.S @@ -152,22 +152,6 @@ CallDescrWorkerInternalReturnAddressOffset: LEAF_END LazyMachStateCaptureState, _TEXT -// void SinglecastDelegateInvokeStub(Delegate *pThis) - LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - cmp r0, #0 - beq LOCAL_LABEL(LNullThis) - - ldr r12, [r0, #DelegateObject___methodPtr] - ldr r0, [r0, #DelegateObject___target] - - bx r12 - -LOCAL_LABEL(LNullThis): - mov r0, #CORINFO_NullReferenceException_ASM - b C_FUNC(JIT_InternalThrow) - - LEAF_END SinglecastDelegateInvokeStub, _TEXT - // // r12 = UMEntryThunk* // diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index 7c2e3b8160bc6..7f6658690a64a 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -939,8 +939,6 @@ class StubLinkerCPU : public StubLinker VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg); }; -extern "C" void SinglecastDelegateInvokeStub(); - #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4359) // Prevent "warning C4359: 'UMEntryThunkCode': Alignment specifier is less than actual alignment (8), and will be ignored." in crossbitness scenario diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index eb2462f8ec78e..8ca80f1767e95 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -109,12 +109,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define DelegateObject___methodPtr 0x18 -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr)); - -#define DelegateObject___target 0x08 -ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target)); - #define SIZEOF__GSCookie 0x8 ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index e163d807404e1..085c8a8259b0d 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -272,22 +272,6 @@ LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT br x17 LEAF_END JIT_WriteBarrier_Callable, _TEXT -// void SinglecastDelegateInvokeStub(Delegate *pThis) -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - cmp x0, #0 - beq LOCAL_LABEL(LNullThis) - - ldr x16, [x0, #DelegateObject___methodPtr] - ldr x0, [x0, #DelegateObject___target] - - br x16 - -LOCAL_LABEL(LNullThis): - mov x0, #CORINFO_NullReferenceException_ASM - b C_FUNC(JIT_InternalThrow) - -LEAF_END SinglecastDelegateInvokeStub, _TEXT - // // x12 = UMEntryThunk* // diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index b602b2cf9fc94..c997e4e822005 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -317,22 +317,6 @@ EphemeralCheckEnabled LEAF_END JIT_UpdateWriteBarrierState -; void SinglecastDelegateInvokeStub(Delegate *pThis) - LEAF_ENTRY SinglecastDelegateInvokeStub - cmp x0, #0 - beq LNullThis - - ldr x16, [x0, #DelegateObject___methodPtr] - ldr x0, [x0, #DelegateObject___target] - - br x16 - -LNullThis - mov x0, #CORINFO_NullReferenceException_ASM - b JIT_InternalThrow - - LEAF_END - #ifdef FEATURE_COMINTEROP ; ------------------------------------------------------------------ diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 2058267df6743..66553fed09812 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -518,8 +518,6 @@ class StubLinkerCPU : public StubLinker }; -extern "C" void SinglecastDelegateInvokeStub(); - // preferred alignment for data #define DATA_ALIGNMENT 8 diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index 2ce218ab50525..e599dd8f46d92 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -283,21 +283,6 @@ ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(Inlin #define InlinedCallFrame__m_pCalleeSavedFP 0x14 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); -// DelegateObject from src/vm/object.h -#define DelegateObject___target 0x04 // offset 0 is m_pMethTab of base class Object -#define DelegateObject___methodBase 0x08 -#define DelegateObject___methodPtr 0x0c -#define DelegateObject___methodPtrAux 0x10 -#define DelegateObject___invocationList 0x14 -#define DelegateObject___invocationCount 0x18 - -ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target)); -ASMCONSTANTS_C_ASSERT(DelegateObject___methodBase == offsetof(DelegateObject, _methodBase)); -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr)); -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtrAux == offsetof(DelegateObject, _methodPtrAux)); -ASMCONSTANTS_C_ASSERT(DelegateObject___invocationList == offsetof(DelegateObject, _invocationList)); -ASMCONSTANTS_C_ASSERT(DelegateObject___invocationCount == offsetof(DelegateObject, _invocationCount)); - // ResolveCacheElem from src/vm/virtualcallstub.h #define ResolveCacheElem__pMT 0x00 #define ResolveCacheElem__token 0x04 diff --git a/src/coreclr/vm/i386/asmhelpers.S b/src/coreclr/vm/i386/asmhelpers.S index 50c90b2d6fa82..bd85a248b1efa 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -737,25 +737,6 @@ NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler jmp eax // continue on into the method NESTED_END ResolveWorkerAsmStub, _TEXT -// ========================================================================== -// void SinglecastDelegateInvokeStub(); -// -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - - test ecx, ecx - jz LOCAL_LABEL(NullObject) - - mov eax, [ecx + DelegateObject___methodPtr] - mov ecx, [ecx + DelegateObject___target] // replace "this" pointer - jmp eax - -LOCAL_LABEL(NullObject): - - mov ecx, CORINFO_NullReferenceException_ASM - jmp C_FUNC(JIT_InternalThrow) - -LEAF_END SinglecastDelegateInvokeStub, _TEXT - // ======================================================================================= // void ResolveWorkerChainLookupAsmStub(); // diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 7634b07db50b1..07f6e8b955d03 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -915,23 +915,6 @@ _ProfileTailcallNaked@4 proc public retn 4 _ProfileTailcallNaked@4 endp -_SinglecastDelegateInvokeStub@0 proc public - - test ecx, ecx - jz NullObject - - - mov eax, [ecx + DelegateObject___methodPtr] - mov ecx, [ecx + DelegateObject___target] ; replace "this" pointer - - jmp eax - -NullObject: - mov ecx, CORINFO_NullReferenceException_ASM - jmp @JIT_InternalThrow@4 - -_SinglecastDelegateInvokeStub@0 endp - ;========================================================================== ; Invoked for vararg forward P/Invoke calls as a stub. ; Except for secret return buffer, arguments come on the stack so EDX is available as scratch. diff --git a/src/coreclr/vm/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index 236475226b4be..407e1ec0ec40e 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -34,8 +34,6 @@ class BaseDomain; // CPU-dependent functions Stub * GenerateInitPInvokeFrameHelper(); -EXTERN_C void SinglecastDelegateInvokeStub(); - #define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) #define COMMETHOD_PREPAD 8 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index 9754443c20be5..804134d0eead9 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -134,12 +134,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define DelegateObject___methodPtr 0x18 -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr)); - -#define DelegateObject___target 0x08 -ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target)); - #define SIZEOF__GSCookie 0x8 ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index 4848fc409ff11..a99cf0c2c4287 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -538,19 +538,6 @@ NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler NESTED_END VirtualMethodFixupStub, _TEXT #endif // FEATURE_PREJIT -// void SinglecastDelegateInvokeStub(Delegate *pThis) -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - beq $a0, $zero, LOCAL_LABEL(LNullThis) - - ld.d $t4, $a0, DelegateObject___methodPtr - ld.d $a0, $a0, DelegateObject___target - jirl $r0, $t4, 0 - -LOCAL_LABEL(LNullThis): - addi.d $a0, $zero, CORINFO_NullReferenceException_ASM - b JIT_InternalThrow -LEAF_END SinglecastDelegateInvokeStub, _TEXT - // ------------------------------------------------------------------ // ThePreStubPatch() LEAF_ENTRY ThePreStubPatch, _TEXT diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index 80d58575e6b57..fd88ed65abffd 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -434,8 +434,6 @@ class StubLinkerCPU : public StubLinker void EmitLoadFloatRegImm(FloatReg ft, IntReg base, int offset); }; -extern "C" void SinglecastDelegateInvokeStub(); - // preferred alignment for data #define DATA_ALIGNMENT 8 diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index 0ba094537ad3e..4d8b8ff67088d 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -129,12 +129,6 @@ ASMCONSTANTS_C_ASSERT(LazyMachState_captureIp == offsetof(LazyMachState, capture #define VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)) -#define DelegateObject___methodPtr 0x18 -ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr)); - -#define DelegateObject___target 0x08 -ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target)); - #define SIZEOF__GSCookie 0x8 ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index ffe13eea7a0fe..84507f726960f 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -477,19 +477,6 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler EPILOG_BRANCH_REG t4 NESTED_END NDirectImportThunk, _TEXT -// void SinglecastDelegateInvokeStub(Delegate *pThis) -LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT - beq a0, zero, LOCAL_LABEL(LNullThis) - - ld t4, (DelegateObject___methodPtr)(a0) - ld a0, (DelegateObject___target)(a0) - jr t4 - -LOCAL_LABEL(LNullThis): - addi a0, zero, CORINFO_NullReferenceException_ASM - tail JIT_InternalThrow -LEAF_END SinglecastDelegateInvokeStub, _TEXT - // ------------------------------------------------------------------ // ThePreStubPatch() LEAF_ENTRY ThePreStubPatch, _TEXT diff --git a/src/coreclr/vm/riscv64/cgencpu.h b/src/coreclr/vm/riscv64/cgencpu.h index 6ce6e5fa90f84..c4400f70d1a3b 100644 --- a/src/coreclr/vm/riscv64/cgencpu.h +++ b/src/coreclr/vm/riscv64/cgencpu.h @@ -414,8 +414,6 @@ class StubLinkerCPU : public StubLinker void EmitEpilog(); }; -extern "C" void SinglecastDelegateInvokeStub(); - // preferred alignment for data #define DATA_ALIGNMENT 8 diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index c24e0c277fd91..851b56be0fd06 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1370,31 +1370,16 @@ static BOOL TraceManagedThunk( LOG((LF_CORDB, LL_INFO10000, "TraceManagedThunk: at %p, retAddr is %p\n", pc, (*pRetAddr))); DELEGATEREF orDelegate; - if (GetEEFuncEntryPoint(SinglecastDelegateInvokeStub) == pc) - { - LOG((LF_CORDB, LL_INFO10000, "TraceManagedThunk: isSingle\n")); - orDelegate = (DELEGATEREF)ObjectToOBJECTREF(StubManagerHelpers::GetThisPtr(pContext)); - destAddr = orDelegate->GetMethodPtr(); - if (StubManager::TraceStub(destAddr, trace)) - { - LOG((LF_CORDB,LL_INFO10000, "TraceManagedThunk: ppbDest: %p\n", destAddr)); - LOG((LF_CORDB,LL_INFO10000, "TraceManagedThunk: res: 1, result type: %d\n", trace->GetTraceType())); - return TRUE; - } - } - else - { - // We get here if we are stopped at the beginning of a shuffle thunk. - // The next address we are going to is _methodPtrAux. - Stub* pStub = Stub::RecoverStub(pc); + // We get here if we are stopped at the beginning of a shuffle thunk. + // The next address we are going to is _methodPtrAux. + Stub* pStub = Stub::RecoverStub(pc); - // We use the patch offset field to indicate whether the stub has a hidden return buffer argument. - // This field is set in SetupShuffleThunk(). - orDelegate = (pStub->GetPatchOffset() != 0) - ? (DELEGATEREF)ObjectToOBJECTREF(StubManagerHelpers::GetSecondArg(pContext)) // This stub has a hidden return buffer argument. - : (DELEGATEREF)ObjectToOBJECTREF(StubManagerHelpers::GetThisPtr(pContext)); - } + // We use the patch offset field to indicate whether the stub has a hidden return buffer argument. + // This field is set in SetupShuffleThunk(). + orDelegate = (pStub->GetPatchOffset() != 0) + ? (DELEGATEREF)ObjectToOBJECTREF(StubManagerHelpers::GetSecondArg(pContext)) // This stub has a hidden return buffer argument. + : (DELEGATEREF)ObjectToOBJECTREF(StubManagerHelpers::GetThisPtr(pContext)); destAddr = orDelegate->GetMethodPtrAux(); @@ -1404,9 +1389,7 @@ static BOOL TraceManagedThunk( // Could be in the singlecast invoke stub (in which case the next destination is in _methodPtr) or a // shuffle thunk (destination in _methodPtrAux). - int offsetOfNextDest = (pc == GetEEFuncEntryPoint(SinglecastDelegateInvokeStub)) - ? DelegateObject::GetOffsetOfMethodPtr() - : DelegateObject::GetOffsetOfMethodPtrAux(); + int offsetOfNextDest = DelegateObject::GetOffsetOfMethodPtrAux(); destAddr = *(PCODE*)(pThis + offsetOfNextDest); #elif defined(TARGET_ARM64) @@ -1415,9 +1398,7 @@ static BOOL TraceManagedThunk( // Could be in the singlecast invoke stub (in which case the next destination is in _methodPtr) or a // shuffle thunk (destination in _methodPtrAux). - int offsetOfNextDest = (pc == GetEEFuncEntryPoint(SinglecastDelegateInvokeStub)) - ? DelegateObject::GetOffsetOfMethodPtr() - : DelegateObject::GetOffsetOfMethodPtrAux(); + int offsetOfNextDest = DelegateObject::GetOffsetOfMethodPtrAux(); destAddr = *(PCODE*)(pThis + offsetOfNextDest); #else From e60b3f1b6eeb992e4538057d6c1da027e465975e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 Jul 2024 19:24:47 +0800 Subject: [PATCH 09/27] Fix method name and argument count --- src/coreclr/vm/comdelegate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index c299e23e43a6f..b60f08569566a 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1931,20 +1931,20 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) // Load the method pointer pCode->EmitLoadThis(); pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__METHOD_PTR))); - + PCCOR_SIGNATURE pSig; DWORD cbSig; pMD->GetSig(&pSig,&cbSig); // call the delegate - pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs(), fReturnVal); + pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs() + 1, fReturnVal); // return pCode->EmitRET(); MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), pMD->GetMethodTable(), - ILSTUB_MULTICASTDELEGATE_INVOKE, + ILSTUB_SINGLECASTDELEGATE_INVOKE, pMD->GetModule(), pSig, cbSig, NULL, From 7f117aa14341508c3a9638b07f3c5d34321fde74 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 Jul 2024 19:29:30 +0800 Subject: [PATCH 10/27] Code quality --- src/coreclr/vm/comdelegate.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index b60f08569566a..a4b3d4116bbe3 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1919,6 +1919,12 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, (ILStubLinkerFlags)(ILSTUB_LINKER_FLAG_STUB_HAS_THIS | ILSTUB_LINKER_FLAG_TARGET_HAS_THIS)); ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); + DWORD numMethodPtr = pCode->NewLocal(ELEMENT_TYPE_I); + + // Load the method pointer + pCode->EmitLoadThis(); + pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__METHOD_PTR))); + pCode->EmitSTLOC(numMethodPtr); // Load the target object pCode->EmitLoadThis(); @@ -1928,16 +1934,13 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) pCode->EmitLDARG(paramCount); - // Load the method pointer - pCode->EmitLoadThis(); - pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__METHOD_PTR))); - PCCOR_SIGNATURE pSig; DWORD cbSig; pMD->GetSig(&pSig,&cbSig); // call the delegate - pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs() + 1, fReturnVal); + pCode->EmitLDLOC(numMethodPtr); + pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs() + 1, fReturnVal); // NumFixedArgs doesn't include "this" // return pCode->EmitRET(); From cd648faa5ce3dd0213678b8b6cd6b3a61b1bb42d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 Jul 2024 22:14:22 +0800 Subject: [PATCH 11/27] Delete JIT_InternalThrow and CorInfoException --- src/coreclr/inc/corinfo.h | 16 -------- src/coreclr/vm/amd64/AsmHelpers.asm | 1 - src/coreclr/vm/amd64/JitHelpers_Fast.asm | 2 - src/coreclr/vm/amd64/JitHelpers_Slow.asm | 2 - src/coreclr/vm/amd64/asmconstants.h | 12 ------ src/coreclr/vm/arm/asmconstants.h | 8 ---- src/coreclr/vm/arm64/asmconstants.h | 9 ----- src/coreclr/vm/arm64/asmhelpers.asm | 1 - src/coreclr/vm/i386/asmconstants.h | 13 ------- src/coreclr/vm/i386/asmhelpers.asm | 9 ----- src/coreclr/vm/jithelpers.cpp | 47 ----------------------- src/coreclr/vm/jitinterface.h | 2 - src/coreclr/vm/loongarch64/asmconstants.h | 9 ----- src/coreclr/vm/riscv64/asmconstants.h | 9 ----- 14 files changed, 140 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index cc1ca62f47485..7dfc2393d895a 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -920,22 +920,6 @@ enum CORINFO_EH_CLAUSE_FLAGS CORINFO_EH_CLAUSE_SAMETRY = 0x0010, // This clause covers same try block as the previous one }; -// This enumeration is passed to InternalThrow -enum CorInfoException -{ - CORINFO_NullReferenceException, - CORINFO_DivideByZeroException, - CORINFO_InvalidCastException, - CORINFO_IndexOutOfRangeException, - CORINFO_OverflowException, - CORINFO_SynchronizationLockException, - CORINFO_ArrayTypeMismatchException, - CORINFO_RankException, - CORINFO_ArgumentNullException, - CORINFO_ArgumentException, - CORINFO_Exception_Count, -}; - // These are used to detect array methods as NamedIntrinsic in JIT importer, // which otherwise don't have a name. enum class CorInfoArrayIntrinsic diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index af3b24773e3e9..1b6fd1c763682 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -4,7 +4,6 @@ include AsmMacros.inc include asmconstants.inc -extern JIT_InternalThrow:proc extern NDirectImportWorker:proc extern ThePreStub:proc extern ProfileEnter:proc diff --git a/src/coreclr/vm/amd64/JitHelpers_Fast.asm b/src/coreclr/vm/amd64/JitHelpers_Fast.asm index 70291c8307dc9..7e38053605ddb 100644 --- a/src/coreclr/vm/amd64/JitHelpers_Fast.asm +++ b/src/coreclr/vm/amd64/JitHelpers_Fast.asm @@ -47,8 +47,6 @@ ifdef _DEBUG extern JIT_WriteBarrier_Debug:proc endif -extern JIT_InternalThrow:proc - ; JIT_ByRefWriteBarrier has weird semantics, see usage in StubLinkerX86.cpp ; diff --git a/src/coreclr/vm/amd64/JitHelpers_Slow.asm b/src/coreclr/vm/amd64/JitHelpers_Slow.asm index 6d322248cdeee..e1bf541092953 100644 --- a/src/coreclr/vm/amd64/JitHelpers_Slow.asm +++ b/src/coreclr/vm/amd64/JitHelpers_Slow.asm @@ -55,8 +55,6 @@ extern g_pStringClass:QWORD extern FramedAllocateString:proc extern JIT_NewArr1:proc -extern JIT_InternalThrow:proc - ifdef _DEBUG ; Version for when we're sure to be in the GC, checks whether or not the card ; needs to be updated diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 69f4f72e83843..2d619a017d0e9 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -192,18 +192,6 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pGCStatics == offsetof(DynamicStaticsInfo, m_pGCStatics)); -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM - == CORINFO_NullReferenceException); - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM - == CORINFO_IndexOutOfRangeException); - -#define CORINFO_ArgumentException_ASM 9 -ASMCONSTANTS_C_ASSERT( CORINFO_ArgumentException_ASM - == CORINFO_ArgumentException); - // MachState offsets (AMD64\gmscpu.h) diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 3eee96811bfd4..dbd83bd6a947a 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -35,14 +35,6 @@ #define REDIRECTSTUB_SP_OFFSET_CONTEXT 0 -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM - == CORINFO_NullReferenceException); - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM - == CORINFO_IndexOutOfRangeException); - // Offset of the array containing the address of captured registers in MachState #define MachState__captureR4_R11 0x0 diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index 8ca80f1767e95..af87ba2700fc0 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -72,15 +72,6 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__pTarget == offsetof(CallDescrD ASMCONSTANTS_C_ASSERT(CallDescrData__pRetBuffArg == offsetof(CallDescrData, pRetBuffArg)) ASMCONSTANTS_C_ASSERT(CallDescrData__returnValue == offsetof(CallDescrData, returnValue)) -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM - == CORINFO_NullReferenceException); - - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM - == CORINFO_IndexOutOfRangeException); - // Offset of the array containing the address of captured registers in MachState #define MachState__captureX19_X29 0x0 diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index c997e4e822005..983142dba748d 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -9,7 +9,6 @@ IMPORT PreStubWorker IMPORT NDirectImportWorker IMPORT VSD_ResolveWorker - IMPORT JIT_InternalThrow IMPORT ComPreStubWorker IMPORT COMToCLRWorker IMPORT CallDescrWorkerUnwindFrameChainHandler diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index e599dd8f46d92..d228c015e337c 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -153,19 +153,6 @@ ASMCONSTANTS_C_ASSERT(SIZEOF_TailCallFrame == sizeof(TailCallFrame)) #define SHADOW_SP_IN_FILTER_ASM 0x1 ASMCONSTANTS_C_ASSERT(SHADOW_SP_IN_FILTER_ASM == ICodeManager::SHADOW_SP_IN_FILTER) -// from clr/src/inc/corinfo.h -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT(CORINFO_NullReferenceException_ASM == CORINFO_NullReferenceException) - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT(CORINFO_IndexOutOfRangeException_ASM == CORINFO_IndexOutOfRangeException) - -#define CORINFO_OverflowException_ASM 4 -ASMCONSTANTS_C_ASSERT(CORINFO_OverflowException_ASM == CORINFO_OverflowException) - -#define CORINFO_ArgumentException_ASM 9 -ASMCONSTANTS_C_ASSERT(CORINFO_ArgumentException_ASM == CORINFO_ArgumentException) - #define Thread_m_State 0x00 diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 07f6e8b955d03..21ebe0bb84f2e 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -59,8 +59,6 @@ ifdef FEATURE_READYTORUN EXTERN _DynamicHelperWorker@20:PROC endif -EXTERN @JIT_InternalThrow@4:PROC - EXTERN @ProfileEnter@8:PROC EXTERN @ProfileLeave@8:PROC EXTERN @ProfileTailcall@8:PROC @@ -418,13 +416,6 @@ _StubRareDisableTHROW proc public _StubRareDisableTHROW endp -InternalExceptionWorker proc public - pop edx ; recover RETADDR - add esp, eax ; release caller's args - push edx ; restore RETADDR - jmp @JIT_InternalThrow@4 -InternalExceptionWorker endp - ;------------------------------------------------------------------------------ ; This helper routine enregisters the appropriate arguments and makes the ; actual call. diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index ca062d92631bb..49d57c702c6ca 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -3876,53 +3876,6 @@ HCIMPL1(void, IL_VerificationError, int ilOffset) } HCIMPLEND -/*********************************************************************/ -static RuntimeExceptionKind MapCorInfoExceptionToRuntimeExceptionKind(unsigned exceptNum) -{ - LIMITED_METHOD_CONTRACT; - - static const RuntimeExceptionKind map[CORINFO_Exception_Count] = - { - kNullReferenceException, - kDivideByZeroException, - kInvalidCastException, - kIndexOutOfRangeException, - kOverflowException, - kSynchronizationLockException, - kArrayTypeMismatchException, - kRankException, - kArgumentNullException, - kArgumentException, - }; - - // spot check of the array above - _ASSERTE(map[CORINFO_NullReferenceException] == kNullReferenceException); - _ASSERTE(map[CORINFO_DivideByZeroException] == kDivideByZeroException); - _ASSERTE(map[CORINFO_IndexOutOfRangeException] == kIndexOutOfRangeException); - _ASSERTE(map[CORINFO_OverflowException] == kOverflowException); - _ASSERTE(map[CORINFO_SynchronizationLockException] == kSynchronizationLockException); - _ASSERTE(map[CORINFO_ArrayTypeMismatchException] == kArrayTypeMismatchException); - _ASSERTE(map[CORINFO_RankException] == kRankException); - _ASSERTE(map[CORINFO_ArgumentNullException] == kArgumentNullException); - _ASSERTE(map[CORINFO_ArgumentException] == kArgumentException); - - PREFIX_ASSUME(exceptNum < CORINFO_Exception_Count); - return map[exceptNum]; -} - -/*********************************************************************/ -HCIMPL1(void, JIT_InternalThrow, unsigned exceptNum) -{ - FCALL_CONTRACT; - - FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC - - HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_EXACT_DEPTH); - COMPlusThrow(MapCorInfoExceptionToRuntimeExceptionKind(exceptNum)); - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - #ifndef STATUS_STACK_BUFFER_OVERRUN // Not defined yet in CESDK includes # define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS)0xC0000409L) #endif diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index cd11551a3292f..42bf20b60da2d 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -251,8 +251,6 @@ extern "C" FCDECL3(void, JIT_Unbox_Nullable, void * destPtr, CORINFO_CLASS_HANDL extern "C" FCDECL2(VOID, JIT_WriteBarrier_Callable, Object **dst, Object *ref); #define WriteBarrier_Helper JIT_WriteBarrier_Callable -extern "C" FCDECL1(void, JIT_InternalThrow, unsigned exceptNum); - #ifdef TARGET_AMD64 diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index 804134d0eead9..99639aca03236 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -101,15 +101,6 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__flagFloatDouble == (int)(STRUCT_FLOAT_ ASMCONSTANTS_C_ASSERT(CallDescrData__flagDoubleFloat == (int)(STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FIRST_FIELD_SIZE_IS8)) ASMCONSTANTS_C_ASSERT(CallDescrData__flagDoubleDouble == (int)(CallDescrData__flagDoubleFloat | STRUCT_SECOND_FIELD_SIZE_IS8)) -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM - == CORINFO_NullReferenceException); - - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM - == CORINFO_IndexOutOfRangeException); - // Offset of the array containing the address of captured registers in MachState #define MachState__captureCalleeSavedRegisters 0x0 diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index 4d8b8ff67088d..fdf4be14f2635 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -96,15 +96,6 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__flagFloatDouble == (int)(STRUCT_FLOAT_ ASMCONSTANTS_C_ASSERT(CallDescrData__flagDoubleFloat == (int)(STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FIRST_FIELD_SIZE_IS8)) ASMCONSTANTS_C_ASSERT(CallDescrData__flagDoubleDouble == (int)(CallDescrData__flagDoubleFloat | STRUCT_SECOND_FIELD_SIZE_IS8)) -#define CORINFO_NullReferenceException_ASM 0 -ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM - == CORINFO_NullReferenceException); - - -#define CORINFO_IndexOutOfRangeException_ASM 3 -ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM - == CORINFO_IndexOutOfRangeException); - // Offset of the array containing the address of captured registers in MachState #define MachState__captureCalleeSavedRegisters 0x0 From b078f3a0d082e766eb173060567ee54c179a1f04 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 Jul 2024 23:49:41 +0800 Subject: [PATCH 12/27] Apply the same codegen to ilc --- .../TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs | 10 ++++++++-- src/coreclr/vm/comdelegate.cpp | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs index baa2ff1f354b0..72b192214f4a6 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs @@ -50,14 +50,20 @@ public static MethodIL EmitIL(MethodDesc method) FieldDesc functionPointerField = delegateType.GetKnownField("_functionPointer"); ILCodeStream codeStream = emit.NewCodeStream(); + // Store the function pointer into local variable to avoid unnecessary register usage by JIT + ILLocalVariable functionPointer = emit.NewLocal(context.GetWellKnownType(WellKnownType.IntPtr)); + + codeStream.EmitLdArg(0); + codeStream.Emit(ILOpcode.ldfld, emit.NewToken(functionPointerField.InstantiateAsOpen())); + codeStream.EmitStLoc(functionPointer); + codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emit.NewToken(firstParameterField.InstantiateAsOpen())); for (int i = 0; i < method.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } - codeStream.EmitLdArg(0); - codeStream.Emit(ILOpcode.ldfld, emit.NewToken(functionPointerField.InstantiateAsOpen())); + codeStream.EmitLdLoc(functionPointer); MethodSignature signature = method.Signature; if (method.OwningType.HasInstantiation) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index a4b3d4116bbe3..15b738fa37674 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1919,6 +1919,8 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, (ILStubLinkerFlags)(ILSTUB_LINKER_FLAG_STUB_HAS_THIS | ILSTUB_LINKER_FLAG_TARGET_HAS_THIS)); ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); + + // Store the function pointer into local variable to avoid unnecessary register usage by JIT DWORD numMethodPtr = pCode->NewLocal(ELEMENT_TYPE_I); // Load the method pointer From 1ae9027acf2496c1a3924471800793d78f390a8f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 18 Jul 2024 22:11:41 +0800 Subject: [PATCH 13/27] Add KeepAlive --- src/coreclr/vm/comdelegate.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 15b738fa37674..7156a1dc5a83a 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1944,6 +1944,15 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) pCode->EmitLDLOC(numMethodPtr); pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs() + 1, fReturnVal); // NumFixedArgs doesn't include "this" + // Keep the delegate object alive. + // If the delegate points to collectible code (dynamic method or collectible assembly), + // the underlying code may be collected before the function pointer is invoked. See https://github.com/dotnet/runtime/issues/105082 + + // TODO: remove the explicit KeepAlive once we get a solution to track the underlying code with GC. + // It impacts code quality significantly. + pCode->EmitLoadThis(); + pCode->EmitCALL(pCode->GetToken(CoreLibBinder::GetMethod(METHOD__GC__KEEP_ALIVE)), 1, 0); + // return pCode->EmitRET(); From a8623682ef6a3d9d8361f8e3088d97efa5f99743 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 Jul 2024 14:24:18 +0800 Subject: [PATCH 14/27] Emit recursive call instead --- src/coreclr/vm/comdelegate.cpp | 37 +++++++++++----------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 7156a1dc5a83a..11a2191e16cc2 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1920,42 +1920,29 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); - // Store the function pointer into local variable to avoid unnecessary register usage by JIT - DWORD numMethodPtr = pCode->NewLocal(ELEMENT_TYPE_I); - - // Load the method pointer - pCode->EmitLoadThis(); - pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__METHOD_PTR))); - pCode->EmitSTLOC(numMethodPtr); + // This stub is only used for rare indirect cases, for example + // when Delegate.Invoke method is wrapped into another delegate. + // Direct invocation of delegate is expanded by JIT. + // Emit a recursive call here to let JIT handle complex cases like + // virtual dispatch and GC safety. - // Load the target object + // Load the delegate object pCode->EmitLoadThis(); - pCode->EmitLDFLD(pCode->GetToken(CoreLibBinder::GetField(FIELD__DELEGATE__TARGET))); // Load the arguments for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) pCode->EmitLDARG(paramCount); - PCCOR_SIGNATURE pSig; - DWORD cbSig; - pMD->GetSig(&pSig,&cbSig); - - // call the delegate - pCode->EmitLDLOC(numMethodPtr); - pCode->EmitCALLI(pCode->GetSigToken(pSig, cbSig), sig.NumFixedArgs() + 1, fReturnVal); // NumFixedArgs doesn't include "this" - - // Keep the delegate object alive. - // If the delegate points to collectible code (dynamic method or collectible assembly), - // the underlying code may be collected before the function pointer is invoked. See https://github.com/dotnet/runtime/issues/105082 - - // TODO: remove the explicit KeepAlive once we get a solution to track the underlying code with GC. - // It impacts code quality significantly. - pCode->EmitLoadThis(); - pCode->EmitCALL(pCode->GetToken(CoreLibBinder::GetMethod(METHOD__GC__KEEP_ALIVE)), 1, 0); + // recursively call the delegate itself + pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal); // return pCode->EmitRET(); + PCCOR_SIGNATURE pSig; + DWORD cbSig; + pMD->GetSig(&pSig,&cbSig); + MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), pMD->GetMethodTable(), ILSTUB_SINGLECASTDELEGATE_INVOKE, From 98b8b4e7296a86b9693fb8c06c719943200039b7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 23 Jul 2024 23:58:41 +0800 Subject: [PATCH 15/27] Fix type --- src/coreclr/vm/comdelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 11a2191e16cc2..881cf522914d9 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1908,7 +1908,7 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) if (*pMD->GetSig() != (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_DEFAULT)) COMPlusThrow(kInvalidProgramException); - Stub *pStub = pClass->m_pMultiCastInvokeStub; + Stub *pStub = pClass->m_pSingleCastInvokeStub; if (pStub == NULL) { MetaSig sig(pMD); From ee90e035309390fb616e9bc21a665f4ca15ed50a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 1 Aug 2024 21:34:03 +0800 Subject: [PATCH 16/27] Add tests for indirect delegate invocation --- .../miscellaneous/SecondLevelIndirection.cs | 28 +++++++++++++ .../SecondLevelIndirection.csproj | 12 ++++++ .../SecondLevelIndirectionWithNullThis.cs | 39 +++++++++++++++++++ .../SecondLevelIndirectionWithNullThis.csproj | 12 ++++++ 4 files changed, 91 insertions(+) create mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.cs create mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.csproj create mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs create mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.cs b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.cs new file mode 100644 index 0000000000000..d4826b78a7ab5 --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; + +public class Program +{ + public int value = 23; + + public void Update(int num) + { + value += num; + } + + [Fact] + public static int TestEntryPoint() + { + Program prog = new Program(); + + Action action = prog.Update; + Action secondLevel = action.Invoke; + + secondLevel(77); + + // Update should be invoked exactly once + return prog.value; + } +} diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.csproj b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.csproj new file mode 100644 index 0000000000000..acc6ceb425b23 --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirection.csproj @@ -0,0 +1,12 @@ + + + true + 1 + + + + + + + + diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs new file mode 100644 index 0000000000000..b066f94c009cc --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Reflection; +using Xunit; + +public class Program +{ + public int value = 100; + + public void Update(int num) + { + value += num; + } + + [Fact] + public static int TestEntryPoint() + { + Program prog = new Program(); + + Action action = prog.Update; + Action secondLevel = action.Invoke; + + FieldInfo targetField = typeof(Delegate).GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic); + Assert.NotNull(targetField); + targetField.SetValue(secondLevel, null); + + try + { + secondLevel(23); + } + catch (NullReferenceException) + { + return prog.value; + } + + return 101; + } +} diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj new file mode 100644 index 0000000000000..9cf31b3e021df --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj @@ -0,0 +1,12 @@ + + + true + 1 + + + + + + + + From b5304ad221a0683c6147a814ce47f2cee915a625 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 1 Aug 2024 22:56:39 +0800 Subject: [PATCH 17/27] Use public reflection instead. --- .../SecondLevelIndirectionWithNullThis.cs | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs index b066f94c009cc..4b9a40916dc06 100644 --- a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs @@ -6,32 +6,20 @@ public class Program { - public int value = 100; - - public void Update(int num) - { - value += num; - } - [Fact] public static int TestEntryPoint() { - Program prog = new Program(); - - Action action = prog.Update; - Action secondLevel = action.Invoke; - - FieldInfo targetField = typeof(Delegate).GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic); - Assert.NotNull(targetField); - targetField.SetValue(secondLevel, null); + MethodInfo invokeMethod = typeof(Action).GetMethod("Invoke"); + Action wrapperDelegate = invokeMethod.CreateDelegate>(); + Assert.NotNull(wrapperDelegate); try { - secondLevel(23); + wrapperDelegate(null); } catch (NullReferenceException) { - return prog.value; + return 100; } return 101; From 22e344e4744b23cafb992a45d96bc801df248180 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 6 Aug 2024 14:41:54 +0800 Subject: [PATCH 18/27] Use ldvirtftn to bypass this check --- .../delegate/miscellaneous/InvokeNull.il | 58 +++++++++++++++++++ ...nWithNullThis.csproj => InvokeNull.ilproj} | 4 +- .../SecondLevelIndirectionWithNullThis.cs | 27 --------- 3 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.il rename src/tests/CoreMangLib/system/delegate/miscellaneous/{SecondLevelIndirectionWithNullThis.csproj => InvokeNull.ilproj} (75%) delete mode 100644 src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.il b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.il new file mode 100644 index 0000000000000..e2eb734720831 --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.il @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern xunit.core {} +.assembly extern System.Runtime { auto } + +.assembly InvokeNull +{ + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} +.module InvokeNull.dll + +.class public auto ansi abstract sealed beforefieldinit InvokeNull + extends [System.Runtime]System.Object +{ + .method public hidebysig static void + M() cil managed + { + } + + .method public hidebysig static int32 + Main() cil managed + { + .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( + 01 00 00 00 + ) + .locals init (method void *(class [System.Runtime]System.Action) fnptr) + .entrypoint + .maxstack 2 + + ldnull + ldftn void InvokeNull::M() + newobj instance void [System.Runtime]System.Action::.ctor(object, native int) + ldvirtftn instance void [System.Runtime]System.Action::Invoke() + stloc.s fnptr + + .try + { + ldnull + ldloc.s fnptr + calli void(class [System.Runtime]System.Action) + leave.s Fail + } + catch [System.Runtime]System.NullReferenceException + { + pop + leave.s Success + } + + Fail: + ldc.i4 101 + ret + Success: + ldc.i4 100 + ret + } +} diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.ilproj similarity index 75% rename from src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj rename to src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.ilproj index 9cf31b3e021df..211d97247ec1e 100644 --- a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.csproj +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.ilproj @@ -1,10 +1,10 @@ - + true 1 - + diff --git a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs b/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs deleted file mode 100644 index 4b9a40916dc06..0000000000000 --- a/src/tests/CoreMangLib/system/delegate/miscellaneous/SecondLevelIndirectionWithNullThis.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Reflection; -using Xunit; - -public class Program -{ - [Fact] - public static int TestEntryPoint() - { - MethodInfo invokeMethod = typeof(Action).GetMethod("Invoke"); - Action wrapperDelegate = invokeMethod.CreateDelegate>(); - Assert.NotNull(wrapperDelegate); - - try - { - wrapperDelegate(null); - } - catch (NullReferenceException) - { - return 100; - } - - return 101; - } -} From 0785f0bf27a11be84e5677e0c2f91b50949a7592 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 7 Aug 2024 21:29:41 +0800 Subject: [PATCH 19/27] Use winner from CompareExchange --- src/coreclr/vm/comdelegate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 7ddc56287a2e6..aaef1025836ee 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1954,6 +1954,7 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) pStub = Stub::NewStub(JitILStub(pStubMD)); InterlockedCompareExchangeT(&pClass->m_pSingleCastInvokeStub, pStub, NULL); + pStub = pClass->m_pSingleCastInvokeStub; } ret = pStub->GetEntryPoint(); From 8992882607fe8820b9da399aff6ed96c03e115d3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 18 Sep 2024 13:59:29 +0800 Subject: [PATCH 20/27] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/debug/ee/frameinfo.cpp | 1 - src/coreclr/vm/amd64/cgencpu.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/coreclr/debug/ee/frameinfo.cpp b/src/coreclr/debug/ee/frameinfo.cpp index 59945c30c08bc..48e0d2d56c146 100644 --- a/src/coreclr/debug/ee/frameinfo.cpp +++ b/src/coreclr/debug/ee/frameinfo.cpp @@ -1563,7 +1563,6 @@ StackWalkAction DebuggerWalkStackProc(CrawlFrame *pCF, void *data) _ASSERTE(md->IsDynamicMethod()); DynamicMethodDesc* dMD = md->AsDynamicMethodDesc(); use |= dMD->IsMulticastStub(); - use |= dMD->IsSinglecastStub(); use |= dMD->GetILStubType() == DynamicMethodDesc::StubTailCallCallTarget; if (use) diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index 24d0d81e82b4e..a1bf37c295ab9 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -31,9 +31,6 @@ class Module; struct VASigCookie; class ComCallMethodDesc; -// -// functions implemented in AMD64 assembly -// #define COMMETHOD_PREPAD 16 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) #define COMMETHOD_CALL_PRESTUB_SIZE 6 // 32-bit indirect relative call From c221eed64cbe8febe68fbb4a657a62be6107c883 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 18 Sep 2024 20:48:43 +0800 Subject: [PATCH 21/27] Return Stub from GetInvokeMethodStub --- src/coreclr/vm/class.h | 1 - src/coreclr/vm/comdelegate.cpp | 83 +++++++++++++--------------------- src/coreclr/vm/comdelegate.h | 2 +- src/coreclr/vm/prestub.cpp | 3 +- 4 files changed, 34 insertions(+), 55 deletions(-) diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index b91c09bd86592..743d34ca3a88a 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -1895,7 +1895,6 @@ class DelegateEEClass : public EEClass PTR_Stub m_pStaticCallStub; PTR_Stub m_pInstRetBuffCallStub; PTR_MethodDesc m_pInvokeMethod; - PTR_Stub m_pSingleCastInvokeStub; PTR_Stub m_pMultiCastInvokeStub; PTR_Stub m_pWrapperDelegateInvokeStub; UMThunkMarshInfo* m_pUMThunkMarshInfo; diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index aaef1025836ee..35d93b7ac8673 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1886,18 +1886,10 @@ BOOL COMDelegate::IsTrueMulticastDelegate(OBJECTREF delegate) } // Get the cpu stub for a delegate invoke. -PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) +Stub* COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) { - CONTRACT(PCODE) - { - STANDARD_VM_CHECK; - POSTCONDITION(RETVAL != NULL); - - INJECT_FAULT(COMPlusThrowOM()); - } - CONTRACT_END; + STANDARD_VM_CONTRACT; - PCODE ret = (PCODE)NULL; MethodTable * pDelMT = pMD->GetMethodTable(); DelegateEEClass* pClass = (DelegateEEClass*) pDelMT->GetClass(); @@ -1908,56 +1900,47 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) if (*pMD->GetSig() != (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_DEFAULT)) COMPlusThrow(kInvalidProgramException); - Stub *pStub = pClass->m_pSingleCastInvokeStub; - if (pStub == NULL) - { - MetaSig sig(pMD); - - BOOL fReturnVal = !sig.IsReturnTypeVoid(); - - SigTypeContext emptyContext; - ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, (ILStubLinkerFlags)(ILSTUB_LINKER_FLAG_STUB_HAS_THIS | ILSTUB_LINKER_FLAG_TARGET_HAS_THIS)); + MetaSig sig(pMD); - ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); + BOOL fReturnVal = !sig.IsReturnTypeVoid(); - // This stub is only used for rare indirect cases, for example - // when Delegate.Invoke method is wrapped into another delegate. - // Direct invocation of delegate is expanded by JIT. - // Emit a recursive call here to let JIT handle complex cases like - // virtual dispatch and GC safety. + SigTypeContext emptyContext; + ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, (ILStubLinkerFlags)(ILSTUB_LINKER_FLAG_STUB_HAS_THIS | ILSTUB_LINKER_FLAG_TARGET_HAS_THIS)); - // Load the delegate object - pCode->EmitLoadThis(); + ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); - // Load the arguments - for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) - pCode->EmitLDARG(paramCount); + // This stub is only used for rare indirect cases, for example + // when Delegate.Invoke method is wrapped into another delegate. + // Direct invocation of delegate is expanded by JIT. + // Emit a recursive call here to let JIT handle complex cases like + // virtual dispatch and GC safety. - // recursively call the delegate itself - pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal); + // Load the delegate object + pCode->EmitLoadThis(); - // return - pCode->EmitRET(); + // Load the arguments + for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) + pCode->EmitLDARG(paramCount); - PCCOR_SIGNATURE pSig; - DWORD cbSig; - pMD->GetSig(&pSig,&cbSig); + // recursively call the delegate itself + pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal); - MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), - pMD->GetMethodTable(), - ILSTUB_SINGLECASTDELEGATE_INVOKE, - pMD->GetModule(), - pSig, cbSig, - NULL, - &sl); + // return + pCode->EmitRET(); - pStub = Stub::NewStub(JitILStub(pStubMD)); + PCCOR_SIGNATURE pSig; + DWORD cbSig; + pMD->GetSig(&pSig,&cbSig); - InterlockedCompareExchangeT(&pClass->m_pSingleCastInvokeStub, pStub, NULL); - pStub = pClass->m_pSingleCastInvokeStub; - } + MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), + pMD->GetMethodTable(), + ILSTUB_SINGLECASTDELEGATE_INVOKE, + pMD->GetModule(), + pSig, cbSig, + NULL, + &sl); - ret = pStub->GetEntryPoint(); + return Stub::NewStub(JitILStub(pStubMD)); } else { @@ -1975,8 +1958,6 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) _ASSERTE(!"Bad Delegate layout"); COMPlusThrow(kInvalidProgramException); } - - RETURN ret; } extern "C" void QCALLTYPE Delegate_InternalAlloc(QCall::TypeHandle pType, QCall::ObjectHandleOnStack d) diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 3ba47f3fefa83..11a18d57ecbed 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -77,7 +77,7 @@ class COMDelegate static BOOL IsWrapperDelegate(DELEGATEREF dRef); // Get the cpu stub for a delegate invoke. - static PCODE GetInvokeMethodStub(EEImplMethodDesc* pMD); + static Stub* GetInvokeMethodStub(EEImplMethodDesc* pMD); static MethodDesc * __fastcall GetMethodDesc(OBJECTREF obj); static OBJECTREF GetTargetObject(OBJECTREF obj); diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 63189a4780e70..006e16e321ddf 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -2949,8 +2949,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo else if (IsEEImpl()) { _ASSERTE(GetMethodTable()->IsDelegate()); - pCode = COMDelegate::GetInvokeMethodStub((EEImplMethodDesc*)this); - GetOrCreatePrecode(); + pStub = COMDelegate::GetInvokeMethodStub((EEImplMethodDesc*)this); } else { From 1c640f8e79c85eb39edb8929922124a0aeb279ba Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 18 Sep 2024 20:56:49 +0800 Subject: [PATCH 22/27] Delete NEWSTUB_FL_MULTICAST and dependents --- src/coreclr/vm/stublink.cpp | 2 -- src/coreclr/vm/stublink.h | 11 ----------- src/coreclr/vm/stubmgr.cpp | 17 +---------------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/coreclr/vm/stublink.cpp b/src/coreclr/vm/stublink.cpp index be99fec457770..4add2ba92a10f 100644 --- a/src/coreclr/vm/stublink.cpp +++ b/src/coreclr/vm/stublink.cpp @@ -2254,8 +2254,6 @@ void Stub::SetupStub(int numCodeBytes, DWORD flags { if((flags & NEWSTUB_FL_LOADERHEAP) != 0) m_numCodeBytesAndFlags |= LOADER_HEAP_BIT; - if((flags & NEWSTUB_FL_MULTICAST) != 0) - m_numCodeBytesAndFlags |= MULTICAST_DELEGATE_BIT; if ((flags & NEWSTUB_FL_EXTERNAL) != 0) m_numCodeBytesAndFlags |= EXTERNAL_ENTRY_BIT; if ((flags & NEWSTUB_FL_INSTANTIATING_METHOD) != 0) diff --git a/src/coreclr/vm/stublink.h b/src/coreclr/vm/stublink.h index 3d01f2b6561d6..6f31f49f6ff00 100644 --- a/src/coreclr/vm/stublink.h +++ b/src/coreclr/vm/stublink.h @@ -449,7 +449,6 @@ enum NewStubFlags { NEWSTUB_FL_NONE = 0x00000000, NEWSTUB_FL_INSTANTIATING_METHOD = 0x00000001, - NEWSTUB_FL_MULTICAST = 0x00000002, NEWSTUB_FL_EXTERNAL = 0x00000004, NEWSTUB_FL_LOADERHEAP = 0x00000008, NEWSTUB_FL_THUNK = 0x00000010 @@ -472,7 +471,6 @@ class Stub protected: enum { - MULTICAST_DELEGATE_BIT = 0x80000000, EXTERNAL_ENTRY_BIT = 0x40000000, LOADER_HEAP_BIT = 0x20000000, INSTANTIATING_STUB_BIT = 0x10000000, @@ -509,15 +507,6 @@ class Stub return (m_refcount == 1); } - //------------------------------------------------------------------- - // Used by the debugger to help step through stubs - //------------------------------------------------------------------- - BOOL IsMulticastDelegate() - { - LIMITED_METHOD_CONTRACT; - return (m_numCodeBytesAndFlags & MULTICAST_DELEGATE_BIT) != 0; - } - //------------------------------------------------------------------- // Used by the debugger to help step through stubs //------------------------------------------------------------------- diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 023eb8e5783c6..81fd2449743df 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1270,16 +1270,7 @@ BOOL StubLinkStubManager::DoTraceStub(PCODE stubStartAddress, "StubLinkStubManager::DoTraceStub: stub=%p\n", stub)); TADDR pRealAddr = 0; - if (stub->IsMulticastDelegate()) - { - // If it's a MC delegate, then we want to set a BP & do a context-ful - // manager push, so that we can figure out if this call will be to a - // single multicast delegate or a multi multicast delegate - trace->InitForManagerPush(stubStartAddress, this); - LOG_TRACE_DESTINATION(trace, stubStartAddress, "StubLinkStubManager(MCDel)::DoTraceStub"); - return TRUE; - } - else if (stub->IsInstantiatingStub()) + if (stub->IsInstantiatingStub()) { trace->InitForManagerPush(stubStartAddress, this); LOG_TRACE_DESTINATION(trace, stubStartAddress, "StubLinkStubManager(InstantiatingMethod)::DoTraceStub"); @@ -1450,12 +1441,6 @@ BOOL StubLinkStubManager::TraceManager(Thread *thread, trace->InitForManaged(target); return TRUE; } - else if (stub->IsMulticastDelegate()) - { - LOG((LF_CORDB,LL_INFO10000, "SLSM:TM MultiCastDelegate\n")); - BYTE *pbDel = (BYTE *)StubManagerHelpers::GetThisPtr(pContext); - return TraceDelegateObject(pbDel, trace); - } else if (stub->IsManagedThunk()) { LOG((LF_CORDB,LL_INFO10000, "SLSM:TM ManagedThunk\n")); From e39afa15fd86bb1edaa20dcd7dcb7a96c5cbdc14 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 19 Sep 2024 10:59:25 +0800 Subject: [PATCH 23/27] Rename --- src/coreclr/vm/comdelegate.cpp | 2 +- src/coreclr/vm/dllimport.h | 4 ++-- src/coreclr/vm/ilstubcache.cpp | 6 +++--- src/coreclr/vm/method.hpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 35d93b7ac8673..a1c374a5e9f4c 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1934,7 +1934,7 @@ Stub* COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) MethodDesc* pStubMD = ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), pMD->GetMethodTable(), - ILSTUB_SINGLECASTDELEGATE_INVOKE, + ILSTUB_DELEGATE_INVOKE_METHOD, pMD->GetModule(), pSig, cbSig, NULL, diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index c620878730337..77b9bbdfa0c0a 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -202,7 +202,7 @@ enum ILStubTypes ILSTUB_TAILCALL_STOREARGS = 0x80000008, ILSTUB_TAILCALL_CALLTARGET = 0x80000009, ILSTUB_STATIC_VIRTUAL_DISPATCH_STUB = 0x8000000A, - ILSTUB_SINGLECASTDELEGATE_INVOKE = 0x8000000B, + ILSTUB_DELEGATE_INVOKE_METHOD = 0x8000000B, }; #ifdef FEATURE_COMINTEROP @@ -231,7 +231,7 @@ inline bool SF_IsArrayOpStub (DWORD dwStubFlags) { LIMITED_METHOD_CONT (dwStubFlags == ILSTUB_ARRAYOP_ADDRESS)); } inline bool SF_IsMulticastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_MULTICASTDELEGATE_INVOKE); } -inline bool SF_IsSinglecastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_SINGLECASTDELEGATE_INVOKE); } +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 diff --git a/src/coreclr/vm/ilstubcache.cpp b/src/coreclr/vm/ilstubcache.cpp index 02b69a2b80436..89cac9112463a 100644 --- a/src/coreclr/vm/ilstubcache.cpp +++ b/src/coreclr/vm/ilstubcache.cpp @@ -148,7 +148,7 @@ namespace case DynamicMethodDesc::StubStructMarshalInterop: return "IL_STUB_StructMarshal"; case DynamicMethodDesc::StubArrayOp: return "IL_STUB_Array"; case DynamicMethodDesc::StubMulticastDelegate: return "IL_STUB_MulticastDelegate_Invoke"; - case DynamicMethodDesc::StubSinglecastDelegate: return "IL_STUB_SinglecastDelegate_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"; @@ -243,9 +243,9 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa pMD->SetILStubType(DynamicMethodDesc::StubMulticastDelegate); } else - if (SF_IsSinglecastDelegateStub(dwStubFlags)) + if (SF_IsDelegateInvokeMethod(dwStubFlags)) { - pMD->SetILStubType(DynamicMethodDesc::StubSinglecastDelegate); + pMD->SetILStubType(DynamicMethodDesc::StubDelegateInvokeMethod); } else if (SF_IsWrapperDelegateStub(dwStubFlags)) diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index aad3c470949c4..16c74161ddf80 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2513,7 +2513,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc StubVirtualStaticMethodDispatch, - StubSinglecastDelegate, + StubDelegateInvokeMethod, StubLast }; @@ -2666,7 +2666,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); - return GetILStubType() == DynamicMethodDesc::StubSinglecastDelegate; + return GetILStubType() == DynamicMethodDesc::StubDelegateInvokeMethod; } bool IsWrapperDelegateStub() const { From eebbc01f7d1845d9d18c6f3380cd2f1033ad6981 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 19 Sep 2024 11:01:24 +0800 Subject: [PATCH 24/27] Renumber --- src/coreclr/vm/stublink.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/stublink.h b/src/coreclr/vm/stublink.h index 6f31f49f6ff00..4f7f042812b41 100644 --- a/src/coreclr/vm/stublink.h +++ b/src/coreclr/vm/stublink.h @@ -449,9 +449,9 @@ enum NewStubFlags { NEWSTUB_FL_NONE = 0x00000000, NEWSTUB_FL_INSTANTIATING_METHOD = 0x00000001, - NEWSTUB_FL_EXTERNAL = 0x00000004, - NEWSTUB_FL_LOADERHEAP = 0x00000008, - NEWSTUB_FL_THUNK = 0x00000010 + NEWSTUB_FL_EXTERNAL = 0x00000002, + NEWSTUB_FL_LOADERHEAP = 0x00000004, + NEWSTUB_FL_THUNK = 0x00000008 }; @@ -471,11 +471,11 @@ class Stub protected: enum { - EXTERNAL_ENTRY_BIT = 0x40000000, - LOADER_HEAP_BIT = 0x20000000, - INSTANTIATING_STUB_BIT = 0x10000000, - UNWIND_INFO_BIT = 0x08000000, - THUNK_BIT = 0x04000000, + EXTERNAL_ENTRY_BIT = 0x80000000, + LOADER_HEAP_BIT = 0x40000000, + INSTANTIATING_STUB_BIT = 0x20000000, + UNWIND_INFO_BIT = 0x10000000, + THUNK_BIT = 0x08000000, CODEBYTES_MASK = THUNK_BIT - 1, MAX_CODEBYTES = CODEBYTES_MASK + 1, From bc1a766539341089fd209d99889f79afadf062b0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 19 Sep 2024 11:47:17 +0800 Subject: [PATCH 25/27] Format --- src/coreclr/vm/dllimport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index 77b9bbdfa0c0a..b61f8a7f35c3a 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -202,7 +202,7 @@ enum ILStubTypes ILSTUB_TAILCALL_STOREARGS = 0x80000008, ILSTUB_TAILCALL_CALLTARGET = 0x80000009, ILSTUB_STATIC_VIRTUAL_DISPATCH_STUB = 0x8000000A, - ILSTUB_DELEGATE_INVOKE_METHOD = 0x8000000B, + ILSTUB_DELEGATE_INVOKE_METHOD = 0x8000000B, }; #ifdef FEATURE_COMINTEROP From ee674a31d29d9e0c17dce9f76402857aca58e29d Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Wed, 18 Sep 2024 22:15:09 -0700 Subject: [PATCH 26/27] Update src/coreclr/vm/method.hpp --- src/coreclr/vm/method.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 16c74161ddf80..5a9dab1fc25dd 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2662,7 +2662,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc _ASSERTE(IsILStub()); return GetILStubType() == DynamicMethodDesc::StubMulticastDelegate; } - bool IsSinglecastStub() const + bool IsDelegateInvokeMethodStub() const { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); From fdd83eb999dc2293fed8404f8c5e2941318933c2 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Wed, 18 Sep 2024 23:38:55 -0700 Subject: [PATCH 27/27] Handle new stub in ILStubManager --- src/coreclr/vm/stubmgr.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 3129dc5650024..35eefe2116880 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1898,6 +1898,14 @@ BOOL ILStubManager::TraceManager(Thread *thread, } #endif // FEATURE_COMINTEROP } + else if (pStubMD->IsDelegateInvokeMethodStub()) + { + if (pThis == NULL) + return FALSE; + + LOG((LF_CORDB, LL_INFO1000, "ILSM::TraceManager: Delegate Invoke Method\n")); + return StubLinkStubManager::TraceDelegateObject((BYTE*)pThis, trace); + } else { LOG((LF_CORDB, LL_INFO1000, "ILSM::TraceManager: No known target, IL Stub is a leaf\n"));