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

Move all of generic virtual method resolution to the type loader #79925

Merged
merged 2 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -632,11 +632,6 @@ public static IntPtr ResolveDispatch(object instance, RuntimeTypeHandle interfac
return RuntimeImports.RhResolveDispatch(instance, CreateEETypePtr(interfaceType), checked((ushort)slot));
}

public static IntPtr GVMLookupForSlot(RuntimeTypeHandle type, RuntimeMethodHandle slot)
{
return GenericVirtualMethodSupport.GVMLookupForSlot(type, slot);
}

public static bool IsUnmanagedPointerType(RuntimeTypeHandle typeHandle)
{
return typeHandle.ToEETypePtr().IsPointer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public abstract class TypeLoaderCallbacks
public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs);
public abstract bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2);
public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle);
public abstract bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, bool lookForDefaultImplementations, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated);
public abstract IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod);
public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName);
public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName);
public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, out RuntimeTypeHandle pointerTypeHandle);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@
<Compile Include="Internal\Runtime\CompilerServices\FixupRuntimeTypeHandle.cs" />
<Compile Include="Internal\Runtime\CompilerServices\FunctionPointerOps.cs" />
<Compile Include="Internal\Runtime\CompilerServices\GenericMethodDescriptor.cs" />
<Compile Include="Internal\Runtime\CompilerServices\GenericVirtualMethodSupport.cs" />
<Compile Include="Internal\Runtime\CompilerServices\RuntimeFieldHandleInfo.cs" />
<Compile Include="Internal\Runtime\CompilerServices\RuntimeMethodHandleInfo.cs" />
<Compile Include="Internal\Runtime\CompilerServices\RuntimeSignature.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public static unsafe IntPtr GVMLookupForSlot(object obj, RuntimeMethodHandle slo
Entry entry = LookupInCache(s_cache, (IntPtr)obj.GetMethodTable(), *(IntPtr*)&slot);
entry ??= CacheMiss((IntPtr)obj.GetMethodTable(), *(IntPtr*)&slot,
(IntPtr context, IntPtr signature, object contextObject, ref IntPtr auxResult)
=> Internal.Runtime.CompilerServices.GenericVirtualMethodSupport.GVMLookupForSlot(new RuntimeTypeHandle(new EETypePtr(context)), *(RuntimeMethodHandle*)&signature));
=> RuntimeAugments.TypeLoaderCallbacks.ResolveGenericVirtualMethodTarget(new RuntimeTypeHandle(new EETypePtr(context)), *(RuntimeMethodHandle*)&signature));
return entry.Result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Internal.Runtime.TypeLoader
public sealed partial class TypeLoaderEnvironment
{
#if GVM_RESOLUTION_TRACE
private string GetTypeNameDebug(RuntimeTypeHandle rtth)
private static string GetTypeNameDebug(RuntimeTypeHandle rtth)
{
string result;

Expand All @@ -47,6 +47,86 @@ private string GetTypeNameDebug(RuntimeTypeHandle rtth)
}
#endif

private unsafe IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature)
{
bool slotChanged = false;

IntPtr resolution = IntPtr.Zero;
IntPtr functionPointer;
IntPtr genericDictionary;

bool lookForDefaultImplementations = false;

again:
// Walk parent hierarchy attempting to resolve
RuntimeTypeHandle currentType = type;

while (!currentType.IsNull())
{
string methodName = methodNameAndSignature.Name;
RuntimeSignature methodSignature = methodNameAndSignature.Signature;
if (TryGetGenericVirtualTargetForTypeAndSlot(currentType, ref declaringType, genericArguments, ref methodName, ref methodSignature, lookForDefaultImplementations, out functionPointer, out genericDictionary, out slotChanged))
{
methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);

if (!slotChanged)
resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary);
break;
}

bool success = RuntimeAugments.TryGetBaseType(currentType, out currentType);
Debug.Assert(success);
}

// If the current slot to examine has changed, restart the lookup.
// This happens when there is an interface call.
if (slotChanged)
{
return GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature);
}

if (resolution == IntPtr.Zero
&& !lookForDefaultImplementations
&& declaringType.IsInterface())
{
lookForDefaultImplementations = true;
goto again;
}

if (resolution == IntPtr.Zero)
{
var sb = new System.Text.StringBuilder();
sb.AppendLine("Generic virtual method pointer lookup failure.");
sb.AppendLine();
sb.AppendLine("Declaring type: " + RuntimeAugments.GetLastResortString(declaringType));
sb.AppendLine("Target type: " + RuntimeAugments.GetLastResortString(type));
sb.AppendLine("Method name: " + methodNameAndSignature.Name);
sb.AppendLine("Instantiation:");
for (int i = 0; i < genericArguments.Length; i++)
{
sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + RuntimeAugments.GetLastResortString(genericArguments[i]));
}

Environment.FailFast(sb.ToString());
}

return resolution;
}

internal unsafe IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle type, RuntimeMethodHandle slot)
{
RuntimeTypeHandle declaringTypeHandle;
MethodNameAndSignature nameAndSignature;
RuntimeTypeHandle[] genericMethodArgs;
if (!TryGetRuntimeMethodHandleComponents(slot, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs))
{
Debug.Assert(false);
return IntPtr.Zero;
}

return GVMLookupForSlotWorker(type, declaringTypeHandle, genericMethodArgs, nameAndSignature);
}

public bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, bool lookForDefaultImplementation, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated)
{
MethodNameAndSignature methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ public override IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtime
return TypeLoaderEnvironment.Instance.TryGetDefaultConstructorForType(runtimeTypeHandle);
}

public override bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, bool lookForDefaultImplementation, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated)
public override IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod)
{
return TypeLoaderEnvironment.Instance.TryGetGenericVirtualTargetForTypeAndSlot(targetHandle, ref declaringType, genericArguments, ref methodName, ref methodSignature, lookForDefaultImplementation, out methodPointer, out dictionaryPointer, out slotUpdated);
return TypeLoaderEnvironment.Instance.ResolveGenericVirtualMethodTarget(targetTypeHandle, declMethod);
}

public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName)
Expand Down