Uh oh!
There was an error while loading. Please reload this page.
[Async v2] Implement async method variant handling in AddMethod and UpdateMethod - #125397
Conversation
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
76d4eb1 to
437f9edCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…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>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
noahfalk
left a comment
There was a problem hiding this comment.
Looks good 👍 Couple suggestions inline
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ec5469d to
fb41135CompareInstead 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>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
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>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
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>
tommcdon
commented
Apr 23, 2026
/ba-g failures are pre-existing/unrelated |
This change implements a TODO item in
EEClass::AddMethodDescto support Runtime Async