From ae1da30e20267a5c6d9298564a19a1202af7c247 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:05:32 +0000 Subject: [PATCH 01/11] =?UTF-8?q?Rename=20delegate=20fields:=20=5FmethodBa?= =?UTF-8?q?se=E2=86=92=5FhelperObject=20(CoreCLR),=20=5FfirstParameter?= =?UTF-8?q?=E2=86=92=5Ftarget,=20=5FfunctionPointer=E2=86=92=5FmethodPtr?= =?UTF-8?q?=20(NAOT)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../src/System/Delegate.CoreCLR.cs | 12 +- .../src/System/MulticastDelegate.CoreCLR.cs | 14 +- .../src/System/Delegate.cs | 120 +++++++++--------- .../tools/Common/JitInterface/CorInfoImpl.cs | 4 +- .../IL/Stubs/DelegateMethodILEmitter.cs | 4 +- .../Compiler/TypePreinit.cs | 16 +-- src/coreclr/vm/comdelegate.cpp | 8 +- src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/object.h | 6 +- 9 files changed, 93 insertions(+), 93 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..fd954c2f3d47fc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -16,7 +16,7 @@ public abstract partial class Delegate : ICloneable, ISerializable { // MethodBase, either cached after first request or assigned from a DynamicMethod // For open delegates to collectible types, this may be a LoaderAllocator object - internal object? _methodBase; + internal object? _helperObject; // _target is the object we will invoke on; null if static delegate internal object? _target; // Keep _target and _methodPtr next to each other for optimal delegate invoke performance @@ -132,8 +132,8 @@ public override bool Equals([NotNullWhen(true)] object? obj) // method ptrs don't match, go down long path - if (_methodBase is MethodInfo && d._methodBase is MethodInfo) - return _methodBase.Equals(d._methodBase); + if (_helperObject is MethodInfo && d._helperObject is MethodInfo) + return _helperObject.Equals(d._helperObject); else return InternalEqualMethodHandles(this, d); } @@ -158,7 +158,7 @@ public override int GetHashCode() protected virtual MethodInfo GetMethodImpl() { - if (_methodBase is MethodInfo methodInfo) + if (_helperObject is MethodInfo methodInfo) { return methodInfo; } @@ -214,8 +214,8 @@ protected virtual MethodInfo GetMethodImpl() } } - _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method)!; - return (MethodInfo)_methodBase; + _helperObject = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method)!; + return (MethodInfo)_helperObject; } public object? Target => GetTarget(); 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..d5d178ce44ca72 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs @@ -167,7 +167,7 @@ internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int inv internal void StoreDynamicMethod(MethodInfo dynamicMethod) { Debug.Assert(_invocationCount == 0); - _methodBase = dynamicMethod; + _helperObject = dynamicMethod; } // This method will combine this delegate with the passed delegate @@ -455,7 +455,7 @@ protected override MethodInfo GetMethodImpl() { // we handle unmanaged function pointers here because the generic ones (used for WinRT) would otherwise // be treated as open delegates by the base implementation, resulting in failure to get the MethodInfo - if (_methodBase is MethodInfo methodInfo) + if (_helperObject is MethodInfo methodInfo) { return methodInfo; } @@ -471,8 +471,8 @@ protected override MethodInfo GetMethodImpl() declaringType = reflectedType; } - _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method)!; - return (MethodInfo)_methodBase; + _helperObject = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method)!; + return (MethodInfo)_helperObject; } return base.GetMethodImpl(); @@ -537,7 +537,7 @@ private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr { this._target = target; this._methodPtr = methodPtr; - this._methodBase = GCHandle.InternalGet(gchandle); + this._helperObject = GCHandle.InternalGet(gchandle); } [DebuggerNonUserCode] @@ -547,7 +547,7 @@ private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuff this._target = this; this._methodPtr = shuffleThunk; this._methodPtrAux = methodPtr; - this._methodBase = GCHandle.InternalGet(gchandle); + this._helperObject = GCHandle.InternalGet(gchandle); } [DebuggerNonUserCode] @@ -556,7 +556,7 @@ private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, Int { this._target = this; this._methodPtr = shuffleThunk; - this._methodBase = GCHandle.InternalGet(gchandle); + this._helperObject = GCHandle.InternalGet(gchandle); this.InitializeVirtualCallStub(methodPtr); } #pragma warning restore IDE0060 diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs index 9968de32d01574..b59e007cee8d33 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs @@ -42,8 +42,8 @@ protected Delegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Al } private object _helperObject; - private object _firstParameter; // Keep _firstParameter and _functionPointer next to each other for optimal delegate invoke performance - private IntPtr _functionPointer; + private object _target; // Keep _target and _methodPtr next to each other for optimal delegate invoke performance + private IntPtr _methodPtr; private nint _extraFunctionPointerOrData; // _helperObject may point to an array of delegates if this is a multicast delegate. We use this wrapper to distinguish between @@ -90,7 +90,7 @@ internal unsafe IntPtr GetDelegateLdFtnResult(out RuntimeTypeHandle typeOfFirstP if (_extraFunctionPointerOrData != 0) { - if (GetThunk(OpenInstanceThunk) == _functionPointer) + if (GetThunk(OpenInstanceThunk) == _methodPtr) { typeOfFirstParameterIfInstanceDelegate = ((OpenMethodResolver*)_extraFunctionPointerOrData)->DeclaringType; isOpenResolver = true; @@ -99,10 +99,10 @@ internal unsafe IntPtr GetDelegateLdFtnResult(out RuntimeTypeHandle typeOfFirstP } else { - if (_firstParameter != null) - typeOfFirstParameterIfInstanceDelegate = new RuntimeTypeHandle(_firstParameter.GetMethodTable()); + if (_target != null) + typeOfFirstParameterIfInstanceDelegate = new RuntimeTypeHandle(_target.GetMethodTable()); - return _functionPointer; + return _methodPtr; } } @@ -112,8 +112,8 @@ private void InitializeClosedInstance(object firstParameter, IntPtr functionPoin if (firstParameter is null) throw new ArgumentException(SR.Arg_DlgtNullInst); - _functionPointer = functionPointer; - _firstParameter = firstParameter; + _methodPtr = functionPointer; + _target = firstParameter; } // This function is known to the compiler. @@ -126,13 +126,13 @@ private void InitializeClosedInstanceSlow(object firstParameter, IntPtr function if (!FunctionPointerOps.IsGenericMethodPointer(functionPointer)) { - _functionPointer = functionPointer; - _firstParameter = firstParameter; + _methodPtr = functionPointer; + _target = firstParameter; } else { - _firstParameter = this; - _functionPointer = GetThunk(ClosedInstanceThunkOverGenericMethod); + _target = this; + _methodPtr = GetThunk(ClosedInstanceThunkOverGenericMethod); _extraFunctionPointerOrData = functionPointer; _helperObject = firstParameter; } @@ -153,13 +153,13 @@ private void InitializeClosedInstanceWithGVMResolution(object firstParameter, Ru } if (!FunctionPointerOps.IsGenericMethodPointer(functionResolution)) { - _functionPointer = functionResolution; - _firstParameter = firstParameter; + _methodPtr = functionResolution; + _target = firstParameter; } else { - _firstParameter = this; - _functionPointer = GetThunk(ClosedInstanceThunkOverGenericMethod); + _target = this; + _methodPtr = GetThunk(ClosedInstanceThunkOverGenericMethod); _extraFunctionPointerOrData = functionResolution; _helperObject = firstParameter; } @@ -173,8 +173,8 @@ private void InitializeClosedInstanceToInterface(object firstParameter, IntPtr d if (firstParameter is null) throw new NullReferenceException(); - _functionPointer = RuntimeImports.RhpResolveInterfaceMethod(firstParameter, dispatchCell); - _firstParameter = firstParameter; + _methodPtr = RuntimeImports.RhpResolveInterfaceMethod(firstParameter, dispatchCell); + _target = firstParameter; } // This is used to implement MethodInfo.CreateDelegate() in a desktop-compatible way. Yes, the desktop really @@ -183,13 +183,13 @@ private void InitializeClosedInstanceWithoutNullCheck(object firstParameter, Int { if (!FunctionPointerOps.IsGenericMethodPointer(functionPointer)) { - _functionPointer = functionPointer; - _firstParameter = firstParameter; + _methodPtr = functionPointer; + _target = firstParameter; } else { - _firstParameter = this; - _functionPointer = GetThunk(ClosedInstanceThunkOverGenericMethod); + _target = this; + _methodPtr = GetThunk(ClosedInstanceThunkOverGenericMethod); _extraFunctionPointerOrData = functionPointer; _helperObject = firstParameter; } @@ -200,24 +200,24 @@ private void InitializeClosedStaticThunk(object firstParameter, IntPtr functionP { _extraFunctionPointerOrData = functionPointer; _helperObject = firstParameter; - _functionPointer = functionPointerThunk; - _firstParameter = this; + _methodPtr = functionPointerThunk; + _target = this; } // This function is known to the compiler. private void InitializeOpenStaticThunk(object _ /*firstParameter*/, IntPtr functionPointer, IntPtr functionPointerThunk) { // This sort of delegate is invoked by calling the thunk function pointer with the arguments to the delegate + a reference to the delegate object itself. - _firstParameter = this; - _functionPointer = functionPointerThunk; + _target = this; + _methodPtr = functionPointerThunk; _extraFunctionPointerOrData = functionPointer; } private void InitializeOpenInstanceThunkDynamic(IntPtr functionPointer, IntPtr functionPointerThunk) { // This sort of delegate is invoked by calling the thunk function pointer with the arguments to the delegate + a reference to the delegate object itself. - _firstParameter = this; - _functionPointer = functionPointerThunk; + _target = this; + _methodPtr = functionPointerThunk; _extraFunctionPointerOrData = functionPointer; } @@ -245,7 +245,7 @@ private IntPtr GetActualTargetFunctionPointer(object thisObject) { DynamicInvokeInfo dynamicInvokeInfo = ReflectionAugments.GetDelegateDynamicInvokeInfo(GetType()); - object? result = dynamicInvokeInfo.Invoke(_firstParameter, _functionPointer, + object? result = dynamicInvokeInfo.Invoke(_target, _methodPtr, args, binderBundle: null, wrapInTargetInvocationException: true); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; @@ -264,7 +264,7 @@ protected virtual MethodInfo GetMethodImpl() } // Return the delegate Invoke method for marshalled function pointers and LINQ expressions - if ((_firstParameter is NativeFunctionPointerWrapper) || (_functionPointer == GetThunk(ObjectArrayThunk))) + if ((_target is NativeFunctionPointerWrapper) || (_methodPtr == GetThunk(ObjectArrayThunk))) { return GetType().GetMethod("Invoke"); } @@ -284,7 +284,7 @@ internal DiagnosticMethodInfo GetDiagnosticMethodInfo() } // Return the delegate Invoke method for marshalled function pointers and LINQ expressions - if ((_firstParameter is NativeFunctionPointerWrapper) || (_functionPointer == GetThunk(ObjectArrayThunk))) + if ((_target is NativeFunctionPointerWrapper) || (_methodPtr == GetThunk(ObjectArrayThunk))) { Type t = GetType(); return new DiagnosticMethodInfo("Invoke", t.FullName, t.Module.Assembly.FullName); @@ -334,25 +334,25 @@ public object? Target } // Closed static delegates place a value in _helperObject that they pass to the target method. - if (_functionPointer == GetThunk(ClosedStaticThunk) || - _functionPointer == GetThunk(ClosedInstanceThunkOverGenericMethod) || - _functionPointer == GetThunk(ObjectArrayThunk)) + if (_methodPtr == GetThunk(ClosedStaticThunk) || + _methodPtr == GetThunk(ClosedInstanceThunkOverGenericMethod) || + _methodPtr == GetThunk(ObjectArrayThunk)) return _helperObject; - // Other non-closed thunks can be identified as the _firstParameter field points at this. - if (object.ReferenceEquals(_firstParameter, this)) + // Other non-closed thunks can be identified as the _target field points at this. + if (object.ReferenceEquals(_target, this)) { return null; } // NativeFunctionPointerWrapper used by marshalled function pointers is not returned as a public target - if (_firstParameter is NativeFunctionPointerWrapper) + if (_target is NativeFunctionPointerWrapper) { return null; } - // Closed instance delegates place a value in _firstParameter, and we've ruled out all other types of delegates - return _firstParameter; + // Closed instance delegates place a value in _target, and we've ruled out all other types of delegates + return _target; } } @@ -369,9 +369,9 @@ public object? Target // V1 api: Creates open delegates to static methods only, relaxed signature checking disallowed. public static Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.AllMethods)] Type target, string method, bool ignoreCase, bool throwOnBindFailure) => ReflectionAugments.CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure); - internal IntPtr TryGetOpenStaticFunctionPointer() => (GetThunk(OpenStaticThunk) == _functionPointer) ? _extraFunctionPointerOrData : 0; + internal IntPtr TryGetOpenStaticFunctionPointer() => (GetThunk(OpenStaticThunk) == _methodPtr) ? _extraFunctionPointerOrData : 0; - internal NativeFunctionPointerWrapper? TryGetNativeFunctionPointerWrapper() => _firstParameter as NativeFunctionPointerWrapper; + internal NativeFunctionPointerWrapper? TryGetNativeFunctionPointerWrapper() => _target as NativeFunctionPointerWrapper; internal static unsafe bool InternalEqualTypes(object a, object b) { @@ -399,8 +399,8 @@ internal static unsafe Delegate CreateObjectArrayDelegate(Type t, Func(RuntimeImports.RhNewObject(this.GetMethodTable())); // Performance optimization - if this already points to a true multicast delegate, - // copy _functionPointer field rather than calling GetThunk to get it - result._functionPointer = thisIsMultiCastAlready ? _functionPointer : GetThunk(MulticastThunk); - result._firstParameter = result; + // copy _methodPtr field rather than calling GetThunk to get it + result._methodPtr = thisIsMultiCastAlready ? _methodPtr : GetThunk(MulticastThunk); + result._target = result; result._helperObject = invocationList; result._extraFunctionPointerOrData = (IntPtr)invocationCount; @@ -471,10 +471,10 @@ private static bool TrySetSlot(Wrapper[] a, int index, Delegate o) // Optimize this case, because it's cheaper than copying the array. if (a[index].Value is Delegate dd) { - if (object.ReferenceEquals(dd._firstParameter, o._firstParameter) && + if (object.ReferenceEquals(dd._target, o._target) && object.ReferenceEquals(dd._helperObject, o._helperObject) && dd._extraFunctionPointerOrData == o._extraFunctionPointerOrData && - dd._functionPointer == o._functionPointer) + dd._methodPtr == o._methodPtr) { return true; } @@ -718,9 +718,9 @@ public override bool Equals([NotNullWhen(true)] object? obj) return true; } - if (_firstParameter is NativeFunctionPointerWrapper nativeFunctionPointerWrapper) + if (_target is NativeFunctionPointerWrapper nativeFunctionPointerWrapper) { - if (d._firstParameter is not NativeFunctionPointerWrapper dnativeFunctionPointerWrapper) + if (d._target is not NativeFunctionPointerWrapper dnativeFunctionPointerWrapper) return false; return nativeFunctionPointerWrapper.NativeFunctionPointer == dnativeFunctionPointerWrapper.NativeFunctionPointer; @@ -728,19 +728,19 @@ public override bool Equals([NotNullWhen(true)] object? obj) if (!object.ReferenceEquals(_helperObject, d._helperObject) || (!FunctionPointerOps.Compare(_extraFunctionPointerOrData, d._extraFunctionPointerOrData)) || - (!FunctionPointerOps.Compare(_functionPointer, d._functionPointer))) + (!FunctionPointerOps.Compare(_methodPtr, d._methodPtr))) { return false; } - // Those delegate kinds with thunks put themselves into the _firstParameter, so we can't - // blindly compare the _firstParameter fields for equality. - if (object.ReferenceEquals(_firstParameter, this)) + // Those delegate kinds with thunks put themselves into the _target, so we can't + // blindly compare the _target fields for equality. + if (object.ReferenceEquals(_target, this)) { - return object.ReferenceEquals(d._firstParameter, d); + return object.ReferenceEquals(d._target, d); } - return object.ReferenceEquals(_firstParameter, d._firstParameter); + return object.ReferenceEquals(_target, d._target); } public override int GetHashCode() @@ -755,18 +755,18 @@ public override int GetHashCode() return multiCastHash; } - if (_firstParameter is NativeFunctionPointerWrapper nativeFunctionPointerWrapper) + if (_target is NativeFunctionPointerWrapper nativeFunctionPointerWrapper) { return nativeFunctionPointerWrapper.NativeFunctionPointer.GetHashCode(); } int hash = RuntimeHelpers.GetHashCode(_helperObject) + 7 * FunctionPointerOps.GetHashCode(_extraFunctionPointerOrData) + - 13 * FunctionPointerOps.GetHashCode(_functionPointer); + 13 * FunctionPointerOps.GetHashCode(_methodPtr); - if (!object.ReferenceEquals(_firstParameter, this)) + if (!object.ReferenceEquals(_target, this)) { - hash += 17 * RuntimeHelpers.GetHashCode(_firstParameter); + hash += 17 * RuntimeHelpers.GetHashCode(_target); } return hash; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index e11a597e10ce28..3469197007c17c 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3441,9 +3441,9 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut) pEEInfoOut.inlinedCallFrameInfo.size = (uint)SizeOfPInvokeTransitionFrame; - // _target/_firstParameter + // _target pEEInfoOut.offsetOfDelegateInstance = 2 * (uint)pointerSize; - // _methodPtr/_functionPointer + // _methodPtr pEEInfoOut.offsetOfDelegateFirstTarget = pEEInfoOut.offsetOfDelegateInstance + (uint)pointerSize; pEEInfoOut.sizeOfReversePInvokeFrame = (uint)SizeOfReversePInvokeTransitionFrame; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs index 075bd1da26ac2c..12479cdd158aae 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs @@ -48,8 +48,8 @@ public static MethodIL EmitIL(MethodDesc method) ILEmitter emit = new ILEmitter(); TypeDesc delegateType = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType; - FieldDesc firstParameterField = delegateType.GetKnownField("_firstParameter"u8); - FieldDesc functionPointerField = delegateType.GetKnownField("_functionPointer"u8); + FieldDesc firstParameterField = delegateType.GetKnownField("_target"u8); + FieldDesc functionPointerField = delegateType.GetKnownField("_methodPtr"u8); ILCodeStream codeStream = emit.NewCodeStream(); // Store the function pointer into local variable to avoid unnecessary register usage by JIT diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 7529da04eeafba..7f318165119c14 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -3249,13 +3249,13 @@ public virtual void GetConditionalDependencies(ref CombinedDependencyList depend private sealed class DelegateInstance : AllocatedReferenceTypeValue, ISerializableReference { private readonly MethodDesc _methodPointed; - private readonly ReferenceTypeValue _firstParameter; + private readonly ReferenceTypeValue _target; public DelegateInstance(TypeDesc delegateType, MethodDesc methodPointed, ReferenceTypeValue firstParameter, AllocationSite allocationSite) : base(delegateType, allocationSite) { _methodPointed = methodPointed; - _firstParameter = firstParameter; + _target = firstParameter; } private DelegateCreationInfo GetDelegateCreationInfo(NodeFactory factory) @@ -3280,7 +3280,7 @@ public override void GetConditionalDependencies(ref CombinedDependencyList depen public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, NodeFactory factory) { - Debug.Assert(_methodPointed.Signature.IsStatic == (_firstParameter == null)); + Debug.Assert(_methodPointed.Signature.IsStatic == (_target == null)); DelegateCreationInfo creationInfo = GetDelegateCreationInfo(factory); @@ -3298,10 +3298,10 @@ public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, No // _helperObject builder.EmitZeroPointer(); - // _firstParameter + // _target builder.EmitPointerReloc(thisNode); - // _functionPointer + // _methodPtr Debug.Assert(creationInfo.Thunk != null); builder.EmitPointerReloc(creationInfo.Thunk); @@ -3315,10 +3315,10 @@ public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, No // _helperObject builder.EmitZeroPointer(); - // _firstParameter - _firstParameter.WriteFieldData(ref builder, factory); + // _target + _target.WriteFieldData(ref builder, factory); - // _functionPointer + // _methodPtr builder.EmitPointerReloc(creationInfo.GetTargetNode(factory)); // _extraFunctionPointerOrData diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 8f0d4a2438aace..409136ea51db2a 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1294,7 +1294,7 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, LoaderAllocator *pLoaderAllocator = pTargetMethod->GetLoaderAllocator(); if (pLoaderAllocator->IsCollectible()) - (*pRefThis)->SetMethodBase(pLoaderAllocator->GetExposedObject()); + (*pRefThis)->SetHelperObject(pLoaderAllocator->GetExposedObject()); } // Marshals a delegate to a unmanaged callback. @@ -1709,7 +1709,7 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q methodArgCount++; // count 'this' if (pMeth->GetLoaderAllocator()->IsCollectible()) - refThis->SetMethodBase(pMeth->GetLoaderAllocator()->GetExposedObject()); + refThis->SetHelperObject(pMeth->GetLoaderAllocator()->GetExposedObject()); // Open delegates. if (invokeArgCount == methodArgCount) @@ -2634,7 +2634,7 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT LoaderAllocator *pTargetMethodLoaderAllocator = pTargetMethod->GetLoaderAllocator(); BOOL isCollectible = pTargetMethodLoaderAllocator->IsCollectible(); // A method that may be instantiated over a collectible type, and is static will require a delegate - // that has the _methodBase field filled in with the LoaderAllocator of the collectible assembly + // that has the _helperObject field filled in with the LoaderAllocator of the collectible assembly // associated with the instantiation. BOOL fMaybeCollectibleAndStatic = FALSE; @@ -2712,7 +2712,7 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT // 3 - CtorVirtualDispatch // Collectible delegates use the corresponding CtorCollectible* variants. // - // With collectible types, we need to fill the _methodBase field in with a value that represents the LoaderAllocator of the target method + // With collectible types, we need to fill the _helperObject field in with a value that represents the LoaderAllocator of the target method // if the delegate is not a closed instance delegate. // // There are two techniques that will work for this. diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 5d453720aa0ebb..2a5d61be48252d 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -229,7 +229,7 @@ DEFINE_METHOD(DECIMAL, CURRENCY_CTOR, .ctor, DEFINE_CLASS_U(System, Delegate, NoClass) DEFINE_FIELD_U(_target, DelegateObject, _target) -DEFINE_FIELD_U(_methodBase, DelegateObject, _methodBase) +DEFINE_FIELD_U(_helperObject, DelegateObject, _helperObject) DEFINE_FIELD_U(_methodPtr, DelegateObject, _methodPtr) DEFINE_FIELD_U(_methodPtrAux, DelegateObject, _methodPtrAux) DEFINE_CLASS(DELEGATE, System, Delegate) diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 33ec6d6cc7e842..2bdc5b72325f56 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1772,14 +1772,14 @@ class DelegateObject : public Object void SetInvocationCount(INT_PTR invocationCount) { LIMITED_METHOD_CONTRACT; _invocationCount = invocationCount; } static int GetOffsetOfInvocationCount() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationCount); } - void SetMethodBase(OBJECTREF newMethodBase) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_methodBase, newMethodBase); } + void SetHelperObject(OBJECTREF newHelperObject) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_helperObject, newHelperObject); } // README: // If you modify the order of these fields, make sure to update the definition in // BCL for this object. private: // System.Delegate - OBJECTREF _methodBase; + OBJECTREF _helperObject; OBJECTREF _target; PCODE _methodPtr; PCODE _methodPtrAux; @@ -1788,7 +1788,7 @@ class DelegateObject : public Object INT_PTR _invocationCount; }; -#define OFFSETOF__DelegateObject__target (OBJECT_SIZE /* m_pMethTab */ + TARGET_POINTER_SIZE /* _methodBase */) +#define OFFSETOF__DelegateObject__target (OBJECT_SIZE /* m_pMethTab */ + TARGET_POINTER_SIZE /* _helperObject */) #define OFFSETOF__DelegateObject__methodPtr (OFFSETOF__DelegateObject__target + TARGET_POINTER_SIZE /* _target */) #define OFFSETOF__DelegateObject__methodPtrAux (OFFSETOF__DelegateObject__methodPtr + TARGET_POINTER_SIZE /* _methodPtr */) From f641cbde75d29bf93405a5a495c33fef3ec898f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:23:32 +0000 Subject: [PATCH 02/11] Rename local variables in DelegateMethodILEmitter to match renamed fields Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../IL/Stubs/DelegateMethodILEmitter.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs index 12479cdd158aae..fcfe108c42676b 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMethodILEmitter.cs @@ -48,26 +48,26 @@ public static MethodIL EmitIL(MethodDesc method) ILEmitter emit = new ILEmitter(); TypeDesc delegateType = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType; - FieldDesc firstParameterField = delegateType.GetKnownField("_target"u8); - FieldDesc functionPointerField = delegateType.GetKnownField("_methodPtr"u8); + FieldDesc targetField = delegateType.GetKnownField("_target"u8); + FieldDesc methodPtrField = delegateType.GetKnownField("_methodPtr"u8); 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)); + // Store the method pointer into local variable to avoid unnecessary register usage by JIT + ILLocalVariable methodPtr = emit.NewLocal(context.GetWellKnownType(WellKnownType.IntPtr)); MethodSignature signature = method.Signature; codeStream.EmitLdArg(0); - codeStream.Emit(ILOpcode.ldfld, emit.NewToken(functionPointerField.InstantiateAsOpen())); - codeStream.EmitStLoc(functionPointer); + codeStream.Emit(ILOpcode.ldfld, emit.NewToken(methodPtrField.InstantiateAsOpen())); + codeStream.EmitStLoc(methodPtr); codeStream.EmitLdArg(0); - codeStream.Emit(ILOpcode.ldfld, emit.NewToken(firstParameterField.InstantiateAsOpen())); + codeStream.Emit(ILOpcode.ldfld, emit.NewToken(targetField.InstantiateAsOpen())); for (int i = 0; i < signature.Length; i++) { codeStream.EmitLdArg(i + 1); } - codeStream.EmitLdLoc(functionPointer); + codeStream.EmitLdLoc(methodPtr); if (method.OwningType.HasInstantiation) { From 0381c0f14e9563b99642f75c63db5f1accce8c81 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 19 Jun 2026 13:34:25 -0700 Subject: [PATCH 03/11] Apply suggestion from @jkotas --- src/coreclr/vm/comdelegate.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 409136ea51db2a..a85127099e3f6c 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2709,7 +2709,11 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT // 4 - CtorClosedStatic // 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) // 2, 6 - CtorOpened - // 3 - CtorVirtualDispatch +// 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) +// 2, 6 - CtorOpened +// 3 - CtorVirtualDispatch +// 4 - CtorClosedStatic +// 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) // Collectible delegates use the corresponding CtorCollectible* variants. // // With collectible types, we need to fill the _helperObject field in with a value that represents the LoaderAllocator of the target method From 817a146ed1281c37550c64796a9e59bcfc9c425e Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 19 Jun 2026 13:35:10 -0700 Subject: [PATCH 04/11] Apply suggestion from @jkotas --- src/coreclr/vm/comdelegate.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index a85127099e3f6c..f8c834fa970985 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2709,11 +2709,11 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT // 4 - CtorClosedStatic // 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) // 2, 6 - CtorOpened -// 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) -// 2, 6 - CtorOpened -// 3 - CtorVirtualDispatch -// 4 - CtorClosedStatic -// 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) + // 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) + // 2, 6 - CtorOpened + // 3 - CtorVirtualDispatch + // 4 - CtorClosedStatic + // 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) // Collectible delegates use the corresponding CtorCollectible* variants. // // With collectible types, we need to fill the _helperObject field in with a value that represents the LoaderAllocator of the target method From 686321ed2a29f343b4d9b733a9d2aca549f40e35 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 19 Jun 2026 13:36:13 -0700 Subject: [PATCH 05/11] Apply suggestion from @jkotas --- src/coreclr/vm/comdelegate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index f8c834fa970985..af20bfe803723e 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2708,7 +2708,6 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT // 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) // 4 - CtorClosedStatic // 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) - // 2, 6 - CtorOpened // 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) // 2, 6 - CtorOpened // 3 - CtorVirtualDispatch From 4c0aa888446f4d851bb23e0145fdfbbe03fe0776 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 19 Jun 2026 13:37:01 -0700 Subject: [PATCH 06/11] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/vm/comdelegate.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index af20bfe803723e..1549f6aa8f0793 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2706,9 +2706,6 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT // Delegate invoke arg count == 1 + target method arg count - 1, 4, 5 // // 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) - // 4 - CtorClosedStatic - // 5 - Retbuf static closed form (not differentiated on this fast path; see TODO below) - // 1 - CtorClosed (or CtorRTClosed for value-type instance targets needing runtime lookup) // 2, 6 - CtorOpened // 3 - CtorVirtualDispatch // 4 - CtorClosedStatic From dc55c210bc8f62ee8a0737e93eba41a5e3d64788 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:44:39 +0000 Subject: [PATCH 07/11] Remove leftover wrapper delegate comments from comdelegate.cpp Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/vm/comdelegate.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 1549f6aa8f0793..c9c389ce664b4d 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1823,11 +1823,8 @@ 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 + // or _invocationList points to a LoaderAllocator/DynamicResolver innerDel = (DELEGATEREF) thisDel->GetInvocationList(); bool fOpenVirtualDelegate = false; From 25a70fca685ad6619f750686dba74ac248967001 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 00:56:13 +0000 Subject: [PATCH 08/11] Delete unused COMDelegate::GetTargetObject method Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/vm/comdelegate.cpp | 41 ---------------------------------- src/coreclr/vm/comdelegate.h | 2 -- 2 files changed, 43 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index c9c389ce664b4d..527b63af44f77b 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1871,47 +1871,6 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) 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..03a84fabf9f6da 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -60,8 +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); // Throw if the method violates any usage restrictions From 7b666fc49017d673045ac66b4032faf455bca6fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 01:00:48 +0000 Subject: [PATCH 09/11] Remove wrapper delegate handling from COMDelegate::GetMethodDesc Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/vm/comdelegate.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 527b63af44f77b..f42d2464d443e2 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1815,7 +1815,6 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) MethodDesc *pMethodHandle = NULL; DELEGATEREF thisDel = (DELEGATEREF) orDelegate; - DELEGATEREF innerDel = NULL; INT_PTR count = thisDel->GetInvocationCount(); if (count != 0) @@ -1825,15 +1824,12 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) // - unamanaged ftn ptr - _invocationList == NULL && _invocationCount == -1 // - virtual delegate - _invocationList == null && _invocationCount == (target MethodDesc) // or _invocationList points to a LoaderAllocator/DynamicResolver - innerDel = (DELEGATEREF) thisDel->GetInvocationList(); + OBJECTREF innerDel = thisDel->GetInvocationList(); bool fOpenVirtualDelegate = false; if (innerDel != NULL) { - MethodTable *pMT = innerDel->GetMethodTable(); - if (pMT->IsDelegate()) - return GetMethodDesc(innerDel); - if (!pMT->IsArray()) + if (!innerDel->GetMethodTable()->IsArray()) { // must be a virtual one fOpenVirtualDelegate = true; From acf685c04662885aa87fae1cedf0aca5a237e6df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 01:41:33 +0000 Subject: [PATCH 10/11] Revert GetMethodDesc changes and remove this. from delegate fields Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../src/System/MulticastDelegate.CoreCLR.cs | 54 +++++++++---------- src/coreclr/vm/comdelegate.cpp | 8 ++- 2 files changed, 33 insertions(+), 29 deletions(-) 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 d5d178ce44ca72..521000b056cdad 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs @@ -144,8 +144,8 @@ private unsafe MulticastDelegate NewMulticastDelegate(object[] invocationList, i // copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them if (thisIsMultiCastAlready) { - result._methodPtr = this._methodPtr; - result._methodPtrAux = this._methodPtrAux; + result._methodPtr = _methodPtr; + result._methodPtrAux = _methodPtrAux; } else { @@ -304,7 +304,7 @@ private static bool EqualInvocationLists(object[] a, object[] b, int start, int if (_invocationList is not object[] invocationList) { // they are both not real Multicast - if (this.Equals(value)) + if (Equals(value)) return null; } else @@ -466,7 +466,7 @@ protected override MethodInfo GetMethodImpl() // need a proper declaring type instance method on a generic type if (declaringType.IsGenericType) { - // we are returning the 'Invoke' method of this delegate so use this.GetType() for the exact type + // we are returning the 'Invoke' method of this delegate so use GetType() for the exact type RuntimeType reflectedType = (RuntimeType)GetType(); declaringType = reflectedType; } @@ -491,16 +491,16 @@ private void CtorClosed(object target, IntPtr methodPtr) { if (target == null) ThrowNullThisInDelegateToInstance(); - this._target = target; - this._methodPtr = methodPtr; + _target = target; + _methodPtr = methodPtr; } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorClosedStatic(object target, IntPtr methodPtr) { - this._target = target; - this._methodPtr = methodPtr; + _target = target; + _methodPtr = methodPtr; } [DebuggerNonUserCode] @@ -509,55 +509,55 @@ private void CtorRTClosed(object target, IntPtr methodPtr) { if (target == null) ThrowNullThisInDelegateToInstance(); - this._target = target; - this._methodPtr = AdjustTarget(target, methodPtr); + _target = target; + _methodPtr = AdjustTarget(target, methodPtr); } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk) { - this._target = this; - this._methodPtr = shuffleThunk; - this._methodPtrAux = methodPtr; + _target = this; + _methodPtr = shuffleThunk; + _methodPtrAux = methodPtr; } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk) { - this._target = this; - this._methodPtr = shuffleThunk; - this.InitializeVirtualCallStub(methodPtr); + _target = this; + _methodPtr = shuffleThunk; + InitializeVirtualCallStub(methodPtr); } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr gchandle) { - this._target = target; - this._methodPtr = methodPtr; - this._helperObject = GCHandle.InternalGet(gchandle); + _target = target; + _methodPtr = methodPtr; + _helperObject = GCHandle.InternalGet(gchandle); } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { - this._target = this; - this._methodPtr = shuffleThunk; - this._methodPtrAux = methodPtr; - this._helperObject = GCHandle.InternalGet(gchandle); + _target = this; + _methodPtr = shuffleThunk; + _methodPtrAux = methodPtr; + _helperObject = GCHandle.InternalGet(gchandle); } [DebuggerNonUserCode] [DebuggerStepThrough] private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { - this._target = this; - this._methodPtr = shuffleThunk; - this._helperObject = GCHandle.InternalGet(gchandle); - this.InitializeVirtualCallStub(methodPtr); + _target = this; + _methodPtr = shuffleThunk; + _helperObject = GCHandle.InternalGet(gchandle); + InitializeVirtualCallStub(methodPtr); } #pragma warning restore IDE0060 } diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index f42d2464d443e2..527b63af44f77b 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1815,6 +1815,7 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) MethodDesc *pMethodHandle = NULL; DELEGATEREF thisDel = (DELEGATEREF) orDelegate; + DELEGATEREF innerDel = NULL; INT_PTR count = thisDel->GetInvocationCount(); if (count != 0) @@ -1824,12 +1825,15 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) // - unamanaged ftn ptr - _invocationList == NULL && _invocationCount == -1 // - virtual delegate - _invocationList == null && _invocationCount == (target MethodDesc) // or _invocationList points to a LoaderAllocator/DynamicResolver - OBJECTREF innerDel = thisDel->GetInvocationList(); + innerDel = (DELEGATEREF) thisDel->GetInvocationList(); bool fOpenVirtualDelegate = false; if (innerDel != NULL) { - if (!innerDel->GetMethodTable()->IsArray()) + MethodTable *pMT = innerDel->GetMethodTable(); + if (pMT->IsDelegate()) + return GetMethodDesc(innerDel); + if (!pMT->IsArray()) { // must be a virtual one fOpenVirtualDelegate = true; From 70d6bba66000ef060675a550c4a85bcbf2ec907e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 01:46:38 +0000 Subject: [PATCH 11/11] Remove this. from methods in Delegate.CoreCLR.cs Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../System.Private.CoreLib/src/System/Delegate.CoreCLR.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 fd954c2f3d47fc..7539685cb0ad69 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -80,7 +80,7 @@ protected Delegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Al protected virtual object? DynamicInvokeImpl(object?[]? args) { RuntimeMethodHandleInternal method = new RuntimeMethodHandleInternal(GetInvokeMethod()); - RuntimeMethodInfo invoke = (RuntimeMethodInfo)RuntimeType.GetMethodBase((RuntimeType)this.GetType(), method)!; + RuntimeMethodInfo invoke = (RuntimeMethodInfo)RuntimeType.GetMethodBase((RuntimeType)GetType(), method)!; return invoke.Invoke(this, BindingFlags.Default, null, args, null); } @@ -146,9 +146,9 @@ public override int GetHashCode() // different hashcode which is not true. /* if (_methodPtrAux == IntPtr.Zero) - return unchecked((int)((long)this._methodPtr)); + return unchecked((int)((long)_methodPtr)); else - return unchecked((int)((long)this._methodPtrAux)); + return unchecked((int)((long)_methodPtrAux)); */ if (_methodPtrAux == IntPtr.Zero) return (_target != null ? RuntimeHelpers.GetHashCode(_target) * 33 : 0) + GetType().GetHashCode(); @@ -208,7 +208,7 @@ protected virtual MethodInfo GetMethodImpl() else { // it's an open one, need to fetch the first arg of the instantiation - MethodInfo invoke = this.GetType().GetMethod("Invoke")!; + MethodInfo invoke = GetType().GetMethod("Invoke")!; declaringType = (RuntimeType)invoke.GetParametersAsSpan()[0].ParameterType; } }