From a828d07d35af4c8100bd55bb6fd56c36d8b03040 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Thu, 23 Oct 2025 15:11:38 -0700 Subject: [PATCH] Adjustment to get the compiler to finish the jitting Notably, I've tweak the cross module inlining feature to enable compilation of the tokens needed in these thunks. The tweak enables using these particular apis without enabling the cross module switch. It successfully finishes jitting a method. - This does not ... handle the dependency graph issues - I've noticed that we seem to make the thunks as temporary things, and assume they don't need process long lifetime. This is not likely to true, as they are actual useable symbols, so that needs to be fixed so that the various thunk methoddescs aren't treated as transient. (Anything which is a symbol or goes in the dependency graph needs to be non-transient, and able to be looked up later. Newing up a new instance is not a valid thing to do.) - We seem to have a concept of thunks and whatnot in the MethodDescs... I'm seeing us compile the original method... with the IL for a thunk, and then I'm seeing something try to add to the dependency graph a thunk which is supposed to have the calling convention of the method we just compiled, but is MethodDesc of type TaskReturnAsyncMethodDescThunk or something. --- .../Common/JitInterface/AsyncMethodDesc.cs | 1 + .../ReadyToRunCodegenNodeFactory.cs | 2 +- .../IL/ReadyToRunILProvider.cs | 192 ++++++++++++++---- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 18 +- .../TypeSystem/Mutable/MutableModule.cs | 3 +- 5 files changed, 169 insertions(+), 47 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/AsyncMethodDesc.cs b/src/coreclr/tools/Common/JitInterface/AsyncMethodDesc.cs index f5f1fb46aa2052..7c11ddc15453d1 100644 --- a/src/coreclr/tools/Common/JitInterface/AsyncMethodDesc.cs +++ b/src/coreclr/tools/Common/JitInterface/AsyncMethodDesc.cs @@ -10,6 +10,7 @@ namespace Internal.JitInterface /// /// Represents the async-callable (CORINFO_CALLCONV_ASYNCCALL) variant of a Task/ValueTask returning method. /// The wrapper should be short‑lived and only used while interacting with the JIT interface. + /// NOPE: These things aren't short lived in R2R scenarios. Please make a normal method, and give them normal, long lifetimes /// internal sealed class AsyncMethodDesc : MethodDelegator, IJitHashableOnly { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index e644439b2bec67..d186a901c8c6b4 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -708,8 +708,8 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph, I ManifestMetadataTable = new ManifestMetadataTableNode(this); Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable); Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex); - ((ReadyToRunILProvider)ilProvider).InitManifestMutableModule(ManifestMetadataTable._mutableModule); Resolver.InitManifestMutableModule(ManifestMetadataTable._mutableModule); + ((ReadyToRunILProvider)ilProvider).InitManifestMutableModule(ManifestMetadataTable._mutableModule, Resolver); ManifestAssemblyMvidHeaderNode mvidTableNode = new ManifestAssemblyMvidHeaderNode(ManifestMetadataTable); Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestAssemblyMvids, mvidTableNode, mvidTableNode); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs index 99a8a39ef7434c..0661c2f493c092 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs @@ -17,6 +17,7 @@ using Internal.JitInterface; using System.Text; using System.Text.Unicode; +using ILCompiler.DependencyAnalysis.ReadyToRun; namespace Internal.IL { @@ -37,9 +38,10 @@ public ReadyToRunILProvider(CompilationModuleGroup compilationModuleGroup) _compilationModuleGroup = compilationModuleGroup; } - public void InitManifestMutableModule(MutableModule module) + public void InitManifestMutableModule(MutableModule module, ModuleTokenResolver tokenResolver) { _manifestMutableModule = module; + EnsureR2RKnownMethodsAreInManifestModule(tokenResolver); } void IncrementVersion() @@ -213,6 +215,124 @@ public override MethodIL GetMethodIL(MethodDesc method) return null; } } + + public enum R2RKnownType + { + ExecutionAndSyncBlockStore, + SystemException, + } + + public enum R2RKnownMethod + { + ExecutionAndSyncBlockStore_Push, + ExecutionAndSyncBlockStore_Pop, + ValueTask_FromResult, + Task_FromResult, + ValueTask_get_CompletedTask, + Task_get_CompletedTask, + StubHelpers_AsyncCallContinuation, + AsyncHelpers_TaskFromException, + AsyncHelpers_ValueTaskFromException, + AsyncHelpers_TaskFromExceptionGeneric, + AsyncHelpers_ValueTaskFromExceptionGeneric, + AsyncHelpers_FinalizeTaskReturningThunk, + AsyncHelpers_FinalizeValueTaskReturningThunk, + AsyncHelpers_FinalizeTaskReturningThunkGeneric, + AsyncHelpers_FinalizeValueTaskReturningThunkGeneric, + } + + public MetadataType GetR2RKnownType(R2RKnownType knownType) + { + switch (knownType) + { + case R2RKnownType.ExecutionAndSyncBlockStore: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "ExecutionAndSyncBlockStore"u8); + case R2RKnownType.SystemException: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System"u8, "SystemException"u8); + default: + throw new InvalidOperationException($"Unknown R2R known type: {knownType}"); + } + } + + public MethodDesc GetR2RKnownMethod(R2RKnownMethod knownMethod) + { + TypeSystemContext context = _manifestMutableModule.Context; + switch (knownMethod) + { + case R2RKnownMethod.ExecutionAndSyncBlockStore_Push: + return GetR2RKnownType(R2RKnownType.ExecutionAndSyncBlockStore).GetKnownMethod("Push"u8, null); + case R2RKnownMethod.ExecutionAndSyncBlockStore_Pop: + return GetR2RKnownType(R2RKnownType.ExecutionAndSyncBlockStore).GetKnownMethod("Pop"u8, null); + case R2RKnownMethod.ValueTask_FromResult: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8).GetKnownMethod("FromResult"u8, null); + case R2RKnownMethod.Task_FromResult: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8).GetKnownMethod("FromResult"u8, null); + case R2RKnownMethod.ValueTask_get_CompletedTask: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8).GetKnownMethod("get_CompletedTask"u8, null); + case R2RKnownMethod.Task_get_CompletedTask: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8).GetKnownMethod("get_CompletedTask"u8, null); + case R2RKnownMethod.StubHelpers_AsyncCallContinuation: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.StubHelpers"u8, "StubHelpers"u8).GetKnownMethod("AsyncCallContinuation"u8, null); + case R2RKnownMethod.AsyncHelpers_TaskFromException: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("TaskFromException"u8, new MethodSignature(MethodSignatureFlags.Static, 0, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8), new TypeDesc[] { context.SystemModule.GetKnownType("System"u8, "Exception"u8) })); + case R2RKnownMethod.AsyncHelpers_ValueTaskFromException: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("ValueTaskFromException"u8, new MethodSignature(MethodSignatureFlags.Static, 0, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8), new TypeDesc[] { context.SystemModule.GetKnownType("System"u8, "Exception"u8) })); + case R2RKnownMethod.AsyncHelpers_TaskFromExceptionGeneric: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("TaskFromException"u8, new MethodSignature(MethodSignatureFlags.Static, 1, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task`1"u8).MakeInstantiatedType(context.GetSignatureVariable(0, method: true)), new TypeDesc[] { context.SystemModule.GetKnownType("System"u8, "Exception"u8) })); + case R2RKnownMethod.AsyncHelpers_ValueTaskFromExceptionGeneric: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("ValueTaskFromException"u8, new MethodSignature(MethodSignatureFlags.Static, 1, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask`1"u8).MakeInstantiatedType(context.GetSignatureVariable(0, method: true)), new TypeDesc[] { context.SystemModule.GetKnownType("System"u8, "Exception"u8) })); + case R2RKnownMethod.AsyncHelpers_FinalizeTaskReturningThunk: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("FinalizeTaskReturningThunk"u8, new MethodSignature(MethodSignatureFlags.Static, 0, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8), Array.Empty())); + case R2RKnownMethod.AsyncHelpers_FinalizeValueTaskReturningThunk: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("FinalizeValueTaskReturningThunk"u8, new MethodSignature(MethodSignatureFlags.Static, 0, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8), Array.Empty())); + case R2RKnownMethod.AsyncHelpers_FinalizeTaskReturningThunkGeneric: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("FinalizeTaskReturningThunk"u8, new MethodSignature(MethodSignatureFlags.Static, 1, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task`1"u8).MakeInstantiatedType(context.GetSignatureVariable(0, method: true)), Array.Empty())); + case R2RKnownMethod.AsyncHelpers_FinalizeValueTaskReturningThunkGeneric: + return _manifestMutableModule.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8).GetKnownMethod("FinalizeValueTaskReturningThunk"u8, new MethodSignature(MethodSignatureFlags.Static, 1, context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask`1"u8).MakeInstantiatedType(context.GetSignatureVariable(0, method: true)), Array.Empty())); + + default: + throw new InvalidOperationException($"Unknown R2R known method: {knownMethod}"); + } + } + + public void EnsureR2RKnownMethodsAreInManifestModule(ModuleTokenResolver tokenResolver) + { + try + { + Debug.Assert(_manifestMutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences == null); + _manifestMutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences = _manifestMutableModule.Context.SystemModule; + _manifestMutableModule.AddingReferencesToR2RKnownTypesAndMethods = true; + + // Force all known R2R methods to be present in the manifest module + foreach (R2RKnownMethod knownMethod in Enum.GetValues(typeof(R2RKnownMethod))) + { + MethodDesc method = GetR2RKnownMethod(knownMethod); + if (!_compilationModuleGroup.VersionsWithMethodBody(method)) + { + tokenResolver.AddModuleTokenForMethod(method, new ModuleToken(_manifestMutableModule, _manifestMutableModule.TryGetEntityHandle(method).Value)); + + // This is effectively an assert + tokenResolver.GetModuleTokenForMethod(method, allowDynamicallyCreatedReference: true, throwIfNotFound: true); + } + } + // Force all known R2R types to be present in the manifest module + foreach (R2RKnownType knownType in Enum.GetValues(typeof(R2RKnownType))) + { + TypeDesc type = GetR2RKnownType(knownType); + if (!_compilationModuleGroup.VersionsWithType(type)) + { + tokenResolver.AddModuleTokenForType((EcmaType)type, new ModuleToken(_manifestMutableModule, _manifestMutableModule.TryGetEntityHandle(type).Value)); + tokenResolver.GetModuleTokenForType((EcmaType)type, allowDynamicallyCreatedReference: true, throwIfNotFound: true); + } + } + } + finally + { + _manifestMutableModule.AddingReferencesToR2RKnownTypesAndMethods = false; + _manifestMutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences = null; + } + } + // Emits roughly the following code: // // ExecutionAndSyncBlockStore store = default; @@ -251,7 +371,7 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) logicalResultType = retType.Instantiation[0]; logicalResultLocal = ilEmitter.NewLocal(logicalResultType); } - var executionAndSyncBlockStoreType = method.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "ExecutionAndSyncBlockStore"u8); + var executionAndSyncBlockStoreType = GetR2RKnownType(R2RKnownType.ExecutionAndSyncBlockStore); var executionAndSyncBlockStoreLocal = ilEmitter.NewLocal(executionAndSyncBlockStoreType); ILCodeLabel returnTaskLabel = ilEmitter.NewCodeLabel(); @@ -260,10 +380,10 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) // store.Push() il.EmitLdLoca(executionAndSyncBlockStoreLocal); - il.Emit(ILOpcode.call, ilEmitter.NewToken(executionAndSyncBlockStoreType.GetKnownMethod("Push"u8, null))); + il.Emit(ILOpcode.call, ilEmitter.NewToken(GetR2RKnownMethod(R2RKnownMethod.ExecutionAndSyncBlockStore_Push))); // Inner try block must appear first in metadata - var exceptionType = ilEmitter.NewToken(method.Context.GetWellKnownType(WellKnownType.Exception)); + var exceptionType = ilEmitter.NewToken(GetR2RKnownType(R2RKnownType.SystemException)); ILExceptionRegionBuilder innerTryRegion = ilEmitter.NewCatchRegion(exceptionType); // Outer try block ILExceptionRegionBuilder outerTryRegion = ilEmitter.NewFinallyRegion(); @@ -292,9 +412,7 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) il.EmitStLoc(logicalResultLocal); } - il.Emit(ILOpcode.call, ilEmitter.NewToken( - method.Context.SystemModule.GetKnownType("System.StubHelpers"u8, "StubHelpers"u8) - .GetKnownMethod("AsyncCallContinuation"u8, null))); + il.Emit(ILOpcode.call, ilEmitter.NewToken(GetR2RKnownMethod(R2RKnownMethod.StubHelpers_AsyncCallContinuation))); il.Emit(ILOpcode.brfalse, finishedLabel); il.Emit(ILOpcode.leave, suspendedLabel); @@ -303,19 +421,8 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) if (logicalResultLocal != default) { il.EmitLdLoc(logicalResultLocal); - MethodDesc fromResultMethod; - if (isValueTask) - { - fromResultMethod = method.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) - .GetKnownMethod("FromResult"u8, null) - .MakeInstantiatedMethod(logicalResultType); - } - else - { - fromResultMethod = method.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8) - .GetKnownMethod("FromResult"u8, null) - .MakeInstantiatedMethod(logicalResultType); - } + R2RKnownMethod fromResultValue = isValueTask ? R2RKnownMethod.ValueTask_FromResult : R2RKnownMethod.Task_FromResult; + MethodDesc fromResultMethod = GetR2RKnownMethod(fromResultValue).MakeInstantiatedMethod(logicalResultType); il.Emit(ILOpcode.call, ilEmitter.NewToken(fromResultMethod)); } else @@ -323,13 +430,11 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) MethodDesc completedTaskGetter; if (isValueTask) { - completedTaskGetter = method.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) - .GetKnownMethod("get_CompletedTask"u8, null); + completedTaskGetter = GetR2RKnownMethod(R2RKnownMethod.ValueTask_get_CompletedTask); } else { - completedTaskGetter = method.Context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8) - .GetKnownMethod("get_CompletedTask"u8, null); + completedTaskGetter = GetR2RKnownMethod(R2RKnownMethod.Task_get_CompletedTask); } il.Emit(ILOpcode.call, ilEmitter.NewToken(completedTaskGetter)); } @@ -341,15 +446,20 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) il.BeginHandler(innerTryRegion); MethodDesc fromExceptionMethod; - TypeDesc asyncHelpers = method.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8); + R2RKnownMethod fromExceptionKnownMethod; if (isValueTask) { - fromExceptionMethod = GetMethod(asyncHelpers, "ValueTaskFromException"u8, generic: logicalResultLocal != default); + fromExceptionKnownMethod = logicalResultLocal != default ? + R2RKnownMethod.AsyncHelpers_ValueTaskFromExceptionGeneric : + R2RKnownMethod.AsyncHelpers_ValueTaskFromException; } else { - fromExceptionMethod = GetMethod(asyncHelpers, "TaskFromException"u8, generic: logicalResultLocal != default); + fromExceptionKnownMethod = logicalResultLocal != default ? + R2RKnownMethod.AsyncHelpers_TaskFromExceptionGeneric : + R2RKnownMethod.AsyncHelpers_TaskFromException; } + fromExceptionMethod = GetR2RKnownMethod(fromExceptionKnownMethod); if (logicalResultLocal != default) { fromExceptionMethod = fromExceptionMethod.MakeInstantiatedMethod(logicalResultType); @@ -364,14 +474,22 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) il.EmitLabel(suspendedLabel); MethodDesc finalizeMethod; + R2RKnownMethod finalizeKnownMethod; if (isValueTask) { - finalizeMethod = GetMethod(asyncHelpers, "FinalizeValueTaskReturningThunk"u8, generic: logicalResultType != default); + finalizeKnownMethod = logicalResultLocal != default ? + R2RKnownMethod.AsyncHelpers_FinalizeValueTaskReturningThunkGeneric : + R2RKnownMethod.AsyncHelpers_FinalizeValueTaskReturningThunk; } else { - finalizeMethod = GetMethod(asyncHelpers, "FinalizeTaskReturningThunk"u8, generic: logicalResultType != default); + finalizeKnownMethod = logicalResultLocal != default ? + R2RKnownMethod.AsyncHelpers_FinalizeTaskReturningThunkGeneric : + R2RKnownMethod.AsyncHelpers_FinalizeTaskReturningThunk; } + + finalizeMethod = GetR2RKnownMethod(finalizeKnownMethod); + if (logicalResultLocal != default) { finalizeMethod = finalizeMethod.MakeInstantiatedMethod(logicalResultType); @@ -386,7 +504,7 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) // Finally block il.BeginHandler(outerTryRegion); il.EmitLdLoca(executionAndSyncBlockStoreLocal); - il.Emit(ILOpcode.call, ilEmitter.NewToken(executionAndSyncBlockStoreType.GetKnownMethod("Pop"u8, null))); + il.Emit(ILOpcode.call, ilEmitter.NewToken(GetR2RKnownMethod(R2RKnownMethod.ExecutionAndSyncBlockStore_Pop))); il.Emit(ILOpcode.endfinally); il.EndHandler(outerTryRegion); @@ -396,18 +514,6 @@ private MethodIL TryGetTaskReturningAsyncWrapperThunkIL(MethodDesc method) il.Emit(ILOpcode.ret); return ilEmitter.Link(method); - - static MethodDesc GetMethod(TypeDesc type, ReadOnlySpan name, bool generic) - { - foreach (var m in type.GetMethods()) - { - if (m.Name.SequenceEqual(name) && m.HasInstantiation == generic) - { - return m; - } - } - throw new InvalidOperationException($"Cannot find method '{UTF8Encoding.UTF8.GetString(name)}' on {type.GetDisplayName()} {(generic ? "with" : "without")} a generic parameter"); - } } /// @@ -486,7 +592,7 @@ int GetMutableModuleToken(int token) } if (!newToken.HasValue) { - // Toekn replacement has failed. Do not attempt to use this IL. + // Token replacement has failed. Do not attempt to use this IL. failedToReplaceToken = true; return 1; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 7c06e8d84f10f5..176a57d847205b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -1410,8 +1410,17 @@ private ModuleToken HandleToModuleToken(ref CORINFO_RESOLVED_TOKEN pResolvedToke // using instantiation parameters from the MethodDesc entity. resultMethod = resultMethod.GetTypicalMethodDefinition(); + if (resultMethod is AsyncMethodDesc asyncMethodDescMethod) + { + resultMethod = asyncMethodDescMethod.Target; + } Debug.Assert(resultMethod is EcmaMethod); - Debug.Assert(_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(((EcmaMethod)resultMethod).OwningType)); + if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(((EcmaMethod)resultMethod).OwningType)) + { + // TODO Add assert that the method is one of the R2RKnownMethods + ModuleToken result = _compilation.NodeFactory.SignatureContext.Resolver.GetModuleTokenForMethod(resultMethod, allowDynamicallyCreatedReference: true, throwIfNotFound: true); + return result; + } token = (mdToken)MetadataTokens.GetToken(((EcmaMethod)resultMethod).Handle); module = ((EcmaMethod)resultMethod).Module; } @@ -1431,7 +1440,12 @@ private ModuleToken HandleToModuleToken(ref CORINFO_RESOLVED_TOKEN pResolvedToke { if (resultDef is EcmaType ecmaType) { - Debug.Assert(_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(ecmaType)); + if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(ecmaType)) + { + // TODO Add assert that the method is one of the R2RKnownTypes + ModuleToken result = _compilation.NodeFactory.SignatureContext.Resolver.GetModuleTokenForType(ecmaType, allowDynamicallyCreatedReference: true, throwIfNotFound: true); + return result; + } token = (mdToken)MetadataTokens.GetToken(ecmaType.Handle); module = ecmaType.Module; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/TypeSystem/Mutable/MutableModule.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/TypeSystem/Mutable/MutableModule.cs index 79c0853b0d817e..cf743fa703cf87 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/TypeSystem/Mutable/MutableModule.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/TypeSystem/Mutable/MutableModule.cs @@ -39,7 +39,7 @@ protected override EntityHandle GetNonNestedResolutionScope(MetadataType metadat if (!_mutableModule._moduleToModuleRefString.TryGetValue(module, out moduleRefString)) { Debug.Assert(_mutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences != null && - _mutableModule._compilationGroup.CrossModuleInlineableModule(_mutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences)); + _mutableModule._compilationGroup.CrossModuleInlineableModule(_mutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences) || _mutableModule.AddingReferencesToR2RKnownTypesAndMethods); if (module == _typeSystemContext.SystemModule) { @@ -303,6 +303,7 @@ class DisableNewTokensException : Exception { } public bool DisableNewTokens; public ModuleDesc ModuleThatIsCurrentlyTheSourceOfNewReferences; + public bool AddingReferencesToR2RKnownTypesAndMethods; private ReadyToRunCompilationModuleGroupBase _compilationGroup; private Dictionary _moduleToModuleRefString = new Dictionary();