Skip to content
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

Allow GC on the first instruction of NoGC region (except in prologs/epilogs) #103540

Merged
merged 7 commits into from
Jun 24, 2024

Conversation

VSadov
Copy link
Member

@VSadov VSadov commented Jun 16, 2024

NoGC regions are used to temporarily disable GC in otherwise interruptible code. A typical use is during block-copying data that may contain GC references via temporaries that are not GC-reported.

The semantic of NoGC region is that once the first instruction executes, tracking invariants are violated and GC cannot happen, until the execution of the last instruction in the region makes GC safe again.
In particular - once the IP is on the first instruction, but not executed it yet, it is still safe to do GC.

The only special case is when NoGC region is used for prologs/epilogs. In such case the GC info could be incorrect until the prolog completes and epilogs may have unwindability restrictions, so the first instruction cannot have GC.

====== What prompted this change:

While working on #102680. I have discovered that sometimes we start NoGC region on the next instruction after a call. Without this change it means that once the call executes, the caller is in a NoGC state.
As a result there is a rare combination where:

  • the calee was hijacked and upon return tries to initiate a stackwalk at the call site in the caller.
  • the caller is fully-interruptible, thus it checks if a stackwalk starts in interruptible code.

That leads to an assert in gcinfodecoder.cpp:801 executionAborted.
We do not expect to be asked for GC info in non-interruptible code unless it is the executionAborted case.

It would be nice to not mark instructions as NoGC unnecessarily. In particular we should not do that to GC-capable call sites.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 16, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@VSadov VSadov changed the title Allow GC on the first instruction of NoGC region (except in prologs) Allow GC on the first instruction of NoGC region (except in prologs/epilogs) Jun 16, 2024
@VSadov
Copy link
Member Author

VSadov commented Jun 16, 2024

/azp run runtime-coreclr gcstress-extra, runtime-coreclr gcstress0x3-gcstress0xc

Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@VSadov
Copy link
Member Author

VSadov commented Jun 17, 2024

The stress failures look preexisting.

@VSadov
Copy link
Member Author

VSadov commented Jun 19, 2024

/azp run runtime-coreclr gcstress-extra, runtime-coreclr gcstress0x3-gcstress0xc

Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@VSadov VSadov marked this pull request as ready for review June 19, 2024 02:22
@VSadov
Copy link
Member Author

VSadov commented Jun 19, 2024

As compared with a baseline run #85694 with a noop change - the stress failures appear the same or fewer.

@VSadov
Copy link
Member Author

VSadov commented Jun 19, 2024

@dotnet/jit-contrib

BasicBlock* nextBlock = block->Next();

if (block->HasFlag(BBF_RETLESS_CALL))
{
GetEmitter()->emitIns_J(INS_bl, block->GetTarget());
Copy link
Member Author

@VSadov VSadov Jun 19, 2024

Choose a reason for hiding this comment

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

Unlike other uses of NoGC regions, the use in genCallFinally was starting the NoGC region on instruction after the one that makes GC unsafe.

We need to agree on the same semantics for all the uses, so genCallFinally had to be adjusted to work the same as in other uses of NoGC like block copying, tailcall arg setups,...

Copy link
Member Author

@VSadov VSadov Jun 19, 2024

Choose a reason for hiding this comment

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

We could have it the other way (and adjust uses in block copying, etc..), we just need to have it the same way in all cases.

However, starting NoGC region on an instruction group that will make GC unsafe seems a lot more convenient as we may want to start NoGC region before we know exact instructions that will go into it.

if (!isInPrologOrEpilog)
{
interruptibleEnd += firstInstrSize;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the key change in this PR.

@VSadov VSadov requested a review from jakobbotsch June 21, 2024 15:21
Comment on lines +4016 to +4017
unsigned m_uninterruptibleEnd;
Encoder* m_gcInfoEncoder;
Copy link
Member

Choose a reason for hiding this comment

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

Make them private as well?

Copy link
Member

@jakobbotsch jakobbotsch left a comment

Choose a reason for hiding this comment

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

LGTM. Can you add some documentation on emitDisableGC (using new-style function header) that GC will be disabled only once the next instruction emitted has been executed?

@VSadov
Copy link
Member Author

VSadov commented Jun 24, 2024

Can you add some documentation on emitDisableGC (using new-style function header) that GC will be disabled only once the next instruction emitted has been executed?

Good point, Added.

@VSadov
Copy link
Member Author

VSadov commented Jun 24, 2024

Thanks!!

@VSadov VSadov merged commit 9ef950b into dotnet:main Jun 24, 2024
97 of 106 checks passed
@VSadov VSadov deleted the noGC branch June 24, 2024 20:23
@github-actions github-actions bot locked and limited conversation to collaborators Jul 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants