Skip to content

Commit 2bb5fc6

Browse files
Fix runtime async in multifile compilation (#122451)
1. When compiling a library, compile all methods including async variants. 2. When enumerating methods on types, generate variants for every task returning method, not just virtuals. The 2 is a bit surprising but it matches what we now do in https://github.com/dotnet/runtime/blob/d31e5990b896447bfc3dbe98cfe6ec3b169a4896/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs#L1849-L1857. We originally restricted this to methods being runtimeasync but changed it in https://github.com/dotnet/runtime/pull/121622/files#diff-132a77bcd3f74cf0e0b04fbccda246c97c91e40562d78cb01fff61cf69403573L1860. Cc @dotnet/ilc-contrib
1 parent 8b60f00 commit 2bb5fc6

File tree

2 files changed

+10
-4
lines changed

2 files changed

+10
-4
lines changed

src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ internal static IEnumerable<MethodDesc> WithAsyncVariants(CompilerTypeSystemCont
112112
{
113113
yield return method;
114114

115-
// We create an async variant slot for any virtual Task-returning method, not just runtime-async.
115+
// We create an async variant slot for any Task-returning method, not just runtime-async.
116116
// This is not a problem in practice because the slot is still subject to dependency
117117
// analysis and if not used, will not be generated.
118118
//
@@ -137,8 +137,14 @@ internal static IEnumerable<MethodDesc> WithAsyncVariants(CompilerTypeSystemCont
137137
// // didn't know about IFoo in Base either. Who has the slot?
138138
// // A: Base has the runtime-async slot, despite the method not being runtime-async.
139139
// }
140-
if ((method.IsAsync || method.IsVirtual)
141-
&& method.GetTypicalMethodDefinition().Signature.ReturnsTaskOrValueTask())
140+
//
141+
// The other reason is that when the method is awaited, RyuJIT will prefer the AsyncCallable
142+
// variant, no matter if the method is async.
143+
//
144+
// We restrict this to EcmaMethod since AsyncVariantMethod cannot deal with non-ECMA methods
145+
// and we shouldn't be awaiting compiler-generated methods (delegate thunks, etc.) anyway.
146+
if (method.GetTypicalMethodDefinition() is EcmaMethod ecmaMethod
147+
&& ecmaMethod.Signature.ReturnsTaskOrValueTask())
142148
{
143149
yield return context.GetAsyncVariantMethod(method);
144150
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LibraryRootProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
4949

5050
private static void RootMethods(TypeDesc type, string reason, IRootingServiceProvider rootProvider)
5151
{
52-
foreach (MethodDesc method in type.GetAllMethods())
52+
foreach (MethodDesc method in type.GetAllMethodsAndAsyncVariants())
5353
{
5454
// Skip methods with no IL and uninstantiated generic methods
5555
if (method.IsAbstract || method.HasInstantiation)

0 commit comments

Comments
 (0)