1 /*
   2  * Copyright (c) 2017, 2018, 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 package compiler.valhalla.valuetypes;
  25 
  26 import java.lang.reflect.Array;
  27 import jdk.test.lib.Asserts;
  28 
  29 /*
  30  * @test
  31  * @summary Test intrinsic support for value types
  32  * @library /testlibrary /test/lib /compiler/whitebox /
  33  * @requires os.simpleArch == "x64"
  34  * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers TestIntrinsics.java
  35  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  36  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  37  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline
  38  *                   -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  39  *                   -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  40  *                   compiler.valhalla.valuetypes.TestIntrinsics
  41  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  42  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops
  43  *                   -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  44  *                   -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  45  *                   compiler.valhalla.valuetypes.TestIntrinsics
  46  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  47  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops
  48  *                   -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  49  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0
  50  *                   -DVerifyIR=false compiler.valhalla.valuetypes.TestIntrinsics
  51  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  52  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline
  53  *                   -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  54  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0
  55  *                   -XX:-MonomorphicArrayCheck
  56  *                   -DVerifyIR=false compiler.valhalla.valuetypes.TestIntrinsics
  57  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  58  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
  59  *                   -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  60  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  61  *                   -XX:-MonomorphicArrayCheck
  62  *                   -DVerifyIR=false compiler.valhalla.valuetypes.TestIntrinsics
  63  */
  64 public class TestIntrinsics extends ValueTypeTest {
  65 
  66     public static void main(String[] args) throws Throwable {
  67         TestIntrinsics test = new TestIntrinsics();
  68         test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class);
  69     }
  70 
  71     // Test correctness of the Class::isAssignableFrom intrinsic
  72     @Test()
  73     public boolean test1(Class<?> supercls, Class<?> subcls) {
  74         return supercls.isAssignableFrom(subcls);
  75     }
  76 
  77     public void test1_verifier(boolean warmup) {
  78         Asserts.assertTrue(test1(Object.class, MyValue1.class), "test1_1 failed");
  79         Asserts.assertTrue(test1(MyValue1.class, MyValue1.class), "test1_2 failed");
  80         Asserts.assertTrue(test1(Object.class, java.util.ArrayList.class), "test1_3 failed");
  81         Asserts.assertTrue(test1(java.util.ArrayList.class, java.util.ArrayList.class), "test1_4 failed");
  82     }
  83 
  84     // Verify that Class::isAssignableFrom checks with statically known classes are folded
  85     @Test(failOn = LOADK)
  86     public boolean test2() {
  87         boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class);
  88         boolean check2 = MyValue1.class.isAssignableFrom(MyValue1.class);
  89         boolean check3 = Object.class.isAssignableFrom(java.util.ArrayList.class);
  90         boolean check4 = Object.class.isAssignableFrom(MyValue1.class);
  91         boolean check5 = !MyValue1.class.isAssignableFrom(Object.class);
  92         return check1 && check2 && check3 && check4 && check5;
  93     }
  94 
  95     public void test2_verifier(boolean warmup) {
  96         Asserts.assertTrue(test2(), "test2 failed");
  97     }
  98 
  99     // Test correctness of the Class::getSuperclass intrinsic
 100     @Test()
 101     public Class<?> test3(Class<?> cls) {
 102         return cls.getSuperclass();
 103     }
 104 
 105     public void test3_verifier(boolean warmup) {
 106         Asserts.assertTrue(test3(Object.class) == null, "test3_1 failed");
 107         Asserts.assertTrue(test3(MyValue1.class) == Object.class, "test3_2 failed");
 108         Asserts.assertTrue(test3(Class.class) == Object.class, "test3_3 failed");
 109     }
 110 
 111     // Verify that Class::getSuperclass checks with statically known classes are folded
 112     @Test(failOn = LOADK)
 113     public boolean test4() {
 114         boolean check1 = Object.class.getSuperclass() == null;
 115         boolean check2 = MyValue1.class.getSuperclass() == Object.class;
 116         boolean check3 = Class.class.getSuperclass() == Object.class;
 117         return check1 && check2 && check3;
 118     }
 119 
 120     public void test4_verifier(boolean warmup) {
 121         Asserts.assertTrue(test4(), "test4 failed");
 122     }
 123 
 124     // TODO re-enable once Object method support is implemented
 125 /*
 126     // Test toString() method
 127     @Test(failOn = ALLOC + STORE + LOAD)
 128     public String test5(MyValue1 v) {
 129         return v.toString();
 130     }
 131 
 132     @DontCompile
 133     public void test5_verifier(boolean warmup) {
 134         MyValue1 v = MyValue1.createDefaultInline();
 135         test5(v);
 136     }
 137 */
 138 
 139     // Test hashCode() method
 140     // @Test()
 141     // public int test6(MyValue1 v) {
 142     //     return v.hashCode();
 143     // }
 144 
 145     // @DontCompile
 146     // public void test6_verifier(boolean warmup) {
 147     //     MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 148     //     int res = test6(v);
 149     //     Asserts.assertEQ(res, v.hashCode());
 150     // }
 151 
 152     // Test default value type array creation via reflection
 153     @Test()
 154     public void test7(Class<?> componentType, int len, long hash) {
 155         Object[] va = (Object[])Array.newInstance(componentType, len);
 156         for (int i = 0; i < len; ++i) {
 157             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 158         }
 159     }
 160 
 161     @DontCompile
 162     public void test7_verifier(boolean warmup) {
 163         int len = Math.abs(rI) % 42;
 164         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 165         test7(MyValue1.class, len, hash);
 166     }
 167 
 168     // Class.isInstance
 169     @Test()
 170     public boolean test8(Class c, MyValue1 vt) {
 171         return c.isInstance(vt);
 172     }
 173 
 174     @DontCompile
 175     public void test8_verifier(boolean warmup) {
 176         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 177         boolean result = test8(MyValue1.class, vt);
 178         Asserts.assertTrue(result);
 179     }
 180 
 181     @Test()
 182     public boolean test9(Class c, MyValue1 vt) {
 183         return c.isInstance(vt);
 184     }
 185 
 186     @DontCompile
 187     public void test9_verifier(boolean warmup) {
 188         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 189         boolean result = test9(MyValue2.class, vt);
 190         Asserts.assertFalse(result);
 191     }
 192 
 193     // Class.cast
 194     @Test()
 195     public Object test10(Class c, MyValue1 vt) {
 196         return c.cast(vt);
 197     }
 198 
 199     @DontCompile
 200     public void test10_verifier(boolean warmup) {
 201         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 202         Object result = test10(MyValue1.class, vt);
 203         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 204     }
 205 
 206     @Test()
 207     public Object test11(Class c, MyValue1 vt) {
 208         return c.cast(vt);
 209     }
 210 
 211     @DontCompile
 212     public void test11_verifier(boolean warmup) {
 213         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 214         try {
 215             test11(MyValue2.class, vt);
 216             throw new RuntimeException("should have thrown");
 217         } catch(ClassCastException cce) {
 218         }
 219     }
 220 
 221     @Test()
 222     public Object test12(MyValue1 vt) {
 223         return MyValue1.class.cast(vt);
 224     }
 225 
 226     @DontCompile
 227     public void test12_verifier(boolean warmup) {
 228         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 229         Object result = test12(vt);
 230         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 231     }
 232 
 233     @Test()
 234     public Object test13(MyValue1 vt) {
 235         return MyValue2.class.cast(vt);
 236     }
 237 
 238     @DontCompile
 239     public void test13_verifier(boolean warmup) {
 240         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 241         try {
 242             test13(vt);
 243             throw new RuntimeException("should have thrown");
 244         } catch(ClassCastException cce) {
 245         }
 246     }
 247 
 248     // value type array creation via reflection
 249     @Test()
 250     public void test14(int len, long hash) {
 251         Object[] va = (Object[])Array.newInstance(MyValue1.class, len);
 252         for (int i = 0; i < len; ++i) {
 253             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 254         }
 255     }
 256 
 257     @DontCompile
 258     public void test14_verifier(boolean warmup) {
 259         int len = Math.abs(rI) % 42;
 260         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 261         test14(len, hash);
 262     }
 263 
 264     // Test hashCode() method
 265     // @Test()
 266     // public int test15(Object v) {
 267     //     return v.hashCode();
 268     // }
 269 
 270     // @DontCompile
 271     // public void test15_verifier(boolean warmup) {
 272     //     MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 273     //     int res = test15(v);
 274     //     Asserts.assertEQ(res, v.hashCode());
 275     // }
 276 
 277     @Test()
 278     public int test16(Object v) {
 279         return System.identityHashCode(v);
 280     }
 281 
 282     @DontCompile
 283     public void test16_verifier(boolean warmup) {
 284         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 285         int res = test16(v);
 286         Asserts.assertEQ(res, System.identityHashCode((Object)v));
 287     }
 288 
 289     @Test()
 290     public int test17(Object v) {
 291         return System.identityHashCode(v);
 292     }
 293 
 294     @DontCompile
 295     public void test17_verifier(boolean warmup) {
 296         Integer v = new Integer(rI);
 297         int res = test17(v);
 298         Asserts.assertEQ(res, System.identityHashCode(v));
 299     }
 300 
 301     @Test()
 302     public int test18(Object v) {
 303         return System.identityHashCode(v);
 304     }
 305 
 306     @DontCompile
 307     public void test18_verifier(boolean warmup) {
 308         Object v = null;
 309         int res = test18(v);
 310         Asserts.assertEQ(res, System.identityHashCode(v));
 311     }
 312 }