Skip to content
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 @@ -1450,15 +1450,26 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO

if (pResult->exactContextNeedsRuntimeLookup)
{
MethodDesc caller = HandleToObject(callerHandle);

pResult->codePointerOrStubLookup.lookupKind.needsRuntimeLookup = true;
pResult->codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER;
pResult->codePointerOrStubLookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE;
pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(caller);
object helperArg = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
ISymbolNode helper = GetGenericLookupHelper(pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind, ReadyToRunHelperId.MethodEntry, caller, helperArg);
pResult->codePointerOrStubLookup.runtimeLookup.helperEntryPoint = CreateConstLookupToSymbol(helper);

// If this is from a different context, abort. The ReadyToRun helper needs to declare
// its dependencies in terms of the dictionary it will be placed in, but the runtime
// determined method we computed is expressed in terms of the inlinee's generic context.
if (pResolvedToken.tokenContext != contextFromMethodBeingCompiled())
{
pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_NOT_SUPPORTED;
}
else
{
MethodDesc caller = HandleToObject(callerHandle);

pResult->codePointerOrStubLookup.runtimeLookup.indirections = CORINFO.USEHELPER;
pResult->codePointerOrStubLookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE;
pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(caller);
object helperArg = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
ISymbolNode helper = GetGenericLookupHelper(pResult->codePointerOrStubLookup.lookupKind.runtimeLookupKind, ReadyToRunHelperId.MethodEntry, caller, helperArg);
pResult->codePointerOrStubLookup.runtimeLookup.helperEntryPoint = CreateConstLookupToSymbol(helper);
}
}
else
{
Expand Down
28 changes: 28 additions & 0 deletions src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ internal static int Run()
TestGenericInliningTypeGenericsOnly.Run();
Test99198Regression.Run();
Test102259Regression.Run();
Test129093Regression.Run();
Test104913Regression.Run();
Test105397Regression.Run();
Test105880Regression.Run();
Expand Down Expand Up @@ -3790,6 +3791,33 @@ public static void Run()
}
}

class Test129093Regression
{
class Gen<T>
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static Type Method() => typeof(T);
}

// Inlineable generic method taking the address of a method that needs a generic context.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static unsafe nint GetPtr<U>() => (nint)(delegate*<Type>)&Gen<U>.Method;

class Caller<X>
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static nint Run() => GetPtr<X>();
}

public static unsafe void Run()
{
if (((delegate*<Type>)Caller<object>.Run())() != typeof(object))
throw new Exception();
if (((delegate*<Type>)Caller<string>.Run())() != typeof(string))
throw new Exception();
}
}

class Test104913Regression
{
interface IFoo
Expand Down