From 4d89d534d75614c32699cb850719832884371e7b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 01:50:00 +0800 Subject: [PATCH 1/8] Convert CompareUnmanagedFunctionPtrs to managed --- .../src/System/Delegate.CoreCLR.cs | 3 -- .../src/System/MulticastDelegate.cs | 3 +- src/coreclr/vm/comdelegate.cpp | 28 ------------------- src/coreclr/vm/comdelegate.h | 3 -- src/coreclr/vm/ecalllist.h | 1 - 5 files changed, 2 insertions(+), 36 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 0bf04439f20b5b..57daf47ad2b1f2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -441,9 +441,6 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target { return (_methodPtrAux == IntPtr.Zero) ? _target : null; } - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool CompareUnmanagedFunctionPtrs(Delegate d1, Delegate d2); } // These flags effect the way BindToMethodInfo and BindToMethodName are allowed to bind a delegate to a target method. Their diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs index c0ae5b16fe726f..068d915dd4e0a2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -82,7 +82,8 @@ public sealed override bool Equals([NotNullWhen(true)] object? obj) if (!d.IsUnmanagedFunctionPtr()) return false; - return CompareUnmanagedFunctionPtrs(this, d); + return _methodPtr == d._methodPtr + && _methodPtrAux == d._methodPtrAux; } // now we know 'this' is not a special one, so we can work out what the other is diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index c23f1b31de1c1d..741526c1ff4298 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1488,34 +1488,6 @@ MethodDesc* COMDelegate::GetILStubMethodDesc(EEImplMethodDesc* pDelegateMD, DWOR return NDirect::CreateCLRToNativeILStub(&sigInfo, dwStubFlags, pDelegateMD); } - - -FCIMPL2(FC_BOOL_RET, COMDelegate::CompareUnmanagedFunctionPtrs, Object *refDelegate1UNSAFE, Object *refDelegate2UNSAFE) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(refDelegate1UNSAFE != NULL); - PRECONDITION(refDelegate2UNSAFE != NULL); - } - CONTRACTL_END; - - DELEGATEREF refD1 = (DELEGATEREF) ObjectToOBJECTREF(refDelegate1UNSAFE); - DELEGATEREF refD2 = (DELEGATEREF) ObjectToOBJECTREF(refDelegate2UNSAFE); - BOOL ret = FALSE; - - // Make sure this is an unmanaged function pointer wrapped in a delegate. - CONSISTENCY_CHECK(DELEGATE_MARKER_UNMANAGEDFPTR == refD1->GetInvocationCount()); - CONSISTENCY_CHECK(DELEGATE_MARKER_UNMANAGEDFPTR == refD2->GetInvocationCount()); - - ret = (refD1->GetMethodPtr() == refD2->GetMethodPtr() && - refD1->GetMethodPtrAux() == refD2->GetMethodPtrAux()); - - FC_RETURN_BOOL(ret); -} -FCIMPLEND - - void COMDelegate::RemoveEntryFromFPtrHash(UPTR key) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 3a48c2e793d56d..03073bf435b24d 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -90,9 +90,6 @@ class COMDelegate static ComPlusCallInfo * PopulateComPlusCallInfo(MethodTable * pDelMT); #endif // FEATURE_COMINTEROP - // Checks whether two delegates wrapping function pointers have the same unmanaged target - static FCDECL2(FC_BOOL_RET, CompareUnmanagedFunctionPtrs, Object *refDelegate1UNSAFE, Object *refDelegate2UNSAFE); - static PCODE GetStubForILStub(EEImplMethodDesc* pDelegateMD, MethodDesc** ppStubMD, DWORD dwStubFlags); static MethodDesc* GetILStubMethodDesc(EEImplMethodDesc* pDelegateMD, DWORD dwStubFlags); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index a14d5855d59eaa..7b3818860eb87a 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -304,7 +304,6 @@ FCFuncStart(gDelegateFuncs) FCFuncElement("FindMethodHandle", COMDelegate::FindMethodHandle) FCFuncElement("AdjustTarget", COMDelegate::AdjustTarget) FCFuncElement("GetCallStub", COMDelegate::GetCallStub) - FCFuncElement("CompareUnmanagedFunctionPtrs", COMDelegate::CompareUnmanagedFunctionPtrs) // The FCall mechanism knows how to wire multiple different constructor calls into a // single entrypoint, without the following entry. But we need this entry to satisfy From 7f845a031a16dabd00fede982de6686118eaa0d0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 02:06:57 +0800 Subject: [PATCH 2/8] Move simple type match to managed --- .../src/System/Delegate.CoreCLR.cs | 13 +++++++++++-- .../src/System/MulticastDelegate.cs | 4 ++-- src/coreclr/vm/comdelegate.cpp | 14 +++++++------- .../System.Private.CoreLib/src/System/Delegate.cs | 2 +- 4 files changed, 21 insertions(+), 12 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 57daf47ad2b1f2..74c094ceeb33e0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -88,7 +88,7 @@ protected Delegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Al public override bool Equals([NotNullWhen(true)] object? obj) { - if (obj == null || !InternalEqualTypes(this, obj)) + if (obj == null || !EqualTypes(this, obj)) return false; Delegate d = (Delegate)obj; @@ -411,8 +411,17 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target [MethodImpl(MethodImplOptions.InternalCall)] internal static extern MulticastDelegate InternalAllocLike(Delegate d); + internal static bool EqualTypes(object a, object b) + { + // fast check for method table match + if (a.GetType() == b.GetType()) + return true; + + return InternalEqualTypes(a, b); + } + [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool InternalEqualTypes(object a, object b); + private static extern bool InternalEqualTypes(object a, object b); // Used by the ctor. Do not call directly. // The name of this function will appear in managed stacktraces as delegate constructor. diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs index 068d915dd4e0a2..aa64becc7178fd 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -58,7 +58,7 @@ public sealed override bool Equals([NotNullWhen(true)] object? obj) return false; if (object.ReferenceEquals(this, obj)) return true; - if (!InternalEqualTypes(this, obj)) + if (!EqualTypes(this, obj)) return false; // Since this is a MulticastDelegate and we know @@ -225,7 +225,7 @@ protected sealed override Delegate CombineImpl(Delegate? follow) return this; // Verify that the types are the same... - if (!InternalEqualTypes(this, follow)) + if (!EqualTypes(this, follow)) throw new ArgumentException(SR.Arg_DlgtTypeMis); MulticastDelegate dFollow = (MulticastDelegate)follow; diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 741526c1ff4298..4a78b013e50048 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2011,14 +2011,14 @@ FCIMPL2(FC_BOOL_RET, COMDelegate::InternalEqualTypes, Object* pThis, Object *pTh _ASSERTE(pThisMT != NULL && pThisMT->IsDelegate()); _ASSERTE(pThatMT != NULL); - BOOL bResult = (pThisMT == pThatMT); + // simple match should be done in managed code + _ASSERTE(pThisMT != pThatMT); - if (!bResult) - { - HELPER_METHOD_FRAME_BEGIN_RET_0(); - bResult = pThisMT->IsEquivalentTo(pThatMT); - HELPER_METHOD_FRAME_END(); - } + BOOL bResult; + + HELPER_METHOD_FRAME_BEGIN_RET_0(); + bResult = pThisMT->IsEquivalentTo(pThatMT); + HELPER_METHOD_FRAME_END(); FC_RETURN_BOOL(bResult); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs index 9f22b48fde7077..02b434a454ff9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs @@ -73,7 +73,7 @@ public abstract partial class Delegate : ICloneable, ISerializable if (value == null) return source; - if (!InternalEqualTypes(source, value)) + if (!EqualTypes(source, value)) throw new ArgumentException(SR.Arg_DlgtTypeMis); return source.RemoveImpl(value); From bec3064d3c64b18305d7e76298c99c83ff7d2130 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 02:22:48 +0800 Subject: [PATCH 3/8] Add more check in managed portion --- .../src/System/Delegate.CoreCLR.cs | 14 ++++++++++++-- src/coreclr/vm/comdelegate.cpp | 2 ++ 2 files changed, 14 insertions(+), 2 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 74c094ceeb33e0..94a4be2e13f589 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -411,12 +411,22 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target [MethodImpl(MethodImplOptions.InternalCall)] internal static extern MulticastDelegate InternalAllocLike(Delegate d); - internal static bool EqualTypes(object a, object b) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe bool EqualTypes(object a, object b) { - // fast check for method table match if (a.GetType() == b.GetType()) return true; + bool hasTypeEquivalance = + RuntimeHelpers.GetMethodTable(a)->HasTypeEquivalence + && RuntimeHelpers.GetMethodTable(b)->HasTypeEquivalence; + GC.KeepAlive(a); + GC.KeepAlive(b); + + if (!hasTypeEquivalance) + return false; + + // only use FCall to check the type equivalence scenario return InternalEqualTypes(a, b); } diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 4a78b013e50048..18226e70507c87 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2013,6 +2013,8 @@ FCIMPL2(FC_BOOL_RET, COMDelegate::InternalEqualTypes, Object* pThis, Object *pTh // simple match should be done in managed code _ASSERTE(pThisMT != pThatMT); + _ASSERTE(pThisMT->HasTypeEquivalence()); + _ASSERTE(pThatMT->HasTypeEquivalence()); BOOL bResult; From fedccebc9f65be11f375509258e5157eb5a05cfd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 02:53:13 +0800 Subject: [PATCH 4/8] Rename method for FCall --- .../System.Private.CoreLib/src/System/Delegate.CoreCLR.cs | 8 ++++---- .../src/System/MulticastDelegate.cs | 4 ++-- src/coreclr/vm/ecalllist.h | 2 +- .../System.Private.CoreLib/src/System/Delegate.cs | 2 +- 4 files changed, 8 insertions(+), 8 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 94a4be2e13f589..2e4083a51ec544 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -88,7 +88,7 @@ protected Delegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Al public override bool Equals([NotNullWhen(true)] object? obj) { - if (obj == null || !EqualTypes(this, obj)) + if (obj == null || !InternalEqualTypes(this, obj)) return false; Delegate d = (Delegate)obj; @@ -412,7 +412,7 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target internal static extern MulticastDelegate InternalAllocLike(Delegate d); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe bool EqualTypes(object a, object b) + internal static unsafe bool InternalEqualTypes(object a, object b) { if (a.GetType() == b.GetType()) return true; @@ -427,11 +427,11 @@ internal static unsafe bool EqualTypes(object a, object b) return false; // only use FCall to check the type equivalence scenario - return InternalEqualTypes(a, b); + return InternalEqualTypes_Internal(a, b); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool InternalEqualTypes(object a, object b); + private static extern bool InternalEqualTypes_Internal(object a, object b); // Used by the ctor. Do not call directly. // The name of this function will appear in managed stacktraces as delegate constructor. diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs index aa64becc7178fd..068d915dd4e0a2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -58,7 +58,7 @@ public sealed override bool Equals([NotNullWhen(true)] object? obj) return false; if (object.ReferenceEquals(this, obj)) return true; - if (!EqualTypes(this, obj)) + if (!InternalEqualTypes(this, obj)) return false; // Since this is a MulticastDelegate and we know @@ -225,7 +225,7 @@ protected sealed override Delegate CombineImpl(Delegate? follow) return this; // Verify that the types are the same... - if (!EqualTypes(this, follow)) + if (!InternalEqualTypes(this, follow)) throw new ArgumentException(SR.Arg_DlgtTypeMis); MulticastDelegate dFollow = (MulticastDelegate)follow; diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 7b3818860eb87a..b6d2de70cdada9 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -299,7 +299,7 @@ FCFuncStart(gDelegateFuncs) FCFuncElement("GetInvokeMethod", COMDelegate::GetInvokeMethod) FCFuncElement("InternalAlloc", COMDelegate::InternalAlloc) FCFuncElement("InternalAllocLike", COMDelegate::InternalAllocLike) - FCFuncElement("InternalEqualTypes", COMDelegate::InternalEqualTypes) + FCFuncElement("InternalEqualTypes_Internal", COMDelegate::InternalEqualTypes) FCFuncElement("InternalEqualMethodHandles", COMDelegate::InternalEqualMethodHandles) FCFuncElement("FindMethodHandle", COMDelegate::FindMethodHandle) FCFuncElement("AdjustTarget", COMDelegate::AdjustTarget) diff --git a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs index 02b434a454ff9b..9f22b48fde7077 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs @@ -73,7 +73,7 @@ public abstract partial class Delegate : ICloneable, ISerializable if (value == null) return source; - if (!EqualTypes(source, value)) + if (!InternalEqualTypes(source, value)) throw new ArgumentException(SR.Arg_DlgtTypeMis); return source.RemoveImpl(value); From 4e453a943db659e70b2170710cf4a89456b1192a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 12:53:49 +0800 Subject: [PATCH 5/8] Change FCall to directly call IsEquivalentTo --- .../src/System/Delegate.CoreCLR.cs | 23 ++++++++-------- .../RuntimeHelpers.CoreCLR.cs | 3 +++ src/coreclr/vm/comdelegate.cpp | 26 ------------------- src/coreclr/vm/comdelegate.h | 1 - src/coreclr/vm/comutilnative.cpp | 7 +++++ src/coreclr/vm/comutilnative.h | 1 + src/coreclr/vm/ecalllist.h | 2 +- 7 files changed, 24 insertions(+), 39 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 2e4083a51ec544..f9a1f3106d9bb9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -417,21 +417,22 @@ internal static unsafe bool InternalEqualTypes(object a, object b) if (a.GetType() == b.GetType()) return true; - bool hasTypeEquivalance = - RuntimeHelpers.GetMethodTable(a)->HasTypeEquivalence - && RuntimeHelpers.GetMethodTable(b)->HasTypeEquivalence; - GC.KeepAlive(a); - GC.KeepAlive(b); + MethodTable* pMTa = RuntimeHelpers.GetMethodTable(a); + MethodTable* pMTb = RuntimeHelpers.GetMethodTable(b); - if (!hasTypeEquivalance) - return false; + bool ret; // only use FCall to check the type equivalence scenario - return InternalEqualTypes_Internal(a, b); - } + if (pMTa->HasTypeEquivalence && pMTb->HasTypeEquivalence) + ret = pMTa->IsEquivalentTo(pMTb); + else + ret = false; - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool InternalEqualTypes_Internal(object a, object b); + GC.KeepAlive(a); + GC.KeepAlive(b); + + return ret; + } // Used by the ctor. Do not call directly. // The name of this function will appear in managed stacktraces as delegate constructor. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index cb8ca49e068593..817fb751c46a43 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -519,6 +519,9 @@ public int MultiDimensionalArrayRank [MethodImpl(MethodImplOptions.InternalCall)] public extern uint GetNumInstanceFieldBytes(); + + [MethodImpl(MethodImplOptions.InternalCall)] + public extern bool IsEquivalentTo(MethodTable* pMTOther); } // Helper structs used for tail calls via helper. diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 18226e70507c87..53616e81c0f65a 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2001,32 +2001,6 @@ FCIMPL1(Object*, COMDelegate::InternalAllocLike, Object* pThis) } FCIMPLEND -FCIMPL2(FC_BOOL_RET, COMDelegate::InternalEqualTypes, Object* pThis, Object *pThat) -{ - FCALL_CONTRACT; - - MethodTable *pThisMT = pThis->GetMethodTable(); - MethodTable *pThatMT = pThat->GetMethodTable(); - - _ASSERTE(pThisMT != NULL && pThisMT->IsDelegate()); - _ASSERTE(pThatMT != NULL); - - // simple match should be done in managed code - _ASSERTE(pThisMT != pThatMT); - _ASSERTE(pThisMT->HasTypeEquivalence()); - _ASSERTE(pThatMT->HasTypeEquivalence()); - - BOOL bResult; - - HELPER_METHOD_FRAME_BEGIN_RET_0(); - bResult = pThisMT->IsEquivalentTo(pThatMT); - HELPER_METHOD_FRAME_END(); - - FC_RETURN_BOOL(bResult); -} -FCIMPLEND - - void COMDelegate::ThrowIfInvalidUnmanagedCallersOnlyUsage(MethodDesc* pMD) { CONTRACTL diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 03073bf435b24d..f6c45042096262 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -58,7 +58,6 @@ class COMDelegate static FCDECL1(Object*, InternalAlloc, ReflectClassBaseObject* target); static FCDECL1(Object*, InternalAllocLike, Object* pThis); - static FCDECL2(FC_BOOL_RET, InternalEqualTypes, Object* pThis, Object *pThat); static FCDECL3(PCODE, AdjustTarget, Object* refThis, Object* target, PCODE method); static FCDECL2(PCODE, GetCallStub, Object* refThis, PCODE method); diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 5dfaec08323c2f..022a174cda3266 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -2036,6 +2036,13 @@ FCIMPL1(UINT32, MethodTableNative::GetNumInstanceFieldBytes, MethodTable* mt) } FCIMPLEND +FCIMPL2(FC_BOOL_RET, MethodTableNative::IsEquivalentTo, MethodTable* mta, MethodTable* mtb) +{ + FCALL_CONTRACT; + FC_RETURN_BOOL(mta->IsEquivalentTo(mtb)); +} +FCIMPLEND + static MethodTable * g_pStreamMT; static WORD g_slotBeginRead, g_slotEndRead; static WORD g_slotBeginWrite, g_slotEndWrite; diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index cbcc4457ad626c..bca74edf40fd08 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -224,6 +224,7 @@ class ValueTypeHelper { class MethodTableNative { public: static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); + static FCDECL2(FC_BOOL_RET, IsEquivalentTo, MethodTable* mta, MethodTable* mtb); }; class StreamNative { diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index b6d2de70cdada9..d89d00b9348624 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -299,7 +299,6 @@ FCFuncStart(gDelegateFuncs) FCFuncElement("GetInvokeMethod", COMDelegate::GetInvokeMethod) FCFuncElement("InternalAlloc", COMDelegate::InternalAlloc) FCFuncElement("InternalAllocLike", COMDelegate::InternalAllocLike) - FCFuncElement("InternalEqualTypes_Internal", COMDelegate::InternalEqualTypes) FCFuncElement("InternalEqualMethodHandles", COMDelegate::InternalEqualMethodHandles) FCFuncElement("FindMethodHandle", COMDelegate::FindMethodHandle) FCFuncElement("AdjustTarget", COMDelegate::AdjustTarget) @@ -604,6 +603,7 @@ FCFuncEnd() FCFuncStart(gMethodTableFuncs) FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes) + FCFuncElement("IsEquivalentTo", MethodTableNative::IsEquivalentTo) FCFuncEnd() FCFuncStart(gMngdFixedArrayMarshalerFuncs) From 2e580a73ab7307a881e1734d673721c5680850b4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 15:11:22 +0800 Subject: [PATCH 6/8] Add helper method frame --- src/coreclr/vm/comutilnative.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 022a174cda3266..a614dd7b505a24 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -2039,7 +2039,14 @@ FCIMPLEND FCIMPL2(FC_BOOL_RET, MethodTableNative::IsEquivalentTo, MethodTable* mta, MethodTable* mtb) { FCALL_CONTRACT; - FC_RETURN_BOOL(mta->IsEquivalentTo(mtb)); + + BOOL bResult; + + HELPER_METHOD_FRAME_BEGIN_RET_0(); + bResult = mta->IsEquivalentTo(mtb); + HELPER_METHOD_FRAME_END(); + + FC_RETURN_BOOL(bResult); } FCIMPLEND From 6d4935bf2abd3c5e5bc735e6692ffc4fc44a23c4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 31 May 2022 18:00:23 +0800 Subject: [PATCH 7/8] Fix uninitialized result variable --- src/coreclr/vm/comutilnative.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index a614dd7b505a24..a3d95863f8e605 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -2040,7 +2040,7 @@ FCIMPL2(FC_BOOL_RET, MethodTableNative::IsEquivalentTo, MethodTable* mta, Method { FCALL_CONTRACT; - BOOL bResult; + BOOL bResult = FALSE; HELPER_METHOD_FRAME_BEGIN_RET_0(); bResult = mta->IsEquivalentTo(mtb); From a198d972315b11eff789f6261ba856639e9cdbbc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 1 Jun 2022 00:02:24 +0800 Subject: [PATCH 8/8] Change to QCall for type equivalence --- .../src/System/Delegate.CoreCLR.cs | 4 ++-- .../CompilerServices/RuntimeHelpers.CoreCLR.cs | 8 +++++--- src/coreclr/vm/comutilnative.cpp | 13 +++++++------ src/coreclr/vm/comutilnative.h | 3 ++- src/coreclr/vm/ecalllist.h | 1 - src/coreclr/vm/qcallentrypoints.cpp | 1 + 6 files changed, 17 insertions(+), 13 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 f9a1f3106d9bb9..c0d835ef5fc28a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -422,9 +422,9 @@ internal static unsafe bool InternalEqualTypes(object a, object b) bool ret; - // only use FCall to check the type equivalence scenario + // only use QCall to check the type equivalence scenario if (pMTa->HasTypeEquivalence && pMTb->HasTypeEquivalence) - ret = pMTa->IsEquivalentTo(pMTb); + ret = RuntimeHelpers.AreTypesEquivalent(pMTa, pMTb); else ret = false; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 817fb751c46a43..90869c3adda417 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -285,6 +285,11 @@ internal static unsafe bool ObjectHasComponentSize(object obj) return (MethodTable *)Unsafe.Add(ref Unsafe.As(ref obj.GetRawData()), -1); } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MethodTable_AreTypesEquivalent")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static unsafe partial bool AreTypesEquivalent(MethodTable* pMTa, MethodTable* pMTb); + /// /// Allocate memory that is associated with the and /// will be freed if and when the is unloaded. @@ -519,9 +524,6 @@ public int MultiDimensionalArrayRank [MethodImpl(MethodImplOptions.InternalCall)] public extern uint GetNumInstanceFieldBytes(); - - [MethodImpl(MethodImplOptions.InternalCall)] - public extern bool IsEquivalentTo(MethodTable* pMTOther); } // Helper structs used for tail calls via helper. diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index a3d95863f8e605..fc486eb17268d7 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -2036,19 +2036,20 @@ FCIMPL1(UINT32, MethodTableNative::GetNumInstanceFieldBytes, MethodTable* mt) } FCIMPLEND -FCIMPL2(FC_BOOL_RET, MethodTableNative::IsEquivalentTo, MethodTable* mta, MethodTable* mtb) +extern "C" BOOL QCALLTYPE MethodTable_AreTypesEquivalent(MethodTable* mta, MethodTable* mtb) { - FCALL_CONTRACT; + QCALL_CONTRACT; BOOL bResult = FALSE; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + BEGIN_QCALL; + bResult = mta->IsEquivalentTo(mtb); - HELPER_METHOD_FRAME_END(); - FC_RETURN_BOOL(bResult); + END_QCALL; + + return bResult; } -FCIMPLEND static MethodTable * g_pStreamMT; static WORD g_slotBeginRead, g_slotEndRead; diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index bca74edf40fd08..dd0fbd64926581 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -224,9 +224,10 @@ class ValueTypeHelper { class MethodTableNative { public: static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); - static FCDECL2(FC_BOOL_RET, IsEquivalentTo, MethodTable* mta, MethodTable* mtb); }; +extern "C" BOOL QCALLTYPE MethodTable_AreTypesEquivalent(MethodTable* mta, MethodTable* mtb); + class StreamNative { public: static FCDECL1(FC_BOOL_RET, HasOverriddenBeginEndRead, Object *stream); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index d89d00b9348624..b1b8f6fc33cfa7 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -603,7 +603,6 @@ FCFuncEnd() FCFuncStart(gMethodTableFuncs) FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes) - FCFuncElement("IsEquivalentTo", MethodTableNative::IsEquivalentTo) FCFuncEnd() FCFuncStart(gMngdFixedArrayMarshalerFuncs) diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 670698736c7d46..9f4851eb19ef4a 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -86,6 +86,7 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter) DllImportEntry(QCall_GetGCHandleForTypeHandle) DllImportEntry(QCall_FreeGCHandleForTypeHandle) + DllImportEntry(MethodTable_AreTypesEquivalent) DllImportEntry(RuntimeTypeHandle_MakePointer) DllImportEntry(RuntimeTypeHandle_MakeByRef) DllImportEntry(RuntimeTypeHandle_MakeSZArray)