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();