// 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;
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)
{
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)
{
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;
}
}
FCFuncEnd()
FCFuncStart(gEnumFuncs)
- FCFuncElement("InternalGetUnderlyingType", ReflectionEnum::InternalGetEnumUnderlyingType)
FCFuncElement("InternalGetCorElementType", ReflectionEnum::InternalGetCorElementType)
FCFuncElement("InternalBoxEnum", ReflectionEnum::InternalBoxEnum)
FCFuncEnd()
FCFuncEnd()
FCFuncStart(gSystem_Type)
- FCFuncElement("GetTypeFromHandle", RuntimeTypeHandle::GetTypeFromHandle)
FCFuncElement("GetTypeFromHandleUnsafe", RuntimeTypeHandle::GetRuntimeType)
FCFuncEnd()
FCFuncElement("AllocateComObject", RuntimeTypeHandle::AllocateComObject)
#endif // FEATURE_COMINTEROP
FCFuncElement("CompareCanonicalHandles", RuntimeTypeHandle::CompareCanonicalHandles)
- FCFuncElement("GetValueInternal", RuntimeTypeHandle::GetValueInternal)
FCFuncElement("IsEquivalentTo", RuntimeTypeHandle::IsEquivalentTo)
FCFuncEnd()
//*************************************************************************************************
//*************************************************************************************************
-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
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);
};
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;
}
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;
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);