From cfa940d81704b522bdcfb95d61d8e5b941d99bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Sun, 21 Jun 2026 02:30:23 +0200 Subject: [PATCH] Cleanup dead delegate code --- .../src/System/Delegate.CoreCLR.cs | 3 +- .../src/System/MulticastDelegate.CoreCLR.cs | 2 +- src/coreclr/debug/daccess/dacdbiimpl.cpp | 1 - src/coreclr/vm/comdelegate.cpp | 97 +++---------------- src/coreclr/vm/comdelegate.h | 1 - src/coreclr/vm/stubmgr.cpp | 33 ------- 6 files changed, 15 insertions(+), 122 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index 94ed1f03b71ae7..6563f99cbae192 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -379,8 +379,7 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target // Initialize the method... Delegate d = InternalAlloc(rtType); - // This is a new internal API added in Whidbey. Currently it's only - // used by the dynamic method code to generate a wrapper delegate. + // This is a new internal API added in Whidbey. // Allow flexible binding options since the target method is // unambiguously provided to us. diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs index 38fd1f5189f6ec..f206471ec88268 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs @@ -166,7 +166,7 @@ internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int inv internal void StoreDynamicMethod(MethodInfo dynamicMethod) { - Debug.Assert(_invocationCount == 0); + Debug.Assert(HasSingleTarget); _methodBase = dynamicMethod; } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index adb057fba3011a..98e237426966be 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -3268,7 +3268,6 @@ DacDbiInterfaceImpl::DelegateType DacDbiInterfaceImpl::GetDelegateType(VMPTR_Obj { // If this delegate points to a static function or this is a open virtual delegate, this should be non-null // Special case: This might fail in a VSD delegate (instance open virtual)... - // TODO: There is the special signatures cases missing. TADDR targetMethodPtr = PCODEToPINSTR(pDelObj->GetMethodPtrAux()); if (targetMethodPtr == (TADDR)NULL) { diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 8f0d4a2438aace..4e974562af9407 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1812,10 +1812,7 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) // If you modify this logic, please update cDAC IObject.GetDelegateInfo. - MethodDesc *pMethodHandle = NULL; - DELEGATEREF thisDel = (DELEGATEREF) orDelegate; - DELEGATEREF innerDel = NULL; INT_PTR count = thisDel->GetInvocationCount(); if (count != 0) @@ -1823,98 +1820,30 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) // this is one of the following: // - multicast - _invocationList is Array && _invocationCount != 0 // - unamanaged ftn ptr - _invocationList == NULL && _invocationCount == -1 - // - wrapper delegate - _invocationList is Delegate && _invocationCount != NULL // - virtual delegate - _invocationList == null && _invocationCount == (target MethodDesc) - // or _invocationList points to a LoaderAllocator/DynamicResolver (inner open virtual delegate of a Wrapper Delegate) - // in the wrapper delegate case we want to unwrap and return the method desc of the inner delegate - // in the other cases we return the method desc for the invoke - innerDel = (DELEGATEREF) thisDel->GetInvocationList(); - bool fOpenVirtualDelegate = false; + // or _invocationList points to a LoaderAllocator/DynamicResolver - if (innerDel != NULL) - { - MethodTable *pMT = innerDel->GetMethodTable(); - if (pMT->IsDelegate()) - return GetMethodDesc(innerDel); - if (!pMT->IsArray()) - { - // must be a virtual one - fOpenVirtualDelegate = true; - } - } - else - { - if (count != DELEGATE_MARKER_UNMANAGEDFPTR) - { - // must be a virtual one - fOpenVirtualDelegate = true; - } - } + // we return the method desc for the invoke + OBJECTREF invocationList = thisDel->GetInvocationList(); + if ((invocationList != NULL && invocationList->GetMethodTable()->IsArray()) || count == DELEGATE_MARKER_UNMANAGEDFPTR) + return FindDelegateInvokeMethod(thisDel->GetMethodTable()); - if (fOpenVirtualDelegate) - pMethodHandle = GetMethodDescForOpenVirtualDelegate(thisDel); - else - pMethodHandle = FindDelegateInvokeMethod(thisDel->GetMethodTable()); + return GetMethodDescForOpenVirtualDelegate(thisDel); } - else - { - // Next, check for an open delegate - PCODE code = thisDel->GetMethodPtrAux(); - - if (code == (PCODE)NULL) - { - // Must be a normal delegate - code = thisDel->GetMethodPtr(); - } - pMethodHandle = NonVirtualEntry2MethodDesc(code); + // Next, check for an open delegate + PCODE code = thisDel->GetMethodPtrAux(); + if (code == (PCODE)NULL) + { + // Must be a normal delegate + code = thisDel->GetMethodPtr(); } + MethodDesc *pMethodHandle = NonVirtualEntry2MethodDesc(code); _ASSERTE(pMethodHandle); return pMethodHandle; } -OBJECTREF COMDelegate::GetTargetObject(OBJECTREF obj) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - OBJECTREF targetObject = NULL; - - DELEGATEREF thisDel = (DELEGATEREF) obj; - OBJECTREF innerDel = NULL; - - if (thisDel->GetInvocationCount() != 0) - { - // this is one of the following: - // - multicast - // - unmanaged ftn ptr - // - wrapper delegate - // - virtual delegate - _invocationList == null && _invocationCount == (target MethodDesc) - // or _invocationList points to a LoaderAllocator/DynamicResolver (inner open virtual delegate of a Wrapper Delegate) - // in the wrapper delegate case we want to unwrap and return the object of the inner delegate - innerDel = (DELEGATEREF) thisDel->GetInvocationList(); - if (innerDel != NULL) - { - MethodTable *pMT = innerDel->GetMethodTable(); - if (pMT->IsDelegate()) - { - targetObject = GetTargetObject(innerDel); - } - } - } - - if (targetObject == NULL) - targetObject = thisDel->GetTarget(); - - return targetObject; -} - BOOL COMDelegate::IsTrueMulticastDelegate(OBJECTREF delegate) { CONTRACTL diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 4982f93c418744..8e055849936bad 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -60,7 +60,6 @@ class COMDelegate static MethodDesc * __fastcall GetMethodDesc(OBJECTREF obj); static MethodDesc* GetMethodDescForOpenVirtualDelegate(OBJECTREF orDelegate); - static OBJECTREF GetTargetObject(OBJECTREF obj); static BOOL IsTrueMulticastDelegate(OBJECTREF delegate); diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index e8f55803ece74a..1e0811883df545 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1242,39 +1242,6 @@ BOOL StubLinkStubManager::TraceDelegateObject(BYTE* pbDel, TraceDestination *tra return res; } - // invocationList is not null, so it can be one of the following: - // Multicast, Static closed (special sig), Secure - - // rule out the static with special sig - BYTE *pbCount = *(BYTE **)(pbDel + DelegateObject::GetOffsetOfInvocationCount()); - if (pbCount == NULL) - { - // it's a static closed, the target lives in _methodAuxPtr - ppbDest = (BYTE **)(pbDel + DelegateObject::GetOffsetOfMethodPtrAux()); - - if (*ppbDest == NULL) - { - // it's not looking good, bail out - LOG((LF_CORDB,LL_INFO10000, "SLSM::TDO: can't trace into it\n")); - return FALSE; - } - - LOG((LF_CORDB,LL_INFO10000, "SLSM::TDO: ppbDest: %p *ppbDest:%p\n", ppbDest, *ppbDest)); - - BOOL res = StubManager::TraceStub((PCODE) (*ppbDest), trace); - - LOG((LF_CORDB,LL_INFO10000, "SLSM::TDO: res: %d, result type: %d\n", (res ? "true" : "false"), trace->GetTraceType())); - - return res; - } - - MethodTable *pType = *(MethodTable**)pbDelInvocationList; - if (pType->IsDelegate()) - { - // this is a secure delegate. The target is hidden inside this field, so recurse. - return TraceDelegateObject(pbDelInvocationList, trace); - } - // Otherwise, we're going for the first invoke of the multi case. // In order to go to the correct spot, we have just have to fish out // slot 0 of the invocation list, and figure out where that's going to,