1 /* 2 * Copyright (c) 2019, 2025, 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 compiler.lib.ir_framework.*; 27 import jdk.test.lib.Asserts; 28 import test.java.lang.invoke.lib.InstructionHelper; 29 30 import java.lang.invoke.MethodHandle; 31 import java.lang.invoke.MethodHandles; 32 import java.lang.invoke.MethodType; 33 import java.lang.reflect.Method; 34 import java.util.Arrays; 35 import java.util.Objects; 36 37 import jdk.internal.value.ValueClass; 38 import jdk.internal.vm.annotation.LooselyConsistentValue; 39 import jdk.internal.vm.annotation.NullRestricted; 40 import jdk.internal.vm.annotation.Strict; 41 42 import static compiler.valhalla.inlinetypes.InlineTypeIRNode.*; 43 import static compiler.valhalla.inlinetypes.InlineTypes.*; 44 45 /* 46 * @test 47 * @key randomness 48 * @summary Test inline types in LWorld. 49 * @library /test/lib /test/jdk/java/lang/invoke/common / 50 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") 51 * @enablePreview 52 * @modules java.base/jdk.internal.value 53 * java.base/jdk.internal.vm.annotation 54 * @build test.java.lang.invoke.lib.InstructionHelper 55 * @run main/othervm/timeout=450 compiler.valhalla.inlinetypes.TestLWorld 56 */ 57 58 @ForceCompileClassInitializer 59 public class TestLWorld { 60 61 public static void main(String[] args) { 62 // Make sure Test140Value is loaded but not linked 63 Class<?> class1 = Test140Value.class; 64 // Make sure Test141Value is linked but not initialized 65 Class<?> class2 = Test141Value.class; 66 class2.getDeclaredFields(); 67 68 Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS; 69 scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:+UseArrayFlattening"); 70 scenarios[4].addFlags("-XX:-MonomorphicArrayCheck"); 71 72 InlineTypes.getFramework() 73 .addScenarios(scenarios) 74 .addHelperClasses(MyValue1.class, 75 MyValue2.class, 76 MyValue2Inline.class, 77 MyValue3.class, 78 MyValue3Inline.class) 79 .start(); 80 } 81 82 static { 83 // Make sure RuntimeException is loaded to prevent uncommon traps in IR verified tests 84 RuntimeException tmp = new RuntimeException("42"); 85 } 86 87 // Helper methods 88 89 @Strict 90 @NullRestricted 91 private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL); 92 @Strict 93 @NullRestricted 94 private static final MyValue2 testValue2 = MyValue2.createWithFieldsInline(rI, rD); 95 96 protected long hash() { 97 return testValue1.hash(); 98 } 99 100 // Test passing an inline type as an Object 101 @DontInline 102 public Object test1_dontinline1(Object o) { 103 return o; 104 } 105 106 @DontInline 107 public MyValue1 test1_dontinline2(Object o) { 108 return (MyValue1)o; 109 } 110 111 @ForceInline 112 public Object test1_inline1(Object o) { 113 return o; 114 } 115 116 @ForceInline 117 public MyValue1 test1_inline2(Object o) { 118 return (MyValue1)o; 119 } 120 121 @Test 122 @IR(failOn = {ALLOC_G}) 123 public MyValue1 test1() { 124 MyValue1 vt = testValue1; 125 vt = (MyValue1)test1_dontinline1(vt); 126 vt = test1_dontinline2(vt); 127 vt = (MyValue1)test1_inline1(vt); 128 vt = test1_inline2(vt); 129 return vt; 130 } 131 132 @Run(test = "test1") 133 public void test1_verifier() { 134 Asserts.assertEQ(test1().hash(), hash()); 135 } 136 137 // Test storing/loading inline types to/from Object and inline type fields 138 Object objectField1 = null; 139 Object objectField2 = null; 140 Object objectField3 = null; 141 Object objectField4 = null; 142 Object objectField5 = null; 143 Object objectField6 = null; 144 145 @Strict 146 @NullRestricted 147 MyValue1 valueField1 = testValue1; 148 @Strict 149 @NullRestricted 150 MyValue1 valueField2 = testValue1; 151 MyValue1 valueField3 = testValue1; 152 @Strict 153 @NullRestricted 154 MyValue1 valueField4 = MyValue1.DEFAULT; 155 MyValue1 valueField5; 156 157 static MyValue1 staticValueField1 = testValue1; 158 @Strict 159 @NullRestricted 160 static MyValue1 staticValueField2 = testValue1; 161 @Strict 162 @NullRestricted 163 static MyValue1 staticValueField3 = MyValue1.DEFAULT; 164 static MyValue1 staticValueField4; 165 166 @DontInline 167 public Object readValueField5() { 168 return (Object)valueField5; 169 } 170 171 @DontInline 172 public Object readStaticValueField4() { 173 return (Object)staticValueField4; 174 } 175 176 @Test 177 public long test2(MyValue1 vt1, Object vt2) { 178 objectField1 = vt1; 179 objectField2 = (MyValue1)vt2; 180 objectField3 = testValue1; 181 objectField4 = MyValue1.createWithFieldsDontInline(rI, rL); 182 objectField5 = valueField1; 183 objectField6 = valueField3; 184 valueField1 = (MyValue1)objectField1; 185 valueField2 = (MyValue1)vt2; 186 valueField3 = (MyValue1)vt2; 187 staticValueField1 = (MyValue1)objectField1; 188 staticValueField2 = (MyValue1)vt1; 189 // Don't inline these methods because reading NULL will trigger a deoptimization 190 if (readValueField5() != null || readStaticValueField4() != null) { 191 throw new RuntimeException("Should be null"); 192 } 193 return ((MyValue1)objectField1).hash() + ((MyValue1)objectField2).hash() + 194 ((MyValue1)objectField3).hash() + ((MyValue1)objectField4).hash() + 195 ((MyValue1)objectField5).hash() + ((MyValue1)objectField6).hash() + 196 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() + 197 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive(); 198 } 199 200 @Run(test = "test2") 201 public void test2_verifier() { 202 MyValue1 vt = testValue1; 203 MyValue1 def = MyValue1.createDefaultDontInline(); 204 long result = test2(vt, vt); 205 Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive()); 206 } 207 208 // Test merging inline types and objects 209 @Test 210 public Object test3(int state) { 211 Object res = null; 212 if (state == 0) { 213 res = new NonValueClass(rI); 214 } else if (state == 1) { 215 res = MyValue1.createWithFieldsInline(rI, rL); 216 } else if (state == 2) { 217 res = MyValue1.createWithFieldsDontInline(rI, rL); 218 } else if (state == 3) { 219 res = (MyValue1)objectField1; 220 } else if (state == 4) { 221 res = valueField1; 222 } else if (state == 5) { 223 res = null; 224 } else if (state == 6) { 225 res = MyValue2.createWithFieldsInline(rI, rD); 226 } else if (state == 7) { 227 res = testValue2; 228 } 229 return res; 230 } 231 232 @Run(test = "test3") 233 public void test3_verifier() { 234 objectField1 = valueField1; 235 Object result = null; 236 result = test3(0); 237 Asserts.assertEQ(((NonValueClass)result).x, rI); 238 result = test3(1); 239 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 240 result = test3(2); 241 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 242 result = test3(3); 243 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 244 result = test3(4); 245 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 246 result = test3(5); 247 Asserts.assertEQ(result, null); 248 result = test3(6); 249 Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash()); 250 result = test3(7); 251 Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash()); 252 } 253 254 // Test merging inline types and objects in loops 255 @Test 256 public Object test4(int iters) { 257 Object res = new NonValueClass(rI); 258 for (int i = 0; i < iters; ++i) { 259 if (res instanceof NonValueClass) { 260 res = MyValue1.createWithFieldsInline(rI, rL); 261 } else { 262 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL); 263 } 264 } 265 return res; 266 } 267 268 @Run(test = "test4") 269 public void test4_verifier() { 270 NonValueClass result1 = (NonValueClass)test4(0); 271 Asserts.assertEQ(result1.x, rI); 272 int iters = (Math.abs(rI) % 10) + 1; 273 MyValue1 result2 = (MyValue1)test4(iters); 274 MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL); 275 Asserts.assertEQ(result2.hash(), vt.hash()); 276 } 277 278 // Test inline types in object variables that are live at safepoint 279 @Test 280 @IR(failOn = {ALLOC, STORE, LOOP}) 281 public long test5(MyValue1 arg, boolean deopt, Method m) { 282 Object vt1 = MyValue1.createWithFieldsInline(rI, rL); 283 Object vt2 = MyValue1.createWithFieldsDontInline(rI, rL); 284 Object vt3 = arg; 285 Object vt4 = valueField1; 286 if (deopt) { 287 // uncommon trap 288 TestFramework.deoptimize(m); 289 } 290 return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() + 291 ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash(); 292 } 293 294 @Run(test = "test5") 295 public void test5_verifier(RunInfo info) { 296 long result = test5(valueField1, !info.isWarmUp(), info.getTest()); 297 Asserts.assertEQ(result, 4*hash()); 298 } 299 300 // Test comparing inline types with objects 301 @Test 302 public boolean test6(Object arg) { 303 Object vt = MyValue1.createWithFieldsInline(rI, rL); 304 if (vt == arg || vt == (Object)valueField1 || vt == objectField1 || vt == null || 305 arg == vt || (Object)valueField1 == vt || objectField1 == vt || null == vt) { 306 return true; 307 } 308 return false; 309 } 310 311 @Run(test = "test6") 312 public void test6_verifier() { 313 boolean result = test6(null); 314 Asserts.assertFalse(result); 315 } 316 317 // merge of inline type and non-inline type 318 @Test 319 public Object test7(boolean flag) { 320 Object res = null; 321 if (flag) { 322 res = valueField1; 323 } else { 324 res = objectField1; 325 } 326 return res; 327 } 328 329 @Run(test = "test7") 330 public void test7_verifier() { 331 Asserts.assertEQ(test7(true), valueField1); 332 Asserts.assertEQ(test7(false), objectField1); 333 } 334 335 @Test 336 public Object test8(boolean flag) { 337 Object res = null; 338 if (flag) { 339 res = objectField1; 340 } else { 341 res = valueField1; 342 } 343 return res; 344 } 345 346 @Run(test = "test8") 347 public void test8_verifier() { 348 Asserts.assertEQ(test8(true), objectField1); 349 Asserts.assertEQ(test8(false), valueField1); 350 } 351 352 // merge of inline types in a loop, stored in an object local 353 @Test 354 public Object test9() { 355 Object o = valueField1; 356 for (int i = 1; i < 100; i *= 2) { 357 MyValue1 v = (MyValue1)o; 358 o = MyValue1.setX(v, v.x + 1); 359 } 360 return o; 361 } 362 363 @Run(test = "test9") 364 public void test9_verifier() { 365 Asserts.assertEQ(test9(), MyValue1.setX(valueField1, valueField1.x + 7)); 366 } 367 368 // merge of inline types in an object local 369 @ForceInline 370 public Object test10_helper() { 371 return valueField1; 372 } 373 374 @Test 375 @IR(failOn = {ALLOC_G}) 376 public void test10(boolean flag) { 377 Object o = null; 378 if (flag) { 379 o = valueField1; 380 } else { 381 o = test10_helper(); 382 } 383 valueField1 = (MyValue1)o; 384 } 385 386 @Run(test = "test10") 387 public void test10_verifier() { 388 test10(true); 389 test10(false); 390 } 391 392 // Interface tests 393 394 @DontInline 395 public MyInterface test11_dontinline1(MyInterface o) { 396 return o; 397 } 398 399 @DontInline 400 public MyValue1 test11_dontinline2(MyInterface o) { 401 return (MyValue1)o; 402 } 403 404 @ForceInline 405 public MyInterface test11_inline1(MyInterface o) { 406 return o; 407 } 408 409 @ForceInline 410 public MyValue1 test11_inline2(MyInterface o) { 411 return (MyValue1)o; 412 } 413 414 @Test 415 public MyValue1 test11() { 416 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 417 vt = (MyValue1)test11_dontinline1(vt); 418 vt = test11_dontinline2(vt); 419 vt = (MyValue1)test11_inline1(vt); 420 vt = test11_inline2(vt); 421 return vt; 422 } 423 424 @Run(test = "test11") 425 public void test11_verifier() { 426 Asserts.assertEQ(test11().hash(), hash()); 427 } 428 429 // Test storing/loading inline types to/from interface and inline type fields 430 MyInterface interfaceField1 = null; 431 MyInterface interfaceField2 = null; 432 MyInterface interfaceField3 = null; 433 MyInterface interfaceField4 = null; 434 MyInterface interfaceField5 = null; 435 MyInterface interfaceField6 = null; 436 437 @DontInline 438 public MyInterface readValueField5AsInterface() { 439 return (MyInterface)valueField5; 440 } 441 442 @DontInline 443 public MyInterface readStaticValueField4AsInterface() { 444 return (MyInterface)staticValueField4; 445 } 446 447 @Test 448 public long test12(MyValue1 vt1, MyInterface vt2) { 449 interfaceField1 = vt1; 450 interfaceField2 = (MyValue1)vt2; 451 interfaceField3 = MyValue1.createWithFieldsInline(rI, rL); 452 interfaceField4 = MyValue1.createWithFieldsDontInline(rI, rL); 453 interfaceField5 = valueField1; 454 interfaceField6 = valueField3; 455 valueField1 = (MyValue1)interfaceField1; 456 valueField2 = (MyValue1)vt2; 457 valueField3 = (MyValue1)vt2; 458 staticValueField1 = (MyValue1)interfaceField1; 459 staticValueField2 = (MyValue1)vt1; 460 // Don't inline these methods because reading NULL will trigger a deoptimization 461 if (readValueField5AsInterface() != null || readStaticValueField4AsInterface() != null) { 462 throw new RuntimeException("Should be null"); 463 } 464 return ((MyValue1)interfaceField1).hash() + ((MyValue1)interfaceField2).hash() + 465 ((MyValue1)interfaceField3).hash() + ((MyValue1)interfaceField4).hash() + 466 ((MyValue1)interfaceField5).hash() + ((MyValue1)interfaceField6).hash() + 467 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() + 468 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive(); 469 } 470 471 @Run(test = "test12") 472 public void test12_verifier() { 473 MyValue1 vt = testValue1; 474 MyValue1 def = MyValue1.createDefaultDontInline(); 475 long result = test12(vt, vt); 476 Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive()); 477 } 478 479 class MyObject1 implements MyInterface { 480 public int x; 481 482 public MyObject1(int x) { 483 this.x = x; 484 } 485 486 @ForceInline 487 public long hash() { 488 return x; 489 } 490 } 491 492 // Test merging inline types and interfaces 493 @Test 494 public MyInterface test13(int state) { 495 MyInterface res = null; 496 if (state == 0) { 497 res = new MyObject1(rI); 498 } else if (state == 1) { 499 res = MyValue1.createWithFieldsInline(rI, rL); 500 } else if (state == 2) { 501 res = MyValue1.createWithFieldsDontInline(rI, rL); 502 } else if (state == 3) { 503 res = (MyValue1)objectField1; 504 } else if (state == 4) { 505 res = valueField1; 506 } else if (state == 5) { 507 res = null; 508 } 509 return res; 510 } 511 512 @Run(test = "test13") 513 public void test13_verifier() { 514 objectField1 = valueField1; 515 MyInterface result = null; 516 result = test13(0); 517 Asserts.assertEQ(((MyObject1)result).x, rI); 518 result = test13(1); 519 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 520 result = test13(2); 521 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 522 result = test13(3); 523 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 524 result = test13(4); 525 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 526 result = test13(5); 527 Asserts.assertEQ(result, null); 528 } 529 530 // Test merging inline types and interfaces in loops 531 @Test 532 public MyInterface test14(int iters) { 533 MyInterface res = new MyObject1(rI); 534 for (int i = 0; i < iters; ++i) { 535 if (res instanceof MyObject1) { 536 res = MyValue1.createWithFieldsInline(rI, rL); 537 } else { 538 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL); 539 } 540 } 541 return res; 542 } 543 544 @Run(test = "test14") 545 public void test14_verifier() { 546 MyObject1 result1 = (MyObject1)test14(0); 547 Asserts.assertEQ(result1.x, rI); 548 int iters = (Math.abs(rI) % 10) + 1; 549 MyValue1 result2 = (MyValue1)test14(iters); 550 MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL); 551 Asserts.assertEQ(result2.hash(), vt.hash()); 552 } 553 554 // Test inline types in interface variables that are live at safepoint 555 @Test 556 @IR(failOn = {ALLOC, STORE, LOOP}) 557 public long test15(MyValue1 arg, boolean deopt, Method m) { 558 MyInterface vt1 = MyValue1.createWithFieldsInline(rI, rL); 559 MyInterface vt2 = MyValue1.createWithFieldsDontInline(rI, rL); 560 MyInterface vt3 = arg; 561 MyInterface vt4 = valueField1; 562 return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() + 563 ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash(); 564 } 565 566 @Run(test = "test15") 567 public void test15_verifier(RunInfo info) { 568 long result = test15(valueField1, !info.isWarmUp(), info.getTest()); 569 Asserts.assertEQ(result, 4*hash()); 570 } 571 572 // Test comparing inline types with interfaces 573 @Test 574 public boolean test16(Object arg) { 575 MyInterface vt = MyValue1.createWithFieldsInline(rI, rL); 576 if (vt == arg || vt == (MyInterface)valueField1 || vt == interfaceField1 || vt == null || 577 arg == vt || (MyInterface)valueField1 == vt || interfaceField1 == vt || null == vt) { 578 return true; 579 } 580 return false; 581 } 582 583 @Run(test = "test16") 584 public void test16_verifier() { 585 boolean result = test16(null); 586 Asserts.assertFalse(result); 587 } 588 589 // Test subtype check when casting to inline type 590 @Test 591 @IR(failOn = {ALLOC}) 592 public MyValue1 test17(MyValue1 vt, Object obj) { 593 try { 594 vt = (MyValue1)obj; 595 throw new RuntimeException("ClassCastException expected"); 596 } catch (ClassCastException e) { 597 // Expected 598 } 599 return vt; 600 } 601 602 @Run(test = "test17") 603 public void test17_verifier() { 604 MyValue1 vt = testValue1; 605 MyValue1 result = test17(vt, new NonValueClass(rI)); 606 Asserts.assertEquals(result.hash(), vt.hash()); 607 } 608 609 @Test 610 public MyValue1 test18(MyValue1 vt) { 611 Object obj = vt; 612 vt = (MyValue1)obj; 613 return vt; 614 } 615 616 @Run(test = "test18") 617 public void test18_verifier() { 618 MyValue1 vt = testValue1; 619 MyValue1 result = test18(vt); 620 Asserts.assertEquals(result.hash(), vt.hash()); 621 } 622 623 @Test 624 @IR(failOn = {ALLOC_G}) 625 public void test19(MyValue1 vt) { 626 if (vt == null) { 627 return; 628 } 629 Object obj = vt; 630 try { 631 MyValue2 vt2 = (MyValue2)obj; 632 throw new RuntimeException("ClassCastException expected"); 633 } catch (ClassCastException e) { 634 // Expected 635 } 636 } 637 638 @Run(test = "test19") 639 public void test19_verifier() { 640 test19(valueField1); 641 } 642 643 @Test 644 @IR(failOn = {ALLOC_G}) 645 public void test20(MyValue1 vt) { 646 if (vt == null) { 647 return; 648 } 649 Object obj = vt; 650 try { 651 NonValueClass i = (NonValueClass)obj; 652 throw new RuntimeException("ClassCastException expected"); 653 } catch (ClassCastException e) { 654 // Expected 655 } 656 } 657 658 @Run(test = "test20") 659 public void test20_verifier() { 660 test20(valueField1); 661 } 662 663 // Array tests 664 665 private static final MyValue1[] testValue1Array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 3, MyValue1.DEFAULT); 666 static { 667 for (int i = 0; i < 3; ++i) { 668 testValue1Array[i] = testValue1; 669 } 670 } 671 672 private static final MyValue1[][] testValue1Array2 = new MyValue1[][] {testValue1Array, 673 testValue1Array, 674 testValue1Array}; 675 676 private static final MyValue2[] testValue2Array = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 3, MyValue2.DEFAULT); 677 static { 678 for (int i = 0; i < 3; ++i) { 679 testValue2Array[i] = testValue2; 680 } 681 } 682 683 private static final NonValueClass[] testNonValueArray = new NonValueClass[42]; 684 685 // Test load from (flattened) inline type array disguised as object array 686 @Test 687 public Object test21(Object[] oa, int index) { 688 return oa[index]; 689 } 690 691 @Run(test = "test21") 692 public void test21_verifier() { 693 MyValue1 result = (MyValue1)test21(testValue1Array, Math.abs(rI) % 3); 694 Asserts.assertEQ(result.hash(), hash()); 695 } 696 697 // Test load from (flattened) inline type array disguised as interface array 698 @Test 699 public Object test22Interface(MyInterface[] ia, int index) { 700 return ia[index]; 701 } 702 703 @Run(test = "test22Interface") 704 public void test22Interface_verifier() { 705 MyValue1 result = (MyValue1)test22Interface(testValue1Array, Math.abs(rI) % 3); 706 Asserts.assertEQ(result.hash(), hash()); 707 } 708 709 // Test load from (flattened) inline type array disguised as abstract array 710 @Test 711 public Object test22Abstract(MyAbstract[] ia, int index) { 712 return ia[index]; 713 } 714 715 @Run(test = "test22Abstract") 716 public void test22Abstract_verifier() { 717 MyValue1 result = (MyValue1)test22Abstract(testValue1Array, Math.abs(rI) % 3); 718 Asserts.assertEQ(result.hash(), hash()); 719 } 720 721 // Test inline store to (flattened) inline type array disguised as object array 722 @ForceInline 723 public void test23_inline(Object[] oa, Object o, int index) { 724 oa[index] = o; 725 } 726 727 @Test 728 public void test23(Object[] oa, MyValue1 vt, int index) { 729 test23_inline(oa, vt, index); 730 } 731 732 @Run(test = "test23") 733 public void test23_verifier() { 734 int index = Math.abs(rI) % 3; 735 MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 736 test23(testValue1Array, vt, index); 737 Asserts.assertEQ(testValue1Array[index].hash(), vt.hash()); 738 testValue1Array[index] = testValue1; 739 try { 740 test23(testValue2Array, vt, index); 741 throw new RuntimeException("No ArrayStoreException thrown"); 742 } catch (ArrayStoreException e) { 743 // Expected 744 } 745 Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash()); 746 } 747 748 @ForceInline 749 public void test24_inline(Object[] oa, Object o, int index) { 750 oa[index] = o; 751 } 752 753 @Test 754 public void test24(Object[] oa, MyValue1 vt, int index) { 755 test24_inline(oa, vt, index); 756 } 757 758 @Run(test = "test24") 759 public void test24_verifier() { 760 int index = Math.abs(rI) % 3; 761 try { 762 test24(testNonValueArray, testValue1, index); 763 throw new RuntimeException("No ArrayStoreException thrown"); 764 } catch (ArrayStoreException e) { 765 // Expected 766 } 767 } 768 769 @ForceInline 770 public void test25_inline(Object[] oa, Object o, int index) { 771 oa[index] = o; 772 } 773 774 @Test 775 public void test25(Object[] oa, MyValue1 vt, int index) { 776 test25_inline(oa, vt, index); 777 } 778 779 @Run(test = "test25") 780 public void test25_verifier() { 781 int index = Math.abs(rI) % 3; 782 try { 783 test25(null, testValue1, index); 784 throw new RuntimeException("No NPE thrown"); 785 } catch (NullPointerException e) { 786 // Expected 787 } 788 } 789 790 // Test inline store to (flattened) inline type array disguised as interface array 791 @ForceInline 792 public void test26Interface_inline(MyInterface[] ia, MyInterface i, int index) { 793 ia[index] = i; 794 } 795 796 @Test 797 public void test26Interface(MyInterface[] ia, MyValue1 vt, int index) { 798 test26Interface_inline(ia, vt, index); 799 } 800 801 @Run(test = "test26Interface") 802 public void test26Interface_verifier() { 803 int index = Math.abs(rI) % 3; 804 MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 805 test26Interface(testValue1Array, vt, index); 806 Asserts.assertEQ(testValue1Array[index].hash(), vt.hash()); 807 testValue1Array[index] = testValue1; 808 try { 809 test26Interface(testValue2Array, vt, index); 810 throw new RuntimeException("No ArrayStoreException thrown"); 811 } catch (ArrayStoreException e) { 812 // Expected 813 } 814 Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash()); 815 } 816 817 @ForceInline 818 public void test27Interface_inline(MyInterface[] ia, MyInterface i, int index) { 819 ia[index] = i; 820 } 821 822 @Test 823 public void test27Interface(MyInterface[] ia, MyValue1 vt, int index) { 824 test27Interface_inline(ia, vt, index); 825 } 826 827 @Run(test = "test27Interface") 828 public void test27Interface_verifier() { 829 int index = Math.abs(rI) % 3; 830 try { 831 test27Interface(null, testValue1, index); 832 throw new RuntimeException("No NPE thrown"); 833 } catch (NullPointerException e) { 834 // Expected 835 } 836 } 837 838 // Test inline store to (flattened) inline type array disguised as abstract array 839 @ForceInline 840 public void test26Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) { 841 ia[index] = i; 842 } 843 844 @Test 845 public void test26Abstract(MyAbstract[] ia, MyValue1 vt, int index) { 846 test26Abstract_inline(ia, vt, index); 847 } 848 849 @Run(test = "test26Abstract") 850 public void test26Abstract_verifier() { 851 int index = Math.abs(rI) % 3; 852 MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 853 test26Abstract(testValue1Array, vt, index); 854 Asserts.assertEQ(testValue1Array[index].hash(), vt.hash()); 855 testValue1Array[index] = testValue1; 856 try { 857 test26Abstract(testValue2Array, vt, index); 858 throw new RuntimeException("No ArrayStoreException thrown"); 859 } catch (ArrayStoreException e) { 860 // Expected 861 } 862 Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash()); 863 } 864 865 @ForceInline 866 public void test27Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) { 867 ia[index] = i; 868 } 869 870 @Test 871 public void test27Abstract(MyAbstract[] ia, MyValue1 vt, int index) { 872 test27Abstract_inline(ia, vt, index); 873 } 874 875 @Run(test = "test27Abstract") 876 public void test27Abstract_verifier() { 877 int index = Math.abs(rI) % 3; 878 try { 879 test27Abstract(null, testValue1, index); 880 throw new RuntimeException("No NPE thrown"); 881 } catch (NullPointerException e) { 882 // Expected 883 } 884 } 885 886 // Test object store to (flattened) inline type array disguised as object array 887 @ForceInline 888 public void test28_inline(Object[] oa, Object o, int index) { 889 oa[index] = o; 890 } 891 892 @Test 893 public void test28(Object[] oa, Object o, int index) { 894 test28_inline(oa, o, index); 895 } 896 897 @Run(test = "test28") 898 public void test28_verifier() { 899 int index = Math.abs(rI) % 3; 900 MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 901 test28(testValue1Array, vt1, index); 902 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 903 try { 904 test28(testValue1Array, testValue2, index); 905 throw new RuntimeException("No ArrayStoreException thrown"); 906 } catch (ArrayStoreException e) { 907 // Expected 908 } 909 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 910 testValue1Array[index] = testValue1; 911 } 912 913 @ForceInline 914 public void test29_inline(Object[] oa, Object o, int index) { 915 oa[index] = o; 916 } 917 918 @Test 919 public void test29(Object[] oa, Object o, int index) { 920 test29_inline(oa, o, index); 921 } 922 923 @Run(test = "test29") 924 public void test29_verifier() { 925 int index = Math.abs(rI) % 3; 926 try { 927 test29(testValue2Array, testValue1, index); 928 throw new RuntimeException("No ArrayStoreException thrown"); 929 } catch (ArrayStoreException e) { 930 // Expected 931 } 932 Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash()); 933 } 934 935 @ForceInline 936 public void test30_inline(Object[] oa, Object o, int index) { 937 oa[index] = o; 938 } 939 940 @Test 941 public void test30(Object[] oa, Object o, int index) { 942 test30_inline(oa, o, index); 943 } 944 945 @Run(test = "test30") 946 public void test30_verifier() { 947 int index = Math.abs(rI) % 3; 948 try { 949 test30(testNonValueArray, testValue1, index); 950 throw new RuntimeException("No ArrayStoreException thrown"); 951 } catch (ArrayStoreException e) { 952 // Expected 953 } 954 } 955 956 // Test inline store to (flattened) inline type array disguised as interface array 957 @ForceInline 958 public void test31Interface_inline(MyInterface[] ia, MyInterface i, int index) { 959 ia[index] = i; 960 } 961 962 @Test 963 public void test31Interface(MyInterface[] ia, MyInterface i, int index) { 964 test31Interface_inline(ia, i, index); 965 } 966 967 @Run(test = "test31Interface") 968 public void test31Interface_verifier() { 969 int index = Math.abs(rI) % 3; 970 MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 971 test31Interface(testValue1Array, vt1, index); 972 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 973 try { 974 test31Interface(testValue1Array, testValue2, index); 975 throw new RuntimeException("No ArrayStoreException thrown"); 976 } catch (ArrayStoreException e) { 977 // Expected 978 } 979 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 980 testValue1Array[index] = testValue1; 981 } 982 983 @ForceInline 984 public void test32Interface_inline(MyInterface[] ia, MyInterface i, int index) { 985 ia[index] = i; 986 } 987 988 @Test 989 public void test32Interface(MyInterface[] ia, MyInterface i, int index) { 990 test32Interface_inline(ia, i, index); 991 } 992 993 @Run(test = "test32Interface") 994 public void test32Interface_verifier() { 995 int index = Math.abs(rI) % 3; 996 try { 997 test32Interface(testValue2Array, testValue1, index); 998 throw new RuntimeException("No ArrayStoreException thrown"); 999 } catch (ArrayStoreException e) { 1000 // Expected 1001 } 1002 } 1003 1004 // Test inline store to (flattened) inline type array disguised as abstract array 1005 @ForceInline 1006 public void test31Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) { 1007 ia[index] = i; 1008 } 1009 1010 @Test 1011 public void test31Abstract(MyAbstract[] ia, MyAbstract i, int index) { 1012 test31Abstract_inline(ia, i, index); 1013 } 1014 1015 @Run(test = "test31Abstract") 1016 public void test31Abstract_verifier() { 1017 int index = Math.abs(rI) % 3; 1018 MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 1019 test31Abstract(testValue1Array, vt1, index); 1020 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 1021 try { 1022 test31Abstract(testValue1Array, testValue2, index); 1023 throw new RuntimeException("No ArrayStoreException thrown"); 1024 } catch (ArrayStoreException e) { 1025 // Expected 1026 } 1027 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 1028 testValue1Array[index] = testValue1; 1029 } 1030 1031 @ForceInline 1032 public void test32Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) { 1033 ia[index] = i; 1034 } 1035 1036 @Test 1037 public void test32Abstract(MyAbstract[] ia, MyAbstract i, int index) { 1038 test32Abstract_inline(ia, i, index); 1039 } 1040 1041 @Run(test = "test32Abstract") 1042 public void test32Abstract_verifier() { 1043 int index = Math.abs(rI) % 3; 1044 try { 1045 test32Abstract(testValue2Array, testValue1, index); 1046 throw new RuntimeException("No ArrayStoreException thrown"); 1047 } catch (ArrayStoreException e) { 1048 // Expected 1049 } 1050 } 1051 1052 // Test writing null to a (flattened) inline type array disguised as object array 1053 @ForceInline 1054 public void test33_inline(Object[] oa, Object o, int index) { 1055 oa[index] = o; 1056 } 1057 1058 @Test 1059 public void test33(Object[] oa, Object o, int index) { 1060 test33_inline(oa, o, index); 1061 } 1062 1063 @Run(test = "test33") 1064 public void test33_verifier() { 1065 int index = Math.abs(rI) % 3; 1066 try { 1067 test33(testValue1Array, null, index); 1068 throw new RuntimeException("No NPE thrown"); 1069 } catch (NullPointerException e) { 1070 // Expected 1071 } 1072 Asserts.assertEQ(testValue1Array[index].hash(), hash()); 1073 } 1074 1075 // Test writing constant null to a (flattened) inline type array disguised as object array 1076 1077 @ForceInline 1078 public void test34_inline(Object[] oa, Object o, int index) { 1079 oa[index] = o; 1080 } 1081 1082 @Test 1083 public void test34(Object[] oa, int index) { 1084 test34_inline(oa, null, index); 1085 } 1086 1087 @Run(test = "test34") 1088 public void test34_verifier() { 1089 int index = Math.abs(rI) % 3; 1090 try { 1091 test34(testValue1Array, index); 1092 throw new RuntimeException("No NPE thrown"); 1093 } catch (NullPointerException e) { 1094 // Expected 1095 } 1096 Asserts.assertEQ(testValue1Array[index].hash(), hash()); 1097 } 1098 1099 // Test writing constant null to a (flattened) inline type array 1100 1101 private static final MethodHandle setArrayElementNull = InstructionHelper.buildMethodHandle(MethodHandles.lookup(), 1102 "setArrayElementNull", 1103 MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class), 1104 CODE -> { 1105 CODE. 1106 aload(1). 1107 iload(2). 1108 aconst_null(). 1109 aastore(). 1110 return_(); 1111 }); 1112 1113 @Test 1114 public void test35(MyValue1[] va, int index) throws Throwable { 1115 setArrayElementNull.invoke(this, va, index); 1116 } 1117 1118 @Run(test = "test35") 1119 @Warmup(10000) 1120 public void test35_verifier() throws Throwable { 1121 int index = Math.abs(rI) % 3; 1122 try { 1123 test35(testValue1Array, index); 1124 throw new RuntimeException("No NPE thrown"); 1125 } catch (NullPointerException e) { 1126 // Expected 1127 } 1128 Asserts.assertEQ(testValue1Array[index].hash(), hash()); 1129 } 1130 1131 // Test writing an inline type to a null inline type array 1132 @Test 1133 public void test36(MyValue1[] va, MyValue1 vt, int index) { 1134 va[index] = vt; 1135 } 1136 1137 @Run(test = "test36") 1138 public void test36_verifier() { 1139 int index = Math.abs(rI) % 3; 1140 try { 1141 test36(null, testValue1Array[index], index); 1142 throw new RuntimeException("No NPE thrown"); 1143 } catch (NullPointerException e) { 1144 // Expected 1145 } 1146 } 1147 1148 // Test incremental inlining 1149 @ForceInline 1150 public void test37_inline(Object[] oa, Object o, int index) { 1151 oa[index] = o; 1152 } 1153 1154 @Test 1155 @IR(failOn = {ALLOC_G}) 1156 public void test37(MyValue1[] va, Object o, int index) { 1157 test37_inline(va, o, index); 1158 } 1159 1160 @Run(test = "test37") 1161 public void test37_verifier() { 1162 int index = Math.abs(rI) % 3; 1163 MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 1164 test37(testValue1Array, vt1, index); 1165 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 1166 try { 1167 test37(testValue1Array, testValue2, index); 1168 throw new RuntimeException("No ArrayStoreException thrown"); 1169 } catch (ArrayStoreException e) { 1170 // Expected 1171 } 1172 Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash()); 1173 testValue1Array[index] = testValue1; 1174 } 1175 1176 // Test merging of inline type arrays 1177 1178 @ForceInline 1179 public Object[] test38_inline() { 1180 return (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT); 1181 } 1182 1183 @Test 1184 @IR(failOn = {ALLOC}) 1185 public Object[] test38(Object[] oa, Object o, int i1, int i2, int num) { 1186 Object[] result = null; 1187 switch (num) { 1188 case 0: 1189 result = test38_inline(); 1190 break; 1191 case 1: 1192 result = oa; 1193 break; 1194 case 2: 1195 result = testValue1Array; 1196 break; 1197 case 3: 1198 result = testValue2Array; 1199 break; 1200 case 4: 1201 result = testNonValueArray; 1202 break; 1203 case 5: 1204 result = null; 1205 break; 1206 case 6: 1207 result = testValue1Array2; 1208 break; 1209 } 1210 result[i1] = result[i2]; 1211 result[i2] = o; 1212 return result; 1213 } 1214 1215 @Run(test = "test38") 1216 public void test38_verifier() { 1217 int index = Math.abs(rI) % 3; 1218 MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT); 1219 Object[] result = test38(null, testValue1, index, index, 0); 1220 Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash()); 1221 result = test38(testValue1Array, testValue1, index, index, 1); 1222 Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash()); 1223 result = test38(null, testValue1, index, index, 2); 1224 Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash()); 1225 result = test38(null, testValue2, index, index, 3); 1226 Asserts.assertEQ(((MyValue2)result[index]).hash(), testValue2.hash()); 1227 try { 1228 result = test38(null, null, index, index, 3); 1229 throw new RuntimeException("No NPE thrown"); 1230 } catch (NullPointerException e) { 1231 // Expected 1232 } 1233 result = test38(null, null, index, index, 4); 1234 try { 1235 result = test38(null, testValue1, index, index, 4); 1236 throw new RuntimeException("No ArrayStoreException thrown"); 1237 } catch (ArrayStoreException e) { 1238 // Expected 1239 } 1240 try { 1241 result = test38(null, testValue1, index, index, 5); 1242 throw new RuntimeException("No NPE thrown"); 1243 } catch (NullPointerException e) { 1244 // Expected 1245 } 1246 result = test38(null, testValue1Array, index, index, 6); 1247 Asserts.assertEQ(((MyValue1[][])result)[index][index].hash(), testValue1.hash()); 1248 } 1249 1250 @ForceInline 1251 public Object test39_inline() { 1252 return (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT); 1253 } 1254 1255 // Same as above but merging into Object instead of Object[] 1256 @Test 1257 public Object test39(Object oa, Object o, int i1, int i2, int num) { 1258 Object result = null; 1259 switch (num) { 1260 case 0: 1261 result = test39_inline(); 1262 break; 1263 case 1: 1264 result = oa; 1265 break; 1266 case 2: 1267 result = testValue1Array; 1268 break; 1269 case 3: 1270 result = testValue2Array; 1271 break; 1272 case 4: 1273 result = testNonValueArray; 1274 break; 1275 case 5: 1276 result = null; 1277 break; 1278 case 6: 1279 result = testValue1; 1280 break; 1281 case 7: 1282 result = testValue2; 1283 break; 1284 case 8: 1285 result = MyValue1.createWithFieldsInline(rI, rL); 1286 break; 1287 case 9: 1288 result = new NonValueClass(42); 1289 break; 1290 case 10: 1291 result = testValue1Array2; 1292 break; 1293 } 1294 if (result instanceof Object[]) { 1295 ((Object[])result)[i1] = ((Object[])result)[i2]; 1296 ((Object[])result)[i2] = o; 1297 } 1298 return result; 1299 } 1300 1301 @Run(test = "test39") 1302 public void test39_verifier() { 1303 int index = Math.abs(rI) % 3; 1304 MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT); 1305 Object result = test39(null, testValue1, index, index, 0); 1306 Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash()); 1307 result = test39(testValue1Array, testValue1, index, index, 1); 1308 Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash()); 1309 result = test39(null, testValue1, index, index, 2); 1310 Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash()); 1311 result = test39(null, testValue2, index, index, 3); 1312 Asserts.assertEQ(((MyValue2[])result)[index].hash(), testValue2.hash()); 1313 try { 1314 result = test39(null, null, index, index, 3); 1315 throw new RuntimeException("No NPE thrown"); 1316 } catch (NullPointerException e) { 1317 // Expected 1318 } 1319 result = test39(null, null, index, index, 4); 1320 try { 1321 result = test39(null, testValue1, index, index, 4); 1322 throw new RuntimeException("No ArrayStoreException thrown"); 1323 } catch (ArrayStoreException e) { 1324 // Expected 1325 } 1326 result = test39(null, testValue1, index, index, 5); 1327 Asserts.assertEQ(result, null); 1328 result = test39(null, testValue1, index, index, 6); 1329 Asserts.assertEQ(((MyValue1)result).hash(), testValue1.hash()); 1330 result = test39(null, testValue1, index, index, 7); 1331 Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash()); 1332 result = test39(null, testValue1, index, index, 8); 1333 Asserts.assertEQ(((MyValue1)result).hash(), testValue1.hash()); 1334 result = test39(null, testValue1, index, index, 9); 1335 Asserts.assertEQ(((NonValueClass)result).x, 42); 1336 result = test39(null, testValue1Array, index, index, 10); 1337 Asserts.assertEQ(((MyValue1[][])result)[index][index].hash(), testValue1.hash()); 1338 } 1339 1340 // Test instanceof with inline types and arrays 1341 @Test 1342 @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"}, 1343 failOn = {ALLOC_G}) 1344 public long test40(Object o, int index) { 1345 if (o instanceof MyValue1) { 1346 return ((MyValue1)o).hashInterpreted(); 1347 } else if (o instanceof MyValue1[]) { 1348 return ((MyValue1[])o)[index].hashInterpreted(); 1349 } else if (o instanceof MyValue2) { 1350 return ((MyValue2)o).hash(); 1351 } else if (o instanceof MyValue2[]) { 1352 return ((MyValue2[])o)[index].hash(); 1353 } else if (o instanceof MyValue1[][]) { 1354 return ((MyValue1[][])o)[index][index].hash(); 1355 } else if (o instanceof Long) { 1356 return (long)o; 1357 } 1358 return 0; 1359 } 1360 1361 @Run(test = "test40") 1362 public void test40_verifier() { 1363 int index = Math.abs(rI) % 3; 1364 long result = test40(testValue1, 0); 1365 Asserts.assertEQ(result, testValue1.hashInterpreted()); 1366 result = test40(testValue1Array, index); 1367 Asserts.assertEQ(result, testValue1.hashInterpreted()); 1368 result = test40(testValue2, index); 1369 Asserts.assertEQ(result, testValue2.hash()); 1370 result = test40(testValue2Array, index); 1371 Asserts.assertEQ(result, testValue2.hash()); 1372 result = test40(testValue1Array2, index); 1373 Asserts.assertEQ(result, testValue1.hash()); 1374 result = test40(Long.valueOf(42), index); 1375 Asserts.assertEQ(result, 42L); 1376 } 1377 1378 // Test for bug in Escape Analysis 1379 @DontInline 1380 public void test41_dontinline(Object o) { 1381 Asserts.assertEQ(o, rI); 1382 } 1383 1384 @Test 1385 @IR(failOn = {ALLOC}) 1386 public void test41() { 1387 MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 1388 vals[0] = testValue1; 1389 test41_dontinline(vals[0].oa[0]); 1390 test41_dontinline(vals[0].oa[0]); 1391 } 1392 1393 @Run(test = "test41") 1394 public void test41_verifier() { 1395 test41(); 1396 } 1397 1398 // Test for bug in Escape Analysis 1399 private static final MyValue1 test42VT1 = MyValue1.createWithFieldsInline(rI, rL); 1400 private static final MyValue1 test42VT2 = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 1401 1402 @Test 1403 @IR(failOn = {ALLOC}) 1404 public void test42() { 1405 MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 2, MyValue1.DEFAULT); 1406 vals[0] = test42VT1; 1407 vals[1] = test42VT2; 1408 Asserts.assertEQ(vals[0].hash(), test42VT1.hash()); 1409 Asserts.assertEQ(vals[1].hash(), test42VT2.hash()); 1410 } 1411 1412 @Run(test = "test42") 1413 public void test42_verifier(RunInfo info) { 1414 if (!info.isWarmUp()) test42(); // We need -Xcomp behavior 1415 } 1416 1417 // Test for bug in Escape Analysis 1418 @Test 1419 @IR(failOn = {ALLOC}) 1420 public long test43(boolean deopt, Method m) { 1421 MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 2, MyValue1.DEFAULT); 1422 vals[0] = test42VT1; 1423 vals[1] = test42VT2; 1424 1425 if (deopt) { 1426 // uncommon trap 1427 TestFramework.deoptimize(m); 1428 Asserts.assertEQ(vals[0].hash(), test42VT1.hash()); 1429 Asserts.assertEQ(vals[1].hash(), test42VT2.hash()); 1430 } 1431 1432 return vals[0].hash(); 1433 } 1434 1435 @Run(test = "test43") 1436 public void test43_verifier(RunInfo info) { 1437 test43(!info.isWarmUp(), info.getTest()); 1438 } 1439 1440 // Tests writing an array element with a (statically known) incompatible type 1441 private static final MethodHandle setArrayElementIncompatible = InstructionHelper.buildMethodHandle(MethodHandles.lookup(), 1442 "setArrayElementIncompatible", 1443 MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class, MyValue2.class), 1444 CODE -> { 1445 CODE. 1446 aload(1). 1447 iload(2). 1448 aload(3). 1449 aastore(). 1450 return_(); 1451 }); 1452 1453 @Test 1454 public void test44(MyValue1[] va, int index, MyValue2 v) throws Throwable { 1455 setArrayElementIncompatible.invoke(this, va, index, v); 1456 } 1457 1458 @Run(test = "test44") 1459 @Warmup(10000) 1460 public void test44_verifier() throws Throwable { 1461 int index = Math.abs(rI) % 3; 1462 try { 1463 test44(testValue1Array, index, testValue2); 1464 throw new RuntimeException("No ArrayStoreException thrown"); 1465 } catch (ArrayStoreException e) { 1466 // Expected 1467 } 1468 Asserts.assertEQ(testValue1Array[index].hash(), hash()); 1469 } 1470 1471 // Tests writing an array element with a (statically known) incompatible type 1472 @ForceInline 1473 public void test45_inline(Object[] oa, Object o, int index) { 1474 oa[index] = o; 1475 } 1476 1477 @Test 1478 public void test45(MyValue1[] va, int index, MyValue2 v) throws Throwable { 1479 test45_inline(va, v, index); 1480 } 1481 1482 @Run(test = "test45") 1483 public void test45_verifier() throws Throwable { 1484 int index = Math.abs(rI) % 3; 1485 try { 1486 test45(testValue1Array, index, testValue2); 1487 throw new RuntimeException("No ArrayStoreException thrown"); 1488 } catch (ArrayStoreException e) { 1489 // Expected 1490 } 1491 Asserts.assertEQ(testValue1Array[index].hash(), hash()); 1492 } 1493 1494 // instanceof tests with inline types 1495 @Test 1496 @IR(failOn = {ALLOC_G}) 1497 public boolean test46(MyValue1 vt) { 1498 Object obj = vt; 1499 return obj instanceof MyValue1; 1500 } 1501 1502 @Run(test = "test46") 1503 public void test46_verifier() { 1504 MyValue1 vt = testValue1; 1505 boolean result = test46(vt); 1506 Asserts.assertTrue(result); 1507 } 1508 1509 @Test 1510 @IR(failOn = {ALLOC_G}) 1511 public boolean test47(MyValue1 vt) { 1512 Object obj = vt; 1513 return obj instanceof MyValue2; 1514 } 1515 1516 @Run(test = "test47") 1517 public void test47_verifier() { 1518 MyValue1 vt = testValue1; 1519 boolean result = test47(vt); 1520 Asserts.assertFalse(result); 1521 } 1522 1523 @Test 1524 @IR(failOn = {ALLOC_G}) 1525 public boolean test48(Object obj) { 1526 return obj instanceof MyValue1; 1527 } 1528 1529 @Run(test = "test48") 1530 public void test48_verifier() { 1531 MyValue1 vt = testValue1; 1532 boolean result = test48(vt); 1533 Asserts.assertTrue(result); 1534 } 1535 1536 @Test 1537 @IR(failOn = {ALLOC_G}) 1538 public boolean test49(Object obj) { 1539 return obj instanceof MyValue2; 1540 } 1541 1542 @Run(test = "test49") 1543 public void test49_verifier() { 1544 MyValue1 vt = testValue1; 1545 boolean result = test49(vt); 1546 Asserts.assertFalse(result); 1547 } 1548 1549 @Test 1550 @IR(failOn = {ALLOC_G}) 1551 public boolean test50(Object obj) { 1552 return obj instanceof MyValue1; 1553 } 1554 1555 @Run(test = "test50") 1556 public void test50_verifier() { 1557 Asserts.assertFalse(test49(new NonValueClass(42))); 1558 } 1559 1560 // Inline type with some non-flattened fields 1561 @LooselyConsistentValue 1562 static value class Test51Value { 1563 Object objectField1; 1564 Object objectField2; 1565 Object objectField3; 1566 Object objectField4; 1567 Object objectField5; 1568 Object objectField6; 1569 1570 @Strict 1571 @NullRestricted 1572 MyValue1 valueField1; 1573 @Strict 1574 @NullRestricted 1575 MyValue1 valueField2; 1576 MyValue1 valueField3; 1577 @Strict 1578 @NullRestricted 1579 MyValue1 valueField4; 1580 MyValue1 valueField5; 1581 1582 public Test51Value() { 1583 objectField1 = null; 1584 objectField2 = null; 1585 objectField3 = null; 1586 objectField4 = null; 1587 objectField5 = null; 1588 objectField6 = null; 1589 valueField1 = testValue1; 1590 valueField2 = testValue1; 1591 valueField3 = testValue1; 1592 valueField4 = MyValue1.createDefaultDontInline(); 1593 valueField5 = MyValue1.createDefaultDontInline(); 1594 } 1595 1596 public Test51Value(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, 1597 MyValue1 vt1, MyValue1 vt2, MyValue1 vt3, MyValue1 vt4, MyValue1 vt5) { 1598 objectField1 = o1; 1599 objectField2 = o2; 1600 objectField3 = o3; 1601 objectField4 = o4; 1602 objectField5 = o5; 1603 objectField6 = o6; 1604 valueField1 = vt1; 1605 valueField2 = vt2; 1606 valueField3 = vt3; 1607 valueField4 = vt4; 1608 valueField5 = vt5; 1609 } 1610 1611 @ForceInline 1612 public long test(Test51Value holder, MyValue1 vt1, Object vt2) { 1613 holder = new Test51Value(vt1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6, 1614 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1615 holder = new Test51Value(holder.objectField1, (MyValue1)vt2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6, 1616 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1617 holder = new Test51Value(holder.objectField1, holder.objectField2, testValue1, holder.objectField4, holder.objectField5, holder.objectField6, 1618 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1619 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, MyValue1.createWithFieldsDontInline(rI, rL), holder.objectField5, holder.objectField6, 1620 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1621 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.valueField1, holder.objectField6, 1622 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1623 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.valueField3, 1624 holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1625 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6, 1626 (MyValue1)holder.objectField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5); 1627 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6, 1628 holder.valueField1, (MyValue1)vt2, holder.valueField3, holder.valueField4, holder.valueField5); 1629 holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6, 1630 holder.valueField1, holder.valueField2, (MyValue1)vt2, holder.valueField4, holder.valueField5); 1631 1632 return ((MyValue1)holder.objectField1).hash() + 1633 ((MyValue1)holder.objectField2).hash() + 1634 ((MyValue1)holder.objectField3).hash() + 1635 ((MyValue1)holder.objectField4).hash() + 1636 ((MyValue1)holder.objectField5).hash() + 1637 ((MyValue1)holder.objectField6).hash() + 1638 holder.valueField1.hash() + 1639 holder.valueField2.hash() + 1640 holder.valueField3.hash() + 1641 holder.valueField4.hashPrimitive(); 1642 } 1643 } 1644 1645 // Pass arguments via fields to avoid exzessive spilling leading to compilation bailouts 1646 @Strict 1647 @NullRestricted 1648 static Test51Value test51_arg1 = new Test51Value(); 1649 @Strict 1650 @NullRestricted 1651 static MyValue1 test51_arg2 = MyValue1.DEFAULT; 1652 static Object test51_arg3; 1653 1654 // Same as test2 but with field holder being an inline type 1655 @Test 1656 public long test51() { 1657 return test51_arg1.test(test51_arg1, test51_arg2, test51_arg3); 1658 } 1659 1660 @Run(test = "test51") 1661 public void test51_verifier() { 1662 MyValue1 vt = testValue1; 1663 MyValue1 def = MyValue1.createDefaultDontInline(); 1664 Test51Value holder = new Test51Value(); 1665 Asserts.assertEQ(testValue1.hash(), vt.hash()); 1666 Asserts.assertEQ(holder.valueField1.hash(), vt.hash()); 1667 test51_arg1 = holder; 1668 test51_arg2 = vt; 1669 test51_arg3 = vt; 1670 long result = test51(); 1671 Asserts.assertEQ(result, 9*vt.hash() + def.hashPrimitive()); 1672 } 1673 1674 // Access non-flattened, uninitialized inline type field with inline type holder 1675 @Test 1676 @IR(failOn = {ALLOC}) 1677 public void test52(Test51Value holder) { 1678 if ((Object)holder.valueField5 != null) { 1679 throw new RuntimeException("Should be null"); 1680 } 1681 } 1682 1683 @Run(test = "test52") 1684 public void test52_verifier() { 1685 Test51Value vt = new Test51Value(null, null, null, null, null, null, 1686 MyValue1.createDefaultInline(), MyValue1.createDefaultInline(), null, MyValue1.createDefaultInline(), null); 1687 test52(vt); 1688 } 1689 1690 // Merging inline types of different types 1691 @Test 1692 public Object test53(Object o, boolean b) { 1693 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 1694 return b ? vt : o; 1695 } 1696 1697 @Run(test = "test53") 1698 public void test53_verifier() { 1699 test53(new Object(), false); 1700 MyValue1 result = (MyValue1)test53(new Object(), true); 1701 Asserts.assertEQ(result.hash(), hash()); 1702 } 1703 1704 @Test 1705 public Object test54(boolean b) { 1706 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 1707 return b ? vt : testValue2; 1708 } 1709 1710 @Run(test = "test54") 1711 public void test54_verifier() { 1712 MyValue1 result1 = (MyValue1)test54(true); 1713 Asserts.assertEQ(result1.hash(), hash()); 1714 MyValue2 result2 = (MyValue2)test54(false); 1715 Asserts.assertEQ(result2.hash(), testValue2.hash()); 1716 } 1717 1718 @Test 1719 public Object test55(boolean b) { 1720 MyValue1 vt1 = MyValue1.createWithFieldsInline(rI, rL); 1721 MyValue2 vt2 = MyValue2.createWithFieldsInline(rI, rD); 1722 return b ? vt1 : vt2; 1723 } 1724 1725 @Run(test = "test55") 1726 public void test55_verifier() { 1727 MyValue1 result1 = (MyValue1)test55(true); 1728 Asserts.assertEQ(result1.hash(), hash()); 1729 MyValue2 result2 = (MyValue2)test55(false); 1730 Asserts.assertEQ(result2.hash(), testValue2.hash()); 1731 } 1732 1733 // Test synchronization on inline types 1734 @Test 1735 public void test56(Object vt) { 1736 synchronized (vt) { 1737 throw new RuntimeException("test56 failed: synchronization on inline type should not succeed"); 1738 } 1739 } 1740 1741 @Run(test = "test56") 1742 public void test56_verifier() { 1743 try { 1744 test56(testValue1); 1745 throw new RuntimeException("test56 failed: no exception thrown"); 1746 } catch (IdentityException ex) { 1747 // Expected 1748 } 1749 } 1750 1751 @ForceInline 1752 public void test57_inline(Object vt) { 1753 synchronized (vt) { 1754 throw new RuntimeException("test57 failed: synchronization on inline type should not succeed"); 1755 } 1756 } 1757 1758 @Test 1759 @IR(failOn = {ALLOC_G}) 1760 public void test57(MyValue1 vt) { 1761 test57_inline(vt); 1762 } 1763 1764 @Run(test = "test57") 1765 public void test57_verifier() { 1766 try { 1767 test57(testValue1); 1768 throw new RuntimeException("test57 failed: no exception thrown"); 1769 } catch (IdentityException ex) { 1770 // Expected 1771 } 1772 } 1773 1774 @ForceInline 1775 public void test58_inline(Object vt) { 1776 synchronized (vt) { 1777 throw new RuntimeException("test58 failed: synchronization on inline type should not succeed"); 1778 } 1779 } 1780 1781 @Test 1782 @IR(failOn = {ALLOC}) 1783 public void test58() { 1784 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 1785 test58_inline(vt); 1786 } 1787 1788 @Run(test = "test58") 1789 public void test58_verifier() { 1790 try { 1791 test58(); 1792 throw new RuntimeException("test58 failed: no exception thrown"); 1793 } catch (IdentityException ex) { 1794 // Expected 1795 } 1796 } 1797 1798 @Test 1799 public void test59(Object o, boolean b) { 1800 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 1801 Object sync = b ? vt : o; 1802 synchronized (sync) { 1803 if (b) { 1804 throw new RuntimeException("test59 failed: synchronization on inline type should not succeed"); 1805 } 1806 } 1807 } 1808 1809 @Run(test = "test59") 1810 public void test59_verifier() { 1811 test59(new Object(), false); 1812 try { 1813 test59(new Object(), true); 1814 throw new RuntimeException("test59 failed: no exception thrown"); 1815 } catch (IdentityException ex) { 1816 // Expected 1817 } 1818 } 1819 1820 @Test 1821 public void test60(boolean b) { 1822 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 1823 Object sync = b ? vt : testValue2; 1824 synchronized (sync) { 1825 throw new RuntimeException("test60 failed: synchronization on inline type should not succeed"); 1826 } 1827 } 1828 1829 @Run(test = "test60") 1830 public void test60_verifier() { 1831 try { 1832 test60(false); 1833 throw new RuntimeException("test60 failed: no exception thrown"); 1834 } catch (IdentityException ex) { 1835 // Expected 1836 } 1837 try { 1838 test60(true); 1839 throw new RuntimeException("test60 failed: no exception thrown"); 1840 } catch (IdentityException ex) { 1841 // Expected 1842 } 1843 } 1844 1845 // Test catching the IdentityException in compiled code 1846 @Test 1847 public void test61(Object vt) { 1848 boolean thrown = false; 1849 try { 1850 synchronized (vt) { 1851 throw new RuntimeException("test61 failed: no exception thrown"); 1852 } 1853 } catch (IdentityException ex) { 1854 thrown = true; 1855 } 1856 if (!thrown) { 1857 throw new RuntimeException("test61 failed: no exception thrown"); 1858 } 1859 } 1860 1861 @Run(test = "test61") 1862 public void test61_verifier() { 1863 test61(testValue1); 1864 } 1865 1866 @Test 1867 public void test62(Object o) { 1868 try { 1869 synchronized (o) { } 1870 } catch (IdentityException ex) { 1871 // Expected 1872 return; 1873 } 1874 throw new RuntimeException("test62 failed: no exception thrown"); 1875 } 1876 1877 @Run(test = "test62") 1878 public void test62_verifier() { 1879 test62(testValue1); 1880 } 1881 1882 // Test synchronization without any instructions in the synchronized block 1883 @Test 1884 public void test63(Object o) { 1885 synchronized (o) { } 1886 } 1887 1888 @Run(test = "test63") 1889 public void test63_verifier() { 1890 try { 1891 test63(testValue1); 1892 } catch (IdentityException ex) { 1893 // Expected 1894 return; 1895 } 1896 throw new RuntimeException("test63 failed: no exception thrown"); 1897 } 1898 1899 // type system test with interface and inline type 1900 @ForceInline 1901 public MyInterface test64Interface_helper(MyValue1 vt) { 1902 return vt; 1903 } 1904 1905 @Test 1906 public MyInterface test64Interface(MyValue1 vt) { 1907 return test64Interface_helper(vt); 1908 } 1909 1910 @Run(test = "test64Interface") 1911 public void test64Interface_verifier() { 1912 test64Interface(testValue1); 1913 } 1914 1915 // type system test with abstract and inline type 1916 @ForceInline 1917 public MyAbstract test64Abstract_helper(MyValue1 vt) { 1918 return vt; 1919 } 1920 1921 @Test 1922 public MyAbstract test64Abstract(MyValue1 vt) { 1923 return test64Abstract_helper(vt); 1924 } 1925 1926 @Run(test = "test64Abstract") 1927 public void test64Abstract_verifier() { 1928 test64Abstract(testValue1); 1929 } 1930 1931 // Array store tests 1932 @Test 1933 public void test65(Object[] array, MyValue1 vt) { 1934 array[0] = vt; 1935 } 1936 1937 @Run(test = "test65") 1938 public void test65_verifier() { 1939 Object[] array = new Object[1]; 1940 test65(array, testValue1); 1941 Asserts.assertEQ(((MyValue1)array[0]).hash(), testValue1.hash()); 1942 } 1943 1944 @Test 1945 public void test66(Object[] array, MyValue1 vt) { 1946 array[0] = vt; 1947 } 1948 1949 @Run(test = "test66") 1950 public void test66_verifier() { 1951 MyValue1[] array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 1952 test66(array, testValue1); 1953 Asserts.assertEQ(array[0].hash(), testValue1.hash()); 1954 } 1955 1956 @Test 1957 public void test67(Object[] array, Object vt) { 1958 array[0] = vt; 1959 } 1960 1961 @Run(test = "test67") 1962 public void test67_verifier() { 1963 MyValue1[] array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 1964 test67(array, testValue1); 1965 Asserts.assertEQ(array[0].hash(), testValue1.hash()); 1966 } 1967 1968 @Test 1969 public void test68(Object[] array, NonValueClass o) { 1970 array[0] = o; 1971 } 1972 1973 @Run(test = "test68") 1974 public void test68_verifier() { 1975 NonValueClass[] array = new NonValueClass[1]; 1976 NonValueClass obj = new NonValueClass(1); 1977 test68(array, obj); 1978 Asserts.assertEQ(array[0], obj); 1979 } 1980 1981 // Test convertion between an inline type and java.lang.Object without an allocation 1982 @ForceInline 1983 public Object test69_sum(Object a, Object b) { 1984 int sum = ((MyValue1)a).x + ((MyValue1)b).x; 1985 return MyValue1.setX(((MyValue1)a), sum); 1986 } 1987 1988 @Test 1989 @IR(failOn = {ALLOC_G, STORE}) 1990 public int test69(MyValue1[] array) { 1991 MyValue1 result = MyValue1.createDefaultInline(); 1992 for (int i = 0; i < array.length; ++i) { 1993 result = (MyValue1)test69_sum(result, array[i]); 1994 } 1995 return result.x; 1996 } 1997 1998 @Run(test = "test69") 1999 public void test69_verifier() { 2000 int result = test69(testValue1Array); 2001 Asserts.assertEQ(result, rI * testValue1Array.length); 2002 } 2003 2004 // Same as test69 but with an Interface 2005 @ForceInline 2006 public MyInterface test70Interface_sum(MyInterface a, MyInterface b) { 2007 int sum = ((MyValue1)a).x + ((MyValue1)b).x; 2008 return MyValue1.setX(((MyValue1)a), sum); 2009 } 2010 2011 @Test 2012 @IR(failOn = {ALLOC_G, STORE}) 2013 public int test70Interface(MyValue1[] array) { 2014 MyValue1 result = MyValue1.createDefaultInline(); 2015 for (int i = 0; i < array.length; ++i) { 2016 result = (MyValue1)test70Interface_sum(result, array[i]); 2017 } 2018 return result.x; 2019 } 2020 2021 @Run(test = "test70Interface") 2022 public void test70Interface_verifier() { 2023 int result = test70Interface(testValue1Array); 2024 Asserts.assertEQ(result, rI * testValue1Array.length); 2025 } 2026 2027 // Same as test69 but with an Abstract 2028 @ForceInline 2029 public MyAbstract test70Abstract_sum(MyAbstract a, MyAbstract b) { 2030 int sum = ((MyValue1)a).x + ((MyValue1)b).x; 2031 return MyValue1.setX(((MyValue1)a), sum); 2032 } 2033 2034 @Test 2035 @IR(failOn = {ALLOC_G, STORE}) 2036 public int test70Abstract(MyValue1[] array) { 2037 MyValue1 result = MyValue1.createDefaultInline(); 2038 for (int i = 0; i < array.length; ++i) { 2039 result = (MyValue1)test70Abstract_sum(result, array[i]); 2040 } 2041 return result.x; 2042 } 2043 2044 @Run(test = "test70Abstract") 2045 public void test70Abstract_verifier() { 2046 int result = test70Abstract(testValue1Array); 2047 Asserts.assertEQ(result, rI * testValue1Array.length); 2048 } 2049 2050 // Test that allocated inline type is not used in non-dominated path 2051 public MyValue1 test71_inline(Object obj) { 2052 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 2053 try { 2054 vt = (MyValue1)Objects.requireNonNull(obj); 2055 throw new RuntimeException("NullPointerException expected"); 2056 } catch (NullPointerException e) { 2057 // Expected 2058 } 2059 return vt; 2060 } 2061 2062 @Test 2063 @IR(failOn = {ALLOC}) 2064 public MyValue1 test71() { 2065 return test71_inline(null); 2066 } 2067 2068 @Run(test = "test71") 2069 public void test71_verifier() { 2070 MyValue1 vt = test71(); 2071 Asserts.assertEquals(vt.hash(), hash()); 2072 } 2073 2074 // Test calling a method on an uninitialized inline type 2075 @LooselyConsistentValue 2076 value class Test72Value { 2077 int x = 0; 2078 2079 public int get() { 2080 return x; 2081 } 2082 } 2083 2084 // Make sure Test72Value is loaded but not initialized 2085 public void unused(Test72Value vt) { } 2086 2087 @Test 2088 @IR(failOn = {ALLOC_G}) 2089 public int test72() { 2090 Test72Value vt = new Test72Value(); 2091 return vt.get(); 2092 } 2093 2094 @Run(test = "test72") 2095 @Warmup(0) 2096 public void test72_verifier() { 2097 int result = test72(); 2098 Asserts.assertEquals(result, 0); 2099 } 2100 2101 // Tests for loading/storing unkown values 2102 @Test 2103 public Object test73(Object[] va) { 2104 return va[0]; 2105 } 2106 2107 @Run(test = "test73") 2108 public void test73_verifier() { 2109 MyValue1 vt = (MyValue1)test73(testValue1Array); 2110 Asserts.assertEquals(testValue1Array[0].hash(), vt.hash()); 2111 } 2112 2113 @Test 2114 public void test74(Object[] va, Object vt) { 2115 va[0] = vt; 2116 } 2117 2118 @Run(test = "test74") 2119 public void test74_verifier() { 2120 MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 2121 test74(va, testValue1); 2122 Asserts.assertEquals(va[0].hash(), testValue1.hash()); 2123 } 2124 2125 // Verify that mixing instances and arrays with the clone api 2126 // doesn't break anything 2127 @Test 2128 @IR(failOn = {ALLOC_G}) 2129 public Object test75(Object o) { 2130 MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 2131 Object[] next = va; 2132 Object[] arr = va; 2133 for (int i = 0; i < 10; i++) { 2134 arr = next; 2135 next = new NonValueClass[1]; 2136 } 2137 return arr[0]; 2138 } 2139 2140 @Run(test = "test75") 2141 public void test75_verifier() { 2142 test75(42); 2143 } 2144 2145 // Casting an NonValueClass to a inline type should throw a ClassCastException 2146 @ForceInline 2147 public MyValue1 test77_helper(Object o) { 2148 return (MyValue1)o; 2149 } 2150 2151 @Test 2152 @IR(failOn = {ALLOC_G}) 2153 public MyValue1 test77(NonValueClass obj) throws Throwable { 2154 return test77_helper(obj); 2155 } 2156 2157 @Run(test = "test77") 2158 public void test77_verifier() throws Throwable { 2159 try { 2160 test77(new NonValueClass(42)); 2161 throw new RuntimeException("ClassCastException expected"); 2162 } catch (ClassCastException e) { 2163 // Expected 2164 } catch (Exception e) { 2165 throw new RuntimeException("test77 failed: unexpected exception", e); 2166 } 2167 } 2168 2169 // Casting a null NonValueClass to a nullable inline type should not throw 2170 @ForceInline 2171 public MyValue1 test78_helper(Object o) { 2172 return (MyValue1)o; 2173 } 2174 2175 @Test 2176 @IR(failOn = {ALLOC_G}) 2177 public MyValue1 test78(NonValueClass obj) throws Throwable { 2178 return test78_helper(obj); 2179 } 2180 2181 @Run(test = "test78") 2182 public void test78_verifier() throws Throwable { 2183 try { 2184 test78(null); // Should not throw 2185 } catch (Exception e) { 2186 throw new RuntimeException("test78 failed: unexpected exception", e); 2187 } 2188 } 2189 2190 // Casting an NonValueClass to a nullable inline type should throw a ClassCastException 2191 @ForceInline 2192 public MyValue1 test79_helper(Object o) { 2193 return (MyValue1)o; 2194 } 2195 2196 @Test 2197 @IR(failOn = {ALLOC_G}) 2198 public MyValue1 test79(NonValueClass obj) throws Throwable { 2199 return test79_helper(obj); 2200 } 2201 2202 @Run(test = "test79") 2203 public void test79_verifier() throws Throwable { 2204 try { 2205 test79(new NonValueClass(42)); 2206 throw new RuntimeException("ClassCastException expected"); 2207 } catch (ClassCastException e) { 2208 // Expected 2209 } catch (Exception e) { 2210 throw new RuntimeException("test79 failed: unexpected exception", e); 2211 } 2212 } 2213 2214 // Test flattened field with non-flattenend (but flattenable) inline type field 2215 @LooselyConsistentValue 2216 static value class Small { 2217 int i; 2218 @Strict 2219 @NullRestricted 2220 Big big; // Too big to be flattened 2221 2222 private Small() { 2223 i = rI; 2224 big = new Big(); 2225 } 2226 2227 private Small(int i, Big big) { 2228 this.i = i; 2229 this.big = big; 2230 } 2231 } 2232 2233 @LooselyConsistentValue 2234 static value class Big { 2235 long l0,l1,l2,l3,l4,l5,l6,l7,l8,l9; 2236 long l10,l11,l12,l13,l14,l15,l16,l17,l18,l19; 2237 long l20,l21,l22,l23,l24,l25,l26,l27,l28,l29; 2238 2239 private Big() { 2240 l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = rL; 2241 l10 = l11 = l12 = l13 = l14 = l15 = l16 = l17 = l18 = l19 = rL+1; 2242 l20 = l21 = l22 = l23 = l24 = l25 = l26 = l27 = l28 = l29 = rL+2; 2243 } 2244 2245 private Big(long l) { 2246 l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = l10 = 2247 l11 = l12 = l13 = l14 = l15 = l16 = l17 = l18 = l19 = l20 = 2248 l21 = l22 = l23 = l24 = l25 = l26 = l27 = l28 = l29 = 0; 2249 } 2250 } 2251 2252 @Strict 2253 @NullRestricted 2254 Small small = new Small(); 2255 @Strict 2256 @NullRestricted 2257 Small smallDefault = new Small(0, new Big(0)); 2258 @Strict 2259 @NullRestricted 2260 Big big = new Big(); 2261 @Strict 2262 @NullRestricted 2263 Big bigDefault = new Big(0); 2264 2265 @Test 2266 public long test80() { 2267 return small.i + small.big.l0 + smallDefault.i + smallDefault.big.l29 + big.l0 + bigDefault.l29; 2268 } 2269 2270 @Run(test = "test80") 2271 public void test80_verifier() throws Throwable { 2272 long result = test80(); 2273 Asserts.assertEQ(result, rI + 2*rL); 2274 } 2275 2276 // Test scalarization with exceptional control flow 2277 public int test81Callee(MyValue1 vt) { 2278 return vt.x; 2279 } 2280 2281 @Test 2282 @IR(failOn = {ALLOC_G, LOAD, STORE}) 2283 public int test81() { 2284 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 2285 int result = 0; 2286 for (int i = 0; i < 10; i++) { 2287 try { 2288 result += test81Callee(vt); 2289 } catch (NullPointerException npe) { 2290 result += rI; 2291 } 2292 } 2293 return result; 2294 } 2295 2296 @Run(test = "test81") 2297 public void test81_verifier() { 2298 int result = test81(); 2299 Asserts.assertEQ(result, 10*rI); 2300 } 2301 2302 // Test check for null free array when storing to inline tpye array 2303 @Test 2304 public void test82(Object[] dst, Object v) { 2305 dst[0] = v; 2306 } 2307 2308 @Run(test = "test82") 2309 public void test82_verifier(RunInfo info) { 2310 MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT); 2311 test82(dst, testValue2); 2312 if (!info.isWarmUp()) { 2313 try { 2314 test82(dst, null); 2315 throw new RuntimeException("No ArrayStoreException thrown"); 2316 } catch (NullPointerException e) { 2317 // Expected 2318 } 2319 } 2320 } 2321 2322 @Test 2323 @IR(failOn = {ALLOC_G}) 2324 public void test83(Object[] dst, Object v, boolean flag) { 2325 if (dst == null) { // null check 2326 } 2327 if (flag) { 2328 if (dst.getClass() == MyValue1[].class) { // trigger split if 2329 } 2330 } else { 2331 dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT); // constant null free property 2332 } 2333 dst[0] = v; 2334 } 2335 2336 @Run(test = "test83") 2337 @Warmup(10000) 2338 public void test83_verifier(RunInfo info) { 2339 MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT); 2340 test83(dst, testValue2, false); 2341 test83(dst, testValue2, true); 2342 if (!info.isWarmUp()) { 2343 try { 2344 test83(dst, null, true); 2345 throw new RuntimeException("No ArrayStoreException thrown"); 2346 } catch (NullPointerException e) { 2347 // Expected 2348 } 2349 } 2350 } 2351 2352 private void rerun_and_recompile_for(Method m, int num, Runnable test) { 2353 for (int i = 1; i < num; i++) { 2354 test.run(); 2355 2356 if (!TestFramework.isCompiled(m)) { 2357 TestFramework.compile(m, CompLevel.C2); 2358 } 2359 } 2360 } 2361 2362 // Tests for the Loop Unswitching optimization 2363 // Should make 2 copies of the loop, one for non flattened arrays, one for other cases. 2364 @Test 2365 @IR(applyIf = {"UseArrayFlattening", "true"}, 2366 counts = {COUNTEDLOOP_MAIN, "= 2"}) 2367 @IR(applyIf = {"UseArrayFlattening", "false"}, 2368 counts = {COUNTEDLOOP_MAIN, "= 1"}) 2369 public void test84(Object[] src, Object[] dst) { 2370 for (int i = 0; i < src.length; i++) { 2371 dst[i] = src[i]; 2372 } 2373 } 2374 2375 @Run(test = "test84") 2376 @Warmup(0) 2377 public void test84_verifier(RunInfo info) { 2378 MyValue2[] src = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2379 Arrays.fill(src, testValue2); 2380 MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2381 rerun_and_recompile_for(info.getTest(), 10, 2382 () -> { test84(src, dst); 2383 Asserts.assertTrue(Arrays.equals(src, dst)); }); 2384 } 2385 2386 @Test 2387 @IR(applyIf = {"UseArrayFlattening", "true"}, 2388 counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 1"}) 2389 public void test85(Object[] src, Object[] dst) { 2390 for (int i = 0; i < src.length; i++) { 2391 dst[i] = src[i]; 2392 } 2393 } 2394 2395 @Run(test = "test85") 2396 @Warmup(0) 2397 public void test85_verifier(RunInfo info) { 2398 Object[] src = new Object[100]; 2399 Arrays.fill(src, new Object()); 2400 src[0] = null; 2401 Object[] dst = new Object[100]; 2402 rerun_and_recompile_for(info.getTest(), 10, 2403 () -> { test85(src, dst); 2404 Asserts.assertTrue(Arrays.equals(src, dst)); }); 2405 } 2406 2407 @Test 2408 @IR(applyIf = {"UseArrayFlattening", "true"}, 2409 counts = {COUNTEDLOOP, "= 2"}) 2410 public void test86(Object[] src, Object[] dst) { 2411 for (int i = 0; i < src.length; i++) { 2412 dst[i] = src[i]; 2413 } 2414 } 2415 2416 @Run(test = "test86") 2417 @Warmup(0) 2418 public void test86_verifier(RunInfo info) { 2419 MyValue2[] src = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2420 Arrays.fill(src, testValue2); 2421 Object[] dst = new Object[100]; 2422 rerun_and_recompile_for(info.getTest(), 10, 2423 () -> { test86(src, dst); 2424 Asserts.assertTrue(Arrays.equals(src, dst)); }); 2425 } 2426 2427 @Test 2428 @IR(applyIf = {"UseArrayFlattening", "true"}, 2429 counts = {COUNTEDLOOP_MAIN, "= 2"}) 2430 @IR(applyIf = {"UseArrayFlattening", "false"}, 2431 counts = {COUNTEDLOOP_MAIN, "= 1"}) 2432 public void test87(Object[] src, Object[] dst) { 2433 for (int i = 0; i < src.length; i++) { 2434 dst[i] = src[i]; 2435 } 2436 } 2437 2438 @Run(test = "test87") 2439 @Warmup(0) 2440 public void test87_verifier(RunInfo info) { 2441 Object[] src = new Object[100]; 2442 Arrays.fill(src, testValue2); 2443 MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2444 2445 rerun_and_recompile_for(info.getTest(), 10, 2446 () -> { test87(src, dst); 2447 Asserts.assertTrue(Arrays.equals(src, dst)); }); 2448 } 2449 2450 @Test 2451 @IR(applyIf = {"UseArrayFlattening", "true"}, 2452 counts = {COUNTEDLOOP_MAIN, "= 2"}) 2453 @IR(applyIf = {"UseArrayFlattening", "false"}, 2454 counts = {COUNTEDLOOP_MAIN, "= 0"}) 2455 public void test88(Object[] src1, Object[] dst1, Object[] src2, Object[] dst2) { 2456 for (int i = 0; i < src1.length; i++) { 2457 dst1[i] = src1[i]; 2458 dst2[i] = src2[i]; 2459 } 2460 } 2461 2462 @Run(test = "test88") 2463 @Warmup(0) 2464 public void test88_verifier(RunInfo info) { 2465 MyValue2[] src1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2466 Arrays.fill(src1, testValue2); 2467 MyValue2[] dst1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 2468 Object[] src2 = new Object[100]; 2469 Arrays.fill(src2, new Object()); 2470 Object[] dst2 = new Object[100]; 2471 2472 rerun_and_recompile_for(info.getTest(), 10, 2473 () -> { test88(src1, dst1, src2, dst2); 2474 Asserts.assertTrue(Arrays.equals(src1, dst1)); 2475 Asserts.assertTrue(Arrays.equals(src2, dst2)); }); 2476 } 2477 2478 @Test 2479 public boolean test89(Object obj) { 2480 return obj.getClass() == NonValueClass.class; 2481 } 2482 2483 @Run(test = "test89") 2484 public void test89_verifier() { 2485 Asserts.assertTrue(test89(new NonValueClass(42))); 2486 Asserts.assertFalse(test89(new Object())); 2487 } 2488 2489 @Test 2490 public NonValueClass test90(Object obj) { 2491 return (NonValueClass)obj; 2492 } 2493 2494 @Run(test = "test90") 2495 public void test90_verifier() { 2496 test90(new NonValueClass(42)); 2497 try { 2498 test90(new Object()); 2499 throw new RuntimeException("ClassCastException expected"); 2500 } catch (ClassCastException e) { 2501 // Expected 2502 } 2503 } 2504 2505 @Test 2506 public boolean test91(Object obj) { 2507 return obj.getClass() == MyValue2[].class; 2508 } 2509 2510 @Run(test = "test91") 2511 public void test91_verifier() { 2512 Asserts.assertFalse(test91((MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT))); 2513 Asserts.assertTrue(test91(new MyValue2[1])); 2514 Asserts.assertFalse(test91(new Object())); 2515 } 2516 2517 @LooselyConsistentValue 2518 static value class Test92Value { 2519 int field; 2520 2521 public Test92Value() { 2522 field = 0x42; 2523 } 2524 } 2525 2526 @Test 2527 // TODO 8355382 The optimization only applies to null-free, flat arrays 2528 @IR(applyIfAnd = {"UseArrayFlattening", "true", "UseNullableValueFlattening", "false"}, 2529 counts = {CLASS_CHECK_TRAP, "= 2"}, 2530 failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR}) 2531 public Object test92(Object[] array) { 2532 // Dummy loops to ensure we run enough passes of split if 2533 for (int i = 0; i < 2; i++) { 2534 for (int j = 0; j < 2; j++) { 2535 for (int k = 0; k < 2; k++) { 2536 } 2537 } 2538 } 2539 return (NonValueClass)array[0]; 2540 } 2541 2542 @Run(test = "test92") 2543 @Warmup(10000) 2544 public void test92_verifier() { 2545 Object[] array = new Object[1]; 2546 Object obj = new NonValueClass(rI); 2547 array[0] = obj; 2548 Object result = test92(array); 2549 Asserts.assertEquals(result, obj); 2550 } 2551 2552 // If the class check succeeds, the flattened array check that 2553 // precedes will never succeed and the flat array branch should 2554 // trigger an uncommon trap. 2555 @Test 2556 public Object test93(Object[] array) { 2557 for (int i = 0; i < 2; i++) { 2558 for (int j = 0; j < 2; j++) { 2559 } 2560 } 2561 2562 return (NonValueClass)array[0]; 2563 } 2564 2565 @Run(test = "test93") 2566 @Warmup(10000) 2567 public void test93_verifier(RunInfo info) { 2568 if (info.isWarmUp()) { 2569 Object[] array = new Object[1]; 2570 array[0] = new NonValueClass(42); 2571 Object result = test93(array); 2572 Asserts.assertEquals(((NonValueClass)result).x, 42); 2573 } else { 2574 Object[] array = (Test92Value[])ValueClass.newNullRestrictedNonAtomicArray(Test92Value.class, 1, new Test92Value()); 2575 Method m = info.getTest(); 2576 int extra = 3; 2577 for (int j = 0; j < extra; j++) { 2578 for (int i = 0; i < 10; i++) { 2579 try { 2580 test93(array); 2581 } catch (ClassCastException cce) { 2582 } 2583 } 2584 boolean compiled = TestFramework.isCompiled(m); 2585 boolean compilationSkipped = info.isCompilationSkipped(); 2586 Asserts.assertTrue(compilationSkipped || compiled || (j != extra-1)); 2587 if (!compilationSkipped && !compiled) { 2588 TestFramework.compile(m, CompLevel.ANY); 2589 } 2590 } 2591 } 2592 } 2593 2594 @Test 2595 // TODO 8355382 The optimization only applies to null-free, flat arrays 2596 @IR(applyIfAnd = {"UseArrayFlattening", "true", "UseNullableValueFlattening", "false"}, 2597 counts = {CLASS_CHECK_TRAP, "= 2", LOOP, "= 1"}, 2598 failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR}) 2599 public int test94(Object[] array) { 2600 int res = 0; 2601 for (int i = 1; i < 4; i *= 2) { 2602 Object v = array[i]; 2603 res += ((NonValueClass)v).x; 2604 } 2605 return res; 2606 } 2607 2608 @Run(test = "test94") 2609 @Warmup(10000) 2610 public void test94_verifier() { 2611 Object[] array = new Object[4]; 2612 Object obj = new NonValueClass(rI); 2613 array[0] = obj; 2614 array[1] = obj; 2615 array[2] = obj; 2616 array[3] = obj; 2617 int result = test94(array); 2618 Asserts.assertEquals(result, rI * 2); 2619 } 2620 2621 @Test 2622 public boolean test95(Object o1, Object o2) { 2623 return o1 == o2; 2624 } 2625 2626 @Run(test = "test95") 2627 @Warmup(10000) 2628 public void test95_verifier() { 2629 Object o1 = new Object(); 2630 Object o2 = new Object(); 2631 Asserts.assertTrue(test95(o1, o1)); 2632 Asserts.assertTrue(test95(null, null)); 2633 Asserts.assertFalse(test95(o1, null)); 2634 Asserts.assertFalse(test95(o1, o2)); 2635 } 2636 2637 @Test 2638 public boolean test96(Object o1, Object o2) { 2639 return o1 == o2; 2640 } 2641 2642 @Run(test = "test96") 2643 @Warmup(10000) 2644 public void test96_verifier(RunInfo info) { 2645 Object o1 = new Object(); 2646 Object o2 = new Object(); 2647 Asserts.assertTrue(test96(o1, o1)); 2648 Asserts.assertFalse(test96(o1, o2)); 2649 if (!info.isWarmUp()) { 2650 Asserts.assertTrue(test96(null, null)); 2651 Asserts.assertFalse(test96(o1, null)); 2652 } 2653 } 2654 2655 // Abstract class tests 2656 2657 @DontInline 2658 public MyAbstract test97_dontinline1(MyAbstract o) { 2659 return o; 2660 } 2661 2662 @DontInline 2663 public MyValue1 test97_dontinline2(MyAbstract o) { 2664 return (MyValue1)o; 2665 } 2666 2667 @ForceInline 2668 public MyAbstract test97_inline1(MyAbstract o) { 2669 return o; 2670 } 2671 2672 @ForceInline 2673 public MyValue1 test97_inline2(MyAbstract o) { 2674 return (MyValue1)o; 2675 } 2676 2677 @Test 2678 public MyValue1 test97() { 2679 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 2680 vt = (MyValue1)test97_dontinline1(vt); 2681 vt = test97_dontinline2(vt); 2682 vt = (MyValue1)test97_inline1(vt); 2683 vt = test97_inline2(vt); 2684 return vt; 2685 } 2686 2687 @Run(test = "test97") 2688 public void test97_verifier() { 2689 Asserts.assertEQ(test97().hash(), hash()); 2690 } 2691 2692 // Test storing/loading inline types to/from abstract and inline type fields 2693 MyAbstract abstractField1 = null; 2694 MyAbstract abstractField2 = null; 2695 MyAbstract abstractField3 = null; 2696 MyAbstract abstractField4 = null; 2697 MyAbstract abstractField5 = null; 2698 MyAbstract abstractField6 = null; 2699 2700 @DontInline 2701 public MyAbstract readValueField5AsAbstract() { 2702 return (MyAbstract)valueField5; 2703 } 2704 2705 @DontInline 2706 public MyAbstract readStaticValueField4AsAbstract() { 2707 return (MyAbstract)staticValueField4; 2708 } 2709 2710 @Test 2711 public long test98(MyValue1 vt1, MyAbstract vt2) { 2712 abstractField1 = vt1; 2713 abstractField2 = (MyValue1)vt2; 2714 abstractField3 = MyValue1.createWithFieldsInline(rI, rL); 2715 abstractField4 = MyValue1.createWithFieldsDontInline(rI, rL); 2716 abstractField5 = valueField1; 2717 abstractField6 = valueField3; 2718 valueField1 = (MyValue1)abstractField1; 2719 valueField2 = (MyValue1)vt2; 2720 valueField3 = (MyValue1)vt2; 2721 staticValueField1 = (MyValue1)abstractField1; 2722 staticValueField2 = (MyValue1)vt1; 2723 // Don't inline these methods because reading NULL will trigger a deoptimization 2724 if (readValueField5AsAbstract() != null || readStaticValueField4AsAbstract() != null) { 2725 throw new RuntimeException("Should be null"); 2726 } 2727 return ((MyValue1)abstractField1).hash() + ((MyValue1)abstractField2).hash() + 2728 ((MyValue1)abstractField3).hash() + ((MyValue1)abstractField4).hash() + 2729 ((MyValue1)abstractField5).hash() + ((MyValue1)abstractField6).hash() + 2730 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() + 2731 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive(); 2732 } 2733 2734 @Run(test = "test98") 2735 public void test98_verifier() { 2736 MyValue1 vt = testValue1; 2737 MyValue1 def = MyValue1.createDefaultDontInline(); 2738 long result = test98(vt, vt); 2739 Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive()); 2740 } 2741 2742 value class MyObject2 extends MyAbstract { 2743 public int x; 2744 2745 public MyObject2(int x) { 2746 this.x = x; 2747 } 2748 2749 @ForceInline 2750 public long hash() { 2751 return x; 2752 } 2753 } 2754 2755 // Test merging inline types and abstract classes 2756 @Test 2757 public MyAbstract test99(int state) { 2758 MyAbstract res = null; 2759 if (state == 0) { 2760 res = new MyObject2(rI); 2761 } else if (state == 1) { 2762 res = MyValue1.createWithFieldsInline(rI, rL); 2763 } else if (state == 2) { 2764 res = MyValue1.createWithFieldsDontInline(rI, rL); 2765 } else if (state == 3) { 2766 res = (MyValue1)objectField1; 2767 } else if (state == 4) { 2768 res = valueField1; 2769 } else if (state == 5) { 2770 res = null; 2771 } 2772 return res; 2773 } 2774 2775 @Run(test = "test99") 2776 public void test99_verifier() { 2777 objectField1 = valueField1; 2778 MyAbstract result = null; 2779 result = test99(0); 2780 Asserts.assertEQ(((MyObject2)result).x, rI); 2781 result = test99(1); 2782 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 2783 result = test99(2); 2784 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 2785 result = test99(3); 2786 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 2787 result = test99(4); 2788 Asserts.assertEQ(((MyValue1)result).hash(), hash()); 2789 result = test99(5); 2790 Asserts.assertEQ(result, null); 2791 } 2792 2793 // Test merging inline types and abstract classes in loops 2794 @Test 2795 public MyAbstract test100(int iters) { 2796 MyAbstract res = new MyObject2(rI); 2797 for (int i = 0; i < iters; ++i) { 2798 if (res instanceof MyObject2) { 2799 res = MyValue1.createWithFieldsInline(rI, rL); 2800 } else { 2801 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL); 2802 } 2803 } 2804 return res; 2805 } 2806 2807 @Run(test = "test100") 2808 public void test100_verifier() { 2809 MyObject2 result1 = (MyObject2)test100(0); 2810 Asserts.assertEQ(result1.x, rI); 2811 int iters = (Math.abs(rI) % 10) + 1; 2812 MyValue1 result2 = (MyValue1)test100(iters); 2813 MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL); 2814 Asserts.assertEQ(result2.hash(), vt.hash()); 2815 } 2816 2817 // Test inline types in abstract class variables that are live at safepoint 2818 @Test 2819 @IR(failOn = {ALLOC, STORE, LOOP}) 2820 public long test101(MyValue1 arg, boolean deopt, Method m) { 2821 MyAbstract vt1 = MyValue1.createWithFieldsInline(rI, rL); 2822 MyAbstract vt2 = MyValue1.createWithFieldsDontInline(rI, rL); 2823 MyAbstract vt3 = arg; 2824 MyAbstract vt4 = valueField1; 2825 if (deopt) { 2826 // uncommon trap 2827 TestFramework.deoptimize(m); 2828 } 2829 return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() + 2830 ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash(); 2831 } 2832 2833 @Run(test = "test101") 2834 public void test101_verifier(RunInfo info) { 2835 long result = test101(valueField1, !info.isWarmUp(), info.getTest()); 2836 Asserts.assertEQ(result, 4*hash()); 2837 } 2838 2839 // Test comparing inline types with abstract classes 2840 @Test 2841 public boolean test102(Object arg) { 2842 MyAbstract vt = MyValue1.createWithFieldsInline(rI, rL); 2843 if (vt == arg || vt == (MyAbstract)valueField1 || vt == abstractField1 || vt == null || 2844 arg == vt || (MyAbstract)valueField1 == vt || abstractField1 == vt || null == vt) { 2845 return true; 2846 } 2847 return false; 2848 } 2849 2850 @Run(test = "test102") 2851 public void test102_verifier() { 2852 boolean result = test102(null); 2853 Asserts.assertFalse(result); 2854 } 2855 2856 // An abstract class with a non-static field can never be implemented by an inline type 2857 abstract class NoValueImplementors1 { 2858 int field = 42; 2859 } 2860 2861 class MyObject3 extends NoValueImplementors1 { 2862 2863 } 2864 2865 class MyObject4 extends NoValueImplementors1 { 2866 2867 } 2868 2869 // Loading from an abstract class array does not require a flatness check if the abstract class has a non-static field 2870 @Test 2871 @IR(failOn = {ALLOC_G, MEMBAR, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}) 2872 public NoValueImplementors1 test103(NoValueImplementors1[] array, int i) { 2873 return array[i]; 2874 } 2875 2876 @Run(test = "test103") 2877 public void test103_verifier() { 2878 NoValueImplementors1[] array1 = new NoValueImplementors1[3]; 2879 MyObject3[] array2 = new MyObject3[3]; 2880 MyObject4[] array3 = new MyObject4[3]; 2881 NoValueImplementors1 result = test103(array1, 0); 2882 Asserts.assertEquals(result, array1[0]); 2883 2884 result = test103(array2, 1); 2885 Asserts.assertEquals(result, array1[1]); 2886 2887 result = test103(array3, 2); 2888 Asserts.assertEquals(result, array1[2]); 2889 } 2890 2891 // Storing to an abstract class array does not require a flatness/null check if the abstract class has a non-static field 2892 @Test 2893 @IR(failOn = {ALLOC_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}) 2894 public NoValueImplementors1 test104(NoValueImplementors1[] array, NoValueImplementors1 v, MyObject3 o, int i) { 2895 array[0] = v; 2896 array[1] = array[0]; 2897 array[2] = o; 2898 return array[i]; 2899 } 2900 2901 @Run(test = "test104") 2902 public void test104_verifier() { 2903 MyObject4 v = new MyObject4(); 2904 MyObject3 o = new MyObject3(); 2905 NoValueImplementors1[] array1 = new NoValueImplementors1[3]; 2906 MyObject3[] array2 = new MyObject3[3]; 2907 MyObject4[] array3 = new MyObject4[3]; 2908 NoValueImplementors1 result = test104(array1, v, o, 0); 2909 Asserts.assertEquals(array1[0], v); 2910 Asserts.assertEquals(array1[1], v); 2911 Asserts.assertEquals(array1[2], o); 2912 Asserts.assertEquals(result, v); 2913 2914 result = test104(array2, o, o, 1); 2915 Asserts.assertEquals(array2[0], o); 2916 Asserts.assertEquals(array2[1], o); 2917 Asserts.assertEquals(array2[2], o); 2918 Asserts.assertEquals(result, o); 2919 2920 result = test104(array3, v, null, 1); 2921 Asserts.assertEquals(array3[0], v); 2922 Asserts.assertEquals(array3[1], v); 2923 Asserts.assertEquals(array3[2], null); 2924 Asserts.assertEquals(result, v); 2925 } 2926 2927 // An abstract class with a single, non-inline implementor 2928 abstract class NoValueImplementors2 { 2929 2930 } 2931 2932 class MyObject5 extends NoValueImplementors2 { 2933 2934 } 2935 2936 // Loading from an abstract class array does not require a flatness check if the abstract class has no inline implementor 2937 @Test 2938 @IR(failOn = {ALLOC_G, MEMBAR, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}) 2939 public NoValueImplementors2 test105(NoValueImplementors2[] array, int i) { 2940 return array[i]; 2941 } 2942 2943 @Run(test = "test105") 2944 public void test105_verifier() { 2945 NoValueImplementors2[] array1 = new NoValueImplementors2[3]; 2946 MyObject5[] array2 = new MyObject5[3]; 2947 NoValueImplementors2 result = test105(array1, 0); 2948 Asserts.assertEquals(result, array1[0]); 2949 2950 result = test105(array2, 1); 2951 Asserts.assertEquals(result, array1[1]); 2952 } 2953 2954 // Storing to an abstract class array does not require a flatness/null check if the abstract class has no inline implementor 2955 @Test 2956 @IR(failOn = {ALLOC_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}) 2957 public NoValueImplementors2 test106(NoValueImplementors2[] array, NoValueImplementors2 v, MyObject5 o, int i) { 2958 array[0] = v; 2959 array[1] = array[0]; 2960 array[2] = o; 2961 return array[i]; 2962 } 2963 2964 @Run(test = "test106") 2965 public void test106_verifier() { 2966 MyObject5 v = new MyObject5(); 2967 NoValueImplementors2[] array1 = new NoValueImplementors2[3]; 2968 MyObject5[] array2 = new MyObject5[3]; 2969 NoValueImplementors2 result = test106(array1, v, null, 0); 2970 Asserts.assertEquals(array1[0], v); 2971 Asserts.assertEquals(array1[1], v); 2972 Asserts.assertEquals(array1[2], null); 2973 Asserts.assertEquals(result, v); 2974 2975 result = test106(array2, v, v, 1); 2976 Asserts.assertEquals(array2[0], v); 2977 Asserts.assertEquals(array2[1], v); 2978 Asserts.assertEquals(array2[2], v); 2979 Asserts.assertEquals(result, v); 2980 } 2981 2982 // More tests for the Loop Unswitching optimization (similar to test84 and following) 2983 Object oFld1, oFld2; 2984 2985 @Test 2986 @IR(applyIf = {"UseArrayFlattening", "true"}, 2987 failOn = {STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}, 2988 counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 2"}, 2989 // Match on CCP since we are removing one of the unswitched loop versions later due to being empty 2990 phase = {CompilePhase.CCP1}) 2991 public void test107(Object[] src1, Object[] src2) { 2992 for (int i = 0; i < src1.length; i++) { 2993 oFld1 = src1[i]; 2994 oFld2 = src2[i]; 2995 } 2996 } 2997 2998 @Run(test = "test107") 2999 @Warmup(0) 3000 public void test107_verifier(RunInfo info) { 3001 MyValue2[] src1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 3002 Arrays.fill(src1, testValue2); 3003 Object[] src2 = new Object[100]; 3004 Object obj = new Object(); 3005 Arrays.fill(src2, obj); 3006 rerun_and_recompile_for(info.getTest(), 10, 3007 () -> { test107(src1, src2); 3008 Asserts.assertEquals(oFld1, testValue2); 3009 Asserts.assertEquals(oFld2, obj); 3010 test107(src2, src1); 3011 Asserts.assertEquals(oFld1, obj); 3012 Asserts.assertEquals(oFld2, testValue2); }); 3013 } 3014 3015 @Test 3016 @IR(applyIf = {"UseArrayFlattening", "true"}, 3017 failOn = {LOAD_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD}, 3018 counts = {COUNTEDLOOP, "= 4", STORE_UNKNOWN_INLINE, "= 9"}) 3019 public void test108(Object[] dst1, Object[] dst2, Object o1, Object o2) { 3020 for (int i = 0; i < dst1.length; i++) { 3021 dst1[i] = o1; 3022 dst2[i] = o2; 3023 } 3024 } 3025 3026 @Run(test = "test108") 3027 @Warmup(0) 3028 public void test108_verifier(RunInfo info) { 3029 MyValue2[] dst1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT); 3030 Object[] dst2 = new Object[100]; 3031 Object o1 = new Object(); 3032 rerun_and_recompile_for(info.getTest(), 10, 3033 () -> { test108(dst1, dst2, testValue2, o1); 3034 for (int i = 0; i < dst1.length; i++) { 3035 Asserts.assertEquals(dst1[i], testValue2); 3036 Asserts.assertEquals(dst2[i], o1); 3037 } 3038 test108(dst2, dst1, o1, testValue2); 3039 for (int i = 0; i < dst1.length; i++) { 3040 Asserts.assertEquals(dst1[i], testValue2); 3041 Asserts.assertEquals(dst2[i], o1); 3042 } }); 3043 } 3044 3045 // Escape analysis tests 3046 3047 static interface WrapperInterface { 3048 long value(); 3049 3050 final static WrapperInterface ZERO = new LongWrapper(0); 3051 3052 @ForceInline 3053 static WrapperInterface wrap(long val) { 3054 return (val == 0L) ? ZERO : new LongWrapper(val); 3055 } 3056 } 3057 3058 @ForceCompileClassInitializer 3059 @LooselyConsistentValue 3060 static value class LongWrapper implements WrapperInterface { 3061 @Strict 3062 @NullRestricted 3063 final static LongWrapper ZERO = new LongWrapper(0); 3064 private long val; 3065 3066 @ForceInline 3067 LongWrapper(long val) { 3068 this.val = val; 3069 } 3070 3071 @ForceInline 3072 static LongWrapper wrap(long val) { 3073 return (val == 0L) ? ZERO : new LongWrapper(val); 3074 } 3075 3076 @ForceInline 3077 public long value() { 3078 return val; 3079 } 3080 } 3081 3082 static class InterfaceBox { 3083 WrapperInterface content; 3084 3085 @ForceInline 3086 InterfaceBox(WrapperInterface content) { 3087 this.content = content; 3088 } 3089 3090 @ForceInline 3091 static InterfaceBox box_sharp(long val) { 3092 return new InterfaceBox(LongWrapper.wrap(val)); 3093 } 3094 3095 @ForceInline 3096 static InterfaceBox box(long val) { 3097 return new InterfaceBox(WrapperInterface.wrap(val)); 3098 } 3099 } 3100 3101 static class ObjectBox { 3102 Object content; 3103 3104 @ForceInline 3105 ObjectBox(Object content) { 3106 this.content = content; 3107 } 3108 3109 @ForceInline 3110 static ObjectBox box_sharp(long val) { 3111 return new ObjectBox(LongWrapper.wrap(val)); 3112 } 3113 3114 @ForceInline 3115 static ObjectBox box(long val) { 3116 return new ObjectBox(WrapperInterface.wrap(val)); 3117 } 3118 } 3119 3120 static class RefBox { 3121 LongWrapper content; 3122 3123 @ForceInline 3124 RefBox(LongWrapper content) { 3125 this.content = content; 3126 } 3127 3128 @ForceInline 3129 static RefBox box_sharp(long val) { 3130 return new RefBox(LongWrapper.wrap(val)); 3131 } 3132 3133 @ForceInline 3134 static RefBox box(long val) { 3135 return new RefBox((LongWrapper)WrapperInterface.wrap(val)); 3136 } 3137 } 3138 3139 static class InlineBox { 3140 @Strict 3141 @NullRestricted 3142 LongWrapper content; 3143 3144 @ForceInline 3145 InlineBox(long val) { 3146 this.content = LongWrapper.wrap(val); 3147 } 3148 3149 @ForceInline 3150 static InlineBox box(long val) { 3151 return new InlineBox(val); 3152 } 3153 } 3154 3155 static class GenericBox<T> { 3156 T content; 3157 3158 @ForceInline 3159 static GenericBox<LongWrapper> box_sharp(long val) { 3160 GenericBox<LongWrapper> res = new GenericBox<>(); 3161 res.content = LongWrapper.wrap(val); 3162 return res; 3163 } 3164 3165 @ForceInline 3166 static GenericBox<WrapperInterface> box(long val) { 3167 GenericBox<WrapperInterface> res = new GenericBox<>(); 3168 res.content = WrapperInterface.wrap(val); 3169 return res; 3170 } 3171 } 3172 3173 long[] lArr = {0L, rL, 0L, rL, 0L, rL, 0L, rL, 0L, rL}; 3174 3175 // Test removal of allocations when inline type instance is wrapped into box object 3176 @Test 3177 @IR(failOn = {ALLOC_G, MEMBAR}, 3178 counts = {PREDICATE_TRAP, "= 1"}) 3179 public long test109() { 3180 long res = 0; 3181 for (int i = 0; i < lArr.length; i++) { 3182 res += InterfaceBox.box(lArr[i]).content.value(); 3183 } 3184 return res; 3185 } 3186 3187 @Run(test = "test109") 3188 @Warmup(10000) // Make sure interface calls are inlined 3189 public void test109_verifier() { 3190 long res = test109(); 3191 Asserts.assertEquals(res, 5*rL); 3192 } 3193 3194 @Test 3195 @IR(failOn = {ALLOC_G, MEMBAR}, 3196 counts = {PREDICATE_TRAP, "= 1"}) 3197 @IR(failOn = {ALLOC_G, MEMBAR}) 3198 public long test109_sharp() { 3199 long res = 0; 3200 for (int i = 0; i < lArr.length; i++) { 3201 res += InterfaceBox.box_sharp(lArr[i]).content.value(); 3202 } 3203 return res; 3204 } 3205 3206 @Run(test = "test109_sharp") 3207 @Warmup(10000) // Make sure interface calls are inlined 3208 public void test109_sharp_verifier() { 3209 long res = test109_sharp(); 3210 Asserts.assertEquals(res, 5*rL); 3211 } 3212 3213 // Same as test109 but with ObjectBox 3214 @Test 3215 @IR(failOn = {ALLOC_G, MEMBAR}, 3216 counts = {PREDICATE_TRAP, "= 1"}) 3217 public long test110() { 3218 long res = 0; 3219 for (int i = 0; i < lArr.length; i++) { 3220 res += ((WrapperInterface)ObjectBox.box(lArr[i]).content).value(); 3221 } 3222 return res; 3223 } 3224 3225 @Run(test = "test110") 3226 @Warmup(10000) // Make sure interface calls are inlined 3227 public void test110_verifier() { 3228 long res = test110(); 3229 Asserts.assertEquals(res, 5*rL); 3230 } 3231 3232 @Test 3233 @IR(failOn = {ALLOC_G, MEMBAR}, 3234 counts = {PREDICATE_TRAP, "= 1"}) 3235 @IR(failOn = {ALLOC_G, MEMBAR}) 3236 public long test110_sharp() { 3237 long res = 0; 3238 for (int i = 0; i < lArr.length; i++) { 3239 res += ((WrapperInterface)ObjectBox.box_sharp(lArr[i]).content).value(); 3240 } 3241 return res; 3242 } 3243 3244 @Run(test = "test110_sharp") 3245 @Warmup(10000) // Make sure interface calls are inlined 3246 public void test110_sharp_verifier() { 3247 long res = test110_sharp(); 3248 Asserts.assertEquals(res, 5*rL); 3249 } 3250 3251 // Same as test109 but with RefBox 3252 @Test 3253 @IR(failOn = {ALLOC_G, MEMBAR}, 3254 counts = {PREDICATE_TRAP, "= 1"}) 3255 public long test111() { 3256 long res = 0; 3257 for (int i = 0; i < lArr.length; i++) { 3258 res += RefBox.box(lArr[i]).content.value(); 3259 } 3260 return res; 3261 } 3262 3263 @Run(test = "test111") 3264 public void test111_verifier() { 3265 long res = test111(); 3266 Asserts.assertEquals(res, 5*rL); 3267 } 3268 3269 @Test 3270 @IR(failOn = {ALLOC_G, MEMBAR}, 3271 counts = {PREDICATE_TRAP, "= 1"}) 3272 public long test111_sharp() { 3273 long res = 0; 3274 for (int i = 0; i < lArr.length; i++) { 3275 res += RefBox.box_sharp(lArr[i]).content.value(); 3276 } 3277 return res; 3278 } 3279 3280 @Run(test = "test111_sharp") 3281 public void test111_sharp_verifier() { 3282 long res = test111_sharp(); 3283 Asserts.assertEquals(res, 5*rL); 3284 } 3285 3286 // Same as test109 but with InlineBox 3287 @Test 3288 @IR(failOn = {ALLOC_G, MEMBAR}, 3289 counts = {PREDICATE_TRAP, "= 1"}) 3290 public long test112() { 3291 long res = 0; 3292 for (int i = 0; i < lArr.length; i++) { 3293 res += InlineBox.box(lArr[i]).content.value(); 3294 } 3295 return res; 3296 } 3297 3298 @Run(test = "test112") 3299 public void test112_verifier() { 3300 long res = test112(); 3301 Asserts.assertEquals(res, 5*rL); 3302 } 3303 3304 // Same as test109 but with GenericBox 3305 @Test 3306 @IR(failOn = {ALLOC_G, MEMBAR}, 3307 counts = {PREDICATE_TRAP, "= 1"}) 3308 public long test113() { 3309 long res = 0; 3310 for (int i = 0; i < lArr.length; i++) { 3311 res += GenericBox.box(lArr[i]).content.value(); 3312 } 3313 return res; 3314 } 3315 3316 @Run(test = "test113") 3317 @Warmup(10000) // Make sure interface calls are inlined 3318 public void test113_verifier() { 3319 long res = test113(); 3320 Asserts.assertEquals(res, 5*rL); 3321 } 3322 3323 @Test 3324 @IR(failOn = {ALLOC_G, MEMBAR}, 3325 counts = {PREDICATE_TRAP, "= 1"}) 3326 public long test113_sharp() { 3327 long res = 0; 3328 for (int i = 0; i < lArr.length; i++) { 3329 res += GenericBox.box_sharp(lArr[i]).content.value(); 3330 } 3331 return res; 3332 } 3333 3334 @Run(test = "test113_sharp") 3335 @Warmup(10000) // Make sure interface calls are inlined 3336 public void test113_sharp_verifier() { 3337 long res = test113_sharp(); 3338 Asserts.assertEquals(res, 5*rL); 3339 } 3340 3341 static interface WrapperInterface2 { 3342 public long value(); 3343 3344 static final InlineWrapper ZERO = new InlineWrapper(0); 3345 3346 @ForceInline 3347 public static WrapperInterface2 wrap(long val) { 3348 return (val == 0) ? ZERO.content : new LongWrapper2(val); 3349 } 3350 3351 @ForceInline 3352 public static WrapperInterface2 wrap_dynamic(long val) { 3353 return (val == 0) ? new LongWrapper2(0) : new LongWrapper2(val); 3354 } 3355 } 3356 3357 @LooselyConsistentValue 3358 static value class LongWrapper2 implements WrapperInterface2 { 3359 private long val; 3360 3361 @ForceInline 3362 public LongWrapper2(long val) { 3363 this.val = val; 3364 } 3365 3366 @ForceInline 3367 public long value() { 3368 return val; 3369 } 3370 } 3371 3372 @LooselyConsistentValue 3373 static value class InlineWrapper { 3374 WrapperInterface2 content; 3375 3376 @ForceInline 3377 public InlineWrapper(long val) { 3378 content = new LongWrapper2(val); 3379 } 3380 } 3381 3382 static class InterfaceBox2 { 3383 WrapperInterface2 content; 3384 3385 @ForceInline 3386 public InterfaceBox2(long val, boolean def) { 3387 this.content = def ? WrapperInterface2.wrap_dynamic(val) : WrapperInterface2.wrap(val); 3388 } 3389 3390 @ForceInline 3391 static InterfaceBox2 box(long val) { 3392 return new InterfaceBox2(val, false); 3393 } 3394 3395 @ForceInline 3396 static InterfaceBox2 box_dynamic(long val) { 3397 return new InterfaceBox2(val, true); 3398 } 3399 } 3400 3401 // Same as tests above but with ZERO hidden in field of another inline type 3402 @Test 3403 @IR(failOn = {ALLOC_G, MEMBAR}, 3404 counts = {PREDICATE_TRAP, "= 1"}) 3405 public long test114() { 3406 long res = 0; 3407 for (int i = 0; i < lArr.length; i++) { 3408 res += InterfaceBox2.box(lArr[i]).content.value(); 3409 } 3410 return res; 3411 } 3412 3413 @Run(test = "test114") 3414 @Warmup(10000) 3415 public void test114_verifier() { 3416 long res = test114(); 3417 Asserts.assertEquals(res, 5*rL); 3418 } 3419 3420 // Same as test114 but with dynamic instead of constant ZERO field 3421 @Test 3422 @IR(failOn = {ALLOC_G, MEMBAR}, 3423 counts = {PREDICATE_TRAP, "= 1"}) 3424 public long test115() { 3425 long res = 0; 3426 for (int i = 0; i < lArr.length; i++) { 3427 res += InterfaceBox2.box_dynamic(lArr[i]).content.value(); 3428 } 3429 return res; 3430 } 3431 3432 @Run(test = "test115") 3433 @Warmup(10000) 3434 public void test115_verifier() { 3435 long res = test115(); 3436 Asserts.assertEquals(res, 5*rL); 3437 } 3438 3439 @Strict 3440 @NullRestricted 3441 static MyValueEmpty fEmpty1 = new MyValueEmpty(); 3442 static MyValueEmpty fEmpty2 = new MyValueEmpty(); 3443 @Strict 3444 @NullRestricted 3445 MyValueEmpty fEmpty3 = new MyValueEmpty(); 3446 MyValueEmpty fEmpty4 = new MyValueEmpty(); 3447 3448 // Test fields loads/stores with empty inline types 3449 @Test 3450 public void test116() { 3451 fEmpty1 = fEmpty4; 3452 fEmpty2 = fEmpty1; 3453 fEmpty3 = fEmpty2; 3454 fEmpty4 = fEmpty3; 3455 } 3456 3457 @Run(test = "test116") 3458 public void test116_verifier() { 3459 test116(); 3460 Asserts.assertEquals(fEmpty1, fEmpty2); 3461 Asserts.assertEquals(fEmpty2, fEmpty3); 3462 Asserts.assertEquals(fEmpty3, fEmpty4); 3463 } 3464 3465 // Test array loads/stores with empty inline types 3466 @Test 3467 public MyValueEmpty test117(MyValueEmpty[] arr1, MyValueEmpty[] arr2) { 3468 arr1[0] = arr2[0]; 3469 arr2[0] = new MyValueEmpty(); 3470 return arr1[0]; 3471 } 3472 3473 @Run(test = "test117") 3474 public void test117_verifier() { 3475 MyValueEmpty[] arr1 = new MyValueEmpty[] { new MyValueEmpty() }; 3476 MyValueEmpty res = test117(arr1, arr1); 3477 Asserts.assertEquals(res, new MyValueEmpty()); 3478 Asserts.assertEquals(arr1[0], new MyValueEmpty()); 3479 } 3480 3481 // Test acmp with empty inline types 3482 @Test 3483 public boolean test118(MyValueEmpty v1, MyValueEmpty v2, Object o1) { 3484 return (v1 == v2) && (v2 == o1); 3485 } 3486 3487 @Run(test = "test118") 3488 public void test118_verifier() { 3489 boolean res = test118(new MyValueEmpty(), new MyValueEmpty(), new MyValueEmpty()); 3490 Asserts.assertTrue(res); 3491 } 3492 3493 @LooselyConsistentValue 3494 static value class EmptyContainer { 3495 @Strict 3496 @NullRestricted 3497 private MyValueEmpty empty = new MyValueEmpty(); 3498 } 3499 3500 @LooselyConsistentValue 3501 static value class MixedContainer { 3502 public int val = 0; 3503 @Strict 3504 @NullRestricted 3505 private EmptyContainer empty = new EmptyContainer(); 3506 } 3507 3508 @Strict 3509 @NullRestricted 3510 static final MyValueEmpty empty = new MyValueEmpty(); 3511 3512 @Strict 3513 @NullRestricted 3514 static final EmptyContainer emptyC = new EmptyContainer(); 3515 3516 @Strict 3517 @NullRestricted 3518 static final MixedContainer mixedContainer = new MixedContainer(); 3519 3520 // Test re-allocation of empty inline type array during deoptimization 3521 @Test 3522 public void test119(boolean deopt, Method m) { 3523 MyValueEmpty[] array1 = new MyValueEmpty[] { empty }; 3524 EmptyContainer[] array2 = (EmptyContainer[])ValueClass.newNullRestrictedNonAtomicArray(EmptyContainer.class, 1, emptyC); 3525 array2[0] = emptyC; 3526 MixedContainer[] array3 = (MixedContainer[])ValueClass.newNullRestrictedNonAtomicArray(MixedContainer.class, 1, mixedContainer); 3527 array3[0] = mixedContainer; 3528 if (deopt) { 3529 // uncommon trap 3530 TestFramework.deoptimize(m); 3531 } 3532 Asserts.assertEquals(array1[0], empty); 3533 Asserts.assertEquals(array2[0], emptyC); 3534 Asserts.assertEquals(array3[0], mixedContainer); 3535 } 3536 3537 @Run(test = "test119") 3538 public void test119_verifier(RunInfo info) { 3539 test119(!info.isWarmUp(), info.getTest()); 3540 } 3541 3542 // Test optimization of empty inline type field stores 3543 @Test 3544 @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP}) 3545 public void test120() { 3546 fEmpty1 = empty; 3547 fEmpty3 = empty; 3548 // fEmpty2 and fEmpty4 could be null, store can't be removed 3549 } 3550 3551 @Run(test = "test120") 3552 public void test120_verifier() { 3553 test120(); 3554 Asserts.assertEquals(fEmpty1, empty); 3555 } 3556 3557 // Test removal of empty inline type field loads 3558 @Test 3559 @IR(failOn = {LOAD, STORE, FIELD_ACCESS, NULL_CHECK_TRAP, TRAP}) 3560 public boolean test121() { 3561 return fEmpty1.equals(fEmpty3); 3562 // fEmpty2 and fEmpty4 could be null, load can't be removed 3563 } 3564 3565 @Run(test = "test121") 3566 public void test121_verifier() { 3567 boolean res = test121(); 3568 Asserts.assertTrue(res); 3569 } 3570 3571 // Verify that empty inline type field loads check for null holder 3572 @Test 3573 @IR(applyIf = {"InlineTypeReturnedAsFields", "true"}, 3574 failOn = {ALLOC_G}) 3575 public MyValueEmpty test122(TestLWorld t) { 3576 return t.fEmpty3; 3577 } 3578 3579 @Run(test = "test122") 3580 public void test122_verifier() { 3581 MyValueEmpty res = test122(this); 3582 Asserts.assertEquals(res, new MyValueEmpty()); 3583 try { 3584 test122(null); 3585 throw new RuntimeException("No NPE thrown"); 3586 } catch (NullPointerException e) { 3587 // Expected 3588 } 3589 } 3590 3591 // Verify that empty inline type field stores check for null holder 3592 @Test 3593 @IR(failOn = {ALLOC_G}) 3594 public void test123(TestLWorld t) { 3595 t.fEmpty3 = new MyValueEmpty(); 3596 } 3597 3598 @Run(test = "test123") 3599 public void test123_verifier() { 3600 test123(this); 3601 Asserts.assertEquals(fEmpty3, new MyValueEmpty()); 3602 try { 3603 test123(null); 3604 throw new RuntimeException("No NPE thrown"); 3605 } catch (NullPointerException e) { 3606 // Expected 3607 } 3608 } 3609 3610 // acmp doesn't need substitutability test when one input is known 3611 // not to be a value type 3612 @Test 3613 @IR(failOn = SUBSTITUTABILITY_TEST) 3614 public boolean test124(NonValueClass o1, Object o2) { 3615 return o1 == o2; 3616 } 3617 3618 @Run(test = "test124") 3619 public void test124_verifier() { 3620 NonValueClass obj = new NonValueClass(rI); 3621 test124(obj, obj); 3622 test124(obj, testValue1); 3623 } 3624 3625 // acmp doesn't need substitutability test when one input is null 3626 @Test 3627 @IR(failOn = {SUBSTITUTABILITY_TEST}) 3628 public boolean test125(Object o1) { 3629 Object o2 = null; 3630 return o1 == o2; 3631 } 3632 3633 @Run(test = "test125") 3634 public void test125_verifier() { 3635 test125(testValue1); 3636 test125(null); 3637 } 3638 3639 // Test inline type that can only be scalarized after loop opts 3640 @Test 3641 @IR(failOn = {ALLOC_G, LOAD, STORE}) 3642 public long test126(boolean trap) { 3643 MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD); 3644 MyValue2 val = null; 3645 3646 for (int i = 0; i < 4; i++) { 3647 if ((i % 2) == 0) { 3648 val = nonNull; 3649 } 3650 } 3651 // 'val' is always non-null here but that's only known after loop opts 3652 if (trap) { 3653 // Uncommon trap with an inline input that can only be scalarized after loop opts 3654 return val.hash(); 3655 } 3656 return 0; 3657 } 3658 3659 @Run(test = "test126") 3660 @Warmup(10000) 3661 public void test126_verifier(RunInfo info) { 3662 long res = test126(false); 3663 Asserts.assertEquals(res, 0L); 3664 if (!info.isWarmUp()) { 3665 res = test126(true); 3666 Asserts.assertEquals(res, testValue2.hash()); 3667 } 3668 } 3669 3670 // Same as test126 but with interface type 3671 @Test 3672 @IR(failOn = {ALLOC_G, LOAD, STORE}) 3673 public long test127(boolean trap) { 3674 MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD); 3675 MyInterface val = null; 3676 3677 for (int i = 0; i < 4; i++) { 3678 if ((i % 2) == 0) { 3679 val = nonNull; 3680 } 3681 } 3682 // 'val' is always non-null here but that's only known after loop opts 3683 if (trap) { 3684 // Uncommon trap with an inline input that can only be scalarized after loop opts 3685 return val.hash(); 3686 } 3687 return 0; 3688 } 3689 3690 @Run(test = "test127") 3691 @Warmup(10000) 3692 public void test127_verifier(RunInfo info) { 3693 long res = test127(false); 3694 Asserts.assertEquals(res, 0L); 3695 if (!info.isWarmUp()) { 3696 res = test127(true); 3697 Asserts.assertEquals(res, testValue2.hash()); 3698 } 3699 } 3700 3701 // Test inline type that can only be scalarized after CCP 3702 @Test 3703 @IR(failOn = {ALLOC_G, LOAD, STORE}) 3704 public long test128(boolean trap) { 3705 MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD); 3706 MyValue2 val = null; 3707 3708 int limit = 2; 3709 for (; limit < 4; limit *= 2); 3710 for (int i = 2; i < limit; i++) { 3711 val = nonNull; 3712 } 3713 // 'val' is always non-null here but that's only known after CCP 3714 if (trap) { 3715 // Uncommon trap with an inline input that can only be scalarized after CCP 3716 return val.hash(); 3717 } 3718 return 0; 3719 } 3720 3721 @Run(test = "test128") 3722 @Warmup(10000) 3723 public void test128_verifier(RunInfo info) { 3724 long res = test128(false); 3725 Asserts.assertEquals(res, 0L); 3726 if (!info.isWarmUp()) { 3727 res = test128(true); 3728 Asserts.assertEquals(res, testValue2.hash()); 3729 } 3730 } 3731 3732 // Same as test128 but with interface type 3733 @Test 3734 @IR(failOn = {ALLOC_G, LOAD, STORE}) 3735 public long test129(boolean trap) { 3736 MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD); 3737 MyInterface val = null; 3738 3739 int limit = 2; 3740 for (; limit < 4; limit *= 2); 3741 for (int i = 0; i < limit; i++) { 3742 val = nonNull; 3743 } 3744 // 'val' is always non-null here but that's only known after CCP 3745 if (trap) { 3746 // Uncommon trap with an inline input that can only be scalarized after CCP 3747 return val.hash(); 3748 } 3749 return 0; 3750 } 3751 3752 @Run(test = "test129") 3753 @Warmup(10000) 3754 public void test129_verifier(RunInfo info) { 3755 long res = test129(false); 3756 Asserts.assertEquals(res, 0L); 3757 if (!info.isWarmUp()) { 3758 res = test129(true); 3759 Asserts.assertEquals(res, testValue2.hash()); 3760 } 3761 } 3762 3763 // Lock on inline type (known after inlining) 3764 @ForceInline 3765 public Object test130_inlinee() { 3766 return MyValue1.createWithFieldsInline(rI, rL); 3767 } 3768 3769 @Test 3770 @IR(failOn = {LOAD}, 3771 // LockNode keeps MyValue1 allocation alive up until macro expansion which in turn keeps MyValue2 3772 // alloc alive. Although the MyValue1 allocation is removed (unused), MyValue2 is expanded first 3773 // and therefore stays. 3774 counts = {ALLOC, "<= 1", STORE, "<= 1"}) 3775 public void test130() { 3776 Object obj = test130_inlinee(); 3777 synchronized (obj) { 3778 throw new RuntimeException("test130 failed: synchronization on inline type should not succeed"); 3779 } 3780 } 3781 3782 @Run(test = "test130") 3783 public void test130_verifier() { 3784 try { 3785 test130(); 3786 throw new RuntimeException("test130 failed: no exception thrown"); 3787 } catch (IdentityException ex) { 3788 // Expected 3789 } 3790 } 3791 3792 // Same as test130 but with field load instead of allocation 3793 @ForceInline 3794 public Object test131_inlinee() { 3795 return testValue1; 3796 } 3797 3798 @Test 3799 @IR(failOn = {ALLOC_G}) 3800 public void test131() { 3801 Object obj = test131_inlinee(); 3802 synchronized (obj) { 3803 throw new RuntimeException("test131 failed: synchronization on inline type should not succeed"); 3804 } 3805 } 3806 3807 @Run(test = "test131") 3808 public void test131_verifier() { 3809 try { 3810 test131(); 3811 throw new RuntimeException("test131 failed: no exception thrown"); 3812 } catch (IdentityException ex) { 3813 // Expected 3814 } 3815 } 3816 3817 // Test locking on object that is known to be an inline type only after CCP 3818 @Test 3819 @IR(failOn = {ALLOC, LOAD, STORE}) 3820 public void test132() { 3821 MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD); 3822 Object obj = new NonValueClass(42); 3823 3824 int limit = 2; 3825 for (; limit < 4; limit *= 2); 3826 for (int i = 2; i < limit; i++) { 3827 obj = vt; 3828 } 3829 synchronized (obj) { 3830 throw new RuntimeException("test132 failed: synchronization on inline type should not succeed"); 3831 } 3832 } 3833 3834 @Run(test = "test132") 3835 @Warmup(10000) 3836 public void test132_verifier() { 3837 try { 3838 test132(); 3839 throw new RuntimeException("test132 failed: no exception thrown"); 3840 } catch (IdentityException ex) { 3841 // Expected 3842 } 3843 } 3844 3845 // Test conditional locking on inline type and non-escaping object 3846 @Test 3847 public void test133(boolean b) { 3848 Object obj = b ? new NonValueClass(rI) : MyValue2.createWithFieldsInline(rI, rD); 3849 synchronized (obj) { 3850 if (!b) { 3851 throw new RuntimeException("test133 failed: synchronization on inline type should not succeed"); 3852 } 3853 } 3854 } 3855 3856 @Run(test = "test133") 3857 public void test133_verifier() { 3858 test133(true); 3859 try { 3860 test133(false); 3861 throw new RuntimeException("test133 failed: no exception thrown"); 3862 } catch (IdentityException ex) { 3863 // Expected 3864 } 3865 } 3866 3867 // Variant with non-scalarized inline type 3868 @Test 3869 @IR(failOn = {ALLOC_G}) 3870 public void test134(boolean b) { 3871 Object obj = null; 3872 if (b) { 3873 obj = MyValue2.createWithFieldsInline(rI, rD); 3874 } 3875 synchronized (obj) { 3876 3877 } 3878 } 3879 3880 @Run(test = "test134") 3881 public void test134_verifier() { 3882 try { 3883 test134(true); 3884 throw new RuntimeException("test134 failed: no exception thrown"); 3885 } catch (IdentityException ex) { 3886 // Expected 3887 } 3888 } 3889 3890 // Test that acmp of the same inline object is removed 3891 @Test 3892 @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP}) 3893 public boolean test135() { 3894 MyValue1 val = MyValue1.createWithFieldsInline(rI, rL); 3895 return val == val; 3896 } 3897 3898 @Run(test = "test135") 3899 public void test135_verifier() { 3900 Asserts.assertTrue(test135()); 3901 } 3902 3903 // Same as test135 but with null 3904 @Test 3905 @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP}) 3906 public boolean test136(boolean b) { 3907 MyValue1 val = MyValue1.createWithFieldsInline(rI, rL); 3908 if (b) { 3909 val = null; 3910 } 3911 return val == val; 3912 } 3913 3914 @Run(test = "test136") 3915 public void test136_verifier() { 3916 Asserts.assertTrue(test136(false)); 3917 Asserts.assertTrue(test136(true)); 3918 } 3919 3920 // Test that acmp of different inline objects with same content is removed 3921 @Test 3922 // TODO 8228361 3923 // @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP}) 3924 public boolean test137(int i) { 3925 MyValue2 val1 = MyValue2.createWithFieldsInline(i, rD); 3926 MyValue2 val2 = MyValue2.createWithFieldsInline(i, rD); 3927 return val1 == val2; 3928 } 3929 3930 @Run(test = "test137") 3931 public void test137_verifier() { 3932 Asserts.assertTrue(test137(rI)); 3933 } 3934 3935 // Same as test137 but with null 3936 @Test 3937 // TODO 8228361 3938 // @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP}) 3939 public boolean test138(int i, boolean b) { 3940 MyValue2 val1 = MyValue2.createWithFieldsInline(i, rD); 3941 MyValue2 val2 = MyValue2.createWithFieldsInline(i, rD); 3942 if (b) { 3943 val1 = null; 3944 val2 = null; 3945 } 3946 return val1 == val2; 3947 } 3948 3949 @Run(test = "test138") 3950 public void test138_verifier() { 3951 Asserts.assertTrue(test138(rI, false)); 3952 Asserts.assertTrue(test138(rI, true)); 3953 } 3954 3955 @LooselyConsistentValue 3956 static value class Test139Value { 3957 Object obj = null; 3958 @Strict 3959 @NullRestricted 3960 MyValueEmpty empty = new MyValueEmpty(); 3961 } 3962 3963 @LooselyConsistentValue 3964 static value class Test139Wrapper { 3965 @Strict 3966 @NullRestricted 3967 Test139Value value = new Test139Value(); 3968 } 3969 3970 @Test 3971 @IR(applyIf = {"InlineTypeReturnedAsFields", "true"}, 3972 failOn = {ALLOC_G}) 3973 @IR(failOn = {LOAD, STORE, TRAP}) 3974 public MyValueEmpty test139() { 3975 Test139Wrapper w = new Test139Wrapper(); 3976 return w.value.empty; 3977 } 3978 3979 @Run(test = "test139") 3980 public void test139_verifier() { 3981 MyValueEmpty empty = test139(); 3982 Asserts.assertEquals(empty, new MyValueEmpty()); 3983 } 3984 3985 // Test calling a method on a loaded but not linked inline type 3986 @LooselyConsistentValue 3987 value class Test140Value { 3988 int x = 0; 3989 3990 public int get() { 3991 return x; 3992 } 3993 } 3994 3995 @Test 3996 @IR(failOn = {ALLOC_G}) 3997 public int test140() { 3998 Test140Value vt = new Test140Value(); 3999 return vt.get(); 4000 } 4001 4002 @Run(test = "test140") 4003 @Warmup(0) 4004 public void test140_verifier() { 4005 int result = test140(); 4006 Asserts.assertEquals(result, 0); 4007 } 4008 4009 // Test calling a method on a linked but not initialized inline type 4010 @LooselyConsistentValue 4011 value class Test141Value { 4012 int x = 0; 4013 4014 public int get() { 4015 return x; 4016 } 4017 } 4018 4019 @Test 4020 @IR(failOn = {ALLOC_G}) 4021 public int test141() { 4022 Test141Value vt = new Test141Value(); 4023 return vt.get(); 4024 } 4025 4026 @Run(test = "test141") 4027 @Warmup(0) 4028 public void test141_verifier() { 4029 int result = test141(); 4030 Asserts.assertEquals(result, 0); 4031 } 4032 4033 // Test that virtual calls on inline type receivers are properly inlined 4034 @Test 4035 @IR(failOn = {ALLOC_G, LOAD, STORE}) 4036 public long test142() { 4037 MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD); 4038 MyInterface val = null; 4039 4040 for (int i = 0; i < 4; i++) { 4041 if ((i % 2) == 0) { 4042 val = nonNull; 4043 } 4044 } 4045 return val.hash(); 4046 } 4047 4048 @Run(test = "test142") 4049 public void test142_verifier() { 4050 long res = test142(); 4051 Asserts.assertEquals(res, testValue2.hash()); 4052 } 4053 4054 // Test merging of buffered inline types 4055 @Test 4056 public Object test144(int i) { 4057 if (i == 0) { 4058 return MyValue1.createDefaultInline(); 4059 } else if (i == 1) { 4060 return testValue1; 4061 } else { 4062 return MyValue1.createDefaultInline(); 4063 } 4064 } 4065 4066 @Run(test = "test144") 4067 public void test144_verifier() { 4068 Asserts.assertEquals(test144(0), MyValue1.createDefaultInline()); 4069 Asserts.assertEquals(test144(1), testValue1); 4070 Asserts.assertEquals(test144(2), MyValue1.createDefaultInline()); 4071 } 4072 4073 // Tests writing an array element with a (statically known) incompatible type 4074 private static final MethodHandle setArrayElementIncompatibleRef = InstructionHelper.buildMethodHandle(MethodHandles.lookup(), 4075 "setArrayElementIncompatibleRef", 4076 MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class, MyValue2.class), 4077 CODE -> { 4078 CODE. 4079 aload(1). 4080 iload(2). 4081 aload(3). 4082 aastore(). 4083 return_(); 4084 }); 4085 4086 // Test inline type connected to result node 4087 @Test 4088 @IR(failOn = {ALLOC_G}) 4089 public MyValue1 test146(Object obj) { 4090 return (MyValue1)obj; 4091 } 4092 4093 @Run(test = "test146") 4094 @Warmup(10000) 4095 public void test146_verifier() { 4096 Asserts.assertEQ(test146(testValue1), testValue1); 4097 } 4098 4099 @ForceInline 4100 public Object test148_helper(Object obj) { 4101 return (MyValue1)obj; 4102 } 4103 4104 // Same as test146 but with helper method 4105 @Test 4106 public Object test148(Object obj) { 4107 return test148_helper(obj); 4108 } 4109 4110 @Run(test = "test148") 4111 @Warmup(10000) 4112 public void test148_verifier() { 4113 Asserts.assertEQ(test148(testValue1), testValue1); 4114 } 4115 4116 @ForceInline 4117 public Object test149_helper(Object obj) { 4118 return (MyValue1)obj; 4119 } 4120 4121 // Same as test147 but with helper method 4122 @Test 4123 public Object test149(Object obj) { 4124 return test149_helper(obj); 4125 } 4126 4127 @Run(test = "test149") 4128 @Warmup(10000) 4129 public void test149_verifier() { 4130 Asserts.assertEQ(test149(testValue1), testValue1); 4131 Asserts.assertEQ(test149(null), null); 4132 } 4133 4134 // Test post-parse call devirtualization with inline type receiver 4135 @Test 4136 @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"}, 4137 failOn = {ALLOC}) 4138 @IR(failOn = {compiler.lib.ir_framework.IRNode.DYNAMIC_CALL_OF_METHOD, "MyValue2::hash"}, 4139 counts = {compiler.lib.ir_framework.IRNode.STATIC_CALL_OF_METHOD, "MyValue2::hash", "= 1"}) 4140 public long test150() { 4141 MyValue2 val = MyValue2.createWithFieldsInline(rI, rD); 4142 MyInterface receiver = MyValue1.createWithFieldsInline(rI, rL); 4143 4144 for (int i = 0; i < 4; i++) { 4145 if ((i % 2) == 0) { 4146 receiver = val; 4147 } 4148 } 4149 // Trigger post parse call devirtualization (strength-reducing 4150 // virtual calls to direct calls). 4151 return receiver.hash(); 4152 } 4153 4154 @Run(test = "test150") 4155 public void test150_verifier() { 4156 Asserts.assertEquals(test150(), testValue2.hash()); 4157 } 4158 4159 // TODO 8336003 This triggers # assert(false) failed: Should have been buffered 4160 /* 4161 // Same as test150 but with val not being allocated in the scope of the method 4162 @Test 4163 @IR(failOn = {compiler.lib.ir_framework.IRNode.DYNAMIC_CALL_OF_METHOD, "MyValue2::hash"}, 4164 counts = {compiler.lib.ir_framework.IRNode.STATIC_CALL_OF_METHOD, "MyValue2::hash", "= 1"}) 4165 public long test151(MyValue2 val) { 4166 MyAbstract receiver = MyValue1.createWithFieldsInline(rI, rL); 4167 4168 for (int i = 0; i < 100; i++) { 4169 if ((i % 2) == 0) { 4170 receiver = val; 4171 } 4172 } 4173 // Trigger post parse call devirtualization (strength-reducing 4174 // virtual calls to direct calls). 4175 return receiver.hash(); 4176 } 4177 4178 @Run(test = "test151") 4179 @Warmup(0) // Make sure there is no receiver type profile 4180 public void test151_verifier() { 4181 Asserts.assertEquals(test151(testValue2), testValue2.hash()); 4182 } 4183 */ 4184 4185 static interface MyInterface2 { 4186 public int val(); 4187 } 4188 4189 static abstract value class MyAbstract2 implements MyInterface2 { 4190 4191 } 4192 4193 static class MyClass152 extends MyAbstract2 { 4194 private int val; 4195 4196 @ForceInline 4197 public MyClass152(int val) { 4198 this.val = val; 4199 } 4200 4201 @Override 4202 public int val() { 4203 return val; 4204 } 4205 } 4206 4207 @LooselyConsistentValue 4208 static value class MyValue152 extends MyAbstract2 { 4209 private int unused = 0; // Make sure sub-offset of val is field non-zero 4210 private int val; 4211 4212 @ForceInline 4213 public MyValue152(int val) { 4214 this.val = val; 4215 } 4216 4217 @Override 4218 public int val() { 4219 return val; 4220 } 4221 } 4222 4223 @LooselyConsistentValue 4224 static value class MyWrapper152 { 4225 private int unused = 0; // Make sure sub-offset of val field is non-zero 4226 @Strict 4227 @NullRestricted 4228 MyValue152 val; 4229 4230 @ForceInline 4231 public MyWrapper152(MyInterface2 val) { 4232 this.val = (MyValue152)val; 4233 } 4234 } 4235 4236 // Test that checkcast with speculative type does not break scalarization in return 4237 @Test 4238 public MyWrapper152 test152(MyInterface2 val) { 4239 return new MyWrapper152(val); 4240 } 4241 4242 @Run(test = "test152") 4243 @Warmup(10000) // Make sure profile information is available at cast 4244 public void test152_verifier() { 4245 MyClass152 unused = new MyClass152(rI); 4246 MyValue152 val = new MyValue152(rI); 4247 Asserts.assertEquals(test152(val).val, val); 4248 } 4249 4250 @DontInline 4251 static void test153_helper(MyWrapper152 arg) { 4252 4253 } 4254 4255 // Test that checkcast with speculative type does not prevent scalarization in args 4256 @Test 4257 public void test153(MyInterface2 val) { 4258 test153_helper(new MyWrapper152(val)); 4259 } 4260 4261 @Run(test = "test153") 4262 @Warmup(10000) // Make sure profile information is available at cast 4263 public void test153_verifier() { 4264 MyClass152 unused = new MyClass152(rI); 4265 MyValue152 val = new MyValue152(rI); 4266 test153(val); 4267 } 4268 4269 // Test that checkcast with speculative type enables scalarization 4270 @Test 4271 @IR(failOn = {ALLOC_G, STORE}) 4272 public int test154(Method m, MyInterface2 val, boolean b1, boolean b2) { 4273 MyInterface2 obj = new MyValue152(rI); 4274 if (b1) { 4275 // Speculative cast to MyValue152 enables scalarization 4276 obj = (MyAbstract2)val; 4277 } 4278 if (b2) { 4279 // Uncommon trap 4280 TestFramework.deoptimize(m); 4281 return obj.val(); 4282 } 4283 return -1; 4284 } 4285 4286 @Run(test = "test154") 4287 @Warmup(10000) // Make sure profile information is available at cast 4288 public void test154_verifier(RunInfo info) { 4289 MyClass152 unused = new MyClass152(rI); 4290 MyValue152 val = new MyValue152(rI); 4291 Asserts.assertEquals(test154(info.getTest(), val, false, false), -1); 4292 Asserts.assertEquals(test154(info.getTest(), val, true, false), -1); 4293 if (!info.isWarmUp()) { 4294 Asserts.assertEquals(test154(info.getTest(), val, false, true), rI); 4295 } 4296 } 4297 4298 // Same as test154 but with null val 4299 @Test 4300 @IR(failOn = {ALLOC_G, STORE}) 4301 public int test155(Method m, MyInterface2 val, boolean b1, boolean b2) { 4302 MyInterface2 obj = new MyValue152(rI); 4303 if (b1) { 4304 // Speculative cast to MyValue152 enables scalarization 4305 obj = (MyAbstract2)val; 4306 } 4307 if (b2) { 4308 // Uncommon trap 4309 TestFramework.deoptimize(m); 4310 return obj.val(); 4311 } 4312 return -1; 4313 } 4314 4315 @Run(test = "test155") 4316 @Warmup(10000) // Make sure profile information is available at cast 4317 public void test155_verifier(RunInfo info) { 4318 MyClass152 unused = new MyClass152(rI); 4319 MyValue152 val = new MyValue152(rI); 4320 Asserts.assertEquals(test155(info.getTest(), val, false, false), -1); 4321 Asserts.assertEquals(test155(info.getTest(), val, true, false), -1); 4322 Asserts.assertEquals(test155(info.getTest(), null, true, false), -1); 4323 if (!info.isWarmUp()) { 4324 Asserts.assertEquals(test155(info.getTest(), val, false, true), rI); 4325 } 4326 } 4327 4328 @Strict 4329 @NullRestricted 4330 final static MyValue1 test157Cache = MyValue1.createWithFieldsInline(rI, 0); 4331 4332 // Test merging buffered inline type from field load with non-buffered inline type 4333 @Test 4334 public MyValue1 test157(long val) { 4335 return (val == 0L) ? test157Cache : MyValue1.createWithFieldsInline(rI, val); 4336 } 4337 4338 @Run(test = "test157") 4339 public void test157_verifier() { 4340 Asserts.assertEquals(test157(0), test157Cache); 4341 Asserts.assertEquals(test157(rL).hash(), testValue1.hash()); 4342 } 4343 4344 @Strict 4345 @NullRestricted 4346 static MyValue1 test158Cache = MyValue1.createWithFieldsInline(rI, 0); 4347 4348 // Same as test157 but with non-final field load 4349 @Test 4350 public MyValue1 test158(long val) { 4351 return (val == 0L) ? test158Cache : MyValue1.createWithFieldsInline(rI, val); 4352 } 4353 4354 @Run(test = "test158") 4355 public void test158_verifier() { 4356 Asserts.assertEquals(test158(0), test158Cache); 4357 Asserts.assertEquals(test158(rL).hash(), testValue1.hash()); 4358 } 4359 4360 // Verify that cast that with incompatible types is properly handled 4361 @Test 4362 public void test160(NonValueClass arg) { 4363 Object tmp = arg; 4364 MyValue1 res = (MyValue1)tmp; 4365 } 4366 4367 @Run(test = "test160") 4368 @Warmup(10000) 4369 public void test160_verifier(RunInfo info) { 4370 try { 4371 test160(new NonValueClass(42)); 4372 throw new RuntimeException("No CCE thrown"); 4373 } catch (ClassCastException e) { 4374 // Expected 4375 } 4376 test160(null); 4377 } 4378 4379 abstract value static class AbstractValueClassSingleSubclass { 4380 } 4381 4382 value static class UniqueValueSubClass extends AbstractValueClassSingleSubclass { 4383 int x = 34; 4384 } 4385 4386 static AbstractValueClassSingleSubclass abstractValueClassSingleSubclass = new UniqueValueSubClass(); 4387 4388 @Test 4389 public void testUniqueConcreteValueSubKlass(boolean flag) { 4390 // C2 should recognize that even though we do not know the exact layout of the underlying inline type of the 4391 // abstract field abstractValueClassSingleSubclass (i.e. cannot scalarize), we only have a unique concrete sub 4392 // class from which we know at compile time whether it can be scalarized or not. This unique sub class 4393 // optimization was missing, resulting in a missing InlineTypeNode assertion failure. 4394 doNothing(abstractValueClassSingleSubclass, flag ? 23 : 34); 4395 } 4396 4397 void doNothing(Object a, int i) {} 4398 4399 @Run(test = "testUniqueConcreteValueSubKlass") 4400 public void testUniqueConcreteValueSubKlass_verifier() { 4401 testUniqueConcreteValueSubKlass(true); 4402 } 4403 4404 static value class MyValueContainer { 4405 private final Object value; 4406 4407 private MyValueContainer(Object value) { 4408 this.value = value; 4409 } 4410 } 4411 4412 static value class MyValue161 { 4413 int x = 0; 4414 } 4415 4416 // Test merging value classes with Object fields 4417 @Test 4418 public MyValueContainer test161(boolean b) { 4419 MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : null; 4420 // Cast to verify that merged values are of correct type 4421 Object obj = b ? (MyValue161)res.value : null; 4422 return res; 4423 } 4424 4425 @Run(test = "test161") 4426 public void test161_verifier() { 4427 Asserts.assertEquals(test161(true), new MyValueContainer(new MyValue161())); 4428 Asserts.assertEquals(test161(false), null); 4429 } 4430 4431 @Test 4432 public MyValueContainer test162(boolean b) { 4433 MyValueContainer res = b ? null : new MyValueContainer(new MyValue161()); 4434 // Cast to verify that merged values are of correct type 4435 Object obj = b ? null : (MyValue161)res.value; 4436 return res; 4437 } 4438 4439 @Run(test = "test162") 4440 public void test162_verifier() { 4441 Asserts.assertEquals(test162(true), null); 4442 Asserts.assertEquals(test162(false), new MyValueContainer(new MyValue161())); 4443 } 4444 4445 @Test 4446 public MyValueContainer test163(boolean b) { 4447 MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : new MyValueContainer(null); 4448 // Cast to verify that merged values are of correct type 4449 Object obj = b ? (MyValue161)res.value : (MyValue161)res.value; 4450 return res; 4451 } 4452 4453 @Run(test = "test163") 4454 public void test163_verifier() { 4455 Asserts.assertEquals(test163(true), new MyValueContainer(new MyValue161())); 4456 Asserts.assertEquals(test163(false), new MyValueContainer(null)); 4457 } 4458 4459 @Test 4460 public MyValueContainer test164(boolean b) { 4461 MyValueContainer res = b ? new MyValueContainer(null) : new MyValueContainer(new MyValue161()); 4462 // Cast to verify that merged values are of correct type 4463 Object obj = b ? (MyValue161)res.value : (MyValue161)res.value; 4464 return res; 4465 } 4466 4467 @Run(test = "test164") 4468 public void test164_verifier() { 4469 Asserts.assertEquals(test164(true), new MyValueContainer(null)); 4470 Asserts.assertEquals(test164(false), new MyValueContainer(new MyValue161())); 4471 } 4472 4473 @Test 4474 public MyValueContainer test165(boolean b) { 4475 MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : new MyValueContainer(42); 4476 // Cast to verify that merged values are of correct type 4477 Object obj = b ? (MyValue161)res.value : (Integer)res.value; 4478 return res; 4479 } 4480 4481 @Run(test = "test165") 4482 public void test165_verifier() { 4483 Asserts.assertEquals(test165(true), new MyValueContainer(new MyValue161())); 4484 Asserts.assertEquals(test165(false), new MyValueContainer(42)); 4485 } 4486 4487 @Test 4488 public MyValueContainer test166(boolean b) { 4489 MyValueContainer res = b ? new MyValueContainer(42) : new MyValueContainer(new MyValue161()); 4490 // Cast to verify that merged values are of correct type 4491 Object obj = b ? (Integer)res.value : (MyValue161)res.value; 4492 return res; 4493 } 4494 4495 @Run(test = "test166") 4496 public void test166_verifier() { 4497 Asserts.assertEquals(test166(true), new MyValueContainer(42)); 4498 Asserts.assertEquals(test166(false), new MyValueContainer(new MyValue161())); 4499 } 4500 4501 // Verify that monitor information in JVMState is correct at method exit 4502 @Test 4503 public synchronized Object test167() { 4504 return MyValue1.createWithFieldsInline(rI, rL); // Might trigger buffering which requires JVMState 4505 } 4506 4507 @Run(test = "test167") 4508 public void test167_verifier() { 4509 Asserts.assertEquals(((MyValue1)test167()).hash(), hash()); 4510 } 4511 4512 @LooselyConsistentValue 4513 static value class ValueClassWithInt { 4514 int i; 4515 4516 ValueClassWithInt(int i) { 4517 this.i = i; 4518 } 4519 } 4520 4521 @LooselyConsistentValue 4522 static value class ValueClassWithDouble { 4523 double d; 4524 4525 ValueClassWithDouble(double d) { 4526 this.d = d; 4527 } 4528 } 4529 4530 @LooselyConsistentValue 4531 static abstract value class AbstractValueClassWithByte { 4532 byte b; 4533 4534 AbstractValueClassWithByte(byte b) { 4535 this.b = b; 4536 } 4537 } 4538 4539 @LooselyConsistentValue 4540 static value class SubValueClassWithInt extends AbstractValueClassWithByte { 4541 int i; 4542 4543 SubValueClassWithInt(int i) { 4544 this.i = i; 4545 super((byte)(i + 1)); 4546 } 4547 } 4548 4549 @LooselyConsistentValue 4550 static value class SubValueClassWithDouble extends AbstractValueClassWithByte { 4551 double d; 4552 4553 SubValueClassWithDouble(double d) { 4554 this.d = d; 4555 super((byte)(d + 1)); 4556 } 4557 } 4558 4559 // TODO 8350865 We need more copies of these tests for all ValueClass array factories 4560 static final ValueClassWithInt[] VALUE_CLASS_WITH_INT_ARRAY = (ValueClassWithInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueClassWithInt.class, 2, new ValueClassWithInt(0)); 4561 static final ValueClassWithDouble[] VALUE_CLASS_WITH_DOUBLE_ARRAY = (ValueClassWithDouble[]) ValueClass.newNullRestrictedNonAtomicArray(ValueClassWithDouble.class, 2, new ValueClassWithDouble(0)); 4562 static final SubValueClassWithInt[] SUB_VALUE_CLASS_WITH_INT_ARRAY = (SubValueClassWithInt[]) ValueClass.newNullRestrictedNonAtomicArray(SubValueClassWithInt.class, 2, new SubValueClassWithInt(0)); 4563 static final SubValueClassWithDouble[] SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY = (SubValueClassWithDouble[]) ValueClass.newNullRestrictedNonAtomicArray(SubValueClassWithDouble.class, 2, new SubValueClassWithDouble(0)); 4564 4565 // TODO: Can only be enabled once JDK-8343835 is fixed. Otherwise, we hit the mismatched stores assert. 4566 // static { 4567 // VALUE_CLASS_WITH_INT_ARRAY[0] = new ValueClassWithInt(5); 4568 // VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new ValueClassWithDouble(6); 4569 // SUB_VALUE_CLASS_WITH_INT_ARRAY[0] = new SubValueClassWithInt(7); 4570 // SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new SubValueClassWithDouble(8); 4571 // } 4572 4573 @Test 4574 static void testFlatArrayInexactObjectStore(Object o, boolean flag) { 4575 Object[] oArr; 4576 if (flag) { 4577 oArr = VALUE_CLASS_WITH_INT_ARRAY; // VALUE_CLASS_WITH_INT_ARRAY is statically known to be flat. 4578 } else { 4579 oArr = VALUE_CLASS_WITH_DOUBLE_ARRAY; // VALUE_CLASS_WITH_DOUBLE_ARRAY is statically known to be flat. 4580 } 4581 // The type of 'oArr' is inexact here because we merge two arrays. Since both arrays are flat, 'oArr' is also flat: 4582 // Type: flat:narrowoop: java/lang/Object:NotNull * (flat in array)[int:2] 4583 // Since the type is inexact, we do not know the exact flat array layout statically and thus need to fall back 4584 // to call "store_unknown_inline_Type()" at runtime where we know the flat array layout 4585 oArr[0] = o; 4586 } 4587 4588 @Test 4589 static Object testFlatArrayInexactObjectLoad(boolean flag) { 4590 Object[] oArr; 4591 if (flag) { 4592 oArr = VALUE_CLASS_WITH_INT_ARRAY; // VALUE_CLASS_WITH_INT_ARRAY is statically known to be flat. 4593 } else { 4594 oArr = VALUE_CLASS_WITH_DOUBLE_ARRAY; // VALUE_CLASS_WITH_DOUBLE_ARRAY is statically known to be flat. 4595 } 4596 // The type of 'oArr' is inexact here because we merge two arrays. Since both arrays are flat, 'oArr' is also flat: 4597 // Type: flat:narrowoop: java/lang/Object:NotNull * (flat in array)[int:2] 4598 // Since the type is inexact, we do not know the exact flat array layout statically and thus need to fall back 4599 // to call "load_unknown_inline_Type()" at runtime where we know the flat array layout 4600 return oArr[0]; 4601 } 4602 4603 @Test 4604 static void testFlatArrayInexactAbstractValueClassStore(AbstractValueClassWithByte abstractValueClassWithByte, 4605 boolean flag) { 4606 AbstractValueClassWithByte[] avArr; 4607 if (flag) { 4608 avArr = SUB_VALUE_CLASS_WITH_INT_ARRAY; 4609 } else { 4610 avArr = SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY; 4611 } 4612 // Same as testFlatArrayInexactObjectStore() but the inexact type is with an abstract value class: 4613 // flat:narrowoop: compiler/valhalla/inlinetypes/TestLWorld$AbstractValueClassWithByte:NotNull * (flat in array)[int:2] 4614 avArr[0] = abstractValueClassWithByte; 4615 } 4616 4617 @Test 4618 static AbstractValueClassWithByte testFlatArrayInexactAbstractValueClassLoad(boolean flag) { 4619 AbstractValueClassWithByte[] avArr; 4620 if (flag) { 4621 avArr = SUB_VALUE_CLASS_WITH_INT_ARRAY; 4622 } else { 4623 avArr = SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY; 4624 } 4625 // Same as testFlatArrayInexactObjectLoad() but the inexact type is with an abstract value class: 4626 // flat:narrowoop: compiler/valhalla/inlinetypes/TestLWorld$AbstractValueClassWithByte:NotNull * (flat in array)[int:2] 4627 return avArr[0]; 4628 } 4629 4630 @Run(test = {"testFlatArrayInexactObjectStore", 4631 "testFlatArrayInexactObjectLoad", 4632 "testFlatArrayInexactAbstractValueClassStore", 4633 "testFlatArrayInexactAbstractValueClassLoad"}) 4634 static void runFlatArrayInexactLoadAndStore() { 4635 // TODO: Remove these again once JDK-8343835 is fixed and uncomment static initializer above 4636 VALUE_CLASS_WITH_INT_ARRAY[0] = new ValueClassWithInt(5); 4637 VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new ValueClassWithDouble(6); 4638 SUB_VALUE_CLASS_WITH_INT_ARRAY[0] = new SubValueClassWithInt(7); 4639 SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new SubValueClassWithDouble(8); 4640 4641 boolean flag = true; 4642 ValueClassWithInt valueClassWithInt = new ValueClassWithInt(15); 4643 ValueClassWithDouble valueClassWithDouble = new ValueClassWithDouble(16); 4644 4645 testFlatArrayInexactObjectStore(valueClassWithInt, true); 4646 Asserts.assertEQ(valueClassWithInt, VALUE_CLASS_WITH_INT_ARRAY[0]); 4647 testFlatArrayInexactObjectStore(valueClassWithDouble, false); 4648 Asserts.assertEQ(valueClassWithDouble, VALUE_CLASS_WITH_DOUBLE_ARRAY[0]); 4649 4650 Asserts.assertEQ(valueClassWithInt, testFlatArrayInexactObjectLoad(true)); 4651 Asserts.assertEQ(valueClassWithDouble, testFlatArrayInexactObjectLoad(false)); 4652 4653 SubValueClassWithInt subValueClassWithInt = new SubValueClassWithInt(17); 4654 SubValueClassWithDouble subValueClassWithDouble = new SubValueClassWithDouble(18); 4655 4656 testFlatArrayInexactAbstractValueClassStore(subValueClassWithInt, true); 4657 Asserts.assertEQ(subValueClassWithInt, SUB_VALUE_CLASS_WITH_INT_ARRAY[0]); 4658 testFlatArrayInexactAbstractValueClassStore(subValueClassWithDouble, false); 4659 Asserts.assertEQ(subValueClassWithDouble, SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0]); 4660 4661 Asserts.assertEQ(subValueClassWithInt, testFlatArrayInexactAbstractValueClassLoad(true)); 4662 Asserts.assertEQ(subValueClassWithDouble, testFlatArrayInexactAbstractValueClassLoad(false)); 4663 } 4664 }