hotspot/test/compiler/controldependency/TestEliminatedCastPPAtPhi.java
changeset 35545 a8f29dfd62b2
child 40059 c2304140ed64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/controldependency/TestEliminatedCastPPAtPhi.java	Fri Dec 11 16:57:08 2015 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, 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 8139771
+ * @summary Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash
+ * @requires vm.gc=="Serial" | vm.gc=="Parallel"
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+StressGCM TestEliminatedCastPPAtPhi
+ *
+ */
+
+public class TestEliminatedCastPPAtPhi {
+
+    static TestEliminatedCastPPAtPhi saved;
+    static TestEliminatedCastPPAtPhi saved_not_null;
+
+    int f;
+
+    static int test(TestEliminatedCastPPAtPhi obj, int[] array, boolean flag) {
+        int ret = array[0] + array[20];
+        saved = obj;
+        if (obj == null) {
+            return ret;
+        }
+        saved_not_null = obj;
+
+        // empty loop to be optimized out. Delays range check smearing
+        // for the array access below until the if diamond is
+        // optimized out
+        int i = 0;
+        for (; i < 10; i++);
+
+        ret += array[i];
+
+        TestEliminatedCastPPAtPhi res;
+        if (flag) {
+            // load is optimized out and res is obj here
+            res = saved;
+        } else {
+            // load is optimized out and res is non null CastPP of res here
+            res = saved_not_null;
+        }
+        // null check + CastPP here for res field load below
+
+        // 1) null check is pushed in the branches of the if above by
+        // split through phi because res is non null in the second
+        // branch and the null check can be optimized out in that
+        // branch. The Castpp stays here.
+
+        // 2) null check in the first branch is also optimized out
+        // because a dominating null check is found (the explicit null
+        // check at the beggining of the test)
+
+        // 3) the Phi for the if above merges a CastPP'ed value and
+        // the same value so it's optimized out and replaced by the
+        // uncasted value: obj
+
+        // 4) the if above has 2 empty branches so it's optimized
+        // out. The control of the CastPP that is still here is now
+        // the success branch of the range check for the array access
+        // above
+
+        // 5) the loop above is optimized out, i = 10, the range check
+        // for the array access above is optimized out and all its
+        // uses are replaced by the range check for the array accesses
+        // at the beginning of the method. The castPP here is one of
+        // the uses and so its control is now the range check at the
+        // beginning of the method: the control of the CastPP bypasses
+        // the explicit null check
+
+        return ret + res.f;
+    }
+
+    static public void main(String[] args) {
+        int[] array = new int[100];
+        TestEliminatedCastPPAtPhi obj = new TestEliminatedCastPPAtPhi();
+        for (int i = 0; i < 20000; i++) {
+            test(obj, array, (i%2) == 0);
+        }
+        test(null, array, true);
+    }
+
+}