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
--- 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);
+ }
+ }
+}