-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
8323274: C2: array load may float above range check #17635
Conversation
👋 Welcome back roland! A progress list of the required criteria for merging this PR into |
Webrevs
|
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.
Generally looks reasonable, I'm mostly suggesting cosmetic changes.
try { | ||
test1(allTrue, array, -1, true, 0); | ||
test2(allTrue, array, -1, true, 0); | ||
} catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { |
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.
Is there a reason both are together in the same try-catch
block? It seems like if the first throws, then the second is never executed (and may as well be removed), or we only expect the second to throw, and so the first one should be outside the bock. What do you think?
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.
You're right. I will change that.
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
src/hotspot/share/opto/loopnode.hpp
Outdated
@@ -1739,6 +1739,8 @@ class PhaseIdealLoop : public PhaseTransform { | |||
void update_addp_chain_base(Node* x, Node* old_base, Node* new_base); | |||
|
|||
bool can_move_to_inner_loop(Node* n, LoopNode* n_loop, Node* x); | |||
|
|||
void pin_array_access_nodes(Node* ctrl); |
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.
void pin_array_access_nodes(Node* ctrl); | |
void pin_array_access_nodes_dependent_on(Node* ctrl); |
Does this even build without?
@rwestrel just ping me again when I should re-review ;) |
Co-authored-by: Emanuel Peter <emanuel.peter@oracle.com>
I updated the change and it's ready for another review. |
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.
Thanks for the updates @rwestrel , looks good to me now 😊
@rwestrel 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:
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 287 new commits pushed to the
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 |
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.
Great analysis, Roland. The fix looks good to me. I'll run correctness and performance testing and report back.
All tests passed. No performance regression detected. |
@eme64 @TobiHartmann thanks for the reviews and testing. |
/integrate |
Going to push as commit 4406915.
Your commit was automatically rebased without conflicts. |
This PR includes 5 test cases in which an array load floats above its
range check and the resulting compiled code can be made to segfault by
passing an out of bound index to the test method. Each test case takes
advantage of a different transformation to make the array load happen
too early:
For instance, with TestArrayAccessAboveRCAfterSplitIf:
The range check is split through phi:
Then an identical dominating range check is found:
Then a branch dies:
The array load is dependent on the
if (l == m) {
condition. Anidentical dominating condition is then found which causes the control
dependent range check to float above the range check.
Something similar can be triggered with:
TestArrayAccessAboveRCAfterPartialPeeling: sometimes, during partial
peeling a load is assigned the loop head as control so something
gets in between the range check and an array load and steps similar
to the above can cause the array load to float above its range check.
TestArrayAccessAboveRCAfterUnswitching: cloning a loop body adds
regions on exits of the loop and nodes that only have uses out of
the loop can end up control dependent on one of the regions. In the
test case, unswitching is what causes the cloning to happen. Again
similar steps as above make the array load floats above its range
check. I suppose similar bugs could be triggered with other loop
transformations that rely on loop body cloning.
TestArrayAccessAboveRCAfterSinking is a bit different in that it can
change the control of an array load to be the projection of some
arbitrary test. That test can then be replaced by a dominating one
causing the array to float.
Finally, in TestArrayAccessAboveRCForArrayCopyLoad, an array copy is
converted to a series of loads/stores that's guarded by a test for
srcPos < dstPos
. A dominating identical test exists so an array loadfloats above the runtime checks that guarantee the arraycopy is legal.
In all cases, the fix I propose is similar to 8319793: mark the array
access nodes pinned when the transformation happens.
This might be over conservative in some cases. I intend to address
some of that with: 8324976 (C2: allow array loads known to be within
bounds to float) which would set a load's control to null in the cases
when it is known to be within bounds.
I've also been working on a verification pass to catch these issues. I
intend to propose it later.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/17635/head:pull/17635
$ git checkout pull/17635
Update a local copy of the PR:
$ git checkout pull/17635
$ git pull https://git.openjdk.org/jdk.git pull/17635/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 17635
View PR using the GUI difftool:
$ git pr show -t 17635
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/17635.diff
Webrev
Link to Webrev Comment