Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove more HelperMethodFrames (HMF) from Reflection #109882

Merged
merged 9 commits into from
Nov 18, 2024
13 changes: 1 addition & 12 deletions src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,14 @@ namespace System
{
public partial class Object
{
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ObjectNative_GetTypeSlow")]
private static unsafe partial void GetTypeSlow(MethodTable* methodTable, ObjectHandleOnStack ret);

// Returns a Type object which represent this object instance.
[Intrinsic]
public unsafe Type GetType()
{
MethodTable* pMT = RuntimeHelpers.GetMethodTable(this);
Type type = pMT->AuxiliaryData->ExposedClassObject ?? GetTypeWorker(pMT);
RuntimeType type = RuntimeTypeHandle.GetRuntimeType(pMT);
GC.KeepAlive(this);
return type;

[MethodImpl(MethodImplOptions.NoInlining)]
static Type GetTypeWorker(MethodTable* pMT)
{
Type? type = null;
GetTypeSlow(pMT, ObjectHandleOnStack.Create(ref type));
return type!;
}
}

// Returns a new object instance that is a memberwise copy of this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private static unsafe ref byte GetSpanDataFrom(
if (!RuntimeFieldHandle.GetRVAFieldInfo(fldInfo.Value, out void* data, out uint totalSize))
throw new ArgumentException(SR.Argument_BadFieldForInitializeArray);

TypeHandle th = targetTypeHandle.GetNativeTypeHandle();
TypeHandle th = targetTypeHandle.GetRuntimeType().GetNativeTypeHandle();
Debug.Assert(!th.IsTypeDesc); // TypeDesc can't be used as generic parameter
MethodTable* targetMT = th.AsMethodTable();

Expand Down
64 changes: 51 additions & 13 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,39 @@ internal RuntimeType GetTypeChecked() =>
/// </summary>
/// <param name="value">An IntPtr handle to a RuntimeType to create a <see cref="RuntimeTypeHandle"/> object from.</param>
/// <returns>A new <see cref="RuntimeTypeHandle"/> object that corresponds to the value parameter.</returns>
public static RuntimeTypeHandle FromIntPtr(IntPtr value) => new RuntimeTypeHandle(Type.GetTypeFromHandleUnsafe(value));
public static RuntimeTypeHandle FromIntPtr(IntPtr value) => new RuntimeTypeHandle(GetTypeFromHandle(value));

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetTypeFromHandleSlow")]
private static partial void GetTypeFromHandleSlow(
IntPtr handle,
ObjectHandleOnStack typeObject);

[MethodImpl(MethodImplOptions.NoInlining)]
private static RuntimeType GetTypeFromHandleSlow(IntPtr handle)
{
RuntimeType? typeObject = null;
GetTypeFromHandleSlow(handle, ObjectHandleOnStack.Create(ref typeObject));
return typeObject!;
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern RuntimeType? GetTypeFromHandleIfExists(IntPtr handle);

private static RuntimeType? GetTypeFromHandle(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
return null;
}

return GetTypeFromHandleIfExists(handle) ?? GetTypeFromHandleSlow(handle);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe RuntimeType GetRuntimeType(MethodTable* pMT)
{
return pMT->AuxiliaryData->ExposedClassObject ?? GetTypeFromHandleSlow((IntPtr)pMT);
}

/// <summary>
/// Returns the internal pointer representation of a <see cref="RuntimeTypeHandle"/> object.
Expand All @@ -49,7 +81,7 @@ internal RuntimeType GetTypeChecked() =>
public static bool operator !=(object? left, RuntimeTypeHandle right) => !right.Equals(left);

// This is the RuntimeType for the type
internal RuntimeType m_type;
internal RuntimeType? m_type;

public override int GetHashCode()
=> m_type?.GetHashCode() ?? 0;
Expand All @@ -62,7 +94,7 @@ public bool Equals(RuntimeTypeHandle handle)

public IntPtr Value => m_type?.m_handle ?? 0;

internal RuntimeTypeHandle(RuntimeType type)
internal RuntimeTypeHandle(RuntimeType? type)
{
m_type = type;
}
Expand All @@ -72,11 +104,6 @@ internal bool IsNullHandle()
return m_type == null;
}

internal TypeHandle GetNativeTypeHandle()
{
return m_type.GetNativeTypeHandle();
}

internal static bool IsTypeDefinition(RuntimeType type)
{
CorElementType corElemType = type.GetCorElementType();
Expand Down Expand Up @@ -304,7 +331,7 @@ private static object AllocateComObject(void* pClassFactory)

internal RuntimeType GetRuntimeType()
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
{
return m_type;
return m_type!;
}

internal static RuntimeAssembly GetAssembly(RuntimeType type)
Expand Down Expand Up @@ -347,12 +374,14 @@ static RuntimeModule GetModuleWorker(RuntimeType type)

public ModuleHandle GetModuleHandle()
{
if (m_type is null)
{
throw new ArgumentNullException(SR.Arg_InvalidHandle);
}

return new ModuleHandle(GetModule(m_type));
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeType GetBaseType(RuntimeType type);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern TypeAttributes GetAttributes(RuntimeType type);

Expand Down Expand Up @@ -1220,7 +1249,16 @@ internal static MdUtf8String GetUtf8Name(RuntimeFieldHandleInternal field)
internal static extern FieldAttributes GetAttributes(RuntimeFieldHandleInternal field);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeType GetApproxDeclaringType(RuntimeFieldHandleInternal field);
private static extern MethodTable* GetApproxDeclaringMethodTable(RuntimeFieldHandleInternal field);

internal static RuntimeType GetApproxDeclaringType(RuntimeFieldHandleInternal field)
{
Debug.Assert(!field.IsNullHandle());
MethodTable* pMT = GetApproxDeclaringMethodTable(field);
Debug.Assert(pMT != null);

return RuntimeTypeHandle.GetRuntimeType(pMT);
}

internal static RuntimeType GetApproxDeclaringType(IRuntimeFieldInfo field)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private BoxCache(RuntimeType rt)
_originalRuntimeType = rt;
#endif

TypeHandle handle = rt.TypeHandle.GetNativeTypeHandle();
TypeHandle handle = rt.GetNativeTypeHandle();

if (handle.IsTypeDesc)
throw new ArgumentException(SR.Arg_TypeNotSupported);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
#endregion
}

declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
declaringType = declaringType.GetParentType()!;
} while (declaringType != null);
#endregion
}
Expand Down Expand Up @@ -814,13 +814,14 @@ private RuntimeFieldInfo[] PopulateFields(Filter filter)
while (RuntimeTypeHandle.IsGenericVariable(declaringType))
declaringType = declaringType.GetBaseType()!;

while (declaringType != null)
RuntimeType? populatingType = declaringType;
while (populatingType != null)
{
PopulateRtFields(filter, declaringType, ref list);
PopulateRtFields(filter, populatingType, ref list);

PopulateLiteralFields(filter, declaringType, ref list);
PopulateLiteralFields(filter, populatingType, ref list);

declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
populatingType = populatingType.GetParentType();
}
#endregion

Expand Down Expand Up @@ -1152,10 +1153,11 @@ private RuntimeEventInfo[] PopulateEvents(Filter filter)
declaringType = declaringType.GetBaseType()!;

// Populate associates off of the class hierarchy
while (declaringType != null)
RuntimeType? populatingType = declaringType;
while (populatingType != null)
{
PopulateEvents(filter, declaringType, csEventInfos, ref list);
declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
PopulateEvents(filter, populatingType, csEventInfos, ref list);
populatingType = populatingType.GetParentType();
}
}
else
Expand Down Expand Up @@ -1261,11 +1263,12 @@ private RuntimePropertyInfo[] PopulateProperties(Filter filter)
}

