[Async v2] Implement async method variant handling in AddMethod and UpdateMethod#125397
Merged
tommcdon merged 29 commits intodotnet:mainfrom Apr 23, 2026
Merged
Conversation
Contributor
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements runtime-async method variant support in the Edit-and-Continue (EnC) path by extending EEClass::AddMethodDesc/EEClass::AddMethod to carry async metadata (flags + optional alternate signature) and by updating EnC method update logic to consider async method variants.
Changes:
- Extend
EEClass::AddMethodDescto accept async flags and an optional async-variant signature, and plumb that intoMethodTableBuilder::InitMethodDesc. - Add async return-type classification and async-variant creation logic to
EEClass::AddMethod. - Update
EditAndContinueModule::UpdateMethodto also reset the entrypoint for the method’s async counterpart.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/coreclr/vm/encee.cpp | Resets entrypoints for async counterparts during EnC method updates. |
| src/coreclr/vm/class.h | Extends AddMethodDesc signature to accept async flags and optional async signature. |
| src/coreclr/vm/class.cpp | Implements async return classification and passes async flags/signature into EnC-added MethodDesc creation. |
You can also share your feedback on Copilot code review. Take the survey.
This was referenced Mar 10, 2026
jkotas
reviewed
Mar 11, 2026
76d4eb1 to
437f9ed
Compare
noahfalk
reviewed
Apr 2, 2026
tommcdon
added a commit
to tommcdon/runtime
that referenced
this pull request
Apr 3, 2026
…ejection, generic UpdateMethod comment - class.cpp:579: Update GC violation comment to acknowledge the extern-alias edge case as Won't Fix per reviewer feedback - class.cpp:597: Reject infrastructure async methods (IsMiAsync but not task-returning) on non-system modules with COR_E_BADIMAGEFORMAT, mirroring MethodTableBuilder validation - encee.cpp:388: Add comment explaining that ResetCodeEntryPointForEnC cascades from thunk to async variant automatically, so generic UpdateMethod path does not need explicit async variant handling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
noahfalk
reviewed
Apr 3, 2026
noahfalk
reviewed
Apr 3, 2026
noahfalk
approved these changes
Apr 3, 2026
Member
noahfalk
left a comment
There was a problem hiding this comment.
Looks good 👍 Couple suggestions inline
jkotas
reviewed
Apr 5, 2026
- Update AsyncVariantLookup enum values: AsyncOtherVariant -> Async, MatchingAsyncVariant -> Ordinary - Update ClassifyMethodReturnKind calls to pass new elementTypeLength param - Update FindOrCreateAssociatedMethodDesc call to match new parameter order (AsyncVariantLookup moved before forceRemotableMethod) - Update debugger.cpp: HasAsyncOtherVariant -> IsAsyncThunkMethod, GetAsyncOtherVariantNoCreate -> GetAsyncVariantNoCreate - Add missing variable declarations in methodtablebuilder.cpp - Remove tautological assert in FCAMD lazy creation block Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cation Reverts the unnecessary variable declaration reordering in EnumerateClassMethods that fell out of the rebase conflict resolution. Keeps the improved comment in InitMethodDesc that clarifies primary thunks use the original metadata signature and do not store one. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ec5469d to
fb41135
Compare
Instead of lazily creating async variant MethodDescs in FindOrCreateAssociatedMethodDesc, create them eagerly alongside the primary thunk in EEClass::AddMethod. The variant signature is computed once from metadata and then AddMethodDesc (GC_NOTRIGGER) creates both MethodDescs. For generic types, each existing instantiation gets its own sig copy from its loader allocator. This eliminates: - Lazy creation block in FCAMD (double-check locking, GCX_COOP, lock) - LoadTypicalMethodDefinition fallback for async variants - EEClass::AddAsyncVariant helper (no longer needed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jkotas
reviewed
Apr 21, 2026
Previously AddMethod only created async variants for IsMiAsync methods. Normal type loading (MethodTableBuilder::EnumerateClassMethods) creates variants for all task-returning methods regardless of IsMiAsync. This change aligns EnC with that behavior: - IsMiAsync: primary is thunk, async variant owns the IL - Non-IsMiAsync: primary owns IL, async variant is a thunk Also removes per-instantiation signature copy for generic types since instantiations cannot have longer lifetime than the definition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace inline NonGenericTask and GenericTask signature rewriting in MethodTableBuilder::EnumerateClassMethods with calls to the shared BuildAsyncVariantSignature function. The ReturnDroppingThunk case (rare covariant override scenario) remains inline since it has unique logic not applicable to the EnC path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
For task-returning methods with async variants, detect when the primary MethodDesc is a thunk and switch to the async variant that owns the user code before planting remap breakpoints. This eliminates the duplicated breakpoint-planting loop that previously handled the async variant separately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jkotas
reviewed
Apr 21, 2026
jkotas
reviewed
Apr 21, 2026
jkotas
reviewed
Apr 21, 2026
This was referenced Apr 21, 2026
Open
noahfalk
reviewed
Apr 22, 2026
Per reviewer feedback, inline the sig construction directly in EEClass::AddMethod instead of using a shared BuildAsyncVariantSignature function. Remove the function from method.cpp/method.hpp. Revert all changes to genmeth.cpp and methodtablebuilder.cpp as no modifications are needed in the normal type loading path for the EnC feature. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per reviewer feedback, return S_OK instead of falling through when GetAsyncVariantNoCreate() returns NULL for an async thunk. There is no user code to plant remap breakpoints on in this case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Re-add comment explaining the Won't Fix corner cases around the CONTRACT_VIOLATION(GCViolation) in EnC async variant creation: type identity may not match well-known types, and the call may trigger GC even for well-known types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jkotas
approved these changes
Apr 23, 2026
Member
Author
|
/ba-g failures are pre-existing/unrelated |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This change implements a TODO item in
EEClass::AddMethodDescto support Runtime Async