From c194074a82ee35f31b1e55233b43256713b26467 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Fri, 8 Mar 2019 17:36:37 -0800 Subject: Properly override IsEquivalentTo() API in RuntimeType (#23137) * Properly override IsEquivalentTo() API in RuntimeType * Add tests for API validation --- src/System.Private.CoreLib/src/System/RtType.cs | 19 +++++++++++++++++++ .../src/System/RuntimeHandles.cs | 5 +++++ src/vm/ecalllist.h | 1 + src/vm/runtimehandles.cpp | 19 +++++++++++++++++++ src/vm/runtimehandles.h | 2 ++ 5 files changed, 46 insertions(+) (limited to 'src') diff --git a/src/System.Private.CoreLib/src/System/RtType.cs b/src/System.Private.CoreLib/src/System/RtType.cs index 2a71d2e759..3d03771258 100644 --- a/src/System.Private.CoreLib/src/System/RtType.cs +++ b/src/System.Private.CoreLib/src/System/RtType.cs @@ -3225,6 +3225,25 @@ namespace System return false; } +#if FEATURE_TYPEEQUIVALENCE + // Reflexive, symmetric, transitive. + public override bool IsEquivalentTo(Type other) + { + var otherRtType = other as RuntimeType; + if (otherRtType is null) + { + return false; + } + + if (otherRtType == this) + { + return true; + } + + return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType); + } +#endif // FEATURE_TYPEEQUIVALENCE + public override Type BaseType => GetBaseType(); private RuntimeType GetBaseType() diff --git a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index 1325aa831f..56694c63b8 100644 --- a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -615,6 +615,11 @@ namespace System { throw new PlatformNotSupportedException(); } + +#if FEATURE_TYPEEQUIVALENCE + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern bool IsEquivalentTo(RuntimeType rtType1, RuntimeType rtType2); +#endif // FEATURE_TYPEEQUIVALENCE } // This type is used to remove the expense of having a managed reference object that is dynamically diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 35fbae2160..0298939dbf 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -268,6 +268,7 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncElement("Allocate", RuntimeTypeHandle::Allocate) //for A.CI FCFuncElement("CompareCanonicalHandles", RuntimeTypeHandle::CompareCanonicalHandles) FCIntrinsic("GetValueInternal", RuntimeTypeHandle::GetValueInternal, CORINFO_INTRINSIC_RTH_GetValueInternal) + FCFuncElement("IsEquivalentTo", RuntimeTypeHandle::IsEquivalentTo) FCFuncEnd() FCFuncStart(gMetaDataImport) diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp index dda5d1d139..c8782db7ef 100644 --- a/src/vm/runtimehandles.cpp +++ b/src/vm/runtimehandles.cpp @@ -250,6 +250,25 @@ FCIMPL1_V(EnregisteredTypeHandle, RuntimeTypeHandle::GetValueInternal, FCALLRunt } FCIMPLEND +FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE) +{ + FCALL_CONTRACT; + + REFLECTCLASSBASEREF rtType1 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType1UNSAFE); + REFLECTCLASSBASEREF rtType2 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType2UNSAFE); + + BOOL areEquivalent = FALSE; + HELPER_METHOD_FRAME_BEGIN_RET_2(rtType1, rtType2); + + if (rtType1 != NULL && rtType2 != NULL) + areEquivalent = rtType1->GetType().IsEquivalentTo(rtType2->GetType()); + + HELPER_METHOD_FRAME_END(); + + FC_RETURN_BOOL(areEquivalent); +} +FCIMPLEND + // TypeEqualsHelper and TypeNotEqualsHelper are almost identical. // Unfortunately we cannot combime them because they need to hardcode the caller's name NOINLINE static BOOL TypeEqualSlow(OBJECTREF refL, OBJECTREF refR, LPVOID __me) diff --git a/src/vm/runtimehandles.h b/src/vm/runtimehandles.h index 6edf61ec99..66a27f4626 100644 --- a/src/vm/runtimehandles.h +++ b/src/vm/runtimehandles.h @@ -152,6 +152,8 @@ public: static FCDECL1_V(ReflectClassBaseObject*, GetTypeFromHandle, FCALLRuntimeTypeHandle th); static FCDECL1_V(EnregisteredTypeHandle, GetValueInternal, FCALLRuntimeTypeHandle RTH); + static FCDECL2(FC_BOOL_RET, IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE); + static FCDECL2(FC_BOOL_RET, TypeEQ, Object* left, Object* right); static FCDECL2(FC_BOOL_RET, TypeNEQ, Object* left, Object* right); -- cgit v1.2.3