Skip to content

Commit

Permalink
Remove Helper Method Frames (HMF) from Reflection (#110481)
Browse files Browse the repository at this point in the history
Convert RuntimeTypeHandle.GetFields() to QCall.
Convert RuntimeTypeHandle.GetInterfaces() to QCall.
Convert Signature.CompareSig() to QCall.
Rename to Signature.CompareSig() to Signature.AreEqual().

---------

Co-authored-by: Adeel Mujahid <[email protected]>
  • Loading branch information
AaronRobinsonMSFT and am11 authored Dec 10, 2024
1 parent cc66c77 commit f9c86dc
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ internal bool EqualsSig(RuntimePropertyInfo target)
Debug.Assert(this != target);
Debug.Assert(this.ReflectedType == target.ReflectedType);

return Signature.CompareSig(this.Signature, target.Signature);
return Signature.AreEqual(this.Signature, target.Signature);
}
internal BindingFlags BindingFlags => m_bindingFlags;
#endregion
Expand Down
60 changes: 52 additions & 8 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,45 @@ internal static IntroducedMethodEnumerator GetIntroducedMethods(RuntimeType type
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void GetNextIntroducedMethod(ref RuntimeMethodHandleInternal method);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool GetFields(RuntimeType type, IntPtr* result, int* count);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetFields")]
private static partial Interop.BOOL GetFields(MethodTable* pMT, Span<IntPtr> data, ref int usedCount);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Type[]? GetInterfaces(RuntimeType type);
internal static bool GetFields(RuntimeType type, Span<IntPtr> buffer, out int count)
{
Debug.Assert(!IsGenericVariable(type));

TypeHandle typeHandle = type.GetNativeTypeHandle();
if (typeHandle.IsTypeDesc)
{
count = 0;
return true;
}

int countLocal = buffer.Length;
bool success = GetFields(typeHandle.AsMethodTable(), buffer, ref countLocal) != Interop.BOOL.FALSE;
GC.KeepAlive(type);
count = countLocal;
return success;
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetInterfaces")]
private static unsafe partial void GetInterfaces(MethodTable* pMT, ObjectHandleOnStack result);

internal static Type[] GetInterfaces(RuntimeType type)
{
Debug.Assert(!IsGenericVariable(type));

TypeHandle typeHandle = type.GetNativeTypeHandle();
if (typeHandle.IsTypeDesc)
{
return [];
}

Type[] result = [];
GetInterfaces(typeHandle.AsMethodTable(), ObjectHandleOnStack.Create(ref result));
GC.KeepAlive(type);
return result;
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetConstraints")]
private static partial void GetConstraints(QCallTypeHandle handle, ObjectHandleOnStack types);
Expand Down Expand Up @@ -1859,10 +1893,11 @@ internal static int GetMDStreamVersion(RuntimeModule module)
public int MDStreamVersion => GetMDStreamVersion(GetRuntimeModule());
}

internal sealed unsafe class Signature
internal sealed unsafe partial class Signature
{
#region FCalls
[MemberNotNull(nameof(m_arguments))]
[MemberNotNull(nameof(m_declaringType))]
[MemberNotNull(nameof(m_returnTypeORfieldType))]
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void GetSignature(
Expand All @@ -1875,7 +1910,7 @@ private extern void GetSignature(
// Keep the layout in sync with SignatureNative in the VM
//
internal RuntimeType[] m_arguments;
internal RuntimeType? m_declaringType;
internal RuntimeType m_declaringType;
internal RuntimeType m_returnTypeORfieldType;
internal object? m_keepalive;
internal void* m_sig;
Expand Down Expand Up @@ -1923,8 +1958,17 @@ public Signature(void* pCorSig, int cCorSig, RuntimeType declaringType)
internal RuntimeType ReturnType => m_returnTypeORfieldType;
internal RuntimeType FieldType => m_returnTypeORfieldType;

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool CompareSig(Signature sig1, Signature sig2);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Signature_AreEqual")]
private static partial Interop.BOOL AreEqual(
void* sig1, int csig1, QCallTypeHandle type1,
void* sig2, int csig2, QCallTypeHandle type2);

internal static bool AreEqual(Signature sig1, Signature sig2)
{
return AreEqual(
sig1.m_sig, sig1.m_csig, new QCallTypeHandle(ref sig1.m_declaringType),
sig2.m_sig, sig2.m_csig, new QCallTypeHandle(ref sig2.m_declaringType)) != Interop.BOOL.FALSE;
}

internal Type[] GetCustomModifiers(int parameterIndex, bool required) =>
GetCustomModifiersAtOffset(GetParameterOffset(parameterIndex), required);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -826,30 +826,21 @@ private RuntimeFieldInfo[] PopulateFields(Filter filter)
#endregion

#region Populate Literal Fields on Interfaces
Type[] interfaces;
if (ReflectedType.IsGenericParameter)
{
Type[] interfaces = ReflectedType.BaseType!.GetInterfaces();

for (int i = 0; i < interfaces.Length; i++)
{
// Populate literal fields defined on any of the interfaces implemented by the declaring type
PopulateLiteralFields(filter, (RuntimeType)interfaces[i], ref list);
PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
}
interfaces = ReflectedType.BaseType!.GetInterfaces();
}
else
{
Type[]? interfaces = RuntimeTypeHandle.GetInterfaces(ReflectedType);
interfaces = RuntimeTypeHandle.GetInterfaces(ReflectedType);
}

if (interfaces != null)
{
for (int i = 0; i < interfaces.Length; i++)
{
// Populate literal fields defined on any of the interfaces implemented by the declaring type
PopulateLiteralFields(filter, (RuntimeType)interfaces[i], ref list);
PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
}
}
foreach (Type iface in interfaces)
{
// Populate literal fields defined on any of the interfaces implemented by the declaring type
PopulateLiteralFields(filter, (RuntimeType)iface, ref list);
PopulateRtFields(filter, (RuntimeType)iface, ref list);
}
#endregion

Expand All @@ -858,35 +849,32 @@ private RuntimeFieldInfo[] PopulateFields(Filter filter)

private unsafe void PopulateRtFields(Filter filter, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
{
IntPtr* pResult = stackalloc IntPtr[64];
int count = 64;

if (!RuntimeTypeHandle.GetFields(declaringType, pResult, &count))
Span<IntPtr> result = stackalloc IntPtr[64];
int count;
while (!RuntimeTypeHandle.GetFields(declaringType, result, out count))
{
fixed (IntPtr* pBigResult = new IntPtr[count])
{
RuntimeTypeHandle.GetFields(declaringType, pBigResult, &count);
PopulateRtFields(filter, pBigResult, count, declaringType, ref list);
}
Debug.Assert(count > result.Length);
result = new IntPtr[count];
}
else if (count > 0)

if (count > 0)
{
PopulateRtFields(filter, pResult, count, declaringType, ref list);
PopulateRtFields(filter, result.Slice(0, count), declaringType, ref list);
}
}

private unsafe void PopulateRtFields(Filter filter,
IntPtr* ppFieldHandles, int count, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
ReadOnlySpan<IntPtr> fieldHandles, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
{
Debug.Assert(declaringType != null);
Debug.Assert(ReflectedType != null);

bool needsStaticFieldForGeneric = declaringType.IsGenericType && !RuntimeTypeHandle.ContainsGenericVariables(declaringType);
bool isInherited = declaringType != ReflectedType;

for (int i = 0; i < count; i++)
foreach (IntPtr handle in fieldHandles)
{
RuntimeFieldHandleInternal runtimeFieldHandle = new RuntimeFieldHandleInternal(ppFieldHandles[i]);
RuntimeFieldHandleInternal runtimeFieldHandle = new RuntimeFieldHandleInternal(handle);

if (filter.RequiresStringComparison())
{
Expand Down Expand Up @@ -1017,23 +1005,19 @@ private RuntimeType[] PopulateInterfaces(Filter filter)

if (!RuntimeTypeHandle.IsGenericVariable(declaringType))
{
Type[]? ifaces = RuntimeTypeHandle.GetInterfaces(declaringType);

if (ifaces != null)
Type[] ifaces = RuntimeTypeHandle.GetInterfaces(declaringType);
foreach (Type iface in ifaces)
{
for (int i = 0; i < ifaces.Length; i++)
{
RuntimeType interfaceType = (RuntimeType)ifaces[i];

if (filter.RequiresStringComparison())
{
if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaceType)))
continue;
}
RuntimeType interfaceType = (RuntimeType)iface;

Debug.Assert(interfaceType.IsInterface);
list.Add(interfaceType);
if (filter.RequiresStringComparison())
{
if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaceType)))
continue;
}

Debug.Assert(interfaceType.IsInterface);
list.Add(interfaceType);
}

if (ReflectedType.IsSZArray)
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/vm/callhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@

// To include declaration of "AppDomainTransitionExceptionFilter"
#include "excep.h"

// To include declaration of "SignatureNative"
#include "runtimehandles.h"

#include "invokeutil.h"
#include "argdestination.h"

Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("GetArrayRank", RuntimeTypeHandle::GetArrayRank)
FCFuncElement("GetToken", RuntimeTypeHandle::GetToken)
FCFuncElement("GetUtf8NameInternal", RuntimeTypeHandle::GetUtf8Name)
FCFuncElement("GetFields", RuntimeTypeHandle::GetFields)
FCFuncElement("GetInterfaces", RuntimeTypeHandle::GetInterfaces)
FCFuncElement("GetAttributes", RuntimeTypeHandle::GetAttributes)
FCFuncElement("GetNumVirtuals", RuntimeTypeHandle::GetNumVirtuals)
FCFuncElement("CanCastTo", RuntimeTypeHandle::CanCastTo)
Expand Down Expand Up @@ -135,7 +133,6 @@ FCFuncEnd()

FCFuncStart(gSignatureNative)
FCFuncElement("GetSignature", SignatureNative::GetSignature)
FCFuncElement("CompareSig", SignatureNative::CompareSig)
FCFuncElement("GetParameterOffsetInternal", SignatureNative::GetParameterOffsetInternal)
FCFuncElement("GetTypeParameterOffset", SignatureNative::GetTypeParameterOffset)
FCFuncElement("GetCustomModifiersAtOffset", SignatureNative::GetCustomModifiersAtOffset)
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ static const Entry s_QCall[] =
DllImportEntry(RuntimeTypeHandle_GetModuleSlow)
DllImportEntry(RuntimeTypeHandle_GetNumVirtualsAndStaticVirtuals)
DllImportEntry(RuntimeTypeHandle_GetMethodAt)
DllImportEntry(RuntimeTypeHandle_GetFields)
DllImportEntry(RuntimeTypeHandle_VerifyInterfaceIsImplemented)
DllImportEntry(RuntimeTypeHandle_GetInterfaceMethodImplementation)
DllImportEntry(RuntimeTypeHandle_GetDeclaringTypeHandleForGenericVariable)
DllImportEntry(RuntimeTypeHandle_GetDeclaringTypeHandle)
DllImportEntry(RuntimeTypeHandle_IsVisible)
DllImportEntry(RuntimeTypeHandle_ConstructName)
DllImportEntry(RuntimeTypeHandle_GetInterfaces)
DllImportEntry(RuntimeTypeHandle_GetInstantiation)
DllImportEntry(RuntimeTypeHandle_Instantiate)
DllImportEntry(RuntimeTypeHandle_GetGenericTypeDefinition)
Expand Down Expand Up @@ -186,6 +188,7 @@ static const Entry s_QCall[] =
DllImportEntry(ModuleHandle_GetPEKind)
DllImportEntry(ModuleHandle_GetDynamicMethod)
DllImportEntry(AssemblyHandle_GetManifestModuleSlow)
DllImportEntry(Signature_AreEqual)
DllImportEntry(TypeBuilder_DefineGenericParam)
DllImportEntry(TypeBuilder_DefineType)
DllImportEntry(TypeBuilder_SetParentType)
Expand Down
Loading

0 comments on commit f9c86dc

Please sign in to comment.