diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index bf57e9ea28073..464bcb47a4ab1 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -826,22 +826,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/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/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index 39bee849fa19e..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 @@ -565,26 +564,6 @@ NESTED_ENTRY ProfileTailcallNaked, _TEXT ret NESTED_END ProfileTailcallNaked, _TEXT - -extern JIT_InternalThrowFromHelper:proc - -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/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 1f4dc158dbda6..bd5eb832005c9 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)); @@ -198,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/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index 75d31ea1a4ad0..a1bf37c295ab9 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -31,10 +31,6 @@ class Module; struct VASigCookie; 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..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 @@ -64,12 +56,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 efd2bcd074bc1..515c6112d2628 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 e5d6ef97e6167..712d3454132d3 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -936,8 +936,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..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 @@ -109,12 +100,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 48c91e65a098d..723bb4b384113 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -271,22 +271,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..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 @@ -317,22 +316,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/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 63eee56011bb0..59a55e2b1cd3d 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1885,52 +1885,11 @@ BOOL COMDelegate::IsTrueMulticastDelegate(OBJECTREF delegate) return isMulticast; } -PCODE COMDelegate::TheDelegateInvokeStub() -{ - CONTRACT(PCODE) - { - STANDARD_VM_CHECK; - POSTCONDITION(RETVAL != NULL); - } - 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. -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(); @@ -1941,15 +1900,53 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) if (*pMD->GetSig() != (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_DEFAULT)) COMPlusThrow(kInvalidProgramException); - ret = COMDelegate::TheDelegateInvokeStub(); + 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); + + // 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 delegate object + pCode->EmitLoadThis(); + + // Load the arguments + for (UINT paramCount = 0; paramCount < sig.NumFixedArgs(); paramCount++) + pCode->EmitLDARG(paramCount); + + // 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_DELEGATE_INVOKE_METHOD, + pMD->GetModule(), + pSig, cbSig, + NULL, + &sl); + + return Stub::NewStub(JitILStub(pStubMD)); } else { // We do not support asynchronous delegates in CoreCLR COMPlusThrow(kPlatformNotSupportedException); } - - 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 a195264acdb23..8b1750fc6579d 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -77,10 +77,7 @@ class COMDelegate static BOOL IsWrapperDelegate(DELEGATEREF dRef); // Get the cpu stub for a delegate invoke. - static PCODE GetInvokeMethodStub(EEImplMethodDesc* pMD); - - // get the one single delegate invoke stub - static PCODE TheDelegateInvokeStub(); + static Stub* GetInvokeMethodStub(EEImplMethodDesc* pMD); 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 5a43d1f8fbfce..b61f8a7f35c3a 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -202,6 +202,7 @@ enum ILStubTypes ILSTUB_TAILCALL_STOREARGS = 0x80000008, ILSTUB_TAILCALL_CALLTARGET = 0x80000009, ILSTUB_STATIC_VIRTUAL_DISPATCH_STUB = 0x8000000A, + ILSTUB_DELEGATE_INVOKE_METHOD = 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_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/dllimportcallback.h b/src/coreclr/vm/dllimportcallback.h index ac2f2e93cdfd0..0d142b2510a68 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/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index 8c8fec685e0f8..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 @@ -283,24 +270,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 -#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)); - -#endif - // 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 54f58fd75bb62..bd85a248b1efa 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -737,27 +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 - 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 -#endif // FEATURE_STUBS_AS_IL - // ======================================================================================= // void ResolveWorkerChainLookupAsmStub(); // diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 801de37407386..7586adab6590b 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -58,8 +58,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 @@ -417,13 +415,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/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index f5783f7350301..b87527be32333 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -33,10 +33,6 @@ class ComCallMethodDesc; // 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) #define COMMETHOD_PREPAD 8 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) 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 cfd814678fdc1..a9167ea4227db 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -3593,56 +3593,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 -VOID StubLinkerCPU::EmitDebugBreak() -{ - STANDARD_VM_CONTRACT; - - // int3 - Emit8(0xCC); -} - #if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) #ifdef _MSC_VER diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 031ca2f9b0aa3..443f3c6685213 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -374,27 +374,11 @@ 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); -#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 diff --git a/src/coreclr/vm/ilstubcache.cpp b/src/coreclr/vm/ilstubcache.cpp index 9935471e7d5f4..89cac9112463a 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::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"; @@ -242,6 +243,11 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa pMD->SetILStubType(DynamicMethodDesc::StubMulticastDelegate); } else + if (SF_IsDelegateInvokeMethod(dwStubFlags)) + { + pMD->SetILStubType(DynamicMethodDesc::StubDelegateInvokeMethod); + } + else if (SF_IsWrapperDelegateStub(dwStubFlags)) { pMD->SetILStubType(DynamicMethodDesc::StubWrapperDelegate); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 553385adb8611..041846b84021a 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -2840,66 +2840,6 @@ HCIMPL0(void, IL_Rethrow) } 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 - -/*********************************************************************/ -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 10682c64736c6..e65d2f9b1dc6d 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -253,9 +253,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); -extern "C" FCDECL1(void*, JIT_InternalThrowFromHelper, unsigned exceptNum); - #ifdef TARGET_AMD64 diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index c4fbdc443e9c4..b92d11716e4c6 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -74,15 +74,6 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__returnValue == offsetof(CallDescrD #define FpStruct__BothFloat 0b10 ASMCONSTANTS_C_ASSERT(FpStruct__BothFloat == (int)FpStruct::BothFloat) -#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 @@ -107,12 +98,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 99889eee097c0..7ee80d9e00edc 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/method.hpp b/src/coreclr/vm/method.hpp index 35882fdde5ddf..5a9dab1fc25dd 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -2513,6 +2513,8 @@ class DynamicMethodDesc : public StoredSigMethodDesc StubVirtualStaticMethodDispatch, + StubDelegateInvokeMethod, + StubLast }; @@ -2660,6 +2662,12 @@ class DynamicMethodDesc : public StoredSigMethodDesc _ASSERTE(IsILStub()); return GetILStubType() == DynamicMethodDesc::StubMulticastDelegate; } + bool IsDelegateInvokeMethodStub() const + { + LIMITED_METHOD_DAC_CONTRACT; + _ASSERTE(IsILStub()); + return GetILStubType() == DynamicMethodDesc::StubDelegateInvokeMethod; + } bool IsWrapperDelegateStub() const { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index af2d2c8ebc060..f7447a60132f2 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 { diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index fb7577c643e94..5dd6c462b27c5 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -69,15 +69,6 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__returnValue == offsetof(CallDescrD #define FpStruct__BothFloat 0b10 ASMCONSTANTS_C_ASSERT(FpStruct__BothFloat == (int)FpStruct::BothFloat) -#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 @@ -102,12 +93,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 94ee7bb6e0304..977d0354e4e80 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 0b9b53fb9f68e..0a489c1b527bb 100644 --- a/src/coreclr/vm/riscv64/cgencpu.h +++ b/src/coreclr/vm/riscv64/cgencpu.h @@ -416,8 +416,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/stublink.cpp b/src/coreclr/vm/stublink.cpp index efe9f73776a9a..edb5d5bbe86cc 100644 --- a/src/coreclr/vm/stublink.cpp +++ b/src/coreclr/vm/stublink.cpp @@ -2217,8 +2217,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 4856aa2e709b8..47ca7d0726641 100644 --- a/src/coreclr/vm/stublink.h +++ b/src/coreclr/vm/stublink.h @@ -440,10 +440,9 @@ 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_SHUFFLE_THUNK = 0x00000010 + NEWSTUB_FL_EXTERNAL = 0x00000002, + NEWSTUB_FL_LOADERHEAP = 0x00000004, + NEWSTUB_FL_SHUFFLE_THUNK = 0x00000008 }; @@ -463,12 +462,11 @@ class Stub protected: enum { - MULTICAST_DELEGATE_BIT = 0x80000000, - EXTERNAL_ENTRY_BIT = 0x40000000, - LOADER_HEAP_BIT = 0x20000000, - INSTANTIATING_STUB_BIT = 0x10000000, - UNWIND_INFO_BIT = 0x08000000, - SHUFFLE_THUNK_BIT = 0x04000000, + EXTERNAL_ENTRY_BIT = 0x80000000, + LOADER_HEAP_BIT = 0x40000000, + INSTANTIATING_STUB_BIT = 0x20000000, + UNWIND_INFO_BIT = 0x10000000, + SHUFFLE_THUNK_BIT = 0x08000000, CODEBYTES_MASK = SHUFFLE_THUNK_BIT - 1, MAX_CODEBYTES = CODEBYTES_MASK + 1, @@ -500,15 +498,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 d7f18a4a54cf2..35eefe2116880 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"); @@ -1385,12 +1376,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->IsShuffleThunk()) { LOG((LF_CORDB,LL_INFO10000, "SLSM:TM ShuffleThunk\n")); @@ -1913,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")); 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/InvokeNull.ilproj b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.ilproj new file mode 100644 index 0000000000000..211d97247ec1e --- /dev/null +++ b/src/tests/CoreMangLib/system/delegate/miscellaneous/InvokeNull.ilproj @@ -0,0 +1,12 @@ + + + true + 1 + + + + + + + + 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 + + + + + + + +