diff --git a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs index 53111252b0a235..9930fd679920b4 100644 --- a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs +++ b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs @@ -200,6 +200,45 @@ protected override bool CompareValueToValue(AsyncMethodVariant value1, AsyncMeth } private AsyncVariantHashtable _asyncVariantHashtable = new AsyncVariantHashtable(); + public AsyncResumptionStub GetAsyncResumptionStub(MethodDesc targetMethod, TypeDesc owningType) + { + return _asyncResumptionStubHashtable.GetOrCreateValue(new AsyncResumptionStubKey(targetMethod, owningType)); + } + + private readonly struct AsyncResumptionStubKey : System.IEquatable + { + public readonly MethodDesc TargetMethod; + public readonly TypeDesc OwningType; + + public AsyncResumptionStubKey(MethodDesc targetMethod, TypeDesc owningType) + { + TargetMethod = targetMethod; + OwningType = owningType; + } + + public bool Equals(AsyncResumptionStubKey other) + => TargetMethod == other.TargetMethod; + + public override bool Equals(object obj) + => obj is AsyncResumptionStubKey other && Equals(other); + + public override int GetHashCode() + => TargetMethod.GetHashCode(); + } + + private sealed class AsyncResumptionStubHashtable : LockFreeReaderHashtable + { + protected override int GetKeyHashCode(AsyncResumptionStubKey key) => key.GetHashCode(); + protected override int GetValueHashCode(AsyncResumptionStub value) => value.TargetMethod.GetHashCode(); + protected override bool CompareKeyToValue(AsyncResumptionStubKey key, AsyncResumptionStub value) + => key.TargetMethod == value.TargetMethod; + protected override bool CompareValueToValue(AsyncResumptionStub value1, AsyncResumptionStub value2) + => value1.TargetMethod == value2.TargetMethod; + protected override AsyncResumptionStub CreateValueFromKey(AsyncResumptionStubKey key) + => new AsyncResumptionStub(key.TargetMethod, key.OwningType); + } + private AsyncResumptionStubHashtable _asyncResumptionStubHashtable = new AsyncResumptionStubHashtable(); + public MetadataType GetContinuationType(GCPointerMap pointerMap) { return _continuationTypeHashtable.GetOrCreateValue(pointerMap); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index a8d0f13e5cde23..b4fde174ed8f6d 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -703,7 +703,6 @@ private void CompileMethodCleanup() #if !READYTORUN _debugInfo = null; #endif - _asyncResumptionStub = null; _debugLocInfos = null; _debugVarInfos = null; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index a67e3048ce7cdf..a4ac471ef55321 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -460,7 +460,7 @@ private void ImportCall(ILOpcode opcode, int token) const string asyncReason = "Async state machine"; - var resumptionStub = new AsyncResumptionStub(_canonMethod, _compilation.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType()); + AsyncResumptionStub resumptionStub = _compilation.TypeSystemContext.GetAsyncResumptionStub(_canonMethod, _compilation.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType()); _dependencies.Add(_compilation.NodeFactory.MethodEntrypoint(resumptionStub), asyncReason); _dependencies.Add(_factory.ConstructedTypeSymbol(_compilation.TypeSystemContext.ContinuationType), asyncReason); 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 58fd3d387ba99a..cb670ba2db0cbe 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -477,8 +477,6 @@ unsafe partial class CorInfoImpl private List _ilBodiesNeeded; private Dictionary _preInitedTypes = new Dictionary(); private HashSet _synthesizedPgoDependencies; - private MethodDesc _asyncResumptionStub; - public bool HasColdCode { get; private set; } public CorInfoImpl(ReadyToRunCodegenCompilation compilation) @@ -500,14 +498,11 @@ private void AddResumptionStubFixup(MethodWithGCInfo compiledStubNode) private CORINFO_METHOD_STRUCT_* getAsyncResumptionStub(ref void* entryPoint) { - if (_asyncResumptionStub is null) - { - _asyncResumptionStub = new AsyncResumptionStub(MethodBeingCompiled, MethodBeingCompiled.OwningType); - AddResumptionStubFixup(_compilation.NodeFactory.CompiledMethodNode(_asyncResumptionStub)); - } + MethodDesc asyncResumptionStub = _compilation.TypeSystemContext.GetAsyncResumptionStub(MethodBeingCompiled, MethodBeingCompiled.OwningType); + AddResumptionStubFixup(_compilation.NodeFactory.CompiledMethodNode(asyncResumptionStub)); - entryPoint = (void*)ObjectToHandle(_compilation.NodeFactory.CompiledMethodNode(_asyncResumptionStub)); - return ObjectToHandle(_asyncResumptionStub); + entryPoint = (void*)ObjectToHandle(_compilation.NodeFactory.CompiledMethodNode(asyncResumptionStub)); + return ObjectToHandle(asyncResumptionStub); } private static mdToken FindGenericMethodArgTypeSpec(EcmaModule module) 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 cb3964df10c304..141ca0c60720b6 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -34,7 +34,6 @@ internal unsafe partial class CorInfoImpl private RyuJitCompilation _compilation; private MethodDebugInformation _debugInfo; - private MethodDesc _asyncResumptionStub; private MethodCodeNode _methodCodeNode; private DebugLocInfo[] _debugLocInfos; private DebugVarInfo[] _debugVarInfos; @@ -57,10 +56,10 @@ private UnboxingMethodDesc getUnboxingThunk(MethodDesc method) private CORINFO_METHOD_STRUCT_* getAsyncResumptionStub(ref void* entryPoint) { - _asyncResumptionStub ??= new AsyncResumptionStub(MethodBeingCompiled, _compilation.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType()); + MethodDesc asyncResumptionStub = _compilation.TypeSystemContext.GetAsyncResumptionStub(MethodBeingCompiled, _compilation.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType()); - entryPoint = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(_asyncResumptionStub)); - return ObjectToHandle(_asyncResumptionStub); + entryPoint = (void*)ObjectToHandle(_compilation.NodeFactory.MethodEntrypoint(asyncResumptionStub)); + return ObjectToHandle(asyncResumptionStub); } public void CompileMethod(MethodCodeNode methodCodeNodeNeedingCode, MethodIL methodIL = null)