Skip to content

Commit 142bd45

Browse files
Refactor async calling convention detection to use MethodDesc extension method (#121420)
Consolidates async calling convention detection logic into a single `MethodDesc` extension method, removing the need for `MethodSignatureFlags.AsyncCall` flag. **Changes:** - **Added `IsAsyncCall` extension method** on `MethodDesc` that unifies detection logic: returns true for async variants and async intrinsics that don't return Task/ValueTask - **Removed `MethodSignatureFlags.AsyncCall`** enum value and `MethodSignature.IsAsyncCall` property - **Updated call sites** in `CorInfoImpl.cs` to use the new extension method for `CORINFO_CALLCONV_ASYNCCALL` and `CORJIT_FLAG_ASYNC` - **Simplified `AsyncMethodVariant`** to no longer set the AsyncCall flag in signature **Rationale:** Async calling convention is now determined at the MethodDesc level (similar to hidden parameters in generic calling conventions) rather than being stored in signature flags. This properly handles both async variants (which have the flag set by signature transformation) and async intrinsics (which have `IsAsync` metadata but don't return Task/ValueTask). ```csharp // Before: Logic scattered across multiple locations if (method.IsAsync && !method.Signature.ReturnsTaskOrValueTask()) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL; // After: Unified in extension method if (method.IsAsyncCall()) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL; ``` <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/runtime/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com>
1 parent ce59648 commit 142bd45

File tree

4 files changed

+9
-20
lines changed

4 files changed

+9
-20
lines changed

src/coreclr/tools/Common/Compiler/AsyncMethodVariant.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,10 @@ public override MethodSignature Signature
3434
private MethodSignature InitializeSignature()
3535
{
3636
var signature = _wrappedMethod.Signature;
37-
Debug.Assert(!signature.IsAsyncCall);
3837
Debug.Assert(signature.ReturnsTaskOrValueTask());
3938
TypeDesc md = signature.ReturnType;
4039
MethodSignatureBuilder builder = new MethodSignatureBuilder(signature);
4140
builder.ReturnType = md.HasInstantiation ? md.Instantiation[0] : this.Context.GetWellKnownType(WellKnownType.Void);
42-
builder.Flags = signature.Flags | MethodSignatureFlags.AsyncCall;
4341
return (_asyncSignature = builder.ToSignature());
4442
}
4543

src/coreclr/tools/Common/Compiler/MethodExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,12 @@ public static bool ReturnsTaskOrValueTask(this MethodSignature method)
153153
}
154154
return false;
155155
}
156+
157+
/// <summary>
158+
/// Determines whether a method uses the async calling convention.
159+
/// Returns true for async variants (compiler-generated wrappers around Task-returning methods)
160+
/// and for special async intrinsics that don't return Task/ValueTask but use async calling convention.
161+
/// </summary>
162+
public static bool IsAsyncCall(this MethodDesc method) => method.IsAsync && (method.IsAsyncVariant() || !method.Signature.ReturnsTaskOrValueTask());
156163
}
157164
}

src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -833,9 +833,7 @@ private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, Meth
833833
{
834834
Get_CORINFO_SIG_INFO(method.Signature, sig, scope);
835835

836-
// Get_CORINFO_SIG_INFO above will have correctly set CORINFO_CALLCONV_ASYNCCALL for async variants,
837-
// however the special async intrinsics don't set the async bit in their signature. Compensate for that.
838-
if (method.IsAsync && !method.Signature.ReturnsTaskOrValueTask())
836+
if (method.IsAsyncCall())
839837
sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL;
840838

841839
// Does the method have a hidden parameter?
@@ -882,7 +880,6 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s
882880

883881
if (!signature.IsStatic) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_HASTHIS;
884882
if (signature.IsExplicitThis) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_EXPLICITTHIS;
885-
if (signature.IsAsyncCall) sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_ASYNCCALL;
886883

887884
TypeDesc returnType = signature.ReturnType;
888885

@@ -4337,10 +4334,7 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)
43374334
flags.Set(CorJitFlag.CORJIT_FLAG_SOFTFP_ABI);
43384335
}
43394336

4340-
// Signature.IsAsyncCall will do the right thing for async variants, however the special async
4341-
// intrinsics don't set the async bit in their signature. Compensate for that.
4342-
if (this.MethodBeingCompiled.Signature.IsAsyncCall
4343-
|| (this.MethodBeingCompiled.IsAsync && !this.MethodBeingCompiled.Signature.ReturnsTaskOrValueTask()))
4337+
if (this.MethodBeingCompiled.IsAsyncCall())
43444338
{
43454339
flags.Set(CorJitFlag.CORJIT_FLAG_ASYNC);
43464340
}

src/coreclr/tools/Common/TypeSystem/Common/MethodDesc.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ public enum MethodSignatureFlags
2323

2424
Static = 0x0010,
2525
ExplicitThis = 0x0020,
26-
27-
AsyncCall = 0x0100,
2826
}
2927

3028
public enum EmbeddedSignatureDataKind
@@ -140,14 +138,6 @@ public bool IsExplicitThis
140138
}
141139
}
142140

143-
public bool IsAsyncCall
144-
{
145-
get
146-
{
147-
return (_flags & MethodSignatureFlags.AsyncCall) != 0;
148-
}
149-
}
150-
151141
public int GenericParameterCount
152142
{
153143
get

0 commit comments

Comments
 (0)