8357381: C2: assert(false) failed: should not be here - #31037
Conversation
|
👋 Welcome back snatarajan! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
|
The total number of required reviews for this PR has been set to 2 based on the presence of this label: |
Webrevs
|
| } else if (use->Opcode() == Op_AryEq || use->Opcode() == Op_StrComp || use->Opcode() == Op_CountPositives || | ||
| use->Opcode() == Op_StrEquals || use->Opcode() == Op_StrIndexOf || use->Opcode() == Op_StrIndexOfChar) { |
There was a problem hiding this comment.
Can you add a new method to combine these check into one place and use it here and other places where which check these intrinsics?
| if (alias_idx == general_idx) | ||
| continue; |
There was a problem hiding this comment.
Could you add braces here?
| uint orig_uniq = C->unique(); | ||
| Node* m = find_inst_mem(n, general_idx, orig_phis); | ||
| assert(orig_uniq == C->unique(), "no new nodes"); | ||
| igvn->hash_delete(use); | ||
| imax -= use->replace_edge(n, m, igvn); | ||
| igvn->hash_insert(use); | ||
| record_for_optimizer(use); | ||
| --i; |
There was a problem hiding this comment.
Also this pattern (or part of it) seems quite repeated across this if...else. Maybe it would it be worth extracting it?
|
And... I think adding a regression test for this would be easy 😉, and probably worth it |
| return result; | ||
| } | ||
|
|
||
| Node* ConnectionGraph::find_inst_mem_assert_no_new_node(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis) { |
There was a problem hiding this comment.
| Node* ConnectionGraph::find_inst_mem_assert_no_new_node(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis) { | |
| Node* ConnectionGraph::find_inst_mem_assert_no_new_node(Node* orig_mem, int alias_idx, GrowableArray<PhiNode*>& orig_phis) { |
|
|
||
| void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis); | ||
| Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, uint rec_depth = 0); | ||
| Node* find_inst_mem_assert_no_new_node(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist); |
There was a problem hiding this comment.
| Node* find_inst_mem_assert_no_new_node(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist); | |
| Node* find_inst_mem_assert_no_new_node(Node* mem, int alias_idx,GrowableArray<PhiNode*>& orig_phi_worklist); |
|
Added the test from JDK-8384257 (which is a duplicate) to the regression test as suggested by @chhagedorn. |
| * @test | ||
| * @bug 8357381 | ||
| * @summary C2 compilation fails with C2: assert(false) failed: should not be here | ||
| * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestReadOnlyStringIntrinsicDuringEA::main |
There was a problem hiding this comment.
Why you need -XX:+UnlockDiagnosticVMOptions ?
You also need @requires vm.compiler2.enabled I think.
Compile only main will produce only OSR compilation. Is 10K iterations is enough for that?
Consider using -XX:CompileThreshold=n to reduce number of iterations to trigger C2 compilation early.
There was a problem hiding this comment.
Thank you for the review. I removed -XX:+UnlockDiagnosticVMOptions and made modifications to address your comments.
|
@sarannat please see GHA failures: |
| } | ||
|
|
||
| public static void main(String[] strArr) { | ||
| for (int t = 0; t < 100_000; t++) { |
There was a problem hiding this comment.
Do we also need 100000 iterations now that CompileThreshold is in place?
anton-seoane
left a comment
There was a problem hiding this comment.
I think this looks good now
| op == Op_AryEq || op == Op_StrComp || op == Op_CountPositives || | ||
| op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || op == Op_VectorizedHashCode || | ||
| op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) { | ||
| is_mem_read_only_string_intrinsic(use) || op == Op_VectorizedHashCode || |
There was a problem hiding this comment.
What about EncodeISOArray? Should it receive similar treatment?
| return result; | ||
| } | ||
|
|
||
| bool ConnectionGraph::is_mem_read_only_string_intrinsic(Node* n) { |
There was a problem hiding this comment.
This name is a little misleading, AryEq is not a string intrinsic, for example, and why is VectorizedHashCode not here?
|
@sarannat this pull request can not be integrated into git checkout JDK-8357381
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
|
@sarannat Are you planning to keep working on this? I'd assume not? @merykitty @vnkozlov It would be a shame if this patch was dropped. We should see that someone picks it up and brings it over the finish line, with proper attribution. |
|
@eme64 : Thank you for the reminder. I do plan to see this PR to completion. I will start addressing the comments and merge-conflicts this week. |
|
@sarannat This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a |
|
@sarannat This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
|
@sarannat Are you still interested in working on this? |
|
Reopened with #32467. |
Issue
The assertion
assert(false, "should not be here")inConnectionGraph::move_inst_memfires because aStoreBnode hasStrEqualsas a memory user.Analysis
The main issues starts after the first iteration of iterative escape analysis. As mentioned in JDK-8357381, EA#0 does lock removal. During IGVN after EA#0, the string intrinsic node
StrEqualundergoes an ideal transformation (StrIntrinsicNode::Ideal()) which peels itsMergeMeminput node. At this pointStoreBbecomes a direct input ofStrEquals.Now EA#1 runs on the transformed graph. Phase 2 of
split_unique_typesexplicitly allowsStrEqualsas a user ofStoreB. In Phase 4,split_unique_typesthen callsmove_inst_memwhich is responsible for moving memory users to their memory slices. However,move_inst_memonly handlesMergeMem,MemBar,Mem, andPhias memory user. Since,StrEqualsis not handled inmove_inst_memeven though it is allowed in Phase 2 ofsplit_unique_typesit fires the assertionassert(false, "should not be here").Solution
In the proposed fix, I have extended
move_inst_memto move string intrinsic nodes that are explicitly allowed in Phase 2 ofsplit_unique_typeto their appropriate memory slices.Testing
Tier1-3 and Github actions
Question to reviewers
Please let me know if this fix looks reasonable.
Thank you @danielogh for the initial analysis.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/31037/head:pull/31037$ git checkout pull/31037Update a local copy of the PR:
$ git checkout pull/31037$ git pull https://git.openjdk.org/jdk.git pull/31037/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 31037View PR using the GUI difftool:
$ git pr show -t 31037Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/31037.diff
Using Webrev
Link to Webrev Comment