Skip to content

Commit 6faa77c

Browse files
committed
8285835: SIGSEGV in PhaseIdealLoop::build_loop_late_post_work
Reviewed-by: phh Backport-of: 3e7f840859d9081fc6cf1086bda75fa5aa76a4e9
1 parent c20794c commit 6faa77c

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
@@ -242,7 +242,9 @@ bool ConnectionGraph::compute_escape() {
242242
// 3. Adjust scalar_replaceable state of nonescaping objects and push
243243
// scalar replaceable allocations on alloc_worklist for processing
244244
// in split_unique_types().
245+
GrowableArray<JavaObjectNode*> jobj_worklist;
245246
int non_escaped_length = non_escaped_worklist.length();
247+
bool found_nsr_alloc = false;
246248
for (int next = 0; next < non_escaped_length; next++) {
247249
JavaObjectNode* ptn = non_escaped_worklist.at(next);
248250
bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
@@ -256,11 +258,25 @@ bool ConnectionGraph::compute_escape() {
256258
if (noescape && ptn->scalar_replaceable()) {
257259
adjust_scalar_replaceable_state(ptn);
258260
if (ptn->scalar_replaceable()) {
259-
alloc_worklist.append(ptn->ideal_node());
261+
jobj_worklist.push(ptn);
262+
} else {
263+
found_nsr_alloc = true;
260264
}
261265
}
262266
}
263267

268+
// Propagate NSR (Not Scalar Replaceable) state.
269+
if (found_nsr_alloc) {
270+
find_scalar_replaceable_allocs(jobj_worklist);
271+
}
272+
273+
for (int next = 0; next < jobj_worklist.length(); ++next) {
274+
JavaObjectNode* jobj = jobj_worklist.at(next);
275+
if (jobj->scalar_replaceable()) {
276+
alloc_worklist.append(jobj->ideal_node());
277+
}
278+
}
279+
264280
#ifdef ASSERT
265281
if (VerifyConnectionGraph) {
266282
// Verify that graph is complete - no new edges could be added or needed.
@@ -1759,15 +1775,19 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
17591775
jobj->set_scalar_replaceable(false);
17601776
return;
17611777
}
1762-
// 2. An object is not scalar replaceable if the field into which it is
1763-
// stored has multiple bases one of which is null.
1764-
if (field->base_count() > 1) {
1765-
for (BaseIterator i(field); i.has_next(); i.next()) {
1766-
PointsToNode* base = i.get();
1767-
if (base == null_obj) {
1768-
jobj->set_scalar_replaceable(false);
1769-
return;
1770-
}
1778+
for (BaseIterator i(field); i.has_next(); i.next()) {
1779+
PointsToNode* base = i.get();
1780+
// 2. An object is not scalar replaceable if the field into which it is
1781+
// stored has multiple bases one of which is null.
1782+
if ((base == null_obj) && (field->base_count() > 1)) {
1783+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
1784+
return;
1785+
}
1786+
// 2.5. An object is not scalar replaceable if the field into which it is
1787+
// stored has NSR base.
1788+
if (!base->scalar_replaceable()) {
1789+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
1790+
return;
17711791
}
17721792
}
17731793
}
@@ -1857,6 +1877,36 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
18571877
}
18581878
}
18591879

1880+
// Propagate NSR (Not scalar replaceable) state.
1881+
void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist) {
1882+
int jobj_length = jobj_worklist.length();
1883+
bool found_nsr_alloc = true;
1884+
while (found_nsr_alloc) {
1885+
found_nsr_alloc = false;
1886+
for (int next = 0; next < jobj_length; ++next) {
1887+
JavaObjectNode* jobj = jobj_worklist.at(next);
1888+
for (UseIterator i(jobj); (jobj->scalar_replaceable() && i.has_next()); i.next()) {
1889+
PointsToNode* use = i.get();
1890+
if (use->is_Field()) {
1891+
FieldNode* field = use->as_Field();
1892+
assert(field->is_oop() && field->scalar_replaceable(), "sanity");
1893+
assert(field->offset() != Type::OffsetBot, "sanity");
1894+
for (BaseIterator i(field); i.has_next(); i.next()) {
1895+
PointsToNode* base = i.get();
1896+
// An object is not scalar replaceable if the field into which
1897+
// it is stored has NSR base.
1898+
if ((base != null_obj) && !base->scalar_replaceable()) {
1899+
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
1900+
found_nsr_alloc = true;
1901+
break;
1902+
}
1903+
}
1904+
}
1905+
}
1906+
}
1907+
}
1908+
}
1909+
18601910
#ifdef ASSERT
18611911
void ConnectionGraph::verify_connection_graph(
18621912
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);
@@ -582,6 +585,11 @@ class ConnectionGraph: public ResourceObj {
582585
// Compute the escape information
583586
bool compute_escape();
584587

588+
void set_not_scalar_replaceable(PointsToNode* ptn NOT_PRODUCT(COMMA const char* reason)) const {
589+
ptn->set_scalar_replaceable(false);
590+
}
591+
592+
585593
public:
586594
ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
587595

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)