1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 /**
  26  * @test
  27  * @bug 8139771
  28  * @summary Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash
  29  * @requires vm.gc=="Serial" | vm.gc=="Parallel"
  30  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+StressGCM TestEliminatedCastPPAtPhi
  31  *
  32  */
  33 
  34 public class TestEliminatedCastPPAtPhi {
  35 
  36     static TestEliminatedCastPPAtPhi saved;
  37     static TestEliminatedCastPPAtPhi saved_not_null;
  38 
  39     int f;
  40 
  41     static int test(TestEliminatedCastPPAtPhi obj, int[] array, boolean flag) {
  42         int ret = array[0] + array[20];
  43         saved = obj;
  44         if (obj == null) {
  45             return ret;
  46         }
  47         saved_not_null = obj;
  48 
  49         // empty loop to be optimized out. Delays range check smearing
  50         // for the array access below until the if diamond is
  51         // optimized out
  52         int i = 0;
  53         for (; i < 10; i++);
  54 
  55         ret += array[i];
  56 
  57         TestEliminatedCastPPAtPhi res;
  58         if (flag) {
  59             // load is optimized out and res is obj here
  60             res = saved;
  61         } else {
  62             // load is optimized out and res is non null CastPP of res here
  63             res = saved_not_null;
  64         }
  65         // null check + CastPP here for res field load below
  66 
  67         // 1) null check is pushed in the branches of the if above by
  68         // split through phi because res is non null in the second
  69         // branch and the null check can be optimized out in that
  70         // branch. The Castpp stays here.
  71 
  72         // 2) null check in the first branch is also optimized out
  73         // because a dominating null check is found (the explicit null
  74         // check at the beggining of the test)
  75 
  76         // 3) the Phi for the if above merges a CastPP'ed value and
  77         // the same value so it's optimized out and replaced by the
  78         // uncasted value: obj
  79 
  80         // 4) the if above has 2 empty branches so it's optimized
  81         // out. The control of the CastPP that is still here is now
  82         // the success branch of the range check for the array access
  83         // above
  84 
  85         // 5) the loop above is optimized out, i = 10, the range check
  86         // for the array access above is optimized out and all its
  87         // uses are replaced by the range check for the array accesses
  88         // at the beginning of the method. The castPP here is one of
  89         // the uses and so its control is now the range check at the
  90         // beginning of the method: the control of the CastPP bypasses
  91         // the explicit null check
  92 
  93         return ret + res.f;
  94     }
  95 
  96     static public void main(String[] args) {
  97         int[] array = new int[100];
  98         TestEliminatedCastPPAtPhi obj = new TestEliminatedCastPPAtPhi();
  99         for (int i = 0; i < 20000; i++) {
 100             test(obj, array, (i%2) == 0);
 101         }
 102         test(null, array, true);
 103     }
 104 
 105 }