// Populate associates off of the class hierarchy
do
RuntimeType? populatingType = declaringType;
while (populatingType != null)
{
PopulateProperties(filter, declaringType, csPropertyInfos, usedSlots, isInterface: false, ref list);
declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
} while (declaringType != null);
PopulateProperties(filter, populatingType, csPropertyInfos, usedSlots, isInterface: false, ref list);
populatingType = populatingType.GetParentType();
}
}
else
{
Expand Down Expand Up @@ -1778,6 +1781,28 @@ internal FieldInfo GetField(RuntimeFieldHandleInternal field)
#region Static Members

#region Internal

// Returns the type from which the current type directly inherits from (without reflection quirks).
// The parent type is null for interfaces, pointers, byrefs and generic parameters.
internal unsafe RuntimeType? GetParentType()
{
TypeHandle typeHandle = GetNativeTypeHandle();
if (typeHandle.IsTypeDesc)
{
return null;
}

MethodTable* pParentMT = typeHandle.AsMethodTable()->ParentMethodTable;
if (pParentMT == null)
{
return null;
}

RuntimeType result = RuntimeTypeHandle.GetRuntimeType(pParentMT);
GC.KeepAlive(this);
return result;
}

[RequiresUnreferencedCode("Trimming changes metadata tokens")]
internal static MethodBase? GetMethodBase(RuntimeModule scope, int typeMetadataToken)
{
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ public abstract partial class Type : MemberInfo, IReflect
throwOnError: throwOnError, ignoreCase: ignoreCase);
}

