-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RuntimeAsync] Fix support for pinvokes #2847
[RuntimeAsync] Fix support for pinvokes #2847
Conversation
- Make sure async transformation leaves a scratch BB around for the pinvoke prolog to be inserted into - Make sure we properly insert pinvoke epilogs for `GT_RETURN_SUSPEND` nodes (needed on x86) - Ensure the pinvoke frame related locals are not captured by the async transformation
PTAL @VSadov |
private static unsafe delegate* unmanaged<int> GetFPtr() => &GetValue; | ||
|
||
[UnmanagedCallersOnly] | ||
private static int GetValue() => 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A thought: what should happen if UnmanagedCallersOnly
is applied to runtime async method.
Does it work today with ordinary async? (I guess, why not, they are just Task-returning methods)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't checked, but I imagine UnmanagedCallersOnly
on any function returning an object reference should result in IlegalProgramException
. So I would hope that was the case for async1, and we should similarly disallow it for async2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't checked, but I imagine UnmanagedCallersOnly on any function returning an object reference should result in IlegalProgramException. So I would hope that was the case for async1, and we should similarly disallow it for async2.
I checked.
Even though the documentation only mentions that parameters must be blittable, the runtime requires that the return type is blittable as well. That rules out runtime async signatures. Even nongeneric ValueType
, although a struct, is not blittable.
{ | ||
// If previous first BB was a scratch BB then we have to recreate it | ||
// after since later phases may be relying on it. | ||
// TODO-Cleanup: The later phases should be creating it if they need it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you plan to address this TODO or this is just a "good to have" comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree that relying on the presence of scratch is an arbitrary dependency that just happen to hold.
If creating on demand is not too hard, it would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you plan to address this TODO or this is just a "good to have" comment?
I don't plan to address it here, this should rather be cleaned up upstream.
I do agree that relying on the presence of scratch is an arbitrary dependency that just happen to hold.
If creating on demand is not too hard, it would be better.
The frontend does ensure it:
runtimelab/src/coreclr/jit/flowgraph.cpp
Lines 2315 to 2322 in 4daa761
// The backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is | |
// required. Similarly, we need a scratch BB for poisoning and when we have Swift parameters to reassemble. | |
// Create it here. | |
if (compMethodRequiresPInvokeFrame() || compShouldPoisonFrame() || lvaHasAnySwiftStackParamToReassemble()) | |
{ | |
madeChanges |= fgEnsureFirstBBisScratch(); | |
fgFirstBB->SetFlags(BBF_DONT_REMOVE); | |
} |
It's simply that this is a very long-term invariant that is error prone and which feels unnecessary to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. Such dependencies have negative value by default. They must be justified by advantages or scenarios that they enable. If arranging a scratch block was difficult to do later, it could be a possible justification, but, as I understand, it is not the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks!
d38e953
into
dotnet:feature/async2-experiment
GT_RETURN_SUSPEND
nodes (needed on x86)