Skip to content

Commit 3e7f840

Browse files
committed
8285835: SIGSEGV in PhaseIdealLoop::build_loop_late_post_work
Reviewed-by: mdoerr Backport-of: 8aa1526b443025b8606a3668262f46a9cb6ea6f6
1 parent 95f23f7 commit 3e7f840

File tree

3 files changed

+150
-10
lines changed

3 files changed

+150
-10
lines changed

src/hotspot/share/opto/escape.cpp

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ bool ConnectionGraph::compute_escape() {
240240
// 3. Adjust scalar_replaceable state of nonescaping objects and push
241241
// scalar replaceable allocations on alloc_worklist for processing
242242
// in split_unique_types().
243+
GrowableArray<JavaObjectNode*> jobj_worklist;
243244
int non_escaped_length = non_escaped_allocs_worklist.length();
245+
bool found_nsr_alloc = false;
244246
for (int next = 0; next < non_escaped_length; next++) {
245247
JavaObjectNode* ptn = non_escaped_allocs_worklist.at(next);
246248
bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
@@ -251,11 +253,25 @@ bool ConnectionGraph::compute_escape() {
251253
if (noescape && ptn->scalar_replaceable()) {
252254
adjust_scalar_replaceable_state(ptn);
253255
if (ptn->scalar_replaceable()) {
254-
alloc_worklist.append(ptn->ideal_node());
256+
jobj_worklist.push(ptn);
257+
} else {
258+
found_nsr_alloc = true;
255259
}
256260
}
257261
}
258262

263+
// Propagate NSR (Not Scalar Replaceable) state.
264+
if (found_nsr_alloc) {
265+
find_scalar_replaceable_allocs(jobj_worklist);
266+
}
267+
268+
for (int next = 0; next < jobj_worklist.length(); ++next) {
269+
JavaObjectNode* jobj = jobj_worklist.at(next);
270+
if (jobj->scalar_replaceable()) {
271+
alloc_worklist.append(jobj->ideal_node());
272+
}
273+
}
274+
259275
#ifdef ASSERT
260276
if (VerifyConnectionGraph) {
261277
// Verify that graph is complete - no new edges could be added or needed.
@@ -1840,15 +1856,19 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
18401856
jobj->set_scalar_replaceable(false);
18411857
return;
18421858
}
1843-
// 2. An object is not scalar replaceable if the field into which it is
1844-
// stored has multiple bases one of which is null.
1845-
if (field->base_count() > 1) {
1846-
for (BaseIterator i(field); i.has_next(); i.next()) {
1847-
PointsToNode* base = i.get();
1848-
if (base == null_obj) {
1849-
jobj->set_scalar_replaceable(false);
1850-
return;
1851-
}
1859+
for (BaseIterator i(field); i.has_next(); i.next()) {
1860+
PointsToNode* base = i.get();
1861+
// 2. An object is not scalar replaceable if the field into which it is
1862+
// stored has multiple bases one of which is null.
1863+
if ((base == null_obj) && (field->base_count() > 1)) {
1864+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
1865+
return;
1866+
}
1867+
// 2.5. An object is not scalar replaceable if the field into which it is
1868+
// stored has NSR base.
1869+
if (!base->scalar_replaceable()) {
1870+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
1871+
return;
18521872
}
18531873
}
18541874
}
@@ -1938,6 +1958,36 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
19381958
}
19391959
}
19401960

1961+
// Propagate NSR (Not scalar replaceable) state.
1962+
void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist) {
1963+
int jobj_length = jobj_worklist.length();
1964+
bool found_nsr_alloc = true;
1965+
while (found_nsr_alloc) {
1966+
found_nsr_alloc = false;
1967+
for (int next = 0; next < jobj_length; ++next) {
1968+
JavaObjectNode* jobj = jobj_worklist.at(next);
1969+
for (UseIterator i(jobj); (jobj->scalar_replaceable() && i.has_next()); i.next()) {
1970+
PointsToNode* use = i.get();
1971+
if (use->is_Field()) {
1972+
FieldNode* field = use->as_Field();
1973+
assert(field->is_oop() && field->scalar_replaceable(), "sanity");
1974+
assert(field->offset() != Type::OffsetBot, "sanity");
1975+
for (BaseIterator i(field); i.has_next(); i.next()) {
1976+
PointsToNode* base = i.get();
1977+
// An object is not scalar replaceable if the field into which
1978+
// it is stored has NSR base.
1979+
if ((base != null_obj) && !base->scalar_replaceable()) {
1980+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
1981+
found_nsr_alloc = true;
1982+
break;
1983+
}
1984+
}
1985+
}
1986+
}
1987+
}
1988+
}
1989+
}
1990+
19411991
#ifdef ASSERT
19421992
void ConnectionGraph::verify_connection_graph(
19431993
GrowableArray<PointsToNode*>& ptnodes_worklist,

src/hotspot/share/opto/escape.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ class ConnectionGraph: public ResourceObj {
456456
// Adjust scalar_replaceable state after Connection Graph is built.
457457
void adjust_scalar_replaceable_state(JavaObjectNode* jobj);
458458

459+
// Propagate NSR (Not scalar replaceable) state.
460+
void find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist);
461+
459462
// Optimize ideal graph.
460463
void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
461464
GrowableArray<Node*>& storestore_worklist);
@@ -569,6 +572,11 @@ class ConnectionGraph: public ResourceObj {
569572
// Compute the escape information
570573
bool compute_escape();
571574

575+
void set_not_scalar_replaceable(PointsToNode* ptn NOT_PRODUCT(COMMA const char* reason)) const {
576+
ptn->set_scalar_replaceable(false);
577+
}
578+
579+
572580
public:
573581
ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
574582

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
/*
24+
* @test
25+
* @bug 8285835
26+
* @summary EA does not propagate NSR (not scalar replaceable) state.
27+
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBrokenEA
28+
*/
29+
30+
public class TestBrokenEA {
31+
32+
public static void main(String[] args) {
33+
for (int i = 0; i < 20_000; i++) {
34+
test1(true);
35+
test1(false);
36+
test2(true);
37+
test2(false);
38+
}
39+
}
40+
41+
private static void test1(boolean flag) {
42+
A[] array = new A[1];
43+
if (flag) {
44+
C c = new C();
45+
B b = new B();
46+
b.c = c;
47+
A a = new A();
48+
a.b = b;
49+
array[0] = a;
50+
}
51+
A a = array[0];
52+
if (a != null) {
53+
a.b.c.f = 0x42;
54+
}
55+
}
56+
57+
private static void test2(boolean flag) {
58+
A a = null;
59+
if (flag) {
60+
C c = new C();
61+
B b = new B();
62+
b.c = c;
63+
a = new A();
64+
a.b = b;
65+
}
66+
if (a != null) {
67+
a.b.c.f = 0x42;
68+
}
69+
}
70+
71+
private static class A {
72+
public B b;
73+
}
74+
75+
private static class B {
76+
public C c;
77+
}
78+
79+
private static class C {
80+
public int f;
81+
}
82+
}

0 commit comments

Comments
 (0)