diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 7dc65dc4f5ad8c..14f0f9b6c1e33a 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -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 { diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs index 8eca170739f971..6febd238358128 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs @@ -64,6 +64,7 @@ internal static int Run() TestGenericInliningTypeGenericsOnly.Run(); Test99198Regression.Run(); Test102259Regression.Run(); + Test129093Regression.Run(); Test104913Regression.Run(); Test105397Regression.Run(); Test105880Regression.Run(); @@ -3790,6 +3791,33 @@ public static void Run() } } + class Test129093Regression + { + class Gen + { + [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() => (nint)(delegate*)&Gen.Method; + + class Caller + { + [MethodImpl(MethodImplOptions.NoInlining)] + public static nint Run() => GetPtr(); + } + + public static unsafe void Run() + { + if (((delegate*)Caller.Run())() != typeof(object)) + throw new Exception(); + if (((delegate*)Caller.Run())() != typeof(string)) + throw new Exception(); + } + } + class Test104913Regression { interface IFoo