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 java.lang.reflect.Field;
  28 import java.util.Arrays;
  29 import jdk.test.lib.Asserts;
  30 import jdk.internal.misc.Unsafe;
  31 
  32 /*
  33  * @test
  34  * @summary Test intrinsic support for value types
  35  * @library /testlibrary /test/lib /compiler/whitebox /
  36  * @modules java.base/jdk.internal.misc
  37  * @requires os.simpleArch == "x64"
  38  * @compile -XDemitQtypes -XDenableValueTypes -XDallowWithFieldOperator -XDallowFlattenabilityModifiers TestIntrinsics.java
  39  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  40  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  41  *                               -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+EnableValhalla
  42  *                               compiler.valhalla.valuetypes.ValueTypeTest
  43  *                               compiler.valhalla.valuetypes.TestIntrinsics
  44  */
  45 public class TestIntrinsics extends ValueTypeTest {
  46     // Extra VM parameters for some test scenarios. See ValueTypeTest.getVMParameters()
  47     @Override
  48     public String[] getExtraVMParameters(int scenario) {
  49         switch (scenario) {
  50         case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:+ValueArrayFlatten"};
  51         case 4: return new String[] {"-XX:-MonomorphicArrayCheck"};
  52         }
  53         return null;
  54     }
  55 
  56     public static void main(String[] args) throws Throwable {
  57         TestIntrinsics test = new TestIntrinsics();
  58         test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class);
  59     }
  60 
  61     // Test correctness of the Class::isAssignableFrom intrinsic
  62     @Test()
  63     public boolean test1(Class<?> supercls, Class<?> subcls) {
  64         return supercls.isAssignableFrom(subcls);
  65     }
  66 
  67     public void test1_verifier(boolean warmup) {
  68         Asserts.assertTrue(test1(Object.class, MyValue1.class), "test1_1 failed");
  69         Asserts.assertTrue(test1(MyValue1.class, MyValue1.class), "test1_2 failed");
  70         Asserts.assertTrue(test1(Object.class, java.util.ArrayList.class), "test1_3 failed");
  71         Asserts.assertTrue(test1(java.util.ArrayList.class, java.util.ArrayList.class), "test1_4 failed");
  72     }
  73 
  74     // Verify that Class::isAssignableFrom checks with statically known classes are folded
  75     @Test(failOn = LOADK)
  76     public boolean test2() {
  77         boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class);
  78         boolean check2 = MyValue1.class.isAssignableFrom(MyValue1.class);
  79         boolean check3 = Object.class.isAssignableFrom(java.util.ArrayList.class);
  80         boolean check4 = Object.class.isAssignableFrom(MyValue1.class);
  81         boolean check5 = !MyValue1.class.isAssignableFrom(Object.class);
  82         return check1 && check2 && check3 && check4 && check5;
  83     }
  84 
  85     public void test2_verifier(boolean warmup) {
  86         Asserts.assertTrue(test2(), "test2 failed");
  87     }
  88 
  89     // Test correctness of the Class::getSuperclass intrinsic
  90     @Test()
  91     public Class<?> test3(Class<?> cls) {
  92         return cls.getSuperclass();
  93     }
  94 
  95     public void test3_verifier(boolean warmup) {
  96         Asserts.assertTrue(test3(Object.class) == null, "test3_1 failed");
  97         Asserts.assertTrue(test3(MyValue1.class) == Object.class, "test3_2 failed");
  98         Asserts.assertTrue(test3(Class.class) == Object.class, "test3_3 failed");
  99     }
 100 
 101     // Verify that Class::getSuperclass checks with statically known classes are folded
 102     @Test(failOn = LOADK)
 103     public boolean test4() {
 104         boolean check1 = Object.class.getSuperclass() == null;
 105         boolean check2 = MyValue1.class.getSuperclass() == Object.class;
 106         boolean check3 = Class.class.getSuperclass() == Object.class;
 107         return check1 && check2 && check3;
 108     }
 109 
 110     public void test4_verifier(boolean warmup) {
 111         Asserts.assertTrue(test4(), "test4 failed");
 112     }
 113 
 114 // Disabled until 8206274 is fixed
 115 /*
 116     // Test toString() method
 117     @Test(failOn = ALLOC + STORE + LOAD)
 118     public String test5(MyValue1 v) {
 119         return v.toString();
 120     }
 121 
 122     @DontCompile
 123     public void test5_verifier(boolean warmup) {
 124         MyValue1 v = MyValue1.createDefaultInline();
 125         test5(v);
 126     }
 127 */
 128 
 129     // Test hashCode() method
 130     @Test()
 131     public int test6(MyValue1 v) {
 132         return v.hashCode();
 133     }
 134 
 135     @DontCompile
 136     public void test6_verifier(boolean warmup) {
 137         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 138         int res = test6(v);
 139         Asserts.assertEQ(res, v.hashCode());
 140     }
 141 
 142     // Test default value type array creation via reflection
 143     @Test()
 144     public Object[] test7(Class<?> componentType, int len) {
 145         Object[] va = (Object[])Array.newInstance(componentType, len);
 146         return va;
 147     }
 148 
 149     @DontCompile
 150     public void test7_verifier(boolean warmup) {
 151         int len = Math.abs(rI) % 42;
 152         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 153         Object[] va = test7(MyValue1.class, len);
 154         for (int i = 0; i < len; ++i) {
 155             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 156         }
 157     }
 158 
 159     // Class.isInstance
 160     @Test()
 161     public boolean test8(Class c, MyValue1 vt) {
 162         return c.isInstance(vt);
 163     }
 164 
 165     @DontCompile
 166     public void test8_verifier(boolean warmup) {
 167         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 168         boolean result = test8(MyValue1.class, vt);
 169         Asserts.assertTrue(result);
 170     }
 171 
 172     @Test()
 173     public boolean test9(Class c, MyValue1 vt) {
 174         return c.isInstance(vt);
 175     }
 176 
 177     @DontCompile
 178     public void test9_verifier(boolean warmup) {
 179         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 180         boolean result = test9(MyValue2.class, vt);
 181         Asserts.assertFalse(result);
 182     }
 183 
 184     // Class.cast
 185     @Test()
 186     public Object test10(Class c, MyValue1 vt) {
 187         return c.cast(vt);
 188     }
 189 
 190     @DontCompile
 191     public void test10_verifier(boolean warmup) {
 192         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 193         Object result = test10(MyValue1.class, vt);
 194         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 195     }
 196 
 197     @Test()
 198     public Object test11(Class c, MyValue1 vt) {
 199         return c.cast(vt);
 200     }
 201 
 202     @DontCompile
 203     public void test11_verifier(boolean warmup) {
 204         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 205         try {
 206             test11(MyValue2.class, vt);
 207             throw new RuntimeException("should have thrown");
 208         } catch(ClassCastException cce) {
 209         }
 210     }
 211 
 212     @Test()
 213     public Object test12(MyValue1 vt) {
 214         return MyValue1.class.cast(vt);
 215     }
 216 
 217     @DontCompile
 218     public void test12_verifier(boolean warmup) {
 219         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 220         Object result = test12(vt);
 221         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 222     }
 223 
 224     @Test()
 225     public Object test13(MyValue1 vt) {
 226         return MyValue2.class.cast(vt);
 227     }
 228 
 229     @DontCompile
 230     public void test13_verifier(boolean warmup) {
 231         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 232         try {
 233             test13(vt);
 234             throw new RuntimeException("should have thrown");
 235         } catch(ClassCastException cce) {
 236         }
 237     }
 238 
 239     // value type array creation via reflection
 240     @Test()
 241     public void test14(int len, long hash) {
 242         Object[] va = (Object[])Array.newInstance(MyValue1.class, len);
 243         for (int i = 0; i < len; ++i) {
 244             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 245         }
 246     }
 247 
 248     @DontCompile
 249     public void test14_verifier(boolean warmup) {
 250         int len = Math.abs(rI) % 42;
 251         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 252         test14(len, hash);
 253     }
 254 
 255     // Test hashCode() method
 256     @Test()
 257     public int test15(Object v) {
 258         return v.hashCode();
 259     }
 260 
 261     @DontCompile
 262     public void test15_verifier(boolean warmup) {
 263         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 264         int res = test15(v);
 265         Asserts.assertEQ(res, v.hashCode());
 266     }
 267 
 268     @Test()
 269     public int test16(Object v) {
 270         return System.identityHashCode(v);
 271     }
 272 
 273     @DontCompile
 274     public void test16_verifier(boolean warmup) {
 275         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 276         int res = test16(v);
 277         Asserts.assertEQ(res, System.identityHashCode((Object)v));
 278     }
 279 
 280     @Test()
 281     public int test17(Object v) {
 282         return System.identityHashCode(v);
 283     }
 284 
 285     @DontCompile
 286     public void test17_verifier(boolean warmup) {
 287         Integer v = new Integer(rI);
 288         int res = test17(v);
 289         Asserts.assertEQ(res, System.identityHashCode(v));
 290     }
 291 
 292     @Test()
 293     public int test18(Object v) {
 294         return System.identityHashCode(v);
 295     }
 296 
 297     @DontCompile
 298     public void test18_verifier(boolean warmup) {
 299         Object v = null;
 300         int res = test18(v);
 301         Asserts.assertEQ(res, System.identityHashCode(v));
 302     }
 303 
 304     // hashCode() and toString() with different value types
 305     @Test()
 306     public int test19(MyValue1 vt1, MyValue1 vt2, boolean b) {
 307         MyValue1 res = b ? vt1 : vt2;
 308         return res.hashCode();
 309     }
 310 
 311     @DontCompile
 312     public void test19_verifier(boolean warmup) {
 313         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 314         int res = test19(vt, vt, true);
 315         Asserts.assertEQ(res, vt.hashCode());
 316         res = test19(vt, vt, false);
 317         Asserts.assertEQ(res, vt.hashCode());
 318     }
 319 
 320     @Test()
 321     public String test20(MyValue1 vt1, MyValue1 vt2, boolean b) {
 322         MyValue1 res = b ? vt1 : vt2;
 323         return res.toString();
 324     }
 325 
 326     @DontCompile
 327     public void test20_verifier(boolean warmup) {
 328         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 329         String res = test20(vt, vt, true);
 330         Asserts.assertEQ(res, vt.toString());
 331         res = test20(vt, vt, false);
 332         Asserts.assertEQ(res, vt.toString());
 333     }
 334 
 335     private static final Unsafe U = Unsafe.getUnsafe();
 336     private static final long X_OFFSET;
 337     static {
 338         try {
 339             Field xField = MyValue1.class.getDeclaredField("x");
 340             X_OFFSET = U.objectFieldOffset(xField);
 341         } catch (Exception e) {
 342             throw new RuntimeException(e);
 343         }
 344     }
 345 
 346     @Test()
 347     public int test21(MyValue1 v) {
 348        return U.getInt(v, X_OFFSET);
 349     }
 350 
 351     @DontCompile
 352     public void test21_verifier(boolean warmup) {
 353         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 354         int res = test21(v);
 355         Asserts.assertEQ(res, v.x);
 356     }
 357 
 358     @Test()
 359     public void test22(MyValue1 v) {
 360         try {
 361             v = U.makePrivateBuffer(v);
 362             U.putInt(v, X_OFFSET, 0);
 363         } finally {
 364             v = U.finishPrivateBuffer(v);
 365         }
 366     }
 367 
 368     @DontCompile
 369     public void test22_verifier(boolean warmup) {
 370         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 371         test22(v);
 372     }
 373 
 374     @Test()
 375     public int test23(MyValue1 v, long offset) {
 376         return U.getInt(v, offset);
 377     }
 378 
 379     @DontCompile
 380     public void test23_verifier(boolean warmup) {
 381         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 382         int res = test23(v, X_OFFSET);
 383         Asserts.assertEQ(res, v.x);
 384     }
 385 
 386     MyValue1.val test24_vt = MyValue1.createWithFieldsInline(rI, rL);
 387 
 388     @Test()
 389     public int test24(long offset) {
 390         return U.getInt(test24_vt, offset);
 391     }
 392 
 393     @DontCompile
 394     public void test24_verifier(boolean warmup) {
 395         int res = test24(X_OFFSET);
 396         Asserts.assertEQ(res, test24_vt.x);
 397     }
 398 
 399     // Test copyOf intrinsic with allocated value type in it's debug information
 400 // TODO Re-enable if value type arrays become covariant with object arrays
 401 /*
 402     value final class Test25Value {
 403         final int x;
 404         public Test25Value() {
 405             this.x = 42;
 406         }
 407     }
 408 
 409     final Test25Value[] test25Array = new Test25Value[10];
 410 
 411     @Test
 412     public Test25Value[] test25(Test25Value element) {
 413         Test25Value[] newArray = Arrays.copyOf(test25Array, test25Array.length + 1);
 414         newArray[test25Array.length] = element;
 415         return newArray;
 416     }
 417 
 418     @DontCompile
 419     public void test25_verifier(boolean warmup) {
 420         Test25Value vt = new Test25Value();
 421         test25(vt);
 422     }
 423 */
 424 
 425     @Test
 426     public Object test26() {
 427         Class<?>[] ca = new Class<?>[1];
 428         for (int i = 0; i < 1; ++i) {
 429           // Folds during loop opts
 430           ca[i] = MyValue1.class;
 431         }
 432         return Array.newInstance(ca[0], 1);
 433     }
 434 
 435     @DontCompile
 436     public void test26_verifier(boolean warmup) {
 437         Object[] res = (Object[])test26();
 438         Asserts.assertEQ(((MyValue1)res[0]).hashPrimitive(), MyValue1.createDefaultInline().hashPrimitive());
 439     }
 440 
 441     // Load non-flattenable value type field with unsafe
 442     MyValue1.box test27_vt = MyValue1.createWithFieldsInline(rI, rL);
 443     private static final long TEST27_OFFSET;
 444     static {
 445         try {
 446             Field field = TestIntrinsics.class.getDeclaredField("test27_vt");
 447             TEST27_OFFSET = U.objectFieldOffset(field);
 448         } catch (Exception e) {
 449             throw new RuntimeException(e);
 450         }
 451     }
 452 
 453     @Test()
 454     public MyValue1 test27() {
 455         return (MyValue1)U.getObject(this, TEST27_OFFSET);
 456     }
 457 
 458     @DontCompile
 459     public void test27_verifier(boolean warmup) {
 460         MyValue1 res = test27();
 461         Asserts.assertEQ(res.hash(), test24_vt.hash());
 462     }
 463 }