8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943
authorroland
Sat, 02 Aug 2014 07:06:08 +0200
changeset 25935 59b08808cb9c
parent 25934 ba6dabf5c7d9
child 25936 9b693ed74c13
8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943 Summary: PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination Reviewed-by: kvn
hotspot/src/share/vm/opto/callnode.cpp
hotspot/src/share/vm/opto/macro.cpp
hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java
--- a/hotspot/src/share/vm/opto/callnode.cpp	Wed Aug 06 21:21:25 2014 +0400
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Sat Aug 02 07:06:08 2014 +0200
@@ -778,7 +778,7 @@
 }
 
 // Returns the unique CheckCastPP of a call
-// or 'this' if there are several CheckCastPP
+// or 'this' if there are several CheckCastPP or unexpected uses
 // or returns NULL if there is no one.
 Node *CallNode::result_cast() {
   Node *cast = NULL;
@@ -794,6 +794,13 @@
         return this;  // more than 1 CheckCastPP
       }
       cast = use;
+    } else if (!use->is_Initialize() &&
+               !use->is_AddP()) {
+      // Expected uses are restricted to a CheckCastPP, an Initialize
+      // node, and AddP nodes. If we encounter any other use (a Phi
+      // node can be seen in rare cases) return this to prevent
+      // incorrect optimizations.
+      return this;
     }
   }
   return cast;
--- a/hotspot/src/share/vm/opto/macro.cpp	Wed Aug 06 21:21:25 2014 +0400
+++ b/hotspot/src/share/vm/opto/macro.cpp	Sat Aug 02 07:06:08 2014 +0200
@@ -702,6 +702,7 @@
   ciType* elem_type;
 
   Node* res = alloc->result_cast();
+  assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result");
   const TypeOopPtr* res_type = NULL;
   if (res != NULL) { // Could be NULL when there are no users
     res_type = _igvn.type(res)->isa_oopptr();
@@ -1037,6 +1038,8 @@
     return false;
   }
 
+  assert(boxing->result_cast() == NULL, "unexpected boxing node result");
+
   extract_call_projections(boxing);
 
   const TypeTuple* r = boxing->tf()->range();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java	Sat Aug 02 07:06:08 2014 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, 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 8046698
+ * @summary PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminateAllocationPhi
+ *
+ */
+
+public class TestEliminateAllocationPhi {
+
+    // This will return I when called from m(0 and once optimized will
+    // go away but this will confuse escape analysis in m(): it will
+    // find I as non escaping but non scalar replaceable. In its own
+    // method so that we can make the profile of the if() branch look
+    // like it's taken sometimes.
+    static Integer m2(Integer I, int i) {
+        for (; i < 10; i=(i+2)*(i+2)) {
+        }
+        if (i == 121) {
+            return II;
+        }
+        return I;
+    }
+
+    static Integer II = new Integer(42);
+
+    static int m(int[] integers, boolean flag) {
+        int j = 0;
+        while(true) {
+            try {
+                int k = integers[j++];
+                // A branch that will cause loop unswitching
+                if (flag) {
+                    k += 42;
+                }
+                if (k < 1000) {
+                    throw new Exception();
+                }
+                // Because of the try/catch the Allocate node for this
+                // new will be in the loop while the Initialization
+                // node will be outside the loop. When loop
+                // unswitching happens, the Allocate node will be
+                // cloned and the results of both will be inputs to a
+                // Phi that will be between the Allocate nodes and the
+                // Initialization nodes.
+                Integer I = new Integer(k);
+
+                I = m2(I, 0);
+
+                int i = I.intValue();
+                return i;
+            } catch(Exception e) {
+            }
+        }
+    }
+
+    static public void main(String[] args) {
+        for (int i = 0; i < 5000; i++) {
+            m2(null, 1);
+        }
+
+        int[] integers = { 2000 };
+        for (int i = 0; i < 6000; i++) {
+            m(integers, (i%2) == 0);
+        }
+        int[] integers2 = { 1, 2, 3, 4, 5, 2000 };
+        for (int i = 0; i < 10000; i++) {
+            m(integers2, (i%2) == 0);
+        }
+    }
+}