1 /*
   2  * Copyright (c) 2017, 2024, 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.inlinetypes;
  25 
  26 import jdk.internal.misc.Unsafe;
  27 import jdk.test.lib.Asserts;
  28 import compiler.lib.ir_framework.*;
  29 
  30 import java.lang.reflect.Array;
  31 import java.lang.reflect.Field;
  32 import java.util.Arrays;
  33 
  34 import jdk.internal.value.ValueClass;
  35 import jdk.internal.vm.annotation.ImplicitlyConstructible;
  36 import jdk.internal.vm.annotation.LooselyConsistentValue;
  37 import jdk.internal.vm.annotation.NullRestricted;
  38 
  39 import static compiler.valhalla.inlinetypes.InlineTypeIRNode.*;
  40 import static compiler.valhalla.inlinetypes.InlineTypes.rI;
  41 import static compiler.valhalla.inlinetypes.InlineTypes.rL;
  42 
  43 /*
  44  * @test
  45  * @key randomness
  46  * @summary Test intrinsic support for value classes.
  47  * @library /test/lib /
  48  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  49  * @enablePreview
  50  * @modules java.base/jdk.internal.misc
  51  *          java.base/jdk.internal.value
  52  *          java.base/jdk.internal.vm.annotation
  53  * @run main/othervm/timeout=300 compiler.valhalla.inlinetypes.TestIntrinsics
  54  */
  55 
  56 @ForceCompileClassInitializer
  57 public class TestIntrinsics {
  58 
  59     public static void main(String[] args) {
  60 
  61         Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
  62         scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1");
  63         scenarios[4].addFlags("-XX:-MonomorphicArrayCheck", "-XX:+UnlockExperimentalVMOptions", "-XX:PerMethodSpecTrapLimit=0", "-XX:PerMethodTrapLimit=0");
  64 
  65         InlineTypes.getFramework()
  66                    .addScenarios(scenarios)
  67                    .addFlags("--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
  68                              "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED",
  69                              // Don't run with DeoptimizeALot until JDK-8239003 is fixed
  70                              "-XX:-DeoptimizeALot")
  71                    .addHelperClasses(MyValue1.class,
  72                                      MyValue2.class,
  73                                      MyValue2Inline.class)
  74                    .start();
  75     }
  76 
  77     static {
  78         // Make sure RuntimeException is loaded to prevent uncommon traps in IR verified tests
  79         RuntimeException tmp = new RuntimeException("42");
  80     }
  81 
  82     // Test correctness of the Class::isAssignableFrom intrinsic
  83     @Test
  84     public boolean test1(Class<?> supercls, Class<?> subcls) {
  85         return supercls.isAssignableFrom(subcls);
  86     }
  87 
  88     @Run(test = "test1")
  89     public void test1_verifier() {
  90         Asserts.assertTrue(test1(java.util.AbstractList.class, java.util.ArrayList.class), "test1_1 failed");
  91         Asserts.assertTrue(test1(MyValue1.class, MyValue1.class), "test1_2 failed");
  92         Asserts.assertTrue(test1(Object.class, java.util.ArrayList.class), "test1_3 failed");
  93         Asserts.assertTrue(test1(Object.class, MyValue1.class), "test1_4 failed");
  94         Asserts.assertTrue(!test1(MyValue1.class, Object.class), "test1_5 failed");
  95     }
  96 
  97     // Verify that Class::isAssignableFrom checks with statically known classes are folded
  98     @Test
  99     @IR(failOn = {LOADK})
 100     public boolean test2() {
 101         boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class);
 102         boolean check2 = MyValue1.class.isAssignableFrom(MyValue1.class);
 103         boolean check3 = Object.class.isAssignableFrom(java.util.ArrayList.class);
 104         boolean check4 = Object.class.isAssignableFrom(MyValue1.class);
 105         boolean check5 = !MyValue1.class.isAssignableFrom(Object.class);
 106         return check1 && check2 && check3 && check4 && check5;
 107     }
 108 
 109     @Run(test = "test2")
 110     public void test2_verifier() {
 111         Asserts.assertTrue(test2(), "test2 failed");
 112     }
 113 
 114     // Test correctness of the Class::getSuperclass intrinsic
 115     @Test
 116     public Class<?> test3(Class<?> cls) {
 117         return cls.getSuperclass();
 118     }
 119 
 120     @Run(test = "test3")
 121     public void test3_verifier() {
 122         Asserts.assertTrue(test3(Object.class) == null, "test3_1 failed");
 123         Asserts.assertTrue(test3(MyValue1.class) == MyAbstract.class, "test3_2 failed");
 124         Asserts.assertTrue(test3(MyValue1.class) == MyAbstract.class, "test3_3 failed");
 125         Asserts.assertTrue(test3(Class.class) == Object.class, "test3_4 failed");
 126     }
 127 
 128     // Verify that Class::getSuperclass checks with statically known classes are folded
 129     @Test
 130     @IR(failOn = {LOADK})
 131     public boolean test4() {
 132         boolean check1 = Object.class.getSuperclass() == null;
 133         boolean check2 = MyValue1.class.getSuperclass() == MyAbstract.class;
 134         boolean check3 = MyValue1.class.getSuperclass() == MyAbstract.class;
 135         boolean check4 = Class.class.getSuperclass() == Object.class;
 136         return check1 && check2 && check3 && check4;
 137     }
 138 
 139     @Run(test = "test4")
 140     public void test4_verifier() {
 141         Asserts.assertTrue(test4(), "test4 failed");
 142     }
 143 
 144     // Test toString() method
 145     @Test
 146     public String test5(MyValue1 v) {
 147         return v.toString();
 148     }
 149 
 150     @Run(test = "test5")
 151     public void test5_verifier() {
 152         MyValue1 v = MyValue1.createDefaultInline();
 153         test5(v);
 154     }
 155 
 156     // Test hashCode() method
 157     @Test
 158     public int test6(MyValue1 v) {
 159         return v.hashCode();
 160     }
 161 
 162     @Run(test = "test6")
 163     public void test6_verifier() {
 164         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 165         int res = test6(v);
 166         Asserts.assertEQ(res, v.hashCode());
 167     }
 168 
 169     // Test default value class array creation via reflection
 170     @Test
 171     public Object[] test7(Class<?> componentType, int len) {
 172         Object[] va = ValueClass.newNullRestrictedArray(componentType, len);
 173         return va;
 174     }
 175 
 176     @Run(test = "test7")
 177     public void test7_verifier() {
 178         int len = Math.abs(rI) % 42;
 179         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 180         Object[] va = test7(MyValue1.class, len);
 181         for (int i = 0; i < len; ++i) {
 182             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 183         }
 184     }
 185 
 186     // Class.isInstance
 187     @Test
 188     public boolean test8(Class c, MyValue1 vt) {
 189         return c.isInstance(vt);
 190     }
 191 
 192     @Run(test = "test8")
 193     public void test8_verifier() {
 194         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 195         boolean result = test8(MyValue1.class, vt);
 196         Asserts.assertTrue(result);
 197         result = test8(MyValue1.class, vt);
 198         Asserts.assertTrue(result);
 199     }
 200 
 201     @Test
 202     public boolean test9(Class c, MyValue1 vt) {
 203         return c.isInstance(vt);
 204     }
 205 
 206     @Run(test = "test9")
 207     public void test9_verifier() {
 208         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 209         boolean result = test9(MyValue2.class, vt);
 210         Asserts.assertFalse(result);
 211         result = test9(MyValue2.class, vt);
 212         Asserts.assertFalse(result);
 213     }
 214 
 215     // Class.cast
 216     @Test
 217     public Object test10(Class c, MyValue1 vt) {
 218         return c.cast(vt);
 219     }
 220 
 221     @Run(test = "test10")
 222     public void test10_verifier() {
 223         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 224         Object result = test10(MyValue1.class, vt);
 225         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 226     }
 227 
 228     @Test
 229     public Object test11(Class c, MyValue1 vt) {
 230         return c.cast(vt);
 231     }
 232 
 233     @Run(test = "test11")
 234     public void test11_verifier() {
 235         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 236         try {
 237             test11(MyValue2.class, vt);
 238             throw new RuntimeException("should have thrown");
 239         } catch (ClassCastException cce) {
 240         }
 241     }
 242 
 243     @Test
 244     public Object test12(MyValue1 vt) {
 245         return MyValue1.class.cast(vt);
 246     }
 247 
 248     @Run(test = "test12")
 249     public void test12_verifier() {
 250         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 251         Object result = test12(vt);
 252         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 253     }
 254 
 255     @Test
 256     public Object test13(MyValue1 vt) {
 257         return MyValue2.class.cast(vt);
 258     }
 259 
 260     @Run(test = "test13")
 261     public void test13_verifier() {
 262         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 263         try {
 264             test13(vt);
 265             throw new RuntimeException("should have thrown");
 266         } catch (ClassCastException cce) {
 267         }
 268     }
 269 
 270     // Value class array creation via reflection
 271     @Test
 272     public void test14(int len, long hash) {
 273         Object[] va = ValueClass.newNullRestrictedArray(MyValue1.class, len);
 274         for (int i = 0; i < len; ++i) {
 275             Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash);
 276         }
 277     }
 278 
 279     @Run(test = "test14")
 280     public void test14_verifier() {
 281         int len = Math.abs(rI) % 42;
 282         long hash = MyValue1.createDefaultDontInline().hashPrimitive();
 283         test14(len, hash);
 284     }
 285 
 286     // Test hashCode() method
 287     @Test
 288     public int test15(Object v) {
 289         return v.hashCode();
 290     }
 291 
 292     @Run(test = "test15")
 293     public void test15_verifier() {
 294         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 295         int res = test15(v);
 296         Asserts.assertEQ(res, v.hashCode());
 297     }
 298 
 299     @Test
 300     public int test16(Object v) {
 301         return System.identityHashCode(v);
 302     }
 303 
 304     @Run(test = "test16")
 305     public void test16_verifier() {
 306         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 307         int res = test16(v);
 308         Asserts.assertEQ(res, System.identityHashCode((Object)v));
 309     }
 310 
 311     @Test
 312     public int test17(Object v) {
 313         return System.identityHashCode(v);
 314     }
 315 
 316     @Run(test = "test17")
 317     public void test17_verifier() {
 318         Integer v = Integer.valueOf(rI);
 319         int res = test17(v);
 320         Asserts.assertEQ(res, System.identityHashCode(v));
 321     }
 322 
 323     @Test
 324     public int test18(Object v) {
 325         return System.identityHashCode(v);
 326     }
 327 
 328     @Run(test = "test18")
 329     public void test18_verifier() {
 330         Object v = null;
 331         int res = test18(v);
 332         Asserts.assertEQ(res, System.identityHashCode(v));
 333     }
 334 
 335     // hashCode() and toString() with different value objects
 336     @Test
 337     public int test19(MyValue1 vt1, MyValue1 vt2, boolean b) {
 338         MyValue1 res = b ? vt1 : vt2;
 339         return res.hashCode();
 340     }
 341 
 342     @Run(test = "test19")
 343     public void test19_verifier() {
 344         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 345         int res = test19(vt, vt, true);
 346         Asserts.assertEQ(res, vt.hashCode());
 347         res = test19(vt, vt, false);
 348         Asserts.assertEQ(res, vt.hashCode());
 349     }
 350 
 351     @Test
 352     public String test20(MyValue1 vt1, MyValue1 vt2, boolean b) {
 353         MyValue1 res = b ? vt1 : vt2;
 354         return res.toString();
 355     }
 356 
 357     @Run(test = "test20")
 358     public void test20_verifier() {
 359         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 360         String res = test20(vt, vt, true);
 361         Asserts.assertEQ(res, vt.toString());
 362         res = test20(vt, vt, false);
 363         Asserts.assertEQ(res, vt.toString());
 364     }
 365 
 366     private static final Unsafe U = Unsafe.getUnsafe();
 367     private static final long X_OFFSET;
 368     private static final long Y_OFFSET;
 369     private static final long V1_OFFSET;
 370     private static final boolean V1_FLATTENED;
 371 
 372     static {
 373         try {
 374             Field xField = MyValue1.class.getDeclaredField("x");
 375             X_OFFSET = U.objectFieldOffset(xField);
 376             Field yField = MyValue1.class.getDeclaredField("y");
 377             Y_OFFSET = U.objectFieldOffset(yField);
 378             Field v1Field = MyValue1.class.getDeclaredField("v1");
 379             V1_OFFSET = U.objectFieldOffset(v1Field);
 380             V1_FLATTENED = U.isFlatField(v1Field);
 381         } catch (Exception e) {
 382             throw new RuntimeException(e);
 383         }
 384     }
 385 
 386     @Test
 387     @IR(failOn = {CALL_UNSAFE})
 388     public int test21(MyValue1 v) {
 389        return U.getInt(v, X_OFFSET);
 390     }
 391 
 392     @Run(test = "test21")
 393     public void test21_verifier() {
 394         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 395         int res = test21(v);
 396         Asserts.assertEQ(res, v.x);
 397     }
 398 
 399     @NullRestricted
 400     MyValue1 test22_vt;
 401 
 402     @Test
 403     @IR(failOn = {CALL_UNSAFE, ALLOC})
 404     public void test22(MyValue1 v) {
 405         v = U.makePrivateBuffer(v);
 406         U.putInt(v, X_OFFSET, rI);
 407         v = U.finishPrivateBuffer(v);
 408         test22_vt = v;
 409     }
 410 
 411     @Run(test = "test22")
 412     public void test22_verifier() {
 413         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 414         test22(v.setX(v, 0));
 415         Asserts.assertEQ(test22_vt.hash(), v.hash());
 416     }
 417 
 418     @Test
 419     @IR(failOn = {CALL_UNSAFE})
 420     public int test23(MyValue1 v, long offset) {
 421         return U.getInt(v, offset);
 422     }
 423 
 424     @Run(test = "test23")
 425     public void test23_verifier() {
 426         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 427         int res = test23(v, X_OFFSET);
 428         Asserts.assertEQ(res, v.x);
 429     }
 430 
 431     @NullRestricted
 432     MyValue1 test24_vt = MyValue1.createWithFieldsInline(rI, rL);
 433 
 434     @Test
 435     @IR(failOn = {CALL_UNSAFE})
 436     public int test24(long offset) {
 437         return U.getInt(test24_vt, offset);
 438     }
 439 
 440     @Run(test = "test24")
 441     public void test24_verifier() {
 442         int res = test24(X_OFFSET);
 443         Asserts.assertEQ(res, test24_vt.x);
 444     }
 445 
 446     // Test copyOf intrinsic with allocated value object in it's debug information
 447     @ImplicitlyConstructible
 448     @LooselyConsistentValue
 449     value class Test25Value {
 450         int x;
 451 
 452         public Test25Value() {
 453             this.x = 42;
 454         }
 455     }
 456 
 457     final Test25Value[] test25Array = (Test25Value[])ValueClass.newNullRestrictedArray(Test25Value.class, 10);
 458 
 459     @Test
 460     public Test25Value[] test25(Test25Value element) {
 461         Object[] newArray = Arrays.copyOf(test25Array, test25Array.length + 1);
 462         newArray[test25Array.length] = element;
 463         return (Test25Value[]) newArray;
 464     }
 465 
 466     @Run(test = "test25")
 467     public void test25_verifier() {
 468         Test25Value vt = new Test25Value();
 469         test25(vt);
 470     }
 471 
 472     @Test
 473     @IR(failOn = IRNode.LOAD_I) // Load of the default value should be folded
 474     public Object test26() {
 475         Class<?>[] ca = new Class<?>[1];
 476         for (int i = 0; i < 1; ++i) {
 477           // Folds during loop opts
 478           ca[i] = MyValue1.class;
 479         }
 480         return ValueClass.newNullRestrictedArray(ca[0], 1);
 481     }
 482 
 483     @Run(test = "test26")
 484     public void test26_verifier() {
 485         Object[] res = (Object[])test26();
 486         Asserts.assertEQ(((MyValue1)res[0]).hashPrimitive(), MyValue1.createDefaultInline().hashPrimitive());
 487     }
 488 
 489     // Load non-flattenable value class field with unsafe
 490     MyValue1 test27_vt;
 491     private static final long TEST27_OFFSET;
 492     static {
 493         try {
 494             Field field = TestIntrinsics.class.getDeclaredField("test27_vt");
 495             TEST27_OFFSET = U.objectFieldOffset(field);
 496         } catch (Exception e) {
 497             throw new RuntimeException(e);
 498         }
 499     }
 500 
 501     @Test
 502     @IR(failOn = {CALL_UNSAFE})
 503     public MyValue1 test27() {
 504         return (MyValue1)U.getReference(this, TEST27_OFFSET);
 505     }
 506 
 507     @Run(test = "test27")
 508     public void test27_verifier() {
 509         test27_vt = null;
 510         MyValue1 res = test27();
 511         Asserts.assertEQ(res, null);
 512         test27_vt = MyValue1.createWithFieldsInline(rI, rL);
 513         res = test27();
 514         Asserts.assertEQ(res.hash(), test24_vt.hash());
 515     }
 516 
 517     // Mismatched type
 518     @Test
 519     @IR(failOn = {CALL_UNSAFE})
 520     public int test28(MyValue1 v) {
 521         return U.getByte(v, X_OFFSET);
 522     }
 523 
 524     @Run(test = "test28")
 525     public void test28_verifier() {
 526         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 527         int res = test28(v);
 528         if (java.nio.ByteOrder.nativeOrder() == java.nio.ByteOrder.LITTLE_ENDIAN) {
 529             Asserts.assertEQ(res, (int)((byte)v.x));
 530         } else {
 531             Asserts.assertEQ(res, (int)((byte)Integer.reverseBytes(v.x)));
 532         }
 533     }
 534 
 535     // Wrong alignment
 536     @Test
 537     @IR(failOn = {CALL_UNSAFE})
 538     public long test29(MyValue1 v) {
 539         // Read the field that's guaranteed to not be last in the
 540         // value class so we don't read out of bounds.
 541         if (X_OFFSET < Y_OFFSET) {
 542             return U.getInt(v, X_OFFSET+1);
 543         }
 544         return U.getLong(v, Y_OFFSET+1);
 545     }
 546 
 547     @Run(test = "test29")
 548     public void test29_verifier() {
 549         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 550         long res = test29(v);
 551         if (java.nio.ByteOrder.nativeOrder() == java.nio.ByteOrder.LITTLE_ENDIAN) {
 552             if (X_OFFSET < Y_OFFSET) {
 553                 Asserts.assertEQ(((int)res) << 8, (v.x >> 8) << 8);
 554             } else {
 555                 Asserts.assertEQ(res << 8, (v.y >> 8) << 8);
 556             }
 557         } else {
 558             if (X_OFFSET < Y_OFFSET) {
 559                 Asserts.assertEQ(((int)res), v.x >>> 8);
 560             } else {
 561                 Asserts.assertEQ(res, v.y >>> 8);
 562             }
 563         }
 564     }
 565 
 566     // getValue to retrieve flattened field from value object
 567     @Test
 568     @IR(failOn = {CALL_UNSAFE})
 569     public MyValue2 test30(MyValue1 v) {
 570         if (V1_FLATTENED) {
 571             return U.getValue(v, V1_OFFSET, MyValue2.class);
 572         }
 573         return (MyValue2)U.getReference(v, V1_OFFSET);
 574     }
 575 
 576     @Run(test = "test30")
 577     public void test30_verifier(RunInfo info) {
 578         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 579         MyValue2 res = test30(v);
 580         Asserts.assertEQ(res.hash(), v.v1.hash());
 581     }
 582 
 583     @NullRestricted
 584     MyValue1 test31_vt;
 585     private static final long TEST31_VT_OFFSET;
 586     private static final boolean TEST31_VT_FLATTENED;
 587     static {
 588         try {
 589             Field test31_vt_Field = TestIntrinsics.class.getDeclaredField("test31_vt");
 590             TEST31_VT_OFFSET = U.objectFieldOffset(test31_vt_Field);
 591             TEST31_VT_FLATTENED = U.isFlatField(test31_vt_Field);
 592         } catch (Exception e) {
 593             throw new RuntimeException(e);
 594         }
 595     }
 596 
 597     // getValue to retrieve flattened field from object
 598     @Test
 599     @IR(failOn = {CALL_UNSAFE})
 600     public MyValue1 test31() {
 601         if (TEST31_VT_FLATTENED) {
 602             return U.getValue(this, TEST31_VT_OFFSET, MyValue1.class);
 603         }
 604         return (MyValue1)U.getReference(this, TEST31_VT_OFFSET);
 605     }
 606 
 607     @Run(test = "test31")
 608     public void test31_verifier() {
 609         test31_vt = MyValue1.createWithFieldsInline(rI, rL);
 610         MyValue1 res = test31();
 611         Asserts.assertEQ(res.hash(), test31_vt.hash());
 612     }
 613 
 614     // putValue to set flattened field in object
 615     @Test
 616     @IR(failOn = {CALL_UNSAFE})
 617     public void test32(MyValue1 vt) {
 618         if (TEST31_VT_FLATTENED) {
 619             U.putValue(this, TEST31_VT_OFFSET, MyValue1.class, vt);
 620         } else {
 621             U.putReference(this, TEST31_VT_OFFSET, vt);
 622         }
 623     }
 624 
 625     @Run(test = "test32")
 626     public void test32_verifier() {
 627         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 628         test31_vt = MyValue1.createDefaultInline();
 629         test32(vt);
 630         Asserts.assertEQ(vt.hash(), test31_vt.hash());
 631     }
 632 
 633     private static final int TEST33_BASE_OFFSET;
 634     private static final int TEST33_INDEX_SCALE;
 635     private static final MyValue1[] TEST33_ARRAY;
 636     private static final boolean TEST33_FLATTENED_ARRAY;
 637     static {
 638         try {
 639             TEST33_ARRAY = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 2);
 640             TEST33_BASE_OFFSET = U.arrayBaseOffset(TEST33_ARRAY.getClass());
 641             TEST33_INDEX_SCALE = U.arrayIndexScale(TEST33_ARRAY.getClass());
 642             TEST33_FLATTENED_ARRAY = U.isFlatArray(TEST33_ARRAY.getClass());
 643         } catch (Exception e) {
 644             throw new RuntimeException(e);
 645         }
 646     }
 647     // getValue to retrieve flattened field from array
 648     @Test
 649     @IR(failOn = {CALL_UNSAFE})
 650     public MyValue1 test33() {
 651         if (TEST33_FLATTENED_ARRAY) {
 652             return U.getValue(TEST33_ARRAY, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.class);
 653         }
 654         return (MyValue1)U.getReference(TEST33_ARRAY, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE);
 655     }
 656 
 657     @Run(test = "test33")
 658     public void test33_verifier() {
 659         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 660         TEST33_ARRAY[1] = vt;
 661         MyValue1 res = test33();
 662         Asserts.assertEQ(res.hash(), vt.hash());
 663     }
 664 
 665     // putValue to set flattened field in array
 666     @Test
 667     @IR(failOn = {CALL_UNSAFE})
 668     public void test34(MyValue1 vt) {
 669         if (TEST33_FLATTENED_ARRAY) {
 670             U.putValue(TEST33_ARRAY, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.class, vt);
 671         } else {
 672             U.putReference(TEST33_ARRAY, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, vt);
 673         }
 674     }
 675 
 676     @Run(test = "test34")
 677     public void test34_verifier() {
 678         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 679         test34(vt);
 680         Asserts.assertEQ(TEST33_ARRAY[1].hash(), vt.hash());
 681     }
 682 
 683     // getValue to retrieve flattened field from object with unknown
 684     // container type
 685     @Test
 686     @IR(failOn = {CALL_UNSAFE})
 687     public MyValue1 test35(Object o) {
 688         if (TEST31_VT_FLATTENED) {
 689             return U.getValue(o, TEST31_VT_OFFSET, MyValue1.class);
 690         }
 691         return (MyValue1)U.getReference(o, TEST31_VT_OFFSET);
 692     }
 693 
 694     @Run(test = "test35")
 695     public void test35_verifier() {
 696         test31_vt = MyValue1.createWithFieldsInline(rI, rL);
 697         MyValue1 res = test35(this);
 698         Asserts.assertEQ(res.hash(), test31_vt.hash());
 699     }
 700 
 701     // getValue to retrieve flattened field from object at unknown
 702     // offset
 703     @Test
 704     @IR(failOn = {CALL_UNSAFE})
 705     public MyValue1 test36(long offset) {
 706         if (TEST31_VT_FLATTENED) {
 707             return U.getValue(this, offset, MyValue1.class);
 708         }
 709         return (MyValue1)U.getReference(this, offset);
 710     }
 711 
 712     @Run(test = "test36")
 713     public void test36_verifier() {
 714         test31_vt = MyValue1.createWithFieldsInline(rI, rL);
 715         MyValue1 res = test36(TEST31_VT_OFFSET);
 716         Asserts.assertEQ(res.hash(), test31_vt.hash());
 717     }
 718 
 719     // putValue to set flattened field in object with unknown
 720     // container
 721     @Test
 722     @IR(failOn = {CALL_UNSAFE})
 723     public void test37(Object o, MyValue1 vt) {
 724         if (TEST31_VT_FLATTENED) {
 725             U.putValue(o, TEST31_VT_OFFSET, MyValue1.class, vt);
 726         } else {
 727             U.putReference(o, TEST31_VT_OFFSET, vt);
 728         }
 729     }
 730 
 731     @Run(test = "test37")
 732     public void test37_verifier() {
 733         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 734         test31_vt = MyValue1.createDefaultInline();
 735         test37(this, vt);
 736         Asserts.assertEQ(vt.hash(), test31_vt.hash());
 737     }
 738 
 739     // putValue to set flattened field in object, non inline argument
 740     // to store
 741     @Test
 742     @IR(counts = {CALL_UNSAFE, "= 1"})
 743     public void test38(Object o) {
 744         if (TEST31_VT_FLATTENED) {
 745             U.putValue(this, TEST31_VT_OFFSET, MyValue1.class, o);
 746         } else {
 747             U.putReference(this, TEST31_VT_OFFSET, o);
 748         }
 749     }
 750 
 751     @Run(test = "test38")
 752     public void test38_verifier() {
 753         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 754         test31_vt = MyValue1.createDefaultInline();
 755         test38(vt);
 756         Asserts.assertEQ(vt.hash(), test31_vt.hash());
 757     }
 758 
 759     @Test
 760     @IR(failOn = {CALL_UNSAFE})
 761     public MyValue1 test39(MyValue1 v) {
 762         v = U.makePrivateBuffer(v);
 763         U.putInt(v, X_OFFSET, rI);
 764         v = U.finishPrivateBuffer(v);
 765         return v;
 766     }
 767 
 768     @Run(test = "test39")
 769     public void test39_verifier() {
 770         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 771         MyValue1 res = test39(v.setX(v, 0));
 772         Asserts.assertEQ(res.hash(), v.hash());
 773     }
 774 
 775     // Test default value class array creation via reflection
 776     @Test
 777     public Object[] test40(Class<?> componentType, int len) {
 778         Object[] va = (Object[])Array.newInstance(componentType, len);
 779         return va;
 780     }
 781 
 782     @Run(test = "test40")
 783     public void test40_verifier() {
 784         int len = Math.abs(rI) % 42;
 785         Object[] va = test40(MyValue1.class, len);
 786         for (int i = 0; i < len; ++i) {
 787             Asserts.assertEQ(va[i], null);
 788         }
 789     }
 790 
 791     // Class.isInstance
 792     @Test
 793     public boolean test41(Class c, MyValue1 vt) {
 794         return c.isInstance(vt);
 795     }
 796 
 797     @Run(test = "test41")
 798     public void test41_verifier() {
 799         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 800         boolean result = test41(MyValue1.class, vt);
 801         Asserts.assertTrue(result);
 802         result = test41(MyValue1.class, null);
 803         Asserts.assertFalse(result);
 804         result = test41(MyValue1.class, vt);
 805         Asserts.assertTrue(result);
 806         result = test41(MyValue1.class, null);
 807         Asserts.assertFalse(result);
 808     }
 809 
 810     @Test
 811     public boolean test42(Class c, MyValue1 vt) {
 812         return c.isInstance(vt);
 813     }
 814 
 815     @Run(test = "test42")
 816     public void test42_verifier() {
 817         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 818         boolean result = test42(MyValue2.class, vt);
 819         Asserts.assertFalse(result);
 820         result = test42(MyValue2.class, null);
 821         Asserts.assertFalse(result);
 822         result = test42(MyValue2.class, vt);
 823         Asserts.assertFalse(result);
 824         result = test42(MyValue2.class, null);
 825         Asserts.assertFalse(result);
 826     }
 827 
 828     // Class.cast
 829     @Test
 830     public Object test43(Class c, MyValue1 vt) {
 831         return c.cast(vt);
 832     }
 833 
 834     @Run(test = "test43")
 835     public void test43_verifier() {
 836         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 837         Object result = test43(MyValue1.class, vt);
 838         Asserts.assertEQ(result, vt);
 839         result = test43(MyValue1.class, null);
 840         Asserts.assertEQ(result, null);
 841         result = test43(MyValue1.class, vt);
 842         Asserts.assertEQ(result, vt);
 843         result = test43(NonValueClass.class, null);
 844         Asserts.assertEQ(result, null);
 845     }
 846 
 847     @Test
 848     public Object test44(Class c, MyValue1 vt) {
 849         return c.cast(vt);
 850     }
 851 
 852     @Run(test = "test44")
 853     public void test44_verifier() {
 854         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 855         try {
 856             test44(MyValue2.class, vt);
 857             throw new RuntimeException("should have thrown");
 858         } catch (ClassCastException cce) {
 859         }
 860         Object res = test44(MyValue2.class, null);
 861         Asserts.assertEQ(res, null);
 862         try {
 863             test44(MyValue2.class, vt);
 864             throw new RuntimeException("should have thrown");
 865         } catch (ClassCastException cce) {
 866         }
 867     }
 868 
 869     @Test
 870     public Object test45(MyValue1 vt) {
 871         return MyValue1.class.cast(vt);
 872     }
 873 
 874     @Run(test = "test45")
 875     public void test45_verifier() {
 876         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 877         Object result = test45(vt);
 878         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 879         result = test45(null);
 880         Asserts.assertEQ(result, null);
 881     }
 882 
 883     @Test
 884     public Object test46(MyValue1 vt) {
 885         return MyValue2.class.cast(vt);
 886     }
 887 
 888     @Run(test = "test46")
 889     public void test46_verifier() {
 890         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 891         Object result = test46(null);
 892         Asserts.assertEQ(result, null);
 893         try {
 894             test46(vt);
 895             throw new RuntimeException("should have thrown");
 896         } catch (ClassCastException cce) {
 897         }
 898     }
 899 
 900     @Test
 901     public Object test47(MyValue1 vt) {
 902         return MyValue1.class.cast(vt);
 903     }
 904 
 905     @Run(test = "test47")
 906     public void test47_verifier() {
 907         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 908         Object result = test47(vt);
 909         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 910         result = test47(null);
 911         Asserts.assertEQ(result, null);
 912     }
 913 
 914     @Test
 915     public Object test48(Class c, MyValue1 vt) {
 916         return c.cast(vt);
 917     }
 918 
 919     @Run(test = "test48")
 920     public void test48_verifier() {
 921         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 922         Object result = test48(MyValue1.class, vt);
 923         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 924         result = test48(MyValue1.class, null);
 925         Asserts.assertEQ(result, null);
 926     }
 927 
 928     @Test
 929     public Object test49(MyValue1 vt) {
 930         return MyValue1.class.cast(vt);
 931     }
 932 
 933     @Run(test = "test49")
 934     public void test49_verifier() {
 935         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 936         Object result = test49(vt);
 937         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 938     }
 939 
 940     @Test
 941     public Object test50(Class c, Object obj) {
 942         return c.cast(obj);
 943     }
 944 
 945     @Run(test = "test50")
 946     public void test50_verifier() {
 947         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 948         MyValue1[] va  = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 42);
 949         MyValue1[] vba = new MyValue1[42];
 950         Object result = test50(MyValue1.class, vt);
 951         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 952         result = test50(MyValue1.class, vt);
 953         Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
 954         result = test50(MyValue1[].class, va);
 955         Asserts.assertEQ(result, va);
 956         result = test50(MyValue1[].class, vba);
 957         Asserts.assertEQ(result, vba);
 958         result = test50(MyValue1[].class, va);
 959         Asserts.assertEQ(result, va);
 960         result = test50(MyValue1.class, null);
 961         Asserts.assertEQ(result, null);
 962         try {
 963             test50(va.getClass(), vba);
 964             throw new RuntimeException("should have thrown");
 965         } catch (ClassCastException cce) {
 966         }
 967     }
 968 
 969     // Value class array creation via reflection
 970     @Test
 971     public void test51(int len) {
 972         Object[] va = (Object[])Array.newInstance(MyValue1.class, len);
 973         for (int i = 0; i < len; ++i) {
 974             Asserts.assertEQ(va[i], null);
 975         }
 976     }
 977 
 978     @Run(test = "test51")
 979     public void test51_verifier() {
 980         int len = Math.abs(rI) % 42;
 981         test51(len);
 982     }
 983 
 984     // multidimensional value class array creation via reflection
 985     @Test
 986     public Object[][] test52(int len, int val) {
 987         MyValue1[][] va1 = (MyValue1[][])Array.newInstance(MyValue1[].class, len);
 988         MyValue1[][] va2 = (MyValue1[][])Array.newInstance(MyValue1[].class, len);
 989         Object[][] result;
 990         if (val == 1) {
 991             va1[0] = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 1);
 992             result = va1;
 993         } else {
 994             va2[0] = new MyValue1[1];
 995             result = va2;
 996         }
 997         if (val == 1) {
 998             Asserts.assertEQ(va1[0][0].hash(), ((MyValue1)result[0][0]).hash());
 999         } else {
1000             Asserts.assertEQ(result[0][0], null);
1001             result[0][0] = null;
1002         }
1003         return result;
1004     }
1005 
1006     @Run(test = "test52")
1007     public void test52_verifier() {
1008         test52(1, 1);
1009         test52(1, 2);
1010     }
1011 
1012     @Test
1013     public Object[][] test53(Class<?> c1, Class<?> c2, int len, int val) {
1014         MyValue1[][] va1 = (MyValue1[][])Array.newInstance(MyValue1[].class, len);
1015         MyValue1[][] va2 = (MyValue1[][])Array.newInstance(MyValue1[].class, len);
1016         Object[][] va3 = (Object[][])Array.newInstance(c1, len);
1017         Object[][] va4 = (Object[][])Array.newInstance(c2, len);
1018         for (int i = 0; i < len; ++i) {
1019             Asserts.assertEQ(va1[i], null);
1020             Asserts.assertEQ(va2[i], null);
1021             Asserts.assertEQ(va3[i], null);
1022             Asserts.assertEQ(va4[i], null);
1023             va1[i] = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 1);
1024             va2[i] = new MyValue1[1];
1025             va3[i] = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 1);
1026             va4[i] = new MyValue1[1];
1027             Asserts.assertEQ(va1[i][0].hash(), ((MyValue1)va3[i][0]).hash());
1028             Asserts.assertEQ(va2[i][0], null);
1029             Asserts.assertEQ(va4[i][0], null);
1030         }
1031         Object[][] result;
1032         if (val == 1) {
1033             result = va1;
1034         } else if (val == 2) {
1035             result = va2;
1036         } else if (val == 3) {
1037             result = va3;
1038         } else {
1039             result = va4;
1040         }
1041         if ((val == 1 || val == 3) && len > 0) {
1042             Asserts.assertEQ(va1[0][0].hash(), ((MyValue1)result[0][0]).hash());
1043         } else if (len > 0) {
1044             Asserts.assertEQ(result[0][0], null);
1045             result[0][0] = null;
1046         }
1047         return result;
1048     }
1049 
1050     @Run(test = "test53")
1051     public void test53_verifier() {
1052         int len = Math.abs(rI) % 42;
1053         test53(MyValue1[].class, MyValue1[].class, len, 1);
1054         test53(MyValue1[].class, MyValue1[].class, len, 2);
1055         test53(MyValue1[].class, MyValue1[].class, len, 3);
1056         test53(MyValue1[].class, MyValue1[].class, len, 4);
1057     }
1058 
1059     // TODO 8239003 Re-enable
1060     /*
1061     // Same as test39 but Unsafe.putInt to buffer is not intrinsified/compiled
1062     @DontCompile
1063     public void test54_callee(Object v) { // Use Object here to make sure the argument is not scalarized (otherwise larval information is lost)
1064         U.putInt(v, X_OFFSET, rI);
1065     }
1066 
1067     @Test
1068     public MyValue1 test54(MyValue1 v) {
1069         v = U.makePrivateBuffer(v);
1070         test54_callee(v);
1071         v = U.finishPrivateBuffer(v);
1072         return v;
1073     }
1074 
1075     @Run(test = "test54")
1076     @Warmup(10000) // Fill up the TLAB to trigger slow path allocation
1077     public void test54_verifier() {
1078         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1079         MyValue1 res = test54(v.setX(v, 0));
1080         Asserts.assertEQ(res.hash(), v.hash());
1081     }
1082     */
1083 
1084     @NullRestricted
1085     static final MyValue1 test55_vt = MyValue1.createWithFieldsInline(rI, rL);
1086 
1087     // Same as test30 but with constant field holder
1088     @Test
1089     @IR(failOn = {CALL_UNSAFE})
1090     public MyValue2 test55() {
1091         if (V1_FLATTENED) {
1092             return U.getValue(test55_vt, V1_OFFSET, MyValue2.class);
1093         }
1094         return (MyValue2)U.getReference(test55_vt, V1_OFFSET);
1095     }
1096 
1097     @Run(test = "test55")
1098     public void test55_verifier() {
1099         MyValue2 res = test55();
1100         Asserts.assertEQ(res.hash(), test55_vt.v1.hash());
1101     }
1102 
1103     // Test OptimizePtrCompare part of Escape Analysis
1104     @Test
1105     public void test56(int idx) {
1106         Object[] va = ValueClass.newNullRestrictedArray(MyValue1.class, 1);
1107         if (va[idx] == null) {
1108             throw new RuntimeException("Unexpected null");
1109         }
1110     }
1111 
1112     @Run(test = "test56")
1113     public void test56_verifier() {
1114         test56(0);
1115     }
1116 
1117     // Same as test56 but with load from known array index
1118     @Test
1119     public void test57() {
1120         Object[] va = ValueClass.newNullRestrictedArray(MyValue1.class, 1);
1121         if (va[0] == null) {
1122             throw new RuntimeException("Unexpected null");
1123         }
1124     }
1125 
1126     @Run(test = "test57")
1127     public void test57_verifier() {
1128         test57();
1129     }
1130 
1131     // Test unsafe allocation
1132     @Test
1133     public boolean test58(Class<?> c1, Class<?> c2) throws Exception {
1134         Object obj1 = U.allocateInstance(c1);
1135         Object obj2 = U.allocateInstance(c2);
1136         return obj1 == obj2;
1137     }
1138 
1139     @Run(test = "test58")
1140     public void test58_verifier() throws Exception {
1141         boolean res = test58(MyValue1.class, MyValue1.class);
1142         Asserts.assertTrue(res);
1143         res = test58(Object.class, MyValue1.class);
1144         Asserts.assertFalse(res);
1145         res = test58(MyValue1.class, Object.class);
1146         Asserts.assertFalse(res);
1147     }
1148 
1149     // Test synchronization on unsafe value object allocation
1150     @Test
1151     public void test59(Class<?> c) throws Exception {
1152         Object obj = U.allocateInstance(c);
1153         synchronized (obj) {
1154 
1155         }
1156     }
1157 
1158     @Run(test = "test59")
1159     public void test59_verifier() throws Exception {
1160         test59(Object.class);
1161         try {
1162             test59(MyValue1.class);
1163             throw new RuntimeException("test59 failed: synchronization on value object should not succeed");
1164         } catch (IllegalMonitorStateException e) {
1165 
1166         }
1167     }
1168 
1169     // Test mark word load optimization on unsafe value object allocation
1170     @Test
1171     public boolean test60(Class<?> c1, Class<?> c2, boolean b1, boolean b2) throws Exception {
1172         Object obj1 = b1 ? new Object() : U.allocateInstance(c1);
1173         Object obj2 = b2 ? new Object() : U.allocateInstance(c2);
1174         return obj1 == obj2;
1175     }
1176 
1177     @Run(test = "test60")
1178     public void test60_verifier() throws Exception {
1179         Asserts.assertTrue(test60(MyValue1.class, MyValue1.class, false, false));
1180         Asserts.assertFalse(test60(MyValue1.class, MyValue2.class, false, false));
1181         Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, false, true));
1182         Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, true, false));
1183         Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, true, true));
1184     }
1185 
1186     // compareAndSet to flattened field in object
1187     @Test
1188     public boolean test63(MyValue1 oldVal, MyValue1 newVal) {
1189         if (TEST31_VT_FLATTENED) {
1190             return U.compareAndSetValue(this, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1191         } else {
1192             return U.compareAndSetReference(this, TEST31_VT_OFFSET, oldVal, newVal);
1193         }
1194     }
1195 
1196     @Run(test = "test63")
1197     public void test63_verifier() {
1198         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1199         test31_vt = MyValue1.createDefaultInline();
1200 
1201         boolean res = test63(test31_vt, vt);
1202         // Checks are disabled for non-flattened field because reference comparison
1203         // fails if C2 scalarizes and re-allocates the value class arguments.
1204         if (TEST31_VT_FLATTENED) {
1205             Asserts.assertTrue(res);
1206             Asserts.assertEQ(test31_vt, vt);
1207         }
1208 
1209         res = test63(MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1210         if (TEST31_VT_FLATTENED) {
1211             Asserts.assertFalse(res);
1212             Asserts.assertEQ(test31_vt, vt);
1213         }
1214     }
1215 
1216     // compareAndSet to flattened field in array
1217     @Test
1218     public boolean test64(MyValue1[] arr, MyValue1 oldVal, Object newVal) {
1219         if (TEST33_FLATTENED_ARRAY) {
1220             return U.compareAndSetValue(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.class, oldVal, newVal);
1221         } else {
1222             return U.compareAndSetReference(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, oldVal, newVal);
1223         }
1224     }
1225 
1226     @Run(test = "test64")
1227     public void test64_verifier() {
1228         MyValue1[] arr = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 2);
1229         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1230 
1231         boolean res = test64(arr, arr[1], vt);
1232         // Checks are disabled for non-flattened array because reference comparison
1233         // fails if C2 scalarizes and re-allocates the value class arguments.
1234         if (TEST33_FLATTENED_ARRAY) {
1235             Asserts.assertTrue(res);
1236             Asserts.assertEQ(arr[1], vt);
1237         }
1238 
1239         res = test64(arr, MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1240         if (TEST33_FLATTENED_ARRAY) {
1241             Asserts.assertFalse(res);
1242             Asserts.assertEQ(arr[1], vt);
1243         }
1244     }
1245 
1246     // compareAndSet to flattened field in object with unknown container
1247     @Test
1248     public boolean test65(Object o, Object oldVal, MyValue1 newVal) {
1249         if (TEST31_VT_FLATTENED) {
1250             return U.compareAndSetValue(o, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1251         } else {
1252             return U.compareAndSetReference(o, TEST31_VT_OFFSET, oldVal, newVal);
1253         }
1254     }
1255 
1256     @Run(test = "test65")
1257     public void test65_verifier() {
1258         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1259         test31_vt = MyValue1.createDefaultInline();
1260 
1261         boolean res = test65(this, test31_vt, vt);
1262         Asserts.assertTrue(res);
1263         Asserts.assertEQ(test31_vt, vt);
1264 
1265         res = test65(this, MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1266         Asserts.assertFalse(res);
1267         Asserts.assertEQ(test31_vt, vt);
1268     }
1269 
1270     // compareAndSet to flattened field in object, non-inline arguments to compare and set
1271     @Test
1272     public boolean test66(Object oldVal, Object newVal) {
1273         if (TEST31_VT_FLATTENED) {
1274             return U.compareAndSetValue(this, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1275         } else {
1276             return U.compareAndSetReference(this, TEST31_VT_OFFSET, oldVal, newVal);
1277         }
1278     }
1279 
1280     @Run(test = "test66")
1281     public void test66_verifier() {
1282         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1283         test31_vt = MyValue1.createDefaultInline();
1284 
1285         boolean res = test66(test31_vt, vt);
1286         Asserts.assertTrue(res);
1287         Asserts.assertEQ(test31_vt, vt);
1288 
1289         res = test66(MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1290         Asserts.assertFalse(res);
1291         Asserts.assertEQ(test31_vt, vt);
1292     }
1293 
1294     // compareAndExchange to flattened field in object
1295     @Test
1296     public Object test67(MyValue1 oldVal, MyValue1 newVal) {
1297         if (TEST31_VT_FLATTENED) {
1298             return U.compareAndExchangeValue(this, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1299         } else {
1300             return U.compareAndExchangeReference(this, TEST31_VT_OFFSET, oldVal, newVal);
1301         }
1302     }
1303 
1304     @Run(test = "test67")
1305     public void test67_verifier() {
1306         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1307         MyValue1 oldVal = MyValue1.createDefaultInline();
1308         test31_vt = oldVal;
1309 
1310         Object res = test67(test31_vt, vt);
1311         // Checks are disabled for non-flattened field because reference comparison
1312         // fails if C2 scalarizes and re-allocates the value class arguments.
1313         if (TEST31_VT_FLATTENED) {
1314             Asserts.assertEQ(res, oldVal);
1315             Asserts.assertEQ(test31_vt, vt);
1316         }
1317 
1318         res = test67(MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1319         if (TEST31_VT_FLATTENED) {
1320             Asserts.assertEQ(res, vt);
1321             Asserts.assertEQ(test31_vt, vt);
1322         }
1323     }
1324 
1325     // compareAndExchange to flattened field in array
1326     @Test
1327     public Object test68(MyValue1[] arr, MyValue1 oldVal, Object newVal) {
1328         if (TEST33_FLATTENED_ARRAY) {
1329             return U.compareAndExchangeValue(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.class, oldVal, newVal);
1330         } else {
1331             return U.compareAndExchangeReference(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, oldVal, newVal);
1332         }
1333     }
1334 
1335     @Run(test = "test68")
1336     public void test68_verifier() {
1337         MyValue1[] arr = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 2);
1338         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1339 
1340         Object res = test68(arr, arr[1], vt);
1341         // Checks are disabled for non-flattened array because reference comparison
1342         // fails if C2 scalarizes and re-allocates the value class arguments.
1343         if (TEST33_FLATTENED_ARRAY) {
1344             Asserts.assertEQ(res, MyValue1.createDefaultInline());
1345             Asserts.assertEQ(arr[1], vt);
1346         }
1347 
1348         res = test68(arr, MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1349         if (TEST33_FLATTENED_ARRAY) {
1350             Asserts.assertEQ(res, vt);
1351             Asserts.assertEQ(arr[1], vt);
1352         }
1353     }
1354 
1355     // compareAndExchange to flattened field in object with unknown container
1356     @Test
1357     public Object test69(Object o, Object oldVal, MyValue1 newVal) {
1358         if (TEST31_VT_FLATTENED) {
1359             return U.compareAndExchangeValue(o, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1360         } else {
1361             return U.compareAndExchangeReference(o, TEST31_VT_OFFSET, oldVal, newVal);
1362         }
1363     }
1364 
1365     @Run(test = "test69")
1366     public void test69_verifier() {
1367         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1368         MyValue1 oldVal = MyValue1.createDefaultInline();
1369         test31_vt = oldVal;
1370 
1371         Object res = test69(this, test31_vt, vt);
1372         Asserts.assertEQ(res, oldVal);
1373         Asserts.assertEQ(test31_vt, vt);
1374 
1375         res = test69(this, MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1376         Asserts.assertEQ(res, vt);
1377         Asserts.assertEQ(test31_vt, vt);
1378     }
1379 
1380     // compareAndExchange to flattened field in object, non-inline arguments to compare and set
1381     @Test
1382     public Object test70(Object oldVal, Object newVal) {
1383         if (TEST31_VT_FLATTENED) {
1384             return U.compareAndExchangeValue(this, TEST31_VT_OFFSET, MyValue1.class, oldVal, newVal);
1385         } else {
1386             return U.compareAndExchangeReference(this, TEST31_VT_OFFSET, oldVal, newVal);
1387         }
1388     }
1389 
1390     @Run(test = "test70")
1391     public void test70_verifier() {
1392         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1393         MyValue1 oldVal = MyValue1.createDefaultInline();
1394         test31_vt = oldVal;
1395 
1396         Object res = test70(test31_vt, vt);
1397         Asserts.assertEQ(res, oldVal);
1398         Asserts.assertEQ(test31_vt, vt);
1399 
1400         res = test70(MyValue1.createDefaultInline(), MyValue1.createDefaultInline());
1401         Asserts.assertEQ(res, vt);
1402         Asserts.assertEQ(test31_vt, vt);
1403     }
1404 
1405     // getValue to retrieve flattened field from (nullable) value class
1406     @Test
1407     @IR(failOn = {CALL_UNSAFE})
1408     public MyValue2 test71(boolean b, MyValue1 v1, MyValue1 v2) {
1409         if (b) {
1410             if (V1_FLATTENED) {
1411                 return U.getValue(v1, V1_OFFSET, MyValue2.class);
1412             }
1413             return (MyValue2)U.getReference(v1, V1_OFFSET);
1414         } else {
1415             if (V1_FLATTENED) {
1416                 return U.getValue(v2, V1_OFFSET, MyValue2.class);
1417             }
1418             return (MyValue2)U.getReference(v2, V1_OFFSET);
1419         }
1420     }
1421 
1422     @Run(test = "test71")
1423     public void test71_verifier() {
1424         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1425         Asserts.assertEQ(test71(true, v, v), v.v1);
1426         Asserts.assertEQ(test71(false, v, v), v.v1);
1427     }
1428 
1429     // Same as test71 but with non-constant offset
1430     @Test
1431     @IR(failOn = {CALL_UNSAFE})
1432     public MyValue2 test72(boolean b, MyValue1 v1, MyValue1 v2, long offset) {
1433         if (b) {
1434             if (V1_FLATTENED) {
1435                 return U.getValue(v1, offset, MyValue2.class);
1436             }
1437             return (MyValue2)U.getReference(v1, offset);
1438         } else {
1439             if (V1_FLATTENED) {
1440                 return U.getValue(v2, offset, MyValue2.class);
1441             }
1442             return (MyValue2)U.getReference(v2, offset);
1443         }
1444     }
1445 
1446     @Run(test = "test72")
1447     public void test72_verifier() {
1448         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1449         Asserts.assertEQ(test72(true, v, v, V1_OFFSET), v.v1);
1450         Asserts.assertEQ(test72(false, v, v, V1_OFFSET), v.v1);
1451     }
1452 
1453     @NullRestricted
1454     static final MyValue1 test73_value1 = MyValue1.createWithFieldsInline(rI, rL);
1455     static final MyValue1 test73_value2 = MyValue1.createWithFieldsInline(rI+1, rL+1);
1456 
1457     // Same as test72 but with constant base
1458     @Test
1459     @IR(failOn = {CALL_UNSAFE})
1460     public MyValue2 test73(boolean b, long offset) {
1461         if (b) {
1462             if (V1_FLATTENED) {
1463                 return U.getValue(test73_value1, offset, MyValue2.class);
1464             }
1465             return (MyValue2)U.getReference(test73_value1, offset);
1466         } else {
1467             if (V1_FLATTENED) {
1468                 return U.getValue(test73_value2, offset, MyValue2.class);
1469             }
1470             return (MyValue2)U.getReference(test73_value2, offset);
1471         }
1472     }
1473 
1474     @Run(test = "test73")
1475     public void test73_verifier() {
1476         Asserts.assertEQ(test73(true, V1_OFFSET), test73_value1.v1);
1477         Asserts.assertEQ(test73(false, V1_OFFSET), test73_value2.v1);
1478     }
1479 
1480     @ImplicitlyConstructible
1481     @LooselyConsistentValue
1482     static value class EmptyInline {
1483 
1484     }
1485 
1486     @ImplicitlyConstructible
1487     @LooselyConsistentValue
1488     static value class ByteInline {
1489         byte x = 0;
1490     }
1491 
1492     @Test
1493     public void test74(EmptyInline[] emptyArray) {
1494         System.arraycopy(emptyArray, 0, emptyArray, 10, 10);
1495         System.arraycopy(emptyArray, 0, emptyArray, 20, 10);
1496     }
1497 
1498     @Run(test = "test74")
1499     public void test74_verifier() {
1500         EmptyInline[] emptyArray = (EmptyInline[])ValueClass.newNullRestrictedArray(EmptyInline.class, 100);
1501         test74(emptyArray);
1502         for (EmptyInline empty : emptyArray) {
1503             Asserts.assertEQ(empty, new EmptyInline());
1504         }
1505     }
1506 
1507     @Test
1508     public void test75(EmptyInline[] emptyArray) {
1509         System.arraycopy(emptyArray, 0, emptyArray, 10, 10);
1510     }
1511 
1512     @Run(test = "test75")
1513     public void test75_verifier() {
1514         EmptyInline[] emptyArray = (EmptyInline[])ValueClass.newNullRestrictedArray(EmptyInline.class, 100);
1515         test75(emptyArray);
1516         for (EmptyInline empty : emptyArray) {
1517             Asserts.assertEQ(empty, new EmptyInline());
1518         }
1519     }
1520 
1521     @Test
1522     public void test76(ByteInline[] byteArray) {
1523         System.arraycopy(byteArray, 0, byteArray, 10, 10);
1524         System.arraycopy(byteArray, 0, byteArray, 20, 10);
1525     }
1526 
1527     @Run(test = "test76")
1528     public void test76_verifier() {
1529         ByteInline[] byteArray = (ByteInline[])ValueClass.newNullRestrictedArray(ByteInline.class, 100);
1530         test76(byteArray);
1531         for (ByteInline b : byteArray) {
1532             Asserts.assertEQ(b, new ByteInline());
1533         }
1534     }
1535 
1536     @Test
1537     public void test77(ByteInline[] byteArray) {
1538         System.arraycopy(byteArray, 0, byteArray, 10, 10);
1539     }
1540 
1541     @Run(test = "test77")
1542     public void test77_verifier() {
1543         ByteInline[] byteArray = (ByteInline[])ValueClass.newNullRestrictedArray(ByteInline.class, 100);
1544         test77(byteArray);
1545         for (ByteInline b : byteArray) {
1546             Asserts.assertEQ(b, new ByteInline());
1547         }
1548     }
1549 
1550     @Test
1551     public Object test78(MyValue1 vt) {
1552         return NonValueClass.class.cast(vt);
1553     }
1554 
1555     @Run(test = "test78")
1556     public void test78_verifier() {
1557         Object result = test78(null);
1558         Asserts.assertEQ(result, null);
1559         try {
1560             test78(MyValue1.createWithFieldsInline(rI, rL));
1561             throw new RuntimeException("should have thrown");
1562         } catch (ClassCastException cce) {
1563         }
1564     }
1565 
1566     // TODO 8284443 Fix this in GraphKit::gen_checkcast
1567     /*
1568     @Test
1569     public Object test79(MyValue1 vt) {
1570         Object tmp = vt;
1571         return (NonValueClass)tmp;
1572     }
1573 
1574     @Run(test = "test79")
1575     public void test79_verifier() {
1576         Object result = test79(null);
1577         Asserts.assertEQ(result, null);
1578         try {
1579             test79(MyValue1.createWithFieldsInline(rI, rL));
1580             throw new RuntimeException("should have thrown");
1581         } catch (ClassCastException cce) {
1582         }
1583     }
1584     */
1585 
1586     @ImplicitlyConstructible
1587     @LooselyConsistentValue
1588     public static value class Test80Value1 {
1589         @NullRestricted
1590         Test80Value2 v = new Test80Value2();
1591     }
1592 
1593     @ImplicitlyConstructible
1594     @LooselyConsistentValue
1595     public static value class Test80Value2 {
1596         long l = rL;
1597         NonValueClass obj = new NonValueClass(rI);
1598     }
1599 
1600     // Test that unsafe access is not incorrectly classified as mismatched
1601     @Test
1602     @IR(failOn = {CALL_UNSAFE})
1603     public Test80Value2 test80(Test80Value1 v, boolean flat, long offset) {
1604         if (flat) {
1605             return U.getValue(v, offset, Test80Value2.class);
1606         } else {
1607             return (Test80Value2)U.getReference(v, offset);
1608         }
1609     }
1610 
1611     @Run(test = "test80")
1612     public void test80_verifier() throws Exception {
1613         Test80Value1 v = new Test80Value1();
1614         Field field = Test80Value1.class.getDeclaredField("v");
1615         Asserts.assertEQ(test80(v, U.isFlatField(field), U.objectFieldOffset(field)), v.v);
1616     }
1617 
1618     // Test correctness of the Unsafe::isFlatArray intrinsic
1619     @Test
1620     public boolean test81(Class<?> cls) {
1621         return U.isFlatArray(cls);
1622     }
1623 
1624     @Run(test = "test81")
1625     public void test81_verifier() {
1626         Asserts.assertEQ(test81(TEST33_ARRAY.getClass()), TEST33_FLATTENED_ARRAY, "test81_1 failed");
1627         Asserts.assertFalse(test81(String[].class), "test81_2 failed");
1628         Asserts.assertFalse(test81(String.class), "test81_3 failed");
1629         Asserts.assertFalse(test81(int[].class), "test81_4 failed");
1630     }
1631 
1632     // Verify that Unsafe::isFlatArray checks with statically known classes
1633     // are folded
1634     @Test
1635     @IR(failOn = {LOADK})
1636     public boolean test82() {
1637         boolean check1 = U.isFlatArray(TEST33_ARRAY.getClass());
1638         if (!TEST33_FLATTENED_ARRAY) {
1639             check1 = !check1;
1640         }
1641         boolean check2 = !U.isFlatArray(String[].class);
1642         boolean check3 = !U.isFlatArray(String.class);
1643         boolean check4 = !U.isFlatArray(int[].class);
1644         return check1 && check2 && check3 && check4;
1645     }
1646 
1647     @Run(test = "test82")
1648     public void test82_verifier() {
1649         Asserts.assertTrue(test82(), "test82 failed");
1650     }
1651 
1652     // Test that LibraryCallKit::arraycopy_move_allocation_here works as expected
1653     @Test
1654     public MyValue1 test83(Object[] src) {
1655         MyValue1[] dst = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 10);
1656         System.arraycopy(src, 0, dst, 0, 10);
1657         return dst[0];
1658     }
1659 
1660     @Run(test = "test83")
1661     public void test83_verifier(RunInfo info) {
1662         if (info.isWarmUp()) {
1663             MyValue1[] src = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 10);
1664             Asserts.assertEQ(test83(src), src[0]);
1665         } else {
1666             // Trigger deoptimization to verify that re-execution works
1667             try {
1668                 test83(new NonValueClass[10]);
1669                 throw new RuntimeException("No NullPointerException thrown");
1670             } catch (NullPointerException npe) {
1671                 // Expected
1672             }
1673         }
1674     }
1675 }