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 }