Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
db314fe
Passing async tests
jtschuster Feb 5, 2026
fcf110f
Undo extra changes
jtschuster Feb 5, 2026
e1dec2b
Fix merge issues
jtschuster Feb 5, 2026
696b6b6
Cleanup ManifestModuleWrappedIL creation
jtschuster Feb 6, 2026
d0a228c
Use correct OwningMethod for ManifestMetadataModuleWrappedMethodIL.In…
jtschuster Feb 6, 2026
dea51a8
Merge branch 'main' of https://github.com/dotnet/runtime into runtime16
jtschuster Feb 6, 2026
d37bfc8
Undo formatting in CorInfoImpl.ReadyToRun.cs
jtschuster Feb 6, 2026
af114a0
Remove duplicated method from merge, remove unnecessary token manipul…
jtschuster Feb 6, 2026
bf8f402
Merge branch 'main' of https://github.com/dotnet/runtime into runtime16
jtschuster Feb 6, 2026
435c5d9
Remove duplicates from merge
jtschuster Feb 6, 2026
8465ceb
Use the same version resilient hash code for resumption stub and asyn…
jtschuster Feb 8, 2026
49101ed
Generalize CreateR2RBackedILStub
jtschuster Feb 9, 2026
5bcb9b5
Allow async methods without resumption stubs
jtschuster Feb 9, 2026
17e3358
Allow using code for methods without resumption stubs in the r2r image
jtschuster Feb 9, 2026
c66218c
Enable RuntimeAsync library tests
jtschuster Feb 9, 2026
14973b0
Merge branch 'main' of https://github.com/dotnet/runtime into runtime16
jtschuster Feb 9, 2026
18754ac
Apply suggestions from code review
jtschuster Feb 9, 2026
4dfdfe2
Clean up extraneous changes and fix build
jtschuster Feb 9, 2026
a887cf6
Merge branch 'runtime16' of https://github.com/jtschuster/runtime int…
jtschuster Feb 9, 2026
7f36d5a
Don't use async method code if we can't find resumption stub
jtschuster Feb 10, 2026
5e4a0cd
Merge branch 'main' of https://github.com/dotnet/runtime into runtime16
jtschuster Feb 12, 2026
5c37396
Fix merge issues
jtschuster Feb 12, 2026
d9af071
Add label for resume stub code in r2rdump
jtschuster Feb 12, 2026
d0ff7c1
Don't emit async thunks - there are some issues to sort out
jtschuster Feb 12, 2026
c1ecd59
SetIsAsyncCall even if method is dispatch cell in ComputeCallRefMap
jtschuster Feb 12, 2026
b7604a8
Remove PInvokeTargetNativeMethod from GetPrimaryMethodDesc
jtschuster Feb 12, 2026
5c9cd91
Fix build error
jtschuster Feb 12, 2026
4fe194e
Merge branch 'runtime16' of https://github.com/jtschuster/runtime; br…
jtschuster Feb 18, 2026
1ea81c8
Remove extra GetTypicalMethodDefinition()
jtschuster Feb 18, 2026
eb88cc5
Clean up crossgen changes
jtschuster Feb 18, 2026
4df231a
Refactor ResumptionStub resolution
jtschuster Feb 19, 2026
61f77a1
Remove unused method, move definition of GetEntrypoint
jtschuster Feb 19, 2026
821188c
Remove unused method, move GetEntryPoint declaration, undo extra changes
jtschuster Feb 19, 2026
076b1a6
Merge branch 'runtime16' of https://github.com/jtschuster/runtime int…
jtschuster Feb 19, 2026
1770954
Use AsyncMethodVariant.Target, not GetTargetOfAsyncMethod()
jtschuster Feb 19, 2026
0487f2c
Rename IsAsyncThunk
jtschuster Feb 19, 2026
cc6c6be
Fix bug in SigMatchesMethodDesc
jtschuster Feb 19, 2026
7115923
Don't skip AsyncResumptionStubs in ExceptionInfoLookupTableNode
jtschuster Feb 19, 2026
1770f85
Make resumption stub signature buffer const
jtschuster Feb 19, 2026
e497dd6
Re-add PInvoke unwrapping to GetPrimaryMethodDesc()
jtschuster Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/inc/corcompile.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ enum EncodeMethodSigFlags
ENCODE_METHOD_SIG_OwnerType = 0x40,
ENCODE_METHOD_SIG_UpdateContext = 0x80,
ENCODE_METHOD_SIG_AsyncVariant = 0x100,
ENCODE_METHOD_SIG_ResumptionStub = 0x200,
};

