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