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 /*
  26  * @test
  27  * @bug 8150465
  28  * @summary Unsafe methods to produce uninitialized arrays
  29  * @modules java.base/jdk.internal.misc
  30  *
  31  * @run main/othervm -ea -Diters=200   -Xint
  32  *      compiler.intrinsics.unsafe.AllocateUninitializedArray
  33  * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1
  34  *      compiler.intrinsics.unsafe.AllocateUninitializedArray
  35  * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4
  36  *      compiler.intrinsics.unsafe.AllocateUninitializedArray
  37  */
  38 
  39 package compiler.intrinsics.unsafe;
  40 
  41 import java.lang.reflect.Array;
  42 import java.lang.reflect.Field;
  43 import java.util.concurrent.Callable;
  44 
  45 public class AllocateUninitializedArray {
  46     static final int ITERS = Integer.getInteger("iters", 1);
  47     static final jdk.internal.misc.Unsafe UNSAFE;
  48 
  49     static {
  50         try {
  51             Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
  52             f.setAccessible(true);
  53             UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
  54         } catch (Exception e) {
  55             throw new RuntimeException("Unable to get Unsafe instance.", e);
  56         }
  57     }
  58 
  59     public static void main(String... args) throws Exception {
  60         testIAE(AllConstants::testObject);
  61         testIAE(LengthIsConstant::testObject);
  62         testIAE(ClassIsConstant::testObject);
  63         testIAE(NothingIsConstant::testObject);
  64 
  65         testIAE(AllConstants::testArray);
  66         testIAE(LengthIsConstant::testArray);
  67         testIAE(ClassIsConstant::testArray);
  68         testIAE(NothingIsConstant::testArray);
  69 
  70         testIAE(AllConstants::testNull);
  71         testIAE(LengthIsConstant::testNull);
  72         testIAE(ClassIsConstant::testNull);
  73         testIAE(NothingIsConstant::testNull);
  74 
  75         testOK(boolean[].class, 10, AllConstants::testBoolean);
  76         testOK(byte[].class,    10, AllConstants::testByte);
  77         testOK(short[].class,   10, AllConstants::testShort);
  78         testOK(char[].class,    10, AllConstants::testChar);
  79         testOK(int[].class,     10, AllConstants::testInt);
  80         testOK(float[].class,   10, AllConstants::testFloat);
  81         testOK(long[].class,    10, AllConstants::testLong);
  82         testOK(double[].class,  10, AllConstants::testDouble);
  83 
  84         testOK(boolean[].class, 10, LengthIsConstant::testBoolean);
  85         testOK(byte[].class,    10, LengthIsConstant::testByte);
  86         testOK(short[].class,   10, LengthIsConstant::testShort);
  87         testOK(char[].class,    10, LengthIsConstant::testChar);
  88         testOK(int[].class,     10, LengthIsConstant::testInt);
  89         testOK(float[].class,   10, LengthIsConstant::testFloat);
  90         testOK(long[].class,    10, LengthIsConstant::testLong);
  91         testOK(double[].class,  10, LengthIsConstant::testDouble);
  92 
  93         testOK(boolean[].class, 10, ClassIsConstant::testBoolean);
  94         testOK(byte[].class,    10, ClassIsConstant::testByte);
  95         testOK(short[].class,   10, ClassIsConstant::testShort);
  96         testOK(char[].class,    10, ClassIsConstant::testChar);
  97         testOK(int[].class,     10, ClassIsConstant::testInt);
  98         testOK(float[].class,   10, ClassIsConstant::testFloat);
  99         testOK(long[].class,    10, ClassIsConstant::testLong);
 100         testOK(double[].class,  10, ClassIsConstant::testDouble);
 101 
 102         testOK(boolean[].class, 10, NothingIsConstant::testBoolean);
 103         testOK(byte[].class,    10, NothingIsConstant::testByte);
 104         testOK(short[].class,   10, NothingIsConstant::testShort);
 105         testOK(char[].class,    10, NothingIsConstant::testChar);
 106         testOK(int[].class,     10, NothingIsConstant::testInt);
 107         testOK(float[].class,   10, NothingIsConstant::testFloat);
 108         testOK(long[].class,    10, NothingIsConstant::testLong);
 109         testOK(double[].class,  10, NothingIsConstant::testDouble);
 110     }
 111 
 112     public static void testOK(Class<?> expectClass, int expectLen, Callable<Object> test) throws Exception {
 113         for (int c = 0; c < ITERS; c++) {
 114             Object res = test.call();
 115             Class<?> actualClass = res.getClass();
 116             if (!actualClass.equals(expectClass)) {
 117                 throw new IllegalStateException("Wrong class: expected = " + expectClass + ", but got " + actualClass);
 118             }
 119             int actualLen = Array.getLength(res);
 120             if (actualLen != expectLen) {
 121                 throw new IllegalStateException("Wrong length: expected = " + expectLen + ", but got " + actualLen);
 122             }
 123         }
 124     }
 125 
 126     static volatile Object sink;
 127 
 128     public static void testIAE(Callable<Object> test) throws Exception {
 129         for (int c = 0; c < ITERS; c++) {
 130             try {
 131                sink = test.call();
 132                throw new IllegalStateException("Expected IAE");
 133             } catch (IllegalArgumentException iae) {
 134                // expected
 135             }
 136         }
 137     }
 138 
 139     static volatile int sampleLenNeg  = -1;
 140     static volatile int sampleLenZero = 0;
 141     static volatile int sampleLen     = 10;
 142 
 143 
 144     static volatile Class<?> classBoolean = boolean.class;
 145     static volatile Class<?> classByte    = byte.class;
 146     static volatile Class<?> classShort   = short.class;
 147     static volatile Class<?> classChar    = char.class;
 148     static volatile Class<?> classInt     = int.class;
 149     static volatile Class<?> classFloat   = float.class;
 150     static volatile Class<?> classLong    = long.class;
 151     static volatile Class<?> classDouble  = double.class;
 152     static volatile Class<?> classObject  = Object.class;
 153     static volatile Class<?> classArray   = Object[].class;
 154     static volatile Class<?> classNull    = null;
 155 
 156     static class AllConstants {
 157         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class,  10); }
 158         static Object testByte()    { return UNSAFE.allocateUninitializedArray(byte.class,     10); }
 159         static Object testShort()   { return UNSAFE.allocateUninitializedArray(short.class,    10); }
 160         static Object testChar()    { return UNSAFE.allocateUninitializedArray(char.class,     10); }
 161         static Object testInt()     { return UNSAFE.allocateUninitializedArray(int.class,      10); }
 162         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(float.class,    10); }
 163         static Object testLong()    { return UNSAFE.allocateUninitializedArray(long.class,     10); }
 164         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(double.class,   10); }
 165         static Object testObject()  { return UNSAFE.allocateUninitializedArray(Object.class,   10); }
 166         static Object testArray()   { return UNSAFE.allocateUninitializedArray(Object[].class, 10); }
 167         static Object testNull()    { return UNSAFE.allocateUninitializedArray(null,           10); }
 168         static Object testZero()    { return UNSAFE.allocateUninitializedArray(int.class,      0);  }
 169         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(int.class,      -1); }
 170     }
 171 
 172     static class ClassIsConstant {
 173         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class,  sampleLen); }
 174         static Object testByte()    { return UNSAFE.allocateUninitializedArray(byte.class,     sampleLen); }
 175         static Object testShort()   { return UNSAFE.allocateUninitializedArray(short.class,    sampleLen); }
 176         static Object testChar()    { return UNSAFE.allocateUninitializedArray(char.class,     sampleLen); }
 177         static Object testInt()     { return UNSAFE.allocateUninitializedArray(int.class,      sampleLen); }
 178         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(float.class,    sampleLen); }
 179         static Object testLong()    { return UNSAFE.allocateUninitializedArray(long.class,     sampleLen); }
 180         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(double.class,   sampleLen); }
 181         static Object testObject()  { return UNSAFE.allocateUninitializedArray(Object.class,   sampleLen); }
 182         static Object testArray()   { return UNSAFE.allocateUninitializedArray(Object[].class, sampleLen); }
 183         static Object testNull()    { return UNSAFE.allocateUninitializedArray(null,           sampleLen); }
 184         static Object testZero()    { return UNSAFE.allocateUninitializedArray(int.class,      sampleLenZero); }
 185         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(int.class,      sampleLenNeg); }
 186     }
 187 
 188     static class LengthIsConstant {
 189         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, 10); }
 190         static Object testByte()    { return UNSAFE.allocateUninitializedArray(classByte,    10); }
 191         static Object testShort()   { return UNSAFE.allocateUninitializedArray(classShort,   10); }
 192         static Object testChar()    { return UNSAFE.allocateUninitializedArray(classChar,    10); }
 193         static Object testInt()     { return UNSAFE.allocateUninitializedArray(classInt,     10); }
 194         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(classFloat,   10); }
 195         static Object testLong()    { return UNSAFE.allocateUninitializedArray(classLong,    10); }
 196         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(classDouble,  10); }
 197         static Object testObject()  { return UNSAFE.allocateUninitializedArray(classObject,  10); }
 198         static Object testArray()   { return UNSAFE.allocateUninitializedArray(classArray,   10); }
 199         static Object testNull()    { return UNSAFE.allocateUninitializedArray(classNull,    10); }
 200         static Object testZero()    { return UNSAFE.allocateUninitializedArray(classInt,     0);  }
 201         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(classInt,     -1); }
 202     }
 203 
 204     static class NothingIsConstant {
 205         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, sampleLen); }
 206         static Object testByte()    { return UNSAFE.allocateUninitializedArray(classByte,    sampleLen); }
 207         static Object testShort()   { return UNSAFE.allocateUninitializedArray(classShort,   sampleLen); }
 208         static Object testChar()    { return UNSAFE.allocateUninitializedArray(classChar,    sampleLen); }
 209         static Object testInt()     { return UNSAFE.allocateUninitializedArray(classInt,     sampleLen); }
 210         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(classFloat,   sampleLen); }
 211         static Object testLong()    { return UNSAFE.allocateUninitializedArray(classLong,    sampleLen); }
 212         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(classDouble,  sampleLen); }
 213         static Object testObject()  { return UNSAFE.allocateUninitializedArray(classObject,  sampleLen); }
 214         static Object testArray()   { return UNSAFE.allocateUninitializedArray(classArray,   sampleLen); }
 215         static Object testNull()    { return UNSAFE.allocateUninitializedArray(classNull,    sampleLen); }
 216         static Object testZero()    { return UNSAFE.allocateUninitializedArray(classInt,     sampleLenZero); }
 217         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(classInt,     sampleLenNeg); }
 218     }
 219 }
 220