enum EncodeFieldSigFlags
Expand Down
7 changes: 4 additions & 3 deletions src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,10 @@ enum ReadyToRunHelper

READYTORUN_HELPER_GetCurrentManagedThreadId = 0x112,

READYTORUN_HELPER_AllocContinuation = 0x113,
READYTORUN_HELPER_AllocContinuationClass = 0x114,
READYTORUN_HELPER_AllocContinuationMethod = 0x115,
// Async continuation helpers
READYTORUN_HELPER_AllocContinuation = 0x113,
READYTORUN_HELPER_AllocContinuationClass = 0x114,
READYTORUN_HELPER_AllocContinuationMethod = 0x115,
};

#include "readytoruninstructionset.h"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/inc/readytorunhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ HELPER(READYTORUN_HELPER_RngChkFail, CORINFO_HELP_RNGCHKFAIL,
HELPER(READYTORUN_HELPER_FailFast, CORINFO_HELP_FAIL_FAST, OPTIMIZEFORSIZE)
HELPER(READYTORUN_HELPER_ThrowNullRef, CORINFO_HELP_THROWNULLREF, OPTIMIZEFORSIZE)
HELPER(READYTORUN_HELPER_ThrowDivZero, CORINFO_HELP_THROWDIVZERO, OPTIMIZEFORSIZE)
HELPER(READYTORUN_HELPER_ThrowExact, CORINFO_HELP_THROWEXACT, OPTIMIZEFORSIZE)

HELPER(READYTORUN_HELPER_WriteBarrier, CORINFO_HELP_ASSIGN_REF, )
HELPER(READYTORUN_HELPER_CheckedWriteBarrier, CORINFO_HELP_CHECKED_ASSIGN_REF, )
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/tools/Common/Compiler/AsyncMethodVariant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ public static bool IsAsyncVariant(this MethodDesc method)
return method.GetTypicalMethodDefinition() is AsyncMethodVariant;
}

public static bool IsAsyncThunk(this MethodDesc method)
public static bool IsCompilerGeneratedILBodyForAsync(this MethodDesc method)
{
return method.IsAsyncVariant() ^ method.IsAsync;
return (method.IsAsyncVariant() ^ method.IsAsync) || method is AsyncResumptionStub;
}

