8212673: jtreg/applications/runthese/RunThese30M.java fails in C2 with "assert(!had_error) failed: bad dominance"
Reviewed-by: thartmann, kvn, shade
--- a/src/hotspot/share/opto/callnode.cpp Thu Nov 08 07:42:08 2018 -0500
+++ b/src/hotspot/share/opto/callnode.cpp Thu Nov 08 10:08:52 2018 +0100
@@ -1623,7 +1623,10 @@
Node *n = ctrl_proj->in(0);
if (n != NULL && n->is_Unlock()) {
UnlockNode *unlock = n->as_Unlock();
- if (lock->obj_node()->eqv_uncast(unlock->obj_node()) &&
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node());
+ Node* unlock_obj = bs->step_over_gc_barrier(unlock->obj_node());
+ if (lock_obj->eqv_uncast(unlock_obj) &&
BoxLockNode::same_slot(lock->box_node(), unlock->box_node()) &&
!unlock->is_eliminated()) {
lock_ops.append(unlock);
@@ -1668,7 +1671,10 @@
}
if (ctrl->is_Lock()) {
LockNode *lock = ctrl->as_Lock();
- if (lock->obj_node()->eqv_uncast(unlock->obj_node()) &&
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node());
+ Node* unlock_obj = bs->step_over_gc_barrier(unlock->obj_node());
+ if (lock_obj->eqv_uncast(unlock_obj) &&
BoxLockNode::same_slot(lock->box_node(), unlock->box_node())) {
lock_result = lock;
}
@@ -1699,7 +1705,10 @@
}
if (lock1_node != NULL && lock1_node->is_Lock()) {
LockNode *lock1 = lock1_node->as_Lock();
- if (lock->obj_node()->eqv_uncast(lock1->obj_node()) &&
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ Node* lock_obj = bs->step_over_gc_barrier(lock->obj_node());
+ Node* lock1_obj = bs->step_over_gc_barrier(lock1->obj_node());
+ if (lock_obj->eqv_uncast(lock1_obj) &&
BoxLockNode::same_slot(lock->box_node(), lock1->box_node()) &&
!lock1->is_eliminated()) {
lock_ops.append(lock1);
@@ -1916,6 +1925,8 @@
return false;
}
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ obj = bs->step_over_gc_barrier(obj);
// Look for external lock for the same object.
SafePointNode* sfn = this->as_SafePoint();
JVMState* youngest_jvms = sfn->jvms();
@@ -1926,6 +1937,7 @@
// Loop over monitors
for (int idx = 0; idx < num_mon; idx++) {
Node* obj_node = sfn->monitor_obj(jvms, idx);
+ obj_node = bs->step_over_gc_barrier(obj_node);
BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock();
if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) {
return true;
--- a/src/hotspot/share/opto/node.cpp Thu Nov 08 07:42:08 2018 -0500
+++ b/src/hotspot/share/opto/node.cpp Thu Nov 08 10:08:52 2018 +0100
@@ -899,13 +899,6 @@
return (Node*) this;
}
-bool Node::eqv_uncast(const Node* n) const {
- BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
- Node* obj1 = bs->step_over_gc_barrier(const_cast<Node*>(this));
- Node* obj2 = bs->step_over_gc_barrier(const_cast<Node*>(n));
- return (obj1->uncast() == obj2->uncast());
-}
-
// Find out of current node that matches opcode.
Node* Node::find_out_with(int opcode) {
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
--- a/src/hotspot/share/opto/node.hpp Thu Nov 08 07:42:08 2018 -0500
+++ b/src/hotspot/share/opto/node.hpp Thu Nov 08 10:08:52 2018 +0100
@@ -457,9 +457,10 @@
// Strip away casting. (It is depth-limited.)
Node* uncast() const;
- // Return whether two Nodes are equivalent, after stripping casting
- // and GC barriers.
- bool eqv_uncast(const Node* n) const;
+ // Return whether two Nodes are equivalent, after stripping casting.
+ bool eqv_uncast(const Node* n) const {
+ return (this->uncast() == n->uncast());
+ }
// Find out of current node that matches opcode.
Node* find_out_with(int opcode);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java Thu Nov 08 10:08:52 2018 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. 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 8212673
+ * @summary Node::eqv_uncast() shouldn't step over load barriers unconditionally
+ * @library /test/lib /
+ * @modules java.base/jdk.internal.misc
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseOnStackReplacement -XX:-TieredCompilation -XX:-BackgroundCompilation EqvUncastStepOverBarrier
+ */
+
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Method;
+
+public class EqvUncastStepOverBarrier {
+ static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ private static Object field = new A();
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 0; i < 20_000; i++) {
+ test();
+ test();
+ test_helper(null, 0);
+ }
+ Method m = EqvUncastStepOverBarrier.class.getDeclaredMethod("test");
+ WHITE_BOX.enqueueMethodForCompilation(m, 4);
+ if (!WHITE_BOX.isMethodCompiled(m, false)) {
+ throw new RuntimeException("Method compilation failed");
+ }
+ }
+
+ private static Object test() {
+ Object o = field;
+ if (o == null) {}
+ for (int i = 1; i < 100; i *= 2) {
+ int j = 0;
+ for (; j < 4; j++) ;
+ o = test_helper(o, j);
+ }
+ return o;
+ }
+
+ private static Object test_helper(Object o, int j) {
+ if (j == 4) {
+ A a = (A) o;
+ o = a;
+ } else {
+ o = new Object();
+ }
+ return o;
+ }
+
+ private static class A {
+ }
+}