Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

Commit

Permalink
8285835: SIGSEGV in PhaseIdealLoop::build_loop_late_post_work
Browse files Browse the repository at this point in the history
Backport-of: 8aa1526b443025b8606a3668262f46a9cb6ea6f6
  • Loading branch information
TobiHartmann committed Nov 23, 2022
1 parent 4708c7b commit 3f3bbdf
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 10 deletions.
70 changes: 60 additions & 10 deletions src/hotspot/share/opto/escape.cpp
Expand Up @@ -281,7 +281,9 @@ bool ConnectionGraph::compute_escape() {
// 3. Adjust scalar_replaceable state of nonescaping objects and push
// scalar replaceable allocations on alloc_worklist for processing
// in split_unique_types().
GrowableArray<JavaObjectNode*> jobj_worklist;
int non_escaped_length = non_escaped_allocs_worklist.length();
bool found_nsr_alloc = false;
for (int next = 0; next < non_escaped_length; next++) {
JavaObjectNode* ptn = non_escaped_allocs_worklist.at(next);
bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
Expand All @@ -292,11 +294,25 @@ bool ConnectionGraph::compute_escape() {
if (noescape && ptn->scalar_replaceable()) {
adjust_scalar_replaceable_state(ptn);
if (ptn->scalar_replaceable()) {
alloc_worklist.append(ptn->ideal_node());
jobj_worklist.push(ptn);
} else {
found_nsr_alloc = true;
}
}
}

// Propagate NSR (Not Scalar Replaceable) state.
if (found_nsr_alloc) {
find_scalar_replaceable_allocs(jobj_worklist);
}

for (int next = 0; next < jobj_worklist.length(); ++next) {
JavaObjectNode* jobj = jobj_worklist.at(next);
if (jobj->scalar_replaceable()) {
alloc_worklist.append(jobj->ideal_node());
}
}

#ifdef ASSERT
if (VerifyConnectionGraph) {
// Verify that graph is complete - no new edges could be added or needed.
Expand Down Expand Up @@ -1865,15 +1881,19 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored at unknown offset"));
return;
}
// 2. An object is not scalar replaceable if the field into which it is
// stored has multiple bases one of which is null.
if (field->base_count() > 1) {
for (BaseIterator i(field); i.has_next(); i.next()) {
PointsToNode* base = i.get();
if (base == null_obj) {
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
return;
}
for (BaseIterator i(field); i.has_next(); i.next()) {
PointsToNode* base = i.get();
// 2. An object is not scalar replaceable if the field into which it is
// stored has multiple bases one of which is null.
if ((base == null_obj) && (field->base_count() > 1)) {
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base"));
return;
}
// 2.5. An object is not scalar replaceable if the field into which it is
// stored has NSR base.
if (!base->scalar_replaceable()) {
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
return;
}
}
}
Expand Down Expand Up @@ -1963,6 +1983,36 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
}
}

// Propagate NSR (Not scalar replaceable) state.
void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist) {
int jobj_length = jobj_worklist.length();
bool found_nsr_alloc = true;
while (found_nsr_alloc) {
found_nsr_alloc = false;
for (int next = 0; next < jobj_length; ++next) {
JavaObjectNode* jobj = jobj_worklist.at(next);
for (UseIterator i(jobj); (jobj->scalar_replaceable() && i.has_next()); i.next()) {
PointsToNode* use = i.get();
if (use->is_Field()) {
FieldNode* field = use->as_Field();
assert(field->is_oop() && field->scalar_replaceable(), "sanity");
assert(field->offset() != Type::OffsetBot, "sanity");
for (BaseIterator i(field); i.has_next(); i.next()) {
PointsToNode* base = i.get();
// An object is not scalar replaceable if the field into which
// it is stored has NSR base.
if ((base != null_obj) && !base->scalar_replaceable()) {
set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with NSR base"));
found_nsr_alloc = true;
break;
}
}
}
}
}
}
}

#ifdef ASSERT
void ConnectionGraph::verify_connection_graph(
GrowableArray<PointsToNode*>& ptnodes_worklist,
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/opto/escape.hpp
Expand Up @@ -463,6 +463,9 @@ class ConnectionGraph: public ResourceObj {
// Adjust scalar_replaceable state after Connection Graph is built.
void adjust_scalar_replaceable_state(JavaObjectNode* jobj);

// Propagate NSR (Not scalar replaceable) state.
void find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist);

// Optimize ideal graph.
void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
GrowableArray<MemBarStoreStoreNode*>& storestore_worklist);
Expand Down
82 changes: 82 additions & 0 deletions test/hotspot/jtreg/compiler/escapeAnalysis/TestBrokenEA.java
@@ -0,0 +1,82 @@
/* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8285835
* @summary EA does not propagate NSR (not scalar replaceable) state.
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBrokenEA
*/

public class TestBrokenEA {

public static void main(String[] args) {
for (int i = 0; i < 20_000; i++) {
test1(true);
test1(false);
test2(true);
test2(false);
}
}

private static void test1(boolean flag) {
A[] array = new A[1];
if (flag) {
C c = new C();
B b = new B();
b.c = c;
A a = new A();
a.b = b;
array[0] = a;
}
A a = array[0];
if (a != null) {
a.b.c.f = 0x42;
}
}

private static void test2(boolean flag) {
A a = null;
if (flag) {
C c = new C();
B b = new B();
b.c = c;
a = new A();
a.b = b;
}
if (a != null) {
a.b.c.f = 0x42;
}
}

private static class A {
public B b;
}

private static class B {
public C c;
}

private static class C {
public int f;
}
}

1 comment on commit 3f3bbdf

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.