public static MethodDesc GetAsyncVariant(this MethodDesc method)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ protected override bool CompareValueToValue(AsyncMethodVariant value1, AsyncMeth
public MetadataType GetContinuationType(GCPointerMap pointerMap)
{
var cont = _continuationTypeHashtable.GetOrCreateValue(pointerMap);
_validTypes.TryAdd(cont);
return cont;
Comment on lines 205 to 207
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var cont = _continuationTypeHashtable.GetOrCreateValue(pointerMap);
_validTypes.TryAdd(cont);
return cont;
return _continuationTypeHashtable.GetOrCreateValue(pointerMap);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public enum ReadyToRunMethodSigFlags : uint
READYTORUN_METHOD_SIG_OwnerType = 0x40,
READYTORUN_METHOD_SIG_UpdateContext = 0x80,
READYTORUN_METHOD_SIG_AsyncVariant = 0x100,
READYTORUN_METHOD_SIG_ResumptionStub = 0x200,
}

[Flags]
Expand Down
13 changes: 10 additions & 3 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using ILCompiler.DependencyAnalysis;

#if READYTORUN
using ILCompiler.ReadyToRun.TypeSystem;
using System.Reflection.Metadata.Ecma335;
using ILCompiler.DependencyAnalysis.ReadyToRun;
#endif
Expand Down Expand Up @@ -120,7 +121,7 @@ public LikelyClassMethodRecord(IntPtr handle, uint likelihood)
private static extern uint getLikelyClasses(LikelyClassMethodRecord* pLikelyClasses, uint maxLikelyClasses, PgoInstrumentationSchema* schema, uint countSchemaItems, byte*pInstrumentationData, int ilOffset);

[DllImport(JitLibrary)]
private static extern uint getLikelyMethods(LikelyClassMethodRecord* pLikelyMethods, uint maxLikelyMethods, PgoInstrumentationSchema* schema, uint countSchemaItems, byte*pInstrumentationData, int ilOffset);
private static extern uint getLikelyMethods(LikelyClassMethodRecord* pLikelyMethods, uint maxLikelyMethods, PgoInstrumentationSchema* schema, uint countSchemaItems, byte* pInstrumentationData, int ilOffset);

[DllImport(JitSupportLibrary)]
private static extern IntPtr GetJitHost(IntPtr configProvider);
Expand Down Expand Up @@ -1384,8 +1385,10 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info)
// a safe condition, and we could delete this assert. This assert exists in order to help identify
// cases where the virtual function resolution algorithm either does not function, or is not used
// correctly.
// TODO: Async variant devirtualization algorithm
#if DEBUG
if (info->detail == CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_UNKNOWN)
if (info->detail == CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_UNKNOWN
&& !decl.IsAsyncVariant())
{
Console.Error.WriteLine($"Failed devirtualization with unexpected unknown failure while compiling {MethodBeingCompiled} with decl {decl} targeting type {objType}");
Debug.Assert(info->detail != CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_UNKNOWN);
Expand Down Expand Up @@ -3865,7 +3868,11 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI
#pragma warning restore CA1822 // Mark members as static
{
#if READYTORUN
throw new NotImplementedException("Crossgen2 does not support runtime-async yet");
var resumptionStub = new AsyncResumptionStub(MethodBeingCompiled, MethodBeingCompiled.OwningType);

// CompiledMethodNode instead of MethodEntrypoint for the pointer to the code instead of a fixup
entryPoint = (void*)ObjectToHandle(_compilation.NodeFactory.CompiledMethodNode(resumptionStub));
return ObjectToHandle(resumptionStub);
#else
_asyncResumptionStub ??= new AsyncResumptionStub(MethodBeingCompiled, _compilation.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public InstantiatedMethodIL(MethodDesc owningMethod, MethodIL methodIL)
{
Debug.Assert(methodIL.GetMethodILDefinition() == methodIL);
Debug.Assert(owningMethod.HasInstantiation || owningMethod.OwningType.HasInstantiation);
Debug.Assert(owningMethod.GetTypicalMethodDefinition() == methodIL.OwningMethod);

_methodIL = methodIL;
_method = owningMethod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;

using Internal.IL;
using Internal.IL.Stubs;
using Internal.TypeSystem;
Expand All @@ -26,7 +25,7 @@ public AsyncResumptionStub(MethodDesc targetMethod, TypeDesc owningType)
}

public override ReadOnlySpan<byte> Name => _targetMethod.Name;
public override string DiagnosticName => _targetMethod.DiagnosticName;
public override string DiagnosticName => "RESUME_" + _targetMethod.DiagnosticName;

public override TypeDesc OwningType => _owningType;

Expand All @@ -36,6 +35,12 @@ public AsyncResumptionStub(MethodDesc targetMethod, TypeDesc owningType)

public MethodDesc TargetMethod => _targetMethod;

/// <summary>
/// The hash of the async variant method is used at runtime to find the bucket of the resumption stub.
/// These should be identical for the async variant and the resumption stub.
/// </summary>
protected override int ComputeHashCode() => _targetMethod.GetHashCode();

private MethodSignature InitializeSignature()
{
TypeDesc objectType = Context.GetWellKnownType(WellKnownType.Object);
Expand Down Expand Up @@ -109,6 +114,7 @@ public override MethodIL EmitIL()
}
ilStream.EmitLdLoc(newContinuationLocal);
ilStream.Emit(ILOpcode.ret);
ilEmitter.SetHasGeneratedTokens();

return ilEmitter.Link(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override MethodStackTraceVisibilityFlags GetMethodVisibility(MethodDesc m
if (method.HasCustomAttribute("System.Diagnostics", "StackTraceHiddenAttribute")
|| (method.OwningType is MetadataType mdType && mdType.HasCustomAttribute("System.Diagnostics", "StackTraceHiddenAttribute"))
|| (method is Internal.IL.Stubs.ILStubMethod)
|| method.IsAsyncThunk()) // see MethodDesc::IsDiagnosticsHidden() in src/coreclr/vm/method.inl
|| method.IsCompilerGeneratedILBodyForAsync()) // see MethodDesc::IsDiagnosticsHidden() in src/coreclr/vm/method.inl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep IsAsyncThunk around and use IsCompilerGeneratedILBodyForAsync only where it makes sense.

I think IsAsyncThunk makes more sense here and it works fine here.

{
result |= MethodStackTraceVisibilityFlags.IsHidden;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata.Ecma335;

using ILCompiler.ReadyToRun.TypeSystem;
using Internal;
using Internal.NativeFormat;
using Internal.ReadyToRunConstants;
Expand Down Expand Up @@ -67,8 +67,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
foreach (MethodWithGCInfo methodNode in factory.EnumerateCompiledMethods(_module, CompiledMethodCategory.All))
{
MethodDesc[] inlinees = methodNode.InlinedMethods;
if (inlinees.Length == 0)
{
continue;
}
MethodDesc inliner = methodNode.Method;
EcmaMethod inlinerDefinition = (EcmaMethod)inliner.GetTypicalMethodDefinition();
if (inliner.IsCompilerGeneratedILBodyForAsync())
{
// Async thunks are generated by crossgen and diagnostic tools don't need to worry about them
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diagnostic tools do need to worry about async thunks, e.g. debugger needs to worry about them for stepping.

This comment should be more accurate. It should explain why we are not tracking methods inlined into async thunks.

continue;
}
EcmaMethod inlinerDefinition = (EcmaMethod)inliner.GetPrimaryMethodDesc().GetTypicalMethodDefinition();

if (inlinerDefinition.IsNonVersionable())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.IO;
using System.Linq;
using System.Reflection.Metadata.Ecma335;

using ILCompiler.ReadyToRun.TypeSystem;
using Internal;
using Internal.JitInterface;
using Internal.NativeFormat;
Expand Down Expand Up @@ -53,7 +53,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde

public static byte[] BuildSignatureForMethodDefinedInModule(MethodDesc method, NodeFactory factory)
{
EcmaMethod typicalMethod = (EcmaMethod)method.GetTypicalMethodDefinition();
EcmaMethod typicalMethod = (EcmaMethod)method.GetPrimaryMethodDesc().GetTypicalMethodDefinition();

ModuleToken moduleToken;
if (factory.CompilationModuleGroup.VersionsWithMethodBody(typicalMethod))
Expand All @@ -63,7 +63,7 @@ public static byte[] BuildSignatureForMethodDefinedInModule(MethodDesc method, N
else
{
MutableModule manifestMetadata = factory.ManifestMetadataTable._mutableModule;
var handle = manifestMetadata.TryGetExistingEntityHandle(method.GetTypicalMethodDefinition());
var handle = manifestMetadata.TryGetExistingEntityHandle(typicalMethod);
Debug.Assert(handle.HasValue);
moduleToken = new ModuleToken(factory.ManifestMetadataTable._mutableModule, handle.Value);
}
Expand Down Expand Up @@ -102,7 +102,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods(null, CompiledMethodCategory.Instantiated))
{
Debug.Assert(method.Method.HasInstantiation || method.Method.OwningType.HasInstantiation);
Debug.Assert(method.Method.HasInstantiation || method.Method.OwningType.HasInstantiation || method.Method.IsAsyncVariant() || method.Method is AsyncResumptionStub);

int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

MethodWithToken method = _method;

if (factory.CompilationModuleGroup.VersionsWithMethodBody(method.Method) && !method.Method.IsAsyncVariant())
// If the method can be uniquely identified by a single token in the version bubble, use that instead of the full MethodSpec.
if (factory.CompilationModuleGroup.VersionsWithMethodBody(method.Method) && method.Method.IsPrimaryMethodDesc())
{
if (method.Token.TokenType == CorTokenType.mdtMethodSpec)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Internal.TypeSystem.Ecma;
using Internal.CorConstants;
using System.Diagnostics;
using ILCompiler.ReadyToRun.TypeSystem;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
Expand Down Expand Up @@ -100,7 +101,7 @@ public ModuleToken GetModuleTokenForMethod(MethodDesc method, bool allowDynamica
{
method = method.GetCanonMethodTarget(CanonicalFormKind.Specific);

if (method.GetTypicalMethodDefinition() is EcmaMethod ecmaMethod)
if (method.GetPrimaryMethodDesc().GetTypicalMethodDefinition() is EcmaMethod ecmaMethod)
{
if (_compilationModuleGroup.VersionsWithMethodBody(ecmaMethod))
{
Expand Down Expand Up @@ -160,7 +161,6 @@ public ModuleToken GetModuleTokenForField(FieldDesc field, bool allowDynamically
}
}


public void AddModuleTokenForMethod(MethodDesc method, ModuleToken token)
{
if (token.TokenType == CorTokenType.mdtMethodSpec)
Expand Down Expand Up @@ -332,6 +332,10 @@ public void AddModuleTokenForType(TypeDesc type, ModuleToken token)
SetModuleTokenForTypeSystemEntity(_typeToRefTokens, ecmaType, token);
}
}
else if (type.IsCanonicalDefinitionType(CanonicalFormKind.Specific))
{
return;
}
else if (!specialTypeFound)
{
throw new NotImplementedException(type.ToString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,13 @@ public void EmitMethodSignature(
{
flags |= (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_AsyncVariant;
}
if (method.Method is AsyncResumptionStub)
{
flags |= (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_ResumptionStub;
// For AsyncResumptionStubs, we want to encode the signature of the async variant method, not the resumption stub itself,
// so that they will share the same hash and be placed in the same bucket at runtime
method = new MethodWithToken(((AsyncResumptionStub)method.Method).TargetMethod, method.Token, method.ConstrainedType, method.Unboxing, method.Method);
}

EmitMethodSpecificationSignature(method, flags, enforceDefEncoding, enforceOwningType, context);

Expand Down Expand Up @@ -615,7 +622,7 @@ public SignatureContext EmitFixup(NodeFactory factory, ReadyToRunFixupKind fixup
{
throw new InternalCompilerErrorException("Attempt to use token from a module not within the version bubble");
}

EmitUInt((uint)factory.ManifestMetadataTable.ModuleToIndex(targetModule));
return new SignatureContext(targetModule, outerContext.Resolver);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private static void EncodeTypeLayout(ObjectDataSignatureBuilder dataBuilder, Typ
// Encode the GC pointer map
GCPointerMap gcMap = GCPointerMap.FromInstanceLayout(defType);

byte[] encodedGCRefMap = new byte[(size / pointerSize + 7) / 8];
byte[] encodedGCRefMap = new byte[((size + (pointerSize - 1)) / pointerSize + 7) / 8];
int bitIndex = 0;
foreach (bool bit in gcMap)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ public bool CanInline(MethodDesc caller, MethodDesc callee)
}
}

if (callee.IsAsyncThunk())
if (callee.IsCompilerGeneratedILBodyForAsync() || callee.IsAsyncCall())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsAsyncThunk would work just fine here.

{
// Async thunks require special handling in the compiler and should not be inlined
return false;
}

Expand Down Expand Up @@ -302,7 +301,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation

private readonly ProfileDataManager _profileData;
private readonly FileLayoutOptimizer _fileLayoutOptimizer;
private readonly HashSet<EcmaMethod> _methodsWhichNeedMutableILBodies = new HashSet<EcmaMethod>();
private readonly HashSet<MethodDesc> _methodsWhichNeedMutableILBodies = new HashSet<MethodDesc>();
private readonly HashSet<MethodWithGCInfo> _methodsToRecompile = new HashSet<MethodWithGCInfo>();

public ProfileDataManager ProfileData => _profileData;
Expand Down Expand Up @@ -695,12 +694,15 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
if (dependency is MethodWithGCInfo methodCodeNodeNeedingCode)
{
var method = methodCodeNodeNeedingCode.Method;
if (method.GetTypicalMethodDefinition() is EcmaMethod ecmaMethod)
var typicalDef = method.GetTypicalMethodDefinition();
if (typicalDef is EcmaMethod or AsyncMethodVariant or AsyncResumptionStub)
{
if (ilProvider.NeedsCrossModuleInlineableTokens(ecmaMethod) &&
!_methodsWhichNeedMutableILBodies.Contains(ecmaMethod) &&
CorInfoImpl.IsMethodCompilable(this, methodCodeNodeNeedingCode.Method))
_methodsWhichNeedMutableILBodies.Add(ecmaMethod);
if (ilProvider.NeedsCrossModuleInlineableTokens(typicalDef) &&
!_methodsWhichNeedMutableILBodies.Contains(typicalDef) &&
CorInfoImpl.IsMethodCompilable(this, method))
{
_methodsWhichNeedMutableILBodies.Add(typicalDef);
}
}

if (method.IsAsyncCall()
Expand Down Expand Up @@ -748,11 +750,11 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor

void ProcessMutableMethodBodiesList()
{
EcmaMethod[] mutableMethodBodyNeedList = new EcmaMethod[_methodsWhichNeedMutableILBodies.Count];
MethodDesc[] mutableMethodBodyNeedList = new MethodDesc[_methodsWhichNeedMutableILBodies.Count];
_methodsWhichNeedMutableILBodies.CopyTo(mutableMethodBodyNeedList);
_methodsWhichNeedMutableILBodies.Clear();
TypeSystemComparer comparer = TypeSystemComparer.Instance;
Comparison<EcmaMethod> comparison = (EcmaMethod a, EcmaMethod b) => comparer.Compare(a, b);
Comparison<MethodDesc> comparison = (MethodDesc a, MethodDesc b) => comparer.Compare(a, b);
Array.Sort(mutableMethodBodyNeedList, comparison);
var ilProvider = (ReadyToRunILProvider)_methodILCache.ILProvider;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ private bool CrossModuleInlineableInternal(MethodDesc method)
private bool CrossModuleInlineableUncached(MethodDesc method)
{
// Async thunks and variants cannot currently be inlined cross module
if (method.IsAsyncVariant() || method.IsAsync || method.IsAsyncThunk())
if (method.IsAsyncVariant() || method.IsAsync || method.IsCompilerGeneratedILBodyForAsync())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsAsyncThunk should work just fine here.

return false;

// Defined in corelib
Expand Down
Loading
Loading