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

8277529: SIGSEGV in C2 CompilerThread Node::rematerialize() compiling Packet::readUnsignedTrint #6670

Closed
wants to merge 2 commits into from

Conversation

chhagedorn
Copy link
Member

@chhagedorn chhagedorn commented Dec 2, 2021

This bug was found in internal testing for 17.0.2 after the backport of JDK-8272574. The fix rewires a control input of a split load node through a phi to the same control input as the corresponding memory input into the phi node:

if (this->in(0) == region) {
if (mem->is_Phi() && (mem->in(0) == region) && mem->in(i)->in(0) != NULL &&
MemNode::all_controls_dominate(address, region)) {
// Enable other optimizations such as loop predication which does not work
// if we directly pin the node to node `in`
x->set_req(0, mem->in(i)->in(0)); // Use same control as memory
} else {
x->set_req(0, in);
}

This can lead to an illegal control input for the new load if mem->in(i) is a projection. This situation occurs in the test case: mem->in(i) is a projection of an ArrayCopy node. Having an ArrayCopy node as control input is unexpected and we later fail with an assertion (in product we crash with a segfault).

My initial thought was to just not apply the improved rewiring for memory projections and fall back to the else case on L1636. However, this also does not work as we could then wrongly move a range check out of a loop and creating a cyclic dependency (case described in the review of JDK-8272574) and reproduced with test2() where we hit:

assert(false, "cyclic dependency prevents range check elimination, idx: offset %d, offset_ctrl %d, predicate_proj %d",
offset->_idx, offset_ctrl->_idx, predicate_proj->_idx);

During this analysis I came across the fix for JDK-8146792 which should actually prevent loop predication if we have a data dependency on the projection into a loop. But this does not seem to work correctly as shown in the test case found for JDK-8272574. In the review of JDK-8272574, it was missed that the actual problem could have been traced back to JDK-8146792 and instead we went for an improvement for loads split through phis to not end up with cases supposed to be fixed by JDK-8146972 (which now also causes other problems). But the root problem is still there to be fixed.

I therefore propose to completely undo the fix for JDK-8272574 for now and go for a fix on top of JDK-8146972 to fix JDK-8272574 and also prevent this bug. The assertion code added by JDK-8272574 is still good to have. I suggest to revisit the improved rewiring for loads done with JDK-8272574 in an RFE. I think it should still be beneficial but requires some more careful checking (to avoid the problems reported in this bug).

Explanation of JDK-8272574 with regard to JDK-8146972 (covered by test2-5()):

When deciding if we can apply loop predication to a check inside the loop, we call IdealLoopTree::is_range_check(). This method calls PhaseIdealLoop::is_scaled_iv_plus_offset() which can create new nodes for the offset:

Node* offset = AddNode::make(offset2, exp->in(2), bt);
register_new_node(offset, ctrl_off2);
*p_offset = offset;

get_ctrl() of these new nodes could also be the incoming projection into a loop. But these nodes are not marked as non-loop-invariant as done for the other nodes in Invariant::Invariant():
if (entry->outcnt() != 1) {
// If a node is pinned between the predicates and the loop
// entry, we won't be able to move any node in the loop that
// depends on it above it in a predicate. Mark all those nodes
// as non loop invariatnt.

The proposed fix keeps track when above code was applied (data_dependency_on is set) and does an additional checking for get_ctrl() accordingly if a new node was created for the offset in PhaseIdealLoop::is_scaled_iv_plus_offset(). This should be fine as we are not using the newly created offset node anymore after doing that check.

In discussions with Roland, we think that we should revisit this fix and the fix of JDK-8146972 and clean them up to directly do the invariant checks in compute_invariance()/visit() without special handling in the constructor. But given the deadline of 17.0.2 and the fork soon coming up for 18, we think it's the most safe way to go with the proposed fix - if others agree.

Thanks,
Christian


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8277529: SIGSEGV in C2 CompilerThread Node::rematerialize() compiling Packet::readUnsignedTrint

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6670/head:pull/6670
$ git checkout pull/6670

Update a local copy of the PR:
$ git checkout pull/6670
$ git pull https://git.openjdk.java.net/jdk pull/6670/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 6670

View PR using the GUI difftool:
$ git pr show -t 6670

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6670.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Dec 2, 2021

👋 Welcome back chagedorn! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Dec 2, 2021

@chhagedorn The following label will be automatically applied to this pull request:

  • hotspot-compiler

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.org label Dec 2, 2021
@chhagedorn chhagedorn marked this pull request as ready for review December 2, 2021 14:06
@openjdk openjdk bot added the rfr Pull request is ready for review label Dec 2, 2021
@mlbridge
Copy link

mlbridge bot commented Dec 2, 2021

Webrevs

Comment on lines 775 to 776
if (is_range_check_if(iff, phase, T_INT, iv, range, offset, scale)) {
if (!invar.is_invariant(range)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

First, the fix is reasonable to me.

My only complain is original code flow. If we do return false; for each check we should the same for is_range_check_if() check instead of returning false at the very end you lost logic why it is false.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for your review Vladimir! Good point, I changed that into a direct bailout.

Copy link
Member

@TobiHartmann TobiHartmann left a comment

Choose a reason for hiding this comment

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

Nice analysis and test. Looks good to me.

@openjdk
Copy link

openjdk bot commented Dec 3, 2021

@chhagedorn This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8277529: SIGSEGV in C2 CompilerThread Node::rematerialize() compiling Packet::readUnsignedTrint

Reviewed-by: thartmann, roland, kvn

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 95 new commits pushed to the master branch:

  • fbf096e: 8251400: Fix incorrect addition of library to test in JDK-8237858
  • 0a09092: 8268288: jdk/jfr/api/consumer/streaming/TestOutOfProcessMigration.java fails with "Error: ShouldNotReachHere()"
  • 0d938ce: 8278172: java/nio/channels/FileChannel/BlockDeviceSize.java should only run on Linux
  • 0e7b6bc: 8278141: LIR_OpLoadKlass::_info shadows the field of the same name from LIR_Op
  • 53a4342: 8278137: JFR: PrettyWriter uses incorrect year specifier
  • f723779: 8278079: C2: expand_dtrace_alloc_probe doesn't take effect in macro.cpp
  • 3f28a21: 8278144: Javadoc for MemorySegment::set/MemorySegment::setAtIndex is missing throws tag
  • ba2a8e5: 8278205: jlink plugins should dump .class file in debug mode
  • 18c54b4: 8274640: Cleanup unnecessary null comparison before instanceof check in java.desktop
  • dda8f26: 8278139: G1: Refactor G1BlockOffsetTablePart::block_at_or_preceding
  • ... and 85 more: https://git.openjdk.java.net/jdk/compare/3d39f09c6cdc875b44147b4e84e496b6abf93996...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 3, 2021
@chhagedorn
Copy link
Member Author

Thanks Tobias for your review!

Copy link
Contributor

@rwestrel rwestrel left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@chhagedorn
Copy link
Member Author

Thanks Roland for your review and the offline discussion about it. I will file an RFE once it is integrated to clean it up in JDK 19.

Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

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

Update looks good.

@chhagedorn
Copy link
Member Author

Thanks Vladimir for your review!

@chhagedorn
Copy link
Member Author

/integrate

@openjdk
Copy link

openjdk bot commented Dec 3, 2021

Going to push as commit 01cb2b9.
Since your change was applied there have been 97 commits pushed to the master branch:

  • 660f21a: 8278119: ProblemList few headful test failing in macosx12-aarch64 system
  • 2e30fa9: 8278171: [vectorapi] Mask incorrectly computed for zero extending cast
  • fbf096e: 8251400: Fix incorrect addition of library to test in JDK-8237858
  • 0a09092: 8268288: jdk/jfr/api/consumer/streaming/TestOutOfProcessMigration.java fails with "Error: ShouldNotReachHere()"
  • 0d938ce: 8278172: java/nio/channels/FileChannel/BlockDeviceSize.java should only run on Linux
  • 0e7b6bc: 8278141: LIR_OpLoadKlass::_info shadows the field of the same name from LIR_Op
  • 53a4342: 8278137: JFR: PrettyWriter uses incorrect year specifier
  • f723779: 8278079: C2: expand_dtrace_alloc_probe doesn't take effect in macro.cpp
  • 3f28a21: 8278144: Javadoc for MemorySegment::set/MemorySegment::setAtIndex is missing throws tag
  • ba2a8e5: 8278205: jlink plugins should dump .class file in debug mode
  • ... and 87 more: https://git.openjdk.java.net/jdk/compare/3d39f09c6cdc875b44147b4e84e496b6abf93996...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot closed this Dec 3, 2021
@openjdk openjdk bot added integrated Pull request has been integrated and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Dec 3, 2021
@openjdk
Copy link

openjdk bot commented Dec 3, 2021

@chhagedorn Pushed as commit 01cb2b9.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@chhagedorn chhagedorn deleted the JDK-8277529 branch August 8, 2022 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot-compiler hotspot-compiler-dev@openjdk.org integrated Pull request has been integrated
4 participants