8212673: jtreg/applications/runthese/RunThese30M.java fails in C2 with "assert(!had_error) failed: bad dominance"
authorroland
Thu, 08 Nov 2018 10:08:52 +0100
changeset 52449 bac05440d98c
parent 52448 bc5c7f63dbae
child 52450 2790da836dc3
8212673: jtreg/applications/runthese/RunThese30M.java fails in C2 with "assert(!had_error) failed: bad dominance" Reviewed-by: thartmann, kvn, shade
src/hotspot/share/opto/callnode.cpp
src/hotspot/share/opto/node.cpp
src/hotspot/share/opto/node.hpp
test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java
--- 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 {
+    }
+}