1 /*
   2  * Copyright (c) 2016, 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  * @test
  26  * @bug 8130847 8156760
  27  * @summary Eliminated instance/array written to by an array copy variant must be correctly initialized when reallocated at a deopt
  28  *
  29  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  30  *                   compiler.arraycopy.TestEliminatedArrayCopyDeopt
  31  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  32  *                   -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
  33  *                   compiler.arraycopy.TestEliminatedArrayCopyDeopt
  34  */
  35 
  36 // Test that if an ArrayCopy node is eliminated because it doesn't
  37 // escape, then the correct field/array element values are captured so
  38 // on a deoptimization, when the object/array is reallocated, it is
  39 // correctly initialized
  40 
  41 package compiler.arraycopy;
  42 
  43 public class TestEliminatedArrayCopyDeopt {
  44 
  45     static class A implements Cloneable {
  46         int f0;
  47         int f1;
  48         int f2;
  49         int f3;
  50         int f4;
  51         int f5;
  52         int f6;
  53         int f7;
  54         int f8;
  55         int f9;
  56         int f10;
  57         int f11;
  58         int f12;
  59         int f13;
  60         int f14;
  61         int f15;
  62 
  63         public Object clone() throws CloneNotSupportedException {
  64             return super.clone();
  65         }
  66     }
  67 
  68     // Clone
  69     static boolean m1(A a, boolean flag) throws CloneNotSupportedException {
  70         A c = (A)a.clone();
  71         if (flag) {
  72             // never taken branch that causes the deoptimization
  73             if (c.f0 != 0x42) {
  74                 return false;
  75             }
  76         }
  77         return true;
  78     }
  79 
  80     // Array clone
  81     static int[] m2_src = null;
  82     static boolean m2(boolean flag) throws CloneNotSupportedException {
  83         int[] src  = new int[10];
  84         m2_src = src;
  85         for (int i = 0; i < src.length; i++) {
  86             src[i] = 0x42+i;
  87         }
  88         int[] c = (int[])src.clone();
  89         if (flag) {
  90             for (int i = 0; i < c.length; i++) {
  91                 if (c[i] != src[i]) {
  92                     return false;
  93                 }
  94             }
  95         }
  96         return true;
  97     }
  98 
  99     // Array copy
 100     static boolean m3(int[] src, boolean flag) {
 101         int[] dst = new int[10];
 102         System.arraycopy(src, 0, dst, 0, 10);
 103         if (flag) {
 104             for (int i = 0; i < dst.length; i++) {
 105                 if (dst[i] != src[i]) {
 106                     return false;
 107                 }
 108             }
 109         }
 110         return true;
 111     }
 112 
 113     // Array copy of subrange
 114     static boolean m4(int[] src, boolean flag) {
 115         int[] dst = new int[10];
 116         dst[0] = 0x42;
 117         dst[1] = 0x42 - 1;
 118         dst[2] = 0x42 - 2;
 119         dst[8] = 0x42 - 8;
 120         dst[9] = 0x42 - 9;
 121         int src_off = 2;
 122         int dst_off = 3;
 123         int len = 5;
 124         System.arraycopy(src, src_off, dst, dst_off, len);
 125         if (flag) {
 126             for (int i = 0; i < dst.length; i++) {
 127                 if (i >= dst_off &&  i < dst_off + len) {
 128                     if (dst[i] != src[i - dst_off + src_off]) {
 129                         return false;
 130                     }
 131                 } else {
 132                     if (dst[i] != 0x42-i) {
 133                         return false;
 134                     }
 135                 }
 136             }
 137         }
 138         return true;
 139     }
 140 
 141     // Array copy with Phi
 142     static boolean m5(int[] src, boolean flag1, boolean flag2) {
 143         int[] dst = new int[10];
 144         if (flag1) {
 145             System.arraycopy(src, 0, dst, 0, 10);
 146         }
 147         if (flag2) {
 148             for (int i = 0; i < dst.length; i++) {
 149                 if (dst[i] != src[i]) {
 150                     return false;
 151                 }
 152             }
 153         }
 154         return true;
 155     }
 156 
 157     static public void main(String[] args) throws Exception {
 158         boolean success = true;
 159         A a = new A();
 160         a.f0 = 0x42;
 161         for (int i = 0; i < 20000; i++) {
 162             m1(a, false);
 163         }
 164         if (!m1(a, true)) {
 165             System.out.println("m1 failed");
 166             success = false;
 167         }
 168 
 169         for (int i = 0; i < 20000; i++) {
 170             m2(false);
 171         }
 172         if (!m2(true)) {
 173             System.out.println("m2 failed");
 174             success = false;
 175         }
 176 
 177         int[] src = new int[10];
 178         for (int i = 0; i < src.length; i++) {
 179             src[i] = 0x42+i;
 180         }
 181 
 182         for (int i = 0; i < 20000; i++) {
 183             m3(src, false);
 184         }
 185         if (!m3(src, true)) {
 186             System.out.println("m3 failed");
 187             success = false;
 188         }
 189 
 190         for (int i = 0; i < 20000; i++) {
 191             m4(src, false);
 192         }
 193         if (!m4(src, true)) {
 194             System.out.println("m4 failed");
 195             success = false;
 196         }
 197 
 198         for (int i = 0; i < 20000; i++) {
 199             m5(src, i%2 == 0, false);
 200         }
 201         if (!m5(src, true, true)) {
 202             System.out.println("m4 failed");
 203             success = false;
 204         }
 205 
 206         if (!success) {
 207             throw new RuntimeException("Test failed");
 208         }
 209     }
 210 }