-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[RuntimeAsync] Enable runtime async in Libraries partition #119432
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
base: main
Are you sure you want to change the base?
Conversation
Tagging subscribers to this area: @mangod9 |
CC: @jakobbotsch @agocke |
A lot of tests actually run and pass when I run this locally. More than I expected. :-) |
Some JIT asserts:
|
Something odd is going on with sync context in a few cases:
|
I have a fix for the following assert:
looking at others. |
// TODO: (async) we do not need to save ByRef-containing locals | ||
// as by the spec an await turns them into zero-inited state. | ||
// For now just store/restore as if there are no gc refs. | ||
// This is mostly to handle the "fake" live-across-await byrefs | ||
// in min-opts, since C#-compiled code by itself does not let | ||
// byrefs be live across awaits. | ||
unsigned objCount = layout->HasGCByRef() ? 0 : layout->GetGCPtrCount(); |
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.
We will need to figure out what is creating these LIR edges that are live across the await and stop doing that. This fix will replace assert with bad codegen instead.
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 typically see the assert when compiling Debug
code for Task-returning methods with ref-like parameters.
Ex:
public static Task WhenAll(params ReadOnlySpan<Task> tasks)
{
async
This method is not async, but it's thunk will be async and will also have a byref-like parameter.
The part that the edge lives across the await is likely a result of Debug
not tracking liveness precisely.
Once we have zeroing of byrefs that live across await, we may not need this.
This is not a fix. It is a workaround. - my goal is to get all Libraries tests pass or find something truly blocking.
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.
Assuming that it is a result of Debug
emit, perhaps forcing thunks to always compile optimized might be an alternative workaround, if there is an easy way to force.
I just thought of this workaround first and it seems working well enough.
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.
The part that the edge lives across the await is likely a result of Debug not tracking liveness precisely.
There are two sources of live state across async calls in JIT IR:
- Locals. These behave like IL locals and can be multiply defined and multiply used. They are what liveness analysis treat. They are added by
AsyncLiveness::GetLiveLocals
. - LIR edges. These are single-def single-use (SDSU) values that are defined in one place in a basic block and consumed later in the same basic block. When they overlap an async call (defined before, used after) they must also be preserved on heap. Liveness analysis does not treat these; they are known to be live when they overlap the call. They are added by
AsyncTransformation::LiftLIREdges
.
The liveness imprecision only comes into play for (1). However, we already ignore byref locals for these. It happens here:
runtime/src/coreclr/jit/async.cpp
Lines 507 to 515 in b0b30e7
if ((dsc->TypeIs(TYP_BYREF) && !dsc->IsImplicitByRef()) || | |
(dsc->TypeIs(TYP_STRUCT) && dsc->GetLayout()->HasGCByRef())) | |
{ | |
// Even if these are address exposed we expect them to be dead at | |
// suspension points. TODO: It would be good to somehow verify these | |
// aren't obviously live, if the JIT creates live ranges that span a | |
// suspension point then this makes it quite hard to diagnose that. | |
return false; | |
} |
That just leaves (2). But since these are known to be live, it is (almost?) always going to be a bug that resulted in these.
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.
Good point! I will log an issue on this - to follow up with real fix.
I see only 26 failed tests now in Chk/Ret configuration on win-x64. There are 23 cases of There are also 8 cases of Also fixing one thing sometimes exposes another, but so far with every fix/workaround I see more tests passing. |
The AVs in Logged an issue on that - #119796 and pushed a possible fix here. Now my local run is down to:
|
src/coreclr/jit/codegenxarch.cpp
Outdated
// a return register or contain 'this' pointer (keep alive this), or | ||
// a continuation register, since we are generating GS cookie check | ||
// after a GT_RETURN block. | ||
// ARG_1 is EDX or RSI, depending on platform. Either way it fits our reqirements | ||
regGSCheck = REG_ARG_1; |
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.
Feel free to PR this separately.
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'll make a PR for this and couple other small fixes that seem uncontroversial.
/azp run runtime-libraries-coreclr outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
rebased onto recent main to pick the fix in #119806 |
7c33637
to
ca576eb
Compare
…roduce canceled task.
Mostly to see what happens and how far we can get with this.