-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[clr-interp] Runtime async support #121862
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
54c4cc1
RuntimeAsync for interpreter phase 1
davidwrighton 024ab55
More fixes
davidwrighton 0064807
Current test tweaks
davidwrighton cda2252
Fix this pointer in generics issue
davidwrighton 495abdf
Don't overwrite values that shouldn't be overwritten.
davidwrighton 9dc46af
Add support for direct Async2 to Async2 calls, and fix incorrect hand…
davidwrighton 08ea4fd
Add forward support to call stub generator for async methods
davidwrighton a3c1fdd
Merge branch 'main' of https://github.com/dotnet/runtime into Runtime…
davidwrighton 9fb7e05
Progress towards async calling convention handling in the callstub ge…
davidwrighton 24a3f5c
It all passes the tests!
davidwrighton 9ae0d3b
Remove unnecessary data/dvar from HANDLE_CONTINUATION_RESUME
davidwrighton cd92605
Re-order InterpAsyncSuspendData for easier future diagnostics
davidwrighton 01adff9
Fix setting methodStartIp
davidwrighton 8b61a6f
Update tests to work for both JIT and interpreter scenarios
davidwrighton 9913e56
Merge branch 'main' of https://github.com/dotnet/runtime into Runtime…
davidwrighton 7cf7c52
Tweak the new CallJittedMethodRetBuffRSI function.
davidwrighton 250ee75
Actually handle the merge details
davidwrighton 9d8bf9d
Fix build on Linux x64
davidwrighton a5feaac
Remove ProtectValueClassFrame changes as they are not necessary
davidwrighton 3806ea2
Add some documentation on how runtime generated async code generation…
davidwrighton d99c3f7
Fix WASM build
davidwrighton ded4f49
Fix Unix X64 stubs
davidwrighton 811e321
Fixup formatting and some missing bits of info.
davidwrighton 4765f06
Fit and finish details
davidwrighton ffb1656
Integrate with Jakob's changes around calli signature handling, and a…
davidwrighton 1ea976f
Move the JIT copy of dataAsyncResumeInfo to corinfo.h and rename it C…
davidwrighton c5e0fbb
Fix more code review issues
davidwrighton c0124af
Apply suggestions from code review
davidwrighton 96a9114
Merge branch 'RuntimeAsync_Interpreter' of https://github.com/davidwr…
davidwrighton 2d74b6b
Fix GCC build break
davidwrighton 354e365
More code review + disable RuntimeAsync by default so we can actually…
davidwrighton File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| \## Responsibilities of a code generator for implementing the Runtime Async feature | ||
|
|
||
|
|
||
|
|
||
| This document describes the behaviors that a code generator must conform to to correctly make the runtime async feature work correctly. | ||
|
|
||
|
|
||
|
|
||
| This document is NOT intended to describe the runtime-async feature. That is better described in the runtime-async specification. See (https://github.com/dotnet/runtime/blob/main/docs/design/specs/runtime-async.md). | ||
|
|
||
|
|
||
|
|
||
| The general responsibilities of the runtime-async code generator | ||
|
|
||
| 1\. Wrap the body of Task and ValueTask returning functions in try/finally blocks which set/reset the `ExecutionContext` and `SynchronizationContext`. | ||
|
|
||
| 2\. Allow the async thunk logic to work. | ||
|
|
||
| 3\. Generate Async Debug info (Not yet described in this document)f | ||
|
|
||
|
|
||
|
|
||
| \# Identifying calls to Runtime-Async methods that can be handled by runtime-async | ||
|
|
||
| When compiling a call to a method that might be called in the optimized fashion, recognize the following sequence. | ||
|
|
||
| ``` | ||
|
|
||
| call\[virt] <Method> | ||
|
|
||
| \[ OPTIONAL ] | ||
|
|
||
| { | ||
|
|
||
| \[ OPTIONAL - Used for ValueTask based ConfigureAwait ] | ||
|
|
||
| { | ||
|
|
||
| stloc X; | ||
|
|
||
| ldloca X | ||
|
|
||
| } | ||
|
|
||
| ldc.i4.0 / ldc.i4.1 | ||
|
|
||
| call\[virt] <ConfigureAwait> (The virt instruction is used for ConfigureAwait on a Task based runtime async function) NI\_System\_Threading\_Tasks\_Task\_ConfigureAwait | ||
|
|
||
| } | ||
|
|
||
| call <Await> One of the functions which matches NI\_System\_Runtime\_CompilerServices\_AsyncHelpers\_Await | ||
|
|
||
| ``` | ||
|
|
||
| A search for this sequence is done if Method is known to be async. | ||
|
|
||
|
|
||
|
|
||
| If the pattern is recognized, this is a PREFIX\_IS\_TASK\_AWAIT async call, and if the flag passed to ConfigureAwait is 1, or there is no call to ConfigureAwait, it is also a PREFIX\_TASK\_AWAIT\_CONTINUE\_ON\_CAPTURED\_CONTEXT call. Calls to these functions will save/restore the execution context. | ||
|
|
||
|
|
||
|
|
||
| The dispatch to these functions will save and restore the execution context only on async dispatch. | ||
|
|
||
| If PREFIX\_TASK\_AWAIT\_CONTINUE\_ON\_CAPTURED\_CONTEXT, then continuation mode shall be ContinuationContextHandling::ContinueOnCapturedContext otherwise ContinuationContextHandling::ContinueOnThreadPool. | ||
|
|
||
|
|
||
|
|
||
| \# Non-optimized pattern | ||
|
|
||
| It is also legal for code to have a simple direct usage of NI\_System\_Runtime\_CompilerServices\_AsyncHelpers\_Await or NI\_System\_Runtime\_CompilerServices\_AsyncHelpers\_AwaitAwaiter. To support this, the Await and AwaitAwaiter functions are marked as async even though they do not return a Task/ValueTask. | ||
|
|
||
|
|
||
|
|
||
| The dispatch to these functions will save and restore the execution context only on async dispatch. | ||
|
|
||
| The dispatch to these functions will set continuation mode to ContinuationContextHandling::None | ||
|
|
||
| SaveAndRestoreSynchronizationContextField is disabled | ||
davidwrighton marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
|
|
||
| \# Calli of an async function | ||
|
|
||
| The dispatch to these functions will save and restore the execution context only on async dispatch. | ||
|
|
||
|
|
||
|
|
||
| \# The System.Runtime.CompilerServices.AsyncHelpers::AsyncSuspend intrinsic | ||
|
|
||
| When encountered, triggers the function to suspend immediately, and return the passed in Continuation. | ||
|
|
||
|
|
||
|
|
||
| \# Saving and restoring of contexts | ||
|
|
||
| Capture the execution context before the suspension, and when the function resumes, call `AsyncHelpers.RestoreExecutionContext`. The context should be stored into the Continuation. The context may be captured by calling `AsyncHelpers.CaptureExecutionContext` or it may be captured directly off of the Thread object. | ||
davidwrighton marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
|
|
||
| \# ABI for async function handling | ||
|
|
||
|
|
||
|
|
||
| There is an additional argument which is the Continuation. When calling a function normally, this is always set to 0. When resuming, this is set to the Continuation object. There is also an extra return argument. It is either 0 or a Continuation. If it is a continuation, then the calling function needs to suspend (if it is an async function), or generate a Task/ValueTask (if it is a async function wrapper). | ||
|
|
||
|
|
||
|
|
||
| \## Suspension path | ||
|
|
||
| This is what is used in calls to async functions made from async functions. | ||
|
|
||
|
|
||
|
|
||
| ``` | ||
|
|
||
| bool didSuspend = false; // Needed for the context restore | ||
|
|
||
|
|
||
|
|
||
| (result, continuation) = call func(NULL /\* Continuation argument \*/, args) | ||
|
|
||
| if (continuation != NULL) | ||
|
|
||
| { | ||
|
|
||
| // Allocate new continuation | ||
|
|
||
| // Capture Locals | ||
|
|
||
| // Copy resumption details into continuation (Do things like call AsyncHelpers.CaptureContinuationContext or AsyncHelpers.CaptureExecutionContext as needed) | ||
|
|
||
| // Chain to continuation returned from called function | ||
|
|
||
| // IF in a function which saves the exec and sync contexts, and we haven't yet suspended, restore the old values. | ||
|
|
||
| // return. | ||
|
|
||
|
|
||
|
|
||
| // Resumption point | ||
|
|
||
|
|
||
|
|
||
| // Copy values out of continuation (including captured sync context and execution context locals) | ||
|
|
||
| // If the continuation may have an exception, check to see if its there, and if it is, throw it. Do this if CORINFO\_CONTINUATION\_HAS\_EXCEPTION is set. | ||
|
|
||
| // If the continuation has a return value, copy it out of the continuation. (CORINFO\_CONTINUATION\_HAS\_RESULT is set) | ||
|
|
||
| } | ||
|
|
||
| ``` | ||
|
|
||
| \## Thunks path | ||
|
|
||
| This is what is used in non-async functions when calling an async function. Generally used in the AsyncResumptionStub and in | ||
|
|
||
| ``` | ||
|
|
||
| (result, continuation) = call func(NULL /\* Continuation argument \*/, args) | ||
|
|
||
| place result onto IL evaluation stack | ||
|
|
||
| Place continuation into a local for access using the StubHelpers.AsyncCallContinuation() helper function. | ||
|
|
||
| ``` | ||
|
|
||
| Implement an intrinsic for StubHelpers.AsyncCallContinuation() which will load the most recent value stored into the continuation local. | ||
|
|
||
|
|
||
|
|
||
| \# Behavior of ContinuationContextHandling | ||
|
|
||
| This only applies to calls which where | ||
davidwrighton marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
|
|
||
| If set to ContinuationContextHandling::ContinueOnCapturedContext | ||
|
|
||
| \- The Continuation shall have an allocated data member for the captured context, and the CORINFO\_CONTINUATION\_HAS\_CONTINUATION\_CONTEXT flag shall be set on the continuation. | ||
|
|
||
| \- The Continuation will store the captured synchronization context. This is done by calling `AsyncHelpers.CaptureContinuationContext(syncContextFromBeforeCall, ref newContinuation.ContinuationContext, ref newContinuation.Flags)` while filling in the `Continuation`. | ||
|
|
||
|
|
||
|
|
||
| If set to ContinuationContextHandling::ContinueOnThreadPool | ||
|
|
||
| \- The Continuation shall have the CORINFO\_CONTINUATION\_CONTINUE\_ON\_THREAD\_POOL flag set | ||
|
|
||
|
|
||
|
|
||
| \# Exception handling behavior | ||
|
|
||
| If an async function is called within a try block (In the jit hasTryIndex return true), set the CORINFO\_CONTINUATION\_HAS\_EXCEPTION bit on the Continuation and make it large enough. | ||
|
|
||
|
|
||
|
|
||
| \# Locals handling | ||
|
|
||
| ByRef locals must not be captured. In fact, we should NULL out any locals which are ByRefs or ByRef-like. Currently we do not do this on synchronous execution, but logically possibly we should. | ||
|
|
||
|
|
||
|
|
||
| \# Saving and restoring the synchronization and execution contexts | ||
|
|
||
| The code generator must save/restore the sync and execution contexts around the body of all Task/ValueTask methods when directly called with a null continuation context. | ||
davidwrighton marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.