Skip to content

Commit cc65d0d

Browse files
Dan LutkerPaul Hohensee
Dan Lutker
authored and
Paul Hohensee
committed
8325372: Shenandoah: SIGSEGV crash in unnecessary_acquire due to LoadStore split through phi
Reviewed-by: shade Backport-of: 5d414da50459b7a1e6f0f537ff3b318854b2c427
1 parent 6d8d049 commit cc65d0d

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,11 +1728,26 @@ bool ShenandoahBarrierC2Support::identical_backtoback_ifs(Node* n, PhaseIdealLoo
17281728
return true;
17291729
}
17301730

1731+
bool ShenandoahBarrierC2Support::merge_point_safe(Node* region) {
1732+
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
1733+
Node* n = region->fast_out(i);
1734+
if (n->is_LoadStore()) {
1735+
// Splitting a LoadStore node through phi, causes it to lose its SCMemProj: the split if code doesn't have support
1736+
// for a LoadStore at the region the if is split through because that's not expected to happen (LoadStore nodes
1737+
// should be between barrier nodes). It does however happen with Shenandoah though because barriers can get
1738+
// expanded around a LoadStore node.
1739+
return false;
1740+
}
1741+
}
1742+
return true;
1743+
}
1744+
1745+
17311746
void ShenandoahBarrierC2Support::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) {
17321747
assert(is_heap_stable_test(n), "no other tests");
17331748
if (identical_backtoback_ifs(n, phase)) {
17341749
Node* n_ctrl = n->in(0);
1735-
if (phase->can_split_if(n_ctrl)) {
1750+
if (phase->can_split_if(n_ctrl) && merge_point_safe(n_ctrl)) {
17361751
IfNode* dom_if = phase->idom(n_ctrl)->as_If();
17371752
if (is_heap_stable_test(n)) {
17381753
Node* gc_state_load = n->in(1)->in(1)->in(1)->in(1);

src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class ShenandoahBarrierC2Support : public AllStatic {
6565
static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
6666
static void move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase);
6767
static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase);
68+
static bool merge_point_safe(Node* region);
6869
static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase);
6970
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
7071
static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase);

src/hotspot/share/opto/memnode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3336,6 +3336,7 @@ Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) {
33363336
my_mem = load_node;
33373337
} else {
33383338
assert(my_mem->unique_out() == this, "sanity");
3339+
assert(!trailing_load_store(), "load store node can't be eliminated");
33393340
del_req(Precedent);
33403341
phase->is_IterGVN()->_worklist.push(my_mem); // remove dead node later
33413342
my_mem = nullptr;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2024, Red Hat, Inc. 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 8325372
27+
* @summary fusion of heap stable test causes GetAndSet node to be removed
28+
* @requires vm.gc.Shenandoah
29+
* @modules java.base/jdk.internal.misc:+open
30+
*
31+
* @run main/othervm -XX:+UseShenandoahGC -XX:-BackgroundCompilation TestUnsafeLoadStoreMergedHeapStableTests
32+
*/
33+
34+
import jdk.internal.misc.Unsafe;
35+
36+
import java.lang.reflect.Field;
37+
38+
public class TestUnsafeLoadStoreMergedHeapStableTests {
39+
40+
static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe();
41+
static long F_OFFSET;
42+
43+
static class A {
44+
Object f;
45+
}
46+
47+
static {
48+
try {
49+
Field fField = A.class.getDeclaredField("f");
50+
F_OFFSET = UNSAFE.objectFieldOffset(fField);
51+
} catch (Exception e) {
52+
throw new RuntimeException(e);
53+
}
54+
}
55+
56+
static Object testHelper(boolean flag, Object o, long offset, Object x) {
57+
if (flag) {
58+
return UNSAFE.getAndSetObject(o, offset, x);
59+
}
60+
return null;
61+
}
62+
63+
static Object field;
64+
65+
66+
static Object test1(boolean flag, Object o, long offset) {
67+
return testHelper(flag, null, offset, field);
68+
}
69+
70+
static Object test2(Object o, long offset) {
71+
return UNSAFE.getAndSetObject(o, offset, field);
72+
}
73+
74+
static public void main(String[] args) {
75+
A a = new A();
76+
for (int i = 0; i < 20_000; i++) {
77+
testHelper(true, a, F_OFFSET, null);
78+
test1(false, a, F_OFFSET);
79+
test2(a, F_OFFSET);
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)