Convert a few trivial Type, RuntimeType and Enum FCalls to C# (#71873)
authorJan Kotas <jkotas@microsoft.com>
Sun, 10 Jul 2022 01:01:45 +0000 (18:01 -0700)
committerGitHub <noreply@github.com>
Sun, 10 Jul 2022 01:01:45 +0000 (18:01 -0700)
src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs
src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs
src/coreclr/vm/ecalllist.h
src/coreclr/vm/reflectioninvocation.cpp
src/coreclr/vm/reflectioninvocation.h
src/coreclr/vm/runtimehandles.cpp
src/coreclr/vm/runtimehandles.h

index b8e41c0..fb1dd0a 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.CompilerServices;
@@ -17,10 +18,59 @@ namespace System
         private static extern object InternalBoxEnum(RuntimeType enumType, long value);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private extern CorElementType InternalGetCorElementType();
+        private static extern unsafe CorElementType InternalGetCorElementType(MethodTable* pMT);
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern RuntimeType InternalGetUnderlyingType(RuntimeType enumType);
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe CorElementType InternalGetCorElementType()
+        {
+            CorElementType elementType = InternalGetCorElementType(RuntimeHelpers.GetMethodTable(this));
+            GC.KeepAlive(this);
+            return elementType;
+        }
+
+        // Indexed by CorElementType
+        private static readonly RuntimeType?[] s_underlyingTypes =
+        {
+            null,
+            null,
+            (RuntimeType)typeof(bool),
+            (RuntimeType)typeof(char),
+            (RuntimeType)typeof(sbyte),
+            (RuntimeType)typeof(byte),
+            (RuntimeType)typeof(short),
+            (RuntimeType)typeof(ushort),
+            (RuntimeType)typeof(int),
+            (RuntimeType)typeof(uint),
+            (RuntimeType)typeof(long),
+            (RuntimeType)typeof(ulong),
+            (RuntimeType)typeof(float),
+            (RuntimeType)typeof(double),
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            (RuntimeType)typeof(nint),
+            (RuntimeType)typeof(nuint)
+        };
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static unsafe RuntimeType InternalGetUnderlyingType(RuntimeType enumType)
+        {
+            // Sanity check the last element in the table
+            Debug.Assert(s_underlyingTypes[(int)CorElementType.ELEMENT_TYPE_U] == typeof(nuint));
+
+            RuntimeType? underlyingType = s_underlyingTypes[(int)InternalGetCorElementType((MethodTable*)enumType.GetUnderlyingNativeHandle())];
+            GC.KeepAlive(enumType);
+
+            Debug.Assert(underlyingType != null);
+            return underlyingType;
+        }
 
         private static EnumInfo GetEnumInfo(RuntimeType enumType, bool getNames = true)
         {
index 489c1b8..49b1b5a 100644 (file)
@@ -93,29 +93,19 @@ namespace System
         internal RuntimeType m_type;
 
         public override int GetHashCode()
-        {
-            return m_type != null ? m_type.GetHashCode() : 0;
-        }
+            => m_type?.GetHashCode() ?? 0;
 
         public override bool Equals(object? obj)
-        {
-            if (!(obj is RuntimeTypeHandle))
-                return false;
-
-            RuntimeTypeHandle handle = (RuntimeTypeHandle)obj;
-            return handle.m_type == m_type;
-        }
+            => (obj is RuntimeTypeHandle handle) && ReferenceEquals(handle.m_type, m_type);
 
         public bool Equals(RuntimeTypeHandle handle)
-        {
-            return handle.m_type == m_type;
-        }
+            => ReferenceEquals(handle.m_type, m_type);
 
-        public IntPtr Value => m_type != null ? m_type.m_handle : IntPtr.Zero;
+        public IntPtr Value => m_type?.m_handle ?? 0;
 
         [Intrinsic]
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern IntPtr GetValueInternal(RuntimeTypeHandle handle);
+        internal static IntPtr GetValueInternal(RuntimeTypeHandle handle)
+            => handle.m_type?.GetUnderlyingNativeHandle() ?? 0;
 
         internal RuntimeTypeHandle(RuntimeType type)
         {
index 7fc7504..fa00bf7 100644 (file)
@@ -86,7 +86,7 @@ namespace System
         internal static extern RuntimeType GetTypeFromHandleUnsafe(IntPtr handle);
 
         [Intrinsic]
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        public static extern Type? GetTypeFromHandle(RuntimeTypeHandle handle);
+        public static Type? GetTypeFromHandle(RuntimeTypeHandle handle)
+            => handle.m_type;
     }
 }
index d2c3822..6c06aac 100644 (file)
@@ -55,7 +55,6 @@ FCFuncStart(gDependentHandleFuncs)
 FCFuncEnd()
 
 FCFuncStart(gEnumFuncs)
-    FCFuncElement("InternalGetUnderlyingType",  ReflectionEnum::InternalGetEnumUnderlyingType)
     FCFuncElement("InternalGetCorElementType",  ReflectionEnum::InternalGetCorElementType)
     FCFuncElement("InternalBoxEnum", ReflectionEnum::InternalBoxEnum)
 FCFuncEnd()
