Skip to content

Commit 9f4d3de

Browse files
Cesar Soares LucasVladimir Kozlov
authored andcommitted
8347718: Unexpected NullPointerException in C2 compiled code due to ReduceAllocationMerges
Reviewed-by: kvn, thartmann
1 parent a224f12 commit 9f4d3de

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

src/hotspot/share/opto/escape.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -981,18 +981,24 @@ void ConnectionGraph::reduce_phi_on_cmp(Node* cmp) {
981981

982982
Node* other = cmp->in(1)->is_Con() ? cmp->in(1) : cmp->in(2);
983983
Node* zero = _igvn->intcon(0);
984+
Node* one = _igvn->intcon(1);
984985
BoolTest::mask mask = cmp->unique_out()->as_Bool()->_test._test;
985986

986987
// This Phi will merge the result of the Cmps split through the Phi
987-
Node* res_phi = _igvn->transform(PhiNode::make(ophi->in(0), zero, TypeInt::INT));
988+
Node* res_phi = PhiNode::make(ophi->in(0), zero, TypeInt::INT);
988989

989990
for (uint i=1; i<ophi->req(); i++) {
990991
Node* ophi_input = ophi->in(i);
991992
Node* res_phi_input = nullptr;
992993

993994
const TypeInt* tcmp = optimize_ptr_compare(ophi_input, other);
994995
if (tcmp->singleton()) {
995-
res_phi_input = _igvn->makecon(tcmp);
996+
if ((mask == BoolTest::mask::eq && tcmp == TypeInt::CC_EQ) ||
997+
(mask == BoolTest::mask::ne && tcmp == TypeInt::CC_GT)) {
998+
res_phi_input = one;
999+
} else {
1000+
res_phi_input = zero;
1001+
}
9961002
} else {
9971003
Node* ncmp = _igvn->transform(cmp->clone());
9981004
ncmp->set_req(1, ophi_input);
@@ -1004,7 +1010,8 @@ void ConnectionGraph::reduce_phi_on_cmp(Node* cmp) {
10041010
res_phi->set_req(i, res_phi_input);
10051011
}
10061012

1007-
Node* new_cmp = _igvn->transform(new CmpINode(res_phi, zero));
1013+
// This CMP always compares whether the output of "res_phi" is TRUE as far as the "mask".
1014+
Node* new_cmp = _igvn->transform(new CmpINode(_igvn->transform(res_phi), (mask == BoolTest::mask::eq) ? one : zero));
10081015
_igvn->replace_node(cmp, new_cmp);
10091016
}
10101017

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8347718
27+
* @summary Check that Reduce Allocation Merges correctly handle "NE" pointer comparisons.
28+
* @requires vm.flagless & vm.compiler2.enabled & vm.opt.final.EliminateAllocations
29+
* @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndPointerComparisons*::*
30+
* -XX:CompileCommand=dontinline,*TestReduceAllocationAndPointerComparisons*::*
31+
* -XX:-TieredCompilation -Xcomp -server
32+
* compiler.c2.TestReduceAllocationAndPointerComparisons
33+
* @run main compiler.c2.TestReduceAllocationAndPointerComparisons
34+
*/
35+
36+
package compiler.c2;
37+
38+
public class TestReduceAllocationAndPointerComparisons {
39+
public static void main(String[] args) {
40+
for (int i=0; i<50000; i++) {
41+
if (test(true) == false) {
42+
throw new RuntimeException("Unexpected result.");
43+
}
44+
}
45+
}
46+
47+
public static boolean test(boolean b) {
48+
MyClass obj = new MyClass();
49+
50+
for (int i = 0; i < 100_000; ++i) { }
51+
52+
obj = b ? obj : new MyClass();
53+
obj = b ? obj : new MyClass();
54+
55+
if (obj == null) {
56+
return false;
57+
}
58+
59+
return b;
60+
}
61+
62+
static class MyClass {
63+
}
64+
}

0 commit comments

Comments
 (0)