Make IL Scanner report both variants#128107
Conversation
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
There was a problem hiding this comment.
Pull request overview
Updates the NativeAOT IL scanner’s call dependency tracking for runtime-async “task await” patterns so it no longer reports only the async-variant method, but instead reports both the original method and its async variant, allowing the JIT to select either implementation during compilation.
Changes:
- Stop rewriting the scanned call target to the async variant; instead, keep the original call target and track the async variant in parallel.
- Add dependency reporting for the async variant alongside the original call target, including generic-lookup-related nodes where applicable.
| if (asyncVariantMethod != null && _canonMethod.IsSharedByGenericInstantiations) | ||
| { | ||
| MethodDesc avTargetMethod = asyncVariantMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); | ||
| if (avTargetMethod.RequiresInstMethodDescArg()) | ||
| _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.MethodDictionary, asyncVariantRuntimeDeterminedMethod), reason); | ||
| else if (avTargetMethod.RequiresInstMethodTableArg()) | ||
| _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, asyncVariantRuntimeDeterminedMethod.OwningType), reason); |
| // If this is the task await pattern, the JIT will first resolve the call to the | ||
| // async variant, then may switch back to the original if the async variant is just | ||
| // a thunk (for non-runtime-async methods). Report both variants as dependencies such | ||
| // that the JIT can pick either one. |
| if (asyncVariantMethod != null && _canonMethod.IsSharedByGenericInstantiations) | ||
| { | ||
| MethodDesc avTargetMethod = asyncVariantMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); | ||
| if (avTargetMethod.RequiresInstMethodDescArg()) | ||
| _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.MethodDictionary, asyncVariantRuntimeDeterminedMethod), reason); | ||
| else if (avTargetMethod.RequiresInstMethodTableArg()) | ||
| _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, asyncVariantRuntimeDeterminedMethod.OwningType), reason); |
There was a problem hiding this comment.
This is going to be really difficult to review for correctness. I wonder if we can instead split ImportCall into two methods:
private void ImportCall(ILOpcode opcode, int token);
private void ImportCall(ILOpcode opcode, MethodDesc method, MethodDesc runtimeDeterminedMethod)
and have the token based ImportCall call the other one, potentially twice.
There was a problem hiding this comment.
Ah yes this is much better, will do
IL Scanner currently reports only the async variant inside a runtime async method. While the JIT initially chooses this variant too, it can switch to the task returning variant if the async variant is a thunk. Make IL Scanner report both variants such that the JIT can choose either one.
Fixes #127179.