-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Update EmitTaskReturningThunk in Native AOT #121435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Update EmitTaskReturningThunk in Native AOT #121435
Conversation
I added AsyncHelpers.CoreCLR.cs to native AOT corelib in #121398 so we should have those now. Just do a merge from main! |
|
Once you have this, you should be able to observe this program (same one I pointed you to, but with added using System;
using System.Threading.Tasks;
public class Async2Void
{
public static void Main()
{
var t = AsyncTestEntryPoint(123, 456);
t.Wait();
Console.WriteLine(t.Result);
}
private static async Task<int> AsyncTestEntryPoint(int x, int y)
{
int result = await OtherAsync(x, y);
return result;
}
private static async Task<int> OtherAsync(int x, int y)
{
Console.WriteLine(x);
Console.WriteLine(y);
await Task.Delay(1000);
return x + y;
}
} |
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Unfortunately the program prints the numbers and crashes but doesn't freeze, I'm looking into that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates the EmitTaskReturningThunk method in the Native AOT type system to match the CoreCLR VM implementation. The goal is to generate consistent IL code for async thunk methods across both runtimes.
Key changes:
- Added support for catch exception regions in the IL emitter infrastructure
- Implemented full task-returning thunk logic with nested try-catch-finally blocks
- Added sorting of exception regions to meet ECMA-335 spec requirements
- Created stub for AsyncCallContinuation intrinsic in NativeAOT
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/asyncthunks.cpp | Updated comments to clarify that the code should match the managed type system implementation |
| src/coreclr/tools/Common/TypeSystem/IL/Stubs/ILEmitter.cs | Added support for catch exception regions, updated exception region infrastructure to handle multiple types, and added sorting logic for proper exception region ordering |
| src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs | Implemented comprehensive task-returning thunk logic with proper exception handling, generic instantiation support, and control flow matching CoreCLR |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System/StubHelpers.NativeAot.cs | Added AsyncCallContinuation intrinsic stub for NativeAOT |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj | Added new StubHelpers.NativeAot.cs file to the project |
| .GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) | ||
| .GetKnownMethod("FromException"u8, null); | ||
| } | ||
| else | ||
| { | ||
| fromExceptionMd = context.SystemModule | ||
| .GetKnownType("System.Threading.Tasks"u8, "Task"u8) | ||
| .GetKnownMethod("FromException"u8, null); |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These calls should invoke AsyncHelpers.ValueTaskFromException and AsyncHelpers.TaskFromException instead of ValueTask.FromException and Task.FromException. The CoreCLR implementation (lines 234-247 in asyncthunks.cpp) calls the private TaskFromException and ValueTaskFromException methods from AsyncHelpers, which handle OperationCanceledException specially by setting the task as canceled rather than faulted. The public Task.FromException and ValueTask.FromException methods don't have this special handling.
| .GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) | |
| .GetKnownMethod("FromException"u8, null); | |
| } | |
| else | |
| { | |
| fromExceptionMd = context.SystemModule | |
| .GetKnownType("System.Threading.Tasks"u8, "Task"u8) | |
| .GetKnownMethod("FromException"u8, null); | |
| .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8) | |
| .GetKnownMethod("ValueTaskFromException"u8, null); | |
| } | |
| else | |
| { | |
| fromExceptionMd = context.SystemModule | |
| .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8) | |
| .GetKnownMethod("TaskFromException"u8, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This copilot feedback looks relevant.
src/coreclr/nativeaot/System.Private.CoreLib/src/System/StubHelpers.NativeAot.cs
Outdated
Show resolved
Hide resolved
src/coreclr/nativeaot/System.Private.CoreLib/src/System/StubHelpers.NativeAot.cs
Outdated
Show resolved
Hide resolved
| var inst = new TypeDesc[asyncMethod.OwningType.Instantiation.Length]; | ||
| for (int i = 0; i < inst.Length; i++) | ||
| { | ||
| inst[i] = context.GetSignatureVariable(i, false); | ||
| } | ||
|
|
||
| var instantiatedType = context.GetInstantiatedType((MetadataType)asyncMethod.OwningType, new Instantiation(inst)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use InstantiateAsOpen helper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @MichalStrehovsky mentioned that asyncMethod.OwningType may not be a generic definition so we cannot use the helper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, first thing InstantiateAsOpen currently does is that it asserts the method is not generic; we could have a generic method here:
| Debug.Assert(method.IsMethodDefinition && !method.HasInstantiation); |
But looking at it and all the callsites, it looks like it only asserts because we didn't have a need to do this with a generic method before and so it wasn't implemented. We could also just extend it to handle generic methods and call it from here.
The program works as expected now. |
Updated EmitTaskReturningThunk in Native AOT to match EmitTaskReturningThunk in CoreCLR.