// Given a class handle, this will return the class for that handle.
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeType GetTypeFromHandleUnsafe(IntPtr handle);

[Intrinsic]
public static Type? GetTypeFromHandle(RuntimeTypeHandle handle)
=> handle.m_type;
Expand Down
14 changes: 0 additions & 14 deletions src/coreclr/classlibnative/bcltype/objectnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,6 @@ FCIMPL2(FC_BOOL_RET, ObjectNative::ContentEquals, Object *pThisRef, Object *pCom
}
FCIMPLEND

extern "C" void QCALLTYPE ObjectNative_GetTypeSlow(MethodTable* pMT, QCall::ObjectHandleOnStack ret)
{
QCALL_CONTRACT;
_ASSERTE(pMT != NULL);

BEGIN_QCALL;

GCX_COOP();

ret.Set(pMT->GetManagedClassObject());

END_QCALL;
}

extern "C" void QCALLTYPE ObjectNative_AllocateUninitializedClone(QCall::ObjectHandleOnStack objHandle)
{
QCALL_CONTRACT;
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/classlibnative/bcltype/objectnative.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class ObjectNative
};

extern "C" INT32 QCALLTYPE ObjectNative_GetHashCodeSlow(QCall::ObjectHandleOnStack objHandle);
extern "C" void QCALLTYPE ObjectNative_GetTypeSlow(MethodTable* pMT, QCall::ObjectHandleOnStack ret);
extern "C" void QCALLTYPE ObjectNative_AllocateUninitializedClone(QCall::ObjectHandleOnStack objHandle);
extern "C" BOOL QCALLTYPE Monitor_Wait(QCall::ObjectHandleOnStack pThis, INT32 Timeout);
extern "C" void QCALLTYPE Monitor_Pulse(QCall::ObjectHandleOnStack pThis);
Expand Down
9 changes: 2 additions & 7 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,13 @@ FCFuncStart(gExceptionFuncs)
FCFuncElement("GetExceptionCount", ExceptionNative::GetExceptionCount)
FCFuncEnd()

FCFuncStart(gSystem_Type)
FCFuncElement("GetTypeFromHandleUnsafe", RuntimeTypeHandle::GetRuntimeType)
FCFuncEnd()

FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("GetDeclaringMethod", RuntimeTypeHandle::GetDeclaringMethod)
FCFuncElement("GetDeclaringType", RuntimeTypeHandle::GetDeclaringType)
FCFuncElement("GetFirstIntroducedMethod", RuntimeTypeHandle::GetFirstIntroducedMethod)
FCFuncElement("GetNextIntroducedMethod", RuntimeTypeHandle::GetNextIntroducedMethod)
FCFuncElement("GetAssemblyIfExists", RuntimeTypeHandle::GetAssemblyIfExists)
FCFuncElement("GetModuleIfExists", RuntimeTypeHandle::GetModuleIfExists)
FCFuncElement("GetBaseType", RuntimeTypeHandle::GetBaseType)
FCFuncElement("GetElementType", RuntimeTypeHandle::GetElementType)
FCFuncElement("GetArrayRank", RuntimeTypeHandle::GetArrayRank)
FCFuncElement("GetToken", RuntimeTypeHandle::GetToken)
Expand All @@ -111,6 +106,7 @@ FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("IsUnmanagedFunctionPointer", RuntimeTypeHandle::IsUnmanagedFunctionPointer)
FCFuncElement("CompareCanonicalHandles", RuntimeTypeHandle::CompareCanonicalHandles)
FCFuncElement("IsEquivalentTo", RuntimeTypeHandle::IsEquivalentTo)
FCFuncElement("GetTypeFromHandleIfExists", RuntimeTypeHandle::GetTypeFromHandleIfExists)
FCFuncEnd()

FCFuncStart(gMetaDataImport)
Expand Down Expand Up @@ -176,7 +172,7 @@ FCFuncEnd()
FCFuncStart(gCOMFieldHandleNewFuncs)
FCFuncElement("GetUtf8NameInternal", RuntimeFieldHandle::GetUtf8Name)
FCFuncElement("GetAttributes", RuntimeFieldHandle::GetAttributes)
FCFuncElement("GetApproxDeclaringType", RuntimeFieldHandle::GetApproxDeclaringType)
FCFuncElement("GetApproxDeclaringMethodTable", RuntimeFieldHandle::GetApproxDeclaringMethodTable)
FCFuncElement("GetToken", RuntimeFieldHandle::GetToken)
FCFuncElement("GetStaticFieldForGenericType", RuntimeFieldHandle::GetStaticFieldForGenericType)
FCFuncElement("AcquiresContextFromThis", RuntimeFieldHandle::AcquiresContextFromThis)
Expand Down Expand Up @@ -433,7 +429,6 @@ FCClassElement("String", "System", gStringFuncs)
FCClassElement("StubHelpers", "System.StubHelpers", gStubHelperFuncs)
FCClassElement("Thread", "System.Threading", gThreadFuncs)
FCClassElement("ThreadPool", "System.Threading", gThreadPoolFuncs)
FCClassElement("Type", "System", gSystem_Type)

#undef FCFuncElement
#undef FCFuncElementSig
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ static const Entry s_QCall[] =
DllImportEntry(ExceptionNative_GetMethodFromStackTrace)
DllImportEntry(ExceptionNative_ThrowAmbiguousResolutionException)
DllImportEntry(ExceptionNative_ThrowEntryPointNotFoundException)
DllImportEntry(RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter)
DllImportEntry(QCall_GetGCHandleForTypeHandle)
DllImportEntry(QCall_FreeGCHandleForTypeHandle)
DllImportEntry(MethodTable_AreTypesEquivalent)
Expand Down Expand Up @@ -137,6 +136,8 @@ static const Entry s_QCall[] =
#ifdef FEATURE_COMINTEROP
DllImportEntry(RuntimeTypeHandle_AllocateComObject)
#endif // FEATURE_COMINTEROP
DllImportEntry(RuntimeTypeHandle_GetTypeFromHandleSlow)
DllImportEntry(RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter)
DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemory)
DllImportEntry(RuntimeTypeHandle_RegisterCollectibleTypeDependency)
DllImportEntry(MethodBase_GetCurrentMethod)
Expand Down Expand Up @@ -373,7 +374,6 @@ static const Entry s_QCall[] =
DllImportEntry(FileLoadException_GetMessageForHR)
DllImportEntry(Interlocked_MemoryBarrierProcessWide)
DllImportEntry(ObjectNative_GetHashCodeSlow)
DllImportEntry(ObjectNative_GetTypeSlow)
DllImportEntry(ObjectNative_AllocateUninitializedClone)
DllImportEntry(Monitor_Wait)
DllImportEntry(Monitor_Pulse)
Expand Down
Loading
Loading