Skip to content

JIT: Allow inlining of JIT-inserted AsyncHelpers.TransparentAwait#130482

Open
jakobbotsch wants to merge 1 commit into
dotnet:mainfrom
jakobbotsch:fix-129896
Open

JIT: Allow inlining of JIT-inserted AsyncHelpers.TransparentAwait#130482
jakobbotsch wants to merge 1 commit into
dotnet:mainfrom
jakobbotsch:fix-129896

Conversation

@jakobbotsch

@jakobbotsch jakobbotsch commented Jul 10, 2026

Copy link
Copy Markdown
Member

Fix #129896

Example:

[MethodImpl(MethodImplOptions.NoInlining)]
private static async Task Bar()
{
    Task t = Task.CompletedTask;
    Stopwatch timer = Stopwatch.StartNew();
    for (int i = 0; i < 100_000_000; i++)
        await Foo(t);
    Console.WriteLine("Took {0:F1} ms", timer.Elapsed.TotalMilliseconds);
}

private static Task Foo(Task t) => t;

Inner loop before:

G_M42518_IG10:  ;; offset=0x00F2
       mov      rdx, rbx
       xor      rcx, rcx
       call     [System.Runtime.CompilerServices.AsyncHelpers:TransparentAwait(System.Threading.Tasks.Task)]
       test     rcx, rcx
       jne      G_M42518_IG34
                                                ;; size=20 bbWeight=168.07 PerfScore 798.32
G_M42518_IG11:  ;; offset=0x0106
       dec      edi
       jne      SHORT G_M42518_IG10

Took 191.3 ms
Took 191.0 ms
Took 190.6 ms
Took 192.1 ms
Took 192.1 ms

After:

G_M42518_IG10:  ;; offset=0x00F2
       test     dword ptr [rbx+0x34], 0x1600000
       je       G_M42518_IG21
       mov      edx, dword ptr [rbx+0x34]
       and      edx, 0x11000000
       cmp      edx, 0x1000000
       jne      G_M42518_IG22
                                                ;; size=34 bbWeight=168.07 PerfScore 1092.44
G_M42518_IG11:  ;; offset=0x0114
       dec      edi
       jne      SHORT G_M42518_IG10

...

G_M42518_IG21:  ;; offset=0x0217
       mov      rdx, rbx
       xor      rcx, rcx
       call     [System.Runtime.CompilerServices.AsyncHelpers:TransparentSuspend(System.Threading.Tasks.Task)]
       test     rcx, rcx
       jne      G_M42518_IG36
       jmp      G_M42518_IG11
                                                ;; size=25 bbWeight=0 PerfScore 0.00
G_M42518_IG22:  ;; offset=0x0230
       mov      rcx, rbx
       xor      edx, edx
       call     [System.Runtime.CompilerServices.TaskAwaiter:HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task,int)]
       jmp      G_M42518_IG11

Took 32.4 ms
Took 32.2 ms
Took 32.1 ms
Took 32.4 ms
Took 32.2 ms

Copilot AI review requested due to automatic review settings July 10, 2026 12:10
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jul 10, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 JIT↔EE async-support contract so the EE can also return an inlining context for the JIT-synthesized AsyncHelpers.TransparentAwait call, enabling the JIT to treat that synthesized call as an inline candidate (and to materialize the GT_RET_EXPR placeholder as needed).

Changes:

  • Extend ICorStaticInfo::getAwaitReturnCall to additionally return a CORINFO_CONTEXT_HANDLE suitable for inlining, and bump the JIT-EE version GUID accordingly.
  • Update CoreCLR VM, JIT importer, interpreter, NativeAOT managed JIT interface, and SuperPMI plumbing to pass/record/replay the new out parameter.
  • In the JIT importer, mark the synthesized await call as an inline candidate and, when applicable, append it as its own statement and replace it with a GT_RET_EXPR placeholder for the inliner.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/coreclr/vm/jitinterface.cpp Implements the new getAwaitReturnCall signature and returns an inlining context handle alongside the await helper method.
src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp Updates SuperPMI’s ICorJitInfo shim to forward the new out parameter.
src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp Forwards the new contextHandle parameter through the simple shim.
src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp Forwards and records the updated call signature in the counter shim.
src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp Records/replays getAwaitReturnCall including the returned contextHandle.
src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h Updates SuperPMI MethodContext record/replay signatures for getAwaitReturnCall.
src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp Persists the returned contextHandle in MethodContext capture and restores it on replay.
src/coreclr/tools/superpmi/superpmi-shared/agnostic.h Extends the agnostic record payload to include contextHandle.
src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt Teaches thunk generation about CORINFO_CONTEXT_HANDLE* marshalling.
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs Updates NativeAOT managed JIT interface implementation to return an inlining context handle.
src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs Updates generated interop delegates/wrappers for the new signature.
src/coreclr/tools/aot/jitinterface/jitinterface_generated.h Updates the AOT JIT interface wrapper vtable thunk signature and forwarding.
src/coreclr/jit/importer.cpp Uses returned contextHandle to mark synthesized TransparentAwait as inline-candidate and set up GT_RET_EXPR when applicable.
src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp Updates the JIT-side wrapper to pass/receive the new contextHandle parameter.
src/coreclr/interpreter/compiler.cpp Updates interpreter call sites to pass the new out contextHandle parameter.
src/coreclr/inc/jiteeversionguid.h Bumps the JIT-EE interface version GUID due to the signature change.
src/coreclr/inc/icorjitinfoimpl_generated.h Updates the EE-side interface implementation declaration to match the new signature.
src/coreclr/inc/corinfo.h Updates the ICorStaticInfo interface contract and documents the new contextHandle semantics.

@jakobbotsch

Copy link
Copy Markdown
Member Author

cc @dotnet/jit-contrib PTAL @EgorBo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support inlining of JIT-inserted TransparentAwait in async versions

2 participants