@@ -123,7 +122,6 @@ FCFuncStart(gTypedReferenceFuncs)
 FCFuncEnd()
 
 FCFuncStart(gSystem_Type)
-    FCFuncElement("GetTypeFromHandle", RuntimeTypeHandle::GetTypeFromHandle)
     FCFuncElement("GetTypeFromHandleUnsafe", RuntimeTypeHandle::GetRuntimeType)
 FCFuncEnd()
 
@@ -172,7 +170,6 @@ FCFuncStart(gCOMTypeHandleFuncs)
     FCFuncElement("AllocateComObject", RuntimeTypeHandle::AllocateComObject)
 #endif // FEATURE_COMINTEROP
     FCFuncElement("CompareCanonicalHandles", RuntimeTypeHandle::CompareCanonicalHandles)
-    FCFuncElement("GetValueInternal", RuntimeTypeHandle::GetValueInternal)
     FCFuncElement("IsEquivalentTo", RuntimeTypeHandle::IsEquivalentTo)
 FCFuncEnd()
 
index 83eaa09..3e5d1a8 100644 (file)
@@ -1901,32 +1901,9 @@ extern "C" void QCALLTYPE ReflectionSerialization_GetUninitializedObject(QCall::
 //*************************************************************************************************
 //*************************************************************************************************
 
-FCIMPL1(Object *, ReflectionEnum::InternalGetEnumUnderlyingType, ReflectClassBaseObject *target) {
+FCIMPL1(INT32, ReflectionEnum::InternalGetCorElementType, MethodTable* pMT) {
     FCALL_CONTRACT;
 
-    VALIDATEOBJECT(target);
-    TypeHandle th = target->GetType();
-    _ASSERTE(th.IsEnum());
-
-    OBJECTREF result = NULL;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_0();
-    MethodTable *pMT = CoreLibBinder::GetElementType(th.AsMethodTable()->GetInternalCorElementType());
-    result = pMT->GetManagedClassObject();
-    HELPER_METHOD_FRAME_END();
-
-    return OBJECTREFToObject(result);
-}
-FCIMPLEND
-
-FCIMPL1(INT32, ReflectionEnum::InternalGetCorElementType, Object *pRefThis) {
-    FCALL_CONTRACT;
-
-    VALIDATEOBJECT(pRefThis);
-    if (pRefThis == NULL)
-        FCThrowArgumentNull(NULL);
-
-    MethodTable* pMT = pRefThis->GetMethodTable();
     _ASSERTE(pMT->IsEnum());
 
     // MethodTable::GetInternalCorElementType has unnecessary overhead for enums
index 780ac7a..8ede04b 100644 (file)
@@ -76,8 +76,7 @@ extern "C" void QCALLTYPE ReflectionSerialization_GetUninitializedObject(QCall::
 
 class ReflectionEnum {
 public:
-    static FCDECL1(Object *, InternalGetEnumUnderlyingType, ReflectClassBaseObject *target);
-    static FCDECL1(INT32, InternalGetCorElementType, Object *pRefThis);
+    static FCDECL1(INT32, InternalGetCorElementType, MethodTable* pMT);
     static FCDECL2_IV(Object*, InternalBoxEnum, ReflectClassBaseObject* pEnumType, INT64 value);
 };
 
index c849a0a..b13e4af 100644 (file)
@@ -220,18 +220,6 @@ NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembl
     return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
 }
 
-
-// This is the routine that is called by the 'typeof()' operator in C#.  It is one of the most commonly used
-// reflection operations. This call should be optimized away in nearly all situations
-FCIMPL1_V(ReflectClassBaseObject*, RuntimeTypeHandle::GetTypeFromHandle, FCALLRuntimeTypeHandle th)
-{
-    FCALL_CONTRACT;
-
-    FCUnique(0x31);
-    return FCALL_RTH_TO_REFLECTCLASS(th);
-}
-FCIMPLEND
-
 FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th)
 {
     FCALL_CONTRACT;
@@ -256,17 +244,6 @@ FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, Enregistered
 }
 FCIMPLEND
 
-FCIMPL1_V(EnregisteredTypeHandle, RuntimeTypeHandle::GetValueInternal, FCALLRuntimeTypeHandle RTH)
-{
-    FCALL_CONTRACT;
-
-    if (FCALL_RTH_TO_REFLECTCLASS(RTH) == NULL)
-        return 0;
-
-    return FCALL_RTH_TO_REFLECTCLASS(RTH) ->GetType().AsPtr();
-}
-FCIMPLEND
-
 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE)
 {
     FCALL_CONTRACT;
index a4bddd1..10c2b02 100644 (file)
@@ -121,9 +121,6 @@ public:
 
     static FCDECL1(ReflectClassBaseObject*, GetRuntimeType, void *th);
 
-    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 FCDECL1(AssemblyBaseObject*, GetAssembly, ReflectClassBaseObject *pType);