Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ private void ImportCall(ILOpcode opcode, int token)
Debug.Assert(false); break;
}

MethodDesc asyncVariantMethod = null;
MethodDesc asyncVariantRuntimeDeterminedMethod = null;
// Are we scanning a call within a state machine?
if (opcode is ILOpcode.call or ILOpcode.callvirt
&& _canonMethod.IsAsyncCall())
Expand All @@ -475,8 +477,10 @@ private void ImportCall(ILOpcode opcode, int token)
_dependencies.Add(_factory.MethodEntrypoint(asyncHelpers.GetKnownMethod("FinishSuspensionWithContinuationContext"u8, null)), asyncReason);
}

// If this is the task await pattern, we're actually going to call the variant
// so switch our focus to the variant.
// 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.
Comment on lines +480 to +483

// in rare cases a method that returns Task is not actually TaskReturning (i.e. returns T).
// we cannot resolve to an Async variant in such case.
Expand All @@ -487,8 +491,8 @@ private void ImportCall(ILOpcode opcode, int token)

if (allowAsyncVariant && MatchTaskAwaitPattern())
{
runtimeDeterminedMethod = _factory.TypeSystemContext.GetAsyncVariantMethod(runtimeDeterminedMethod);
method = _factory.TypeSystemContext.GetAsyncVariantMethod(method);
asyncVariantMethod = _factory.TypeSystemContext.GetAsyncVariantMethod(method);
asyncVariantRuntimeDeterminedMethod = _factory.TypeSystemContext.GetAsyncVariantMethod(runtimeDeterminedMethod);
}
}

Expand Down Expand Up @@ -812,6 +816,16 @@ private void ImportCall(ILOpcode opcode, int token)
}

_dependencies.Add(_factory.CanonicalEntrypoint(targetMethod), reason);

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);
Comment on lines +820 to +826
Comment on lines +820 to +826
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes this is much better, will do

_dependencies.Add(_factory.CanonicalEntrypoint(avTargetMethod), reason);
}
}
else
{
Expand Down Expand Up @@ -853,6 +867,16 @@ private void ImportCall(ILOpcode opcode, int token)
}

_dependencies.Add(GetMethodEntrypoint(targetMethod), reason);

if (asyncVariantMethod != null)
{
MethodDesc avTargetMethod = asyncVariantMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
if (avTargetMethod.RequiresInstMethodDescArg())
_dependencies.Add(_compilation.NodeFactory.MethodGenericDictionary(asyncVariantMethod), reason);
else if (avTargetMethod.RequiresInstMethodTableArg())
_dependencies.Add(_compilation.NodeFactory.ConstructedTypeSymbol(asyncVariantMethod.OwningType), reason);
_dependencies.Add(GetMethodEntrypoint(avTargetMethod), reason);
}
}
}
else if (staticResolution is DefaultInterfaceMethodResolution.Diamond or DefaultInterfaceMethodResolution.Reabstraction)
Expand Down
Loading