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 jdk.test.whitebox.WhiteBox; 29 30 import java.lang.reflect.Method; 31 32 import jdk.internal.value.ValueClass; 33 import jdk.internal.vm.annotation.LooselyConsistentValue; 34 import jdk.internal.vm.annotation.NullRestricted; 35 import jdk.internal.vm.annotation.Strict; 36 37 import static compiler.valhalla.inlinetypes.InlineTypeIRNode.*; 38 import static compiler.valhalla.inlinetypes.InlineTypes.*; 39 40 /* 41 * @test 42 * @key randomness 43 * @summary Test value class specific type profiling. 44 * @library /test/lib / 45 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") 46 * @enablePreview 47 * @modules java.base/jdk.internal.value 48 * java.base/jdk.internal.vm.annotation 49 * @run main/othervm/timeout=300 compiler.valhalla.inlinetypes.TestLWorldProfiling 50 */ 51 52 @ForceCompileClassInitializer 53 public class TestLWorldProfiling { 54 55 public static void main(String[] args) { 56 final Scenario[] scenarios = { 57 new Scenario(0, 58 "-XX:+UseArrayFlattening", 59 "-XX:-UseArrayLoadStoreProfile", 60 "-XX:-UseACmpProfile", 61 "-XX:TypeProfileLevel=0", 62 "-XX:-MonomorphicArrayCheck"), 63 new Scenario(1, 64 "-XX:+UseArrayFlattening", 65 "-XX:+UseArrayLoadStoreProfile", 66 "-XX:+UseACmpProfile", 67 "-XX:TypeProfileLevel=0", 68 "-XX:+UseFieldFlattening"), 69 new Scenario(2, 70 "-XX:+UseArrayFlattening", 71 "-XX:-UseArrayLoadStoreProfile", 72 "-XX:-UseACmpProfile", 73 "-XX:TypeProfileLevel=222", 74 "-XX:-MonomorphicArrayCheck"), 75 new Scenario(3, 76 "-XX:+UseArrayFlattening", 77 "-XX:-UseArrayLoadStoreProfile", 78 "-XX:-UseACmpProfile", 79 "-XX:TypeProfileLevel=0", 80 "-XX:-MonomorphicArrayCheck", 81 "-XX:TieredStopAtLevel=4", 82 "-XX:-TieredCompilation"), 83 new Scenario(4, 84 "-XX:+UseArrayFlattening", 85 "-XX:+UseArrayLoadStoreProfile", 86 "-XX:+UseACmpProfile", 87 "-XX:TypeProfileLevel=0", 88 "-XX:TieredStopAtLevel=4", 89 "-XX:-TieredCompilation", 90 "-XX:+UseFieldFlattening"), 91 new Scenario(5, 92 "-XX:+UseArrayFlattening", 93 "-XX:-UseArrayLoadStoreProfile", 94 "-XX:-UseACmpProfile", 95 "-XX:TypeProfileLevel=222", 96 "-XX:-MonomorphicArrayCheck", 97 "-XX:TieredStopAtLevel=4", 98 "-XX:-TieredCompilation") 99 }; 100 101 InlineTypes.getFramework() 102 .addScenarios(scenarios) 103 .addFlags("-XX:+IgnoreUnrecognizedVMOptions", "--enable-preview", 104 "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED", 105 "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED") 106 .addHelperClasses(MyValue1.class, 107 MyValue2.class) 108 .start(); 109 } 110 111 @Strict 112 @NullRestricted 113 private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL); 114 @Strict 115 @NullRestricted 116 private static final MyValue2 testValue2 = MyValue2.createWithFieldsInline(rI, rD); 117 private static final MyValue1[] testValue1Array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT); 118 static { 119 testValue1Array[0] = testValue1; 120 } 121 private static final MyValue2[] testValue2Array = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT); 122 static { 123 testValue2Array[0] = testValue2; 124 } 125 private static final Integer[] testIntegerArray = new Integer[] { 42 }; 126 private static final Long[] testLongArray = new Long[] { 42L }; 127 private static final Double[] testDoubleArray = new Double[] { 42.0D }; 128 private static final MyValue1[] testValue1NotFlatArray = new MyValue1[] { testValue1 }; 129 private static final MyValue1[][] testValue1ArrayArray = new MyValue1[][] { testValue1Array }; 130 131 // Wrap these variables into helper class because 132 // WhiteBox API needs to be initialized by TestFramework first. 133 static class WBFlags { 134 static final boolean UseACmpProfile = (Boolean) WhiteBox.getWhiteBox().getVMFlag("UseACmpProfile"); 135 static final boolean TieredCompilation = (Boolean) WhiteBox.getWhiteBox().getVMFlag("TieredCompilation"); 136 static final boolean ProfileInterpreter = (Boolean) WhiteBox.getWhiteBox().getVMFlag("ProfileInterpreter"); 137 static final boolean UseArrayLoadStoreProfile = (Boolean) WhiteBox.getWhiteBox().getVMFlag("UseArrayLoadStoreProfile"); 138 static final long TypeProfileLevel = (Long) WhiteBox.getWhiteBox().getVMFlag("TypeProfileLevel"); 139 } 140 141 static abstract value class ValueAbstract { 142 143 } 144 145 static class NonValueClass1 extends ValueAbstract { 146 int x; 147 148 public NonValueClass1(int x) { 149 this.x = x; 150 } 151 } 152 153 static class NonValueClass2 extends ValueAbstract { 154 int x; 155 156 public NonValueClass2(int x) { 157 this.x = x; 158 } 159 } 160 161 static final NonValueClass1 obj = new NonValueClass1(rI); 162 static final NonValueClass2 otherObj = new NonValueClass2(rI); 163 164 // aaload 165 166 @Test 167 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 168 failOn = {LOAD_UNKNOWN_INLINE}) 169 @IR(applyIfAnd={"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 170 counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 171 public Object test1(Object[] array) { 172 return array[0]; 173 } 174 175 @Run(test = "test1") 176 @Warmup(10000) 177 public void test1_verifier(RunInfo info) { 178 if (info.isWarmUp()) { 179 Object o = test1(testValue1Array); 180 Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash()); 181 } else { 182 Object o = test1(testValue2Array); 183 Asserts.assertEQ(((MyValue2)o).hash(), testValue2.hash()); 184 } 185 } 186 187 @Test 188 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 189 failOn = {LOAD_UNKNOWN_INLINE}) 190 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 191 counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 192 public Object test2(Object[] array) { 193 return array[0]; 194 } 195 196 @Run(test = "test2") 197 @Warmup(10000) 198 public void test2_verifier(RunInfo info) { 199 if (info.isWarmUp()) { 200 Object o = test2(testIntegerArray); 201 Asserts.assertEQ(o, 42); 202 } else { 203 Object o = test2(testLongArray); 204 Asserts.assertEQ(o, 42L); 205 } 206 } 207 208 @Test 209 @IR(counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 210 public Object test3(Object[] array) { 211 return array[0]; 212 } 213 214 @Run(test = "test3") 215 @Warmup(10000) 216 public void test3_verifier() { 217 Object o = test3(testValue1Array); 218 Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash()); 219 o = test3(testValue2Array); 220 Asserts.assertEQ(((MyValue2)o).hash(), testValue2.hash()); 221 } 222 223 @Test 224 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 225 failOn = {LOAD_UNKNOWN_INLINE}) 226 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 227 counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 228 public Object test4(Object[] array) { 229 return array[0]; 230 } 231 232 @Run(test = "test4") 233 @Warmup(10000) 234 public void test4_verifier(RunInfo info) { 235 if (info.isWarmUp()) { 236 Object o = test4(testIntegerArray); 237 Asserts.assertEQ(o, 42); 238 o = test4(testLongArray); 239 Asserts.assertEQ(o, 42L); 240 } else { 241 Object o = test4(testValue2Array); 242 Asserts.assertEQ(((MyValue2)o).hash(), testValue2.hash()); 243 } 244 } 245 246 @Test 247 @IR(counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 248 public Object test5(Object[] array) { 249 return array[0]; 250 } 251 252 @Run(test = "test5") 253 @Warmup(10000) 254 public void test5_verifier() { 255 Object o = test5(testValue1Array); 256 Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash()); 257 o = test5(testValue1NotFlatArray); 258 Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash()); 259 } 260 261 // Check that profile data that's useless at the aaload is 262 // leveraged at a later point 263 @DontInline 264 public void test6_no_inline() { 265 } 266 267 @ForceInline 268 public void test6_helper(ValueAbstract[] arg) { 269 if (arg instanceof NonValueClass1[]) { 270 test6_no_inline(); 271 } 272 } 273 274 @Test 275 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 276 counts = {CALL, "= 4", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1", RANGE_CHECK_TRAP, "= 1"}) 277 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 278 counts = {CALL, "= 4", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1"}) 279 public Object test6(ValueAbstract[] array) { 280 ValueAbstract v = array[0]; 281 test6_helper(array); 282 return v; 283 } 284 285 @Run(test = "test6") 286 @Warmup(10000) 287 public void test6_verifier(RunInfo info) { 288 if (info.isWarmUp()) { 289 // pollute profile 290 test6_helper(new NonValueClass1[1]); 291 test6_helper(new NonValueClass2[1]); 292 } 293 test6(new NonValueClass1[1]); 294 } 295 296 @DontInline 297 public void test7_no_inline() { 298 } 299 300 @ForceInline 301 public void test7_helper(ValueAbstract arg) { 302 if (arg instanceof NonValueClass1) { 303 test7_no_inline(); 304 } 305 } 306 307 @Test 308 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 309 counts = {CALL, "= 4", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1", RANGE_CHECK_TRAP, "= 1"}) 310 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 311 counts = {CALL, "= 4", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1"}) 312 public Object test7(ValueAbstract[] array) { 313 ValueAbstract v = array[0]; 314 test7_helper(v); 315 return v; 316 } 317 318 @Run(test = "test7") 319 @Warmup(10000) 320 public void test7_verifier(RunInfo info) { 321 if (info.isWarmUp()) { 322 // pollute profile 323 test7_helper(new NonValueClass1(rI)); 324 test7_helper(new NonValueClass2(rI)); 325 } 326 test7(new NonValueClass1[1]); 327 } 328 329 @DontInline 330 public void test8_no_inline() { 331 } 332 333 public void test8_helper(Object arg) { 334 if (arg instanceof Long) { 335 test8_no_inline(); 336 } 337 } 338 339 @Test 340 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 341 counts = {CALL, "= 5", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2", 342 RANGE_CHECK_TRAP, "= 1"}) 343 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 344 counts = {CALL, "= 5", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2"}) 345 public Object test8(Object[] array) { 346 Object v = array[0]; 347 test8_helper(v); 348 return v; 349 } 350 351 @Run(test = "test8") 352 @Warmup(10000) 353 public void test8_verifier(RunInfo info) { 354 if (info.isWarmUp()) { 355 // pollute profile 356 test8_helper(42L); 357 test8_helper(42.0D); 358 } 359 test8(testValue1Array); 360 test8(testValue1NotFlatArray); 361 } 362 363 // aastore 364 365 @Test 366 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 367 failOn = {STORE_UNKNOWN_INLINE}) 368 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 369 counts = {STORE_UNKNOWN_INLINE, "= 1"}) 370 public void test9(Object[] array, Object v) { 371 array[0] = v; 372 } 373 374 @Run(test = "test9") 375 @Warmup(10000) 376 public void test9_verifier() { 377 test9(testValue1Array, testValue1); 378 Asserts.assertEQ(testValue1Array[0].hash(), testValue1.hash()); 379 } 380 381 @Test 382 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 383 failOn = {STORE_UNKNOWN_INLINE}) 384 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 385 counts = {STORE_UNKNOWN_INLINE, "= 1"}) 386 public void test10(Object[] array, Object v) { 387 array[0] = v; 388 } 389 390 @Run(test = "test10") 391 @Warmup(10000) 392 public void test10_verifier() { 393 test10(testIntegerArray, 42); 394 } 395 396 @Test 397 @IR(counts = {STORE_UNKNOWN_INLINE, "= 1"}) 398 public void test11(Object[] array, Object v) { 399 array[0] = v; 400 } 401 402 @Run(test = "test11") 403 @Warmup(10000) 404 public void test11_verifier() { 405 test11(testValue1Array, testValue1); 406 test11(testValue2Array, testValue2); 407 } 408 409 @Test 410 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 411 failOn = {STORE_UNKNOWN_INLINE}) 412 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 413 counts = {STORE_UNKNOWN_INLINE, "= 1"}) 414 public void test12(Object[] array, Object v) { 415 array[0] = v; 416 } 417 418 @Run(test = "test12") 419 @Warmup(10000) 420 public void test12_verifier() { 421 test12(testIntegerArray, 42); 422 test12(testLongArray, 42L); 423 } 424 425 @Test 426 @IR(counts = {STORE_UNKNOWN_INLINE, "= 1"}) 427 public void test13(Object[] array, Object v) { 428 array[0] = v; 429 } 430 431 @Run(test = "test13") 432 @Warmup(10000) 433 public void test13_verifier() { 434 test13(testValue1Array, testValue1); 435 test13(testValue1NotFlatArray, testValue1); 436 } 437 438 // MonomorphicArrayCheck 439 @Test 440 public void test14(Number[] array, Number v) { 441 array[0] = v; 442 } 443 444 @Run(test = "test14") 445 @Warmup(10000) 446 public void test14_verifier(RunInfo info) { 447 if (info.isWarmUp()) { 448 test14(testIntegerArray, 42); 449 } else { 450 Method m = info.getTest(); 451 boolean deopt = false; 452 for (int i = 0; i < 100; i++) { 453 test14(testIntegerArray, 42); 454 if (!info.isCompilationSkipped() && !TestFramework.isCompiled(m)) { 455 deopt = true; 456 } 457 } 458 if (deopt && TestFramework.isStableDeopt(m, CompLevel.C2) && !WBFlags.TieredCompilation && WBFlags.ProfileInterpreter && 459 (WBFlags.UseArrayLoadStoreProfile || WBFlags.TypeProfileLevel == 222)) { 460 throw new RuntimeException("Monomorphic array check should rely on profiling and be accurate"); 461 } 462 } 463 } 464 465 // null free array profiling 466 467 @LooselyConsistentValue 468 static value class NotFlattenable { 469 private Object o1 = null; 470 private Object o2 = null; 471 private Object o3 = null; 472 private Object o4 = null; 473 private Object o5 = null; 474 private Object o6 = null; 475 } 476 477 @Strict 478 @NullRestricted 479 private static final NotFlattenable notFlattenable = new NotFlattenable(); 480 private static final NotFlattenable[] testNotFlattenableArray = (NotFlattenable[])ValueClass.newNullRestrictedNonAtomicArray(NotFlattenable.class, 1, new NotFlattenable()); 481 482 @Test 483 @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"}, 484 counts = {NULL_CHECK_TRAP, "= 2"}, 485 failOn = {STORE_UNKNOWN_INLINE}) 486 @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"}, 487 counts = {NULL_CHECK_TRAP, "= 2", STORE_UNKNOWN_INLINE, "= 1"}) 488 public void test15(Object[] array, Object v) { 489 array[0] = v; 490 } 491 492 @Run(test = "test15") 493 @Warmup(10000) 494 public void test15_verifier() { 495 test15(testNotFlattenableArray, notFlattenable); 496 try { 497 test15(testNotFlattenableArray, null); 498 throw new RuntimeException("NullPointerException expected"); 499 } catch (NullPointerException npe) { 500 // Expected 501 } 502 } 503 504 @Test 505 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 506 counts = {NULL_CHECK_TRAP, "= 2"}, 507 failOn = {STORE_UNKNOWN_INLINE}) 508 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 509 counts = {NULL_CHECK_TRAP, "= 2", STORE_UNKNOWN_INLINE, "= 1"}) 510 public void test16(Object[] array, Object v) { 511 array[0] = v; 512 } 513 514 @Run(test = "test16") 515 @Warmup(10000) 516 public void test16_verifier() { 517 test16(testNotFlattenableArray, notFlattenable); 518 try { 519 test16(testNotFlattenableArray, null); 520 throw new RuntimeException("NullPointerException expected"); 521 } catch (NullPointerException npe) { 522 // Expected 523 } 524 test16(testIntegerArray, 42); 525 } 526 527 @Test 528 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 529 counts = {NULL_CHECK_TRAP, "= 1"}, 530 failOn = {STORE_UNKNOWN_INLINE}) 531 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 532 counts = {NULL_CHECK_TRAP, "= 2", STORE_UNKNOWN_INLINE, "= 1"}) 533 public void test17(Object[] array, Object v) { 534 array[0] = v; 535 } 536 537 @Run(test = "test17") 538 @Warmup(10000) 539 public void test17_verifier() { 540 test17(testIntegerArray, 42); 541 test17(testIntegerArray, null); 542 testIntegerArray[0] = 42; 543 test17(testLongArray, 42L); 544 } 545 546 public void test18_helper(Object[] array, Object v) { 547 array[0] = v; 548 } 549 550 @Test 551 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 552 counts = {NULL_CHECK_TRAP, "= 1"}, 553 failOn = {STORE_UNKNOWN_INLINE}) 554 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 555 counts = {NULL_CHECK_TRAP, "= 2", STORE_UNKNOWN_INLINE, "= 1"}) 556 public Object test18(Object[] array, Object v1) { 557 Object v2 = array[0]; 558 test18_helper(array, v1); 559 return v2; 560 } 561 562 @Run(test = "test18") 563 @Warmup(10000) 564 public void test18_verifier() { 565 test18_helper(testValue1Array, testValue1); // pollute profile 566 test18(testIntegerArray, 42); 567 test18(testIntegerArray, null); 568 testIntegerArray[0] = 42; 569 test18(testLongArray, 42L); 570 } 571 572 // maybe null free, not flat 573 574 @Test 575 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 576 failOn = {LOAD_UNKNOWN_INLINE}) 577 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 578 counts = {LOAD_UNKNOWN_INLINE, "= 1"}) 579 public Object test19(Object[] array) { 580 return array[0]; 581 } 582 583 @Run(test = "test19") 584 @Warmup(10000) 585 public void test19_verifier() { 586 Object o = test19(testIntegerArray); 587 Asserts.assertEQ(o, 42); 588 o = test19(testNotFlattenableArray); 589 Asserts.assertEQ(o, notFlattenable); 590 } 591 592 @Test 593 @IR(applyIf = {"UseArrayLoadStoreProfile", "true"}, 594 failOn = {STORE_UNKNOWN_INLINE}) 595 @IR(applyIf = {"UseArrayLoadStoreProfile", "false"}, 596 counts = {STORE_UNKNOWN_INLINE, "= 1"}) 597 public void test20(Object[] array, Object o) { 598 array[0] = o; 599 } 600 601 @Run(test = "test20") 602 @Warmup(10000) 603 public void test20_verifier() { 604 test20(testIntegerArray, 42); 605 test20(testNotFlattenableArray, notFlattenable); 606 } 607 608 // acmp tests 609 610 // branch frequency profiling causes not equal branch to be optimized out 611 @Test 612 @IR(counts = {IRNode.UNSTABLE_IF_TRAP, " = 1"}) 613 public boolean test21(Object o1, Object o2) { 614 return o1 == o2; 615 } 616 617 @Run(test = "test21") 618 @Warmup(10000) 619 public void test21_verifier() { 620 test21(obj, obj); 621 test21(testValue1, testValue1); 622 } 623 624 // Input profiled non null 625 @Test 626 @IR(applyIf = {"UseACmpProfile", "true"}, 627 failOn = {SUBSTITUTABILITY_TEST}, 628 counts = {NULL_ASSERT_TRAP, "= 1"}) 629 @IR(applyIf = {"UseACmpProfile", "false"}, 630 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 631 public boolean test22(Object o1, Object o2) { 632 return o1 == o2; 633 } 634 635 @Run(test = "test22") 636 @Warmup(10000) 637 public void test22_verifier(RunInfo info) { 638 test22(obj, null); 639 test22(otherObj, null); 640 if (!info.isWarmUp()) { 641 Method m = info.getTest(); 642 TestFramework.assertCompiledByC2(m); 643 test22(obj, otherObj); 644 if (WBFlags.UseACmpProfile) { 645 TestFramework.assertDeoptimizedByC2(m); 646 } 647 } 648 } 649 650 @Test 651 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 652 failOn = {SUBSTITUTABILITY_TEST}, 653 counts = {NULL_ASSERT_TRAP, "= 1"}) 654 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 655 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 656 public boolean test23(Object o1, Object o2) { 657 return o1 == o2; 658 } 659 660 @Run(test = "test23") 661 @Warmup(10000) 662 public void test23_verifier(RunInfo info) { 663 test23(null, obj); 664 test23(null, otherObj); 665 if (!info.isWarmUp()) { 666 Method m = info.getTest(); 667 TestFramework.assertCompiledByC2(m); 668 test23(obj, otherObj); 669 if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) { 670 TestFramework.assertDeoptimizedByC2(m); 671 } 672 } 673 } 674 675 @Test 676 @IR(applyIf = {"UseACmpProfile", "true"}, 677 failOn = {SUBSTITUTABILITY_TEST}, 678 counts = {NULL_ASSERT_TRAP, "= 1"}) 679 @IR(applyIf = {"UseACmpProfile", "false"}, 680 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 681 public boolean test24(Object o1, Object o2) { 682 return o1 != o2; 683 } 684 685 @Run(test = "test24") 686 @Warmup(10000) 687 public void test24_verifier(RunInfo info) { 688 test24(obj, null); 689 test24(otherObj, null); 690 if (!info.isWarmUp()) { 691 Method m = info.getTest(); 692 TestFramework.assertCompiledByC2(m); 693 test24(obj, otherObj); 694 if (WBFlags.UseACmpProfile) { 695 TestFramework.assertDeoptimizedByC2(m); 696 } 697 } 698 } 699 700 @Test 701 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 702 failOn = {SUBSTITUTABILITY_TEST}, 703 counts = {NULL_ASSERT_TRAP, "= 1"}) 704 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 705 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 706 public boolean test25(Object o1, Object o2) { 707 return o1 != o2; 708 } 709 710 @Run(test = "test25") 711 @Warmup(10000) 712 public void test25_verifier(RunInfo info) { 713 test25(null, obj); 714 test25(null, otherObj); 715 if (!info.isWarmUp()) { 716 Method m = info.getTest(); 717 TestFramework.assertCompiledByC2(m); 718 test25(obj, otherObj); 719 if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) { 720 TestFramework.assertDeoptimizedByC2(m); 721 } 722 } 723 } 724 725 // Input profiled not value class with known type 726 @Test 727 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 728 failOn = {SUBSTITUTABILITY_TEST}, 729 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 730 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 731 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 732 public boolean test26(Object o1, Object o2) { 733 return o1 == o2; 734 } 735 736 @Run(test = "test26") 737 @Warmup(10000) 738 public void test26_verifier(RunInfo info) { 739 test26(obj, obj); 740 test26(obj, otherObj); 741 if (!info.isWarmUp()) { 742 Method m = info.getTest(); 743 TestFramework.assertCompiledByC2(m); 744 for (int i = 0; i < 10; i++) { 745 test26(otherObj, obj); 746 } 747 if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) { 748 TestFramework.assertDeoptimizedByC2(m); 749 } 750 } 751 } 752 753 @Test 754 @IR(applyIf = {"UseACmpProfile", "true"}, 755 failOn = {SUBSTITUTABILITY_TEST}, 756 counts = { NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 757 @IR(applyIf = {"UseACmpProfile", "false"}, 758 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 759 public boolean test27(Object o1, Object o2) { 760 return o1 == o2; 761 } 762 763 @Run(test = "test27") 764 @Warmup(10000) 765 public void test27_verifier(RunInfo info) { 766 test27(obj, obj); 767 test27(otherObj, obj); 768 if (!info.isWarmUp()) { 769 Method m = info.getTest(); 770 TestFramework.assertCompiledByC2(m); 771 for (int i = 0; i < 10; i++) { 772 test27(obj, otherObj); 773 } 774 if (WBFlags.UseACmpProfile) { 775 TestFramework.assertDeoptimizedByC2(m); 776 } 777 } 778 } 779 780 @Test 781 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 782 failOn = {SUBSTITUTABILITY_TEST}, 783 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 784 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 785 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 786 public boolean test28(Object o1, Object o2) { 787 return o1 != o2; 788 } 789 790 @Run(test = "test28") 791 @Warmup(10000) 792 public void test28_verifier(RunInfo info) { 793 test28(obj, obj); 794 test28(obj, otherObj); 795 if (!info.isWarmUp()) { 796 Method m = info.getTest(); 797 TestFramework.assertCompiledByC2(m); 798 for (int i = 0; i < 10; i++) { 799 test28(otherObj, obj); 800 } 801 if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) { 802 TestFramework.assertDeoptimizedByC2(m); 803 } 804 } 805 } 806 807 @Test 808 @IR(applyIf = {"UseACmpProfile", "true"}, 809 failOn = {SUBSTITUTABILITY_TEST}, 810 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 811 @IR(applyIf = {"UseACmpProfile", "false"}, 812 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 813 public boolean test29(Object o1, Object o2) { 814 return o1 != o2; 815 } 816 817 @Run(test = "test29") 818 @Warmup(10000) 819 public void test29_verifier(RunInfo info) { 820 test29(obj, obj); 821 test29(otherObj, obj); 822 if (!info.isWarmUp()) { 823 Method m = info.getTest(); 824 TestFramework.assertCompiledByC2(m); 825 for (int i = 0; i < 10; i++) { 826 test29(obj, otherObj); 827 } 828 if (WBFlags.UseACmpProfile) { 829 TestFramework.assertDeoptimizedByC2(m); 830 } 831 } 832 } 833 834 @Test 835 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 836 failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP}, 837 counts = {CLASS_CHECK_TRAP, "= 1"}) 838 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 839 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 840 public boolean test30(Object o1, Object o2) { 841 return o1 == o2; 842 } 843 844 @Run(test = "test30") 845 @Warmup(10000) 846 public void test30_verifier(RunInfo info) { 847 test30(obj, obj); 848 test30(obj, otherObj); 849 test30(null, 42); 850 if (!info.isWarmUp()) { 851 Method m = info.getTest(); 852 TestFramework.assertCompiledByC2(m); 853 for (int i = 0; i < 10; i++) { 854 test30(otherObj, obj); 855 } 856 if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) { 857 TestFramework.assertDeoptimizedByC2(m); 858 } 859 } 860 } 861 862 @Test 863 @IR(applyIf = {"UseACmpProfile", "true"}, 864 failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP}) 865 @IR(applyIf = {"UseACmpProfile", "false"}, 866 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 867 public boolean test31(Object o1, Object o2) { 868 return o1 == o2; 869 } 870 871 @Run(test = "test31") 872 @Warmup(10000) 873 public void test31_verifier(RunInfo info) { 874 test31(obj, obj); 875 test31(otherObj, obj); 876 test31(obj, null); 877 if (!info.isWarmUp()) { 878 Method m = info.getTest(); 879 TestFramework.assertCompiledByC2(m); 880 for (int i = 0; i < 10; i++) { 881 test31(obj, otherObj); 882 } 883 if (WBFlags.UseACmpProfile) { 884 TestFramework.assertDeoptimizedByC2(m); 885 } 886 } 887 } 888 889 // Input profiled not value class with unknown type 890 @Test 891 @IR(applyIf = {"UseACmpProfile", "true"}, 892 failOn = {SUBSTITUTABILITY_TEST}, 893 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 894 @IR(applyIf = {"UseACmpProfile", "false"}, 895 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 896 public boolean test32(Object o1, Object o2) { 897 return o1 == o2; 898 } 899 900 @Run(test = "test32") 901 @Warmup(10000) 902 public void test32_verifier(RunInfo info) { 903 test32(obj, obj); 904 test32(obj, testValue1); 905 test32(otherObj, obj); 906 if (!info.isWarmUp()) { 907 Method m = info.getTest(); 908 TestFramework.assertCompiledByC2(m); 909 for (int i = 0; i < 10; i++) { 910 test32(testValue1, 42); 911 } 912 if (WBFlags.UseACmpProfile) { 913 TestFramework.assertDeoptimizedByC2(m); 914 } 915 } 916 } 917 918 @Test 919 @IR(applyIf = {"UseACmpProfile", "true"}, 920 failOn = {SUBSTITUTABILITY_TEST}, 921 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 922 @IR(applyIf = {"UseACmpProfile", "false"}, 923 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 924 public boolean test33(Object o1, Object o2) { 925 return o1 == o2; 926 } 927 928 @Run(test = "test33") 929 @Warmup(10000) 930 public void test33_verifier(RunInfo info) { 931 test33(obj, obj); 932 test33(testValue1, obj); 933 test33(obj, otherObj); 934 if (!info.isWarmUp()) { 935 Method m = info.getTest(); 936 TestFramework.assertCompiledByC2(m); 937 for (int i = 0; i < 10; i++) { 938 test33(obj, testValue1); 939 } 940 if (WBFlags.UseACmpProfile) { 941 TestFramework.assertDeoptimizedByC2(m); 942 } 943 } 944 } 945 946 @Test 947 @IR(applyIf = {"UseACmpProfile", "true"}, 948 failOn = {SUBSTITUTABILITY_TEST}, 949 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 950 @IR(applyIf = {"UseACmpProfile", "false"}, 951 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 952 public boolean test34(Object o1, Object o2) { 953 return o1 != o2; 954 } 955 956 @Run(test = "test34") 957 @Warmup(10000) 958 public void test34_verifier(RunInfo info) { 959 test34(obj, obj); 960 test34(obj, testValue1); 961 test34(otherObj, obj); 962 if (!info.isWarmUp()) { 963 Method m = info.getTest(); 964 TestFramework.assertCompiledByC2(m); 965 for (int i = 0; i < 10; i++) { 966 test34(testValue1, 42); 967 } 968 if (WBFlags.UseACmpProfile) { 969 TestFramework.assertDeoptimizedByC2(m); 970 } 971 } 972 } 973 974 @Test 975 @IR(applyIf = {"UseACmpProfile", "true"}, 976 failOn = {SUBSTITUTABILITY_TEST}, 977 counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"}) 978 @IR(applyIf = {"UseACmpProfile", "false"}, 979 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 980 public boolean test35(Object o1, Object o2) { 981 return o1 != o2; 982 } 983 984 @Run(test = "test35") 985 @Warmup(10000) 986 public void test35_verifier(RunInfo info) { 987 test35(obj, obj); 988 test35(testValue1, obj); 989 test35(obj, otherObj); 990 if (!info.isWarmUp()) { 991 Method m = info.getTest(); 992 TestFramework.assertCompiledByC2(m); 993 for (int i = 0; i < 10; i++) { 994 test35(obj, testValue1); 995 } 996 if (WBFlags.UseACmpProfile) { 997 TestFramework.assertDeoptimizedByC2(m); 998 } 999 } 1000 } 1001 1002 @Test 1003 @IR(applyIf = {"UseACmpProfile", "true"}, 1004 failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP}, 1005 counts = {CLASS_CHECK_TRAP, "= 1"}) 1006 @IR(applyIf = {"UseACmpProfile", "false"}, 1007 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 1008 public boolean test36(Object o1, Object o2) { 1009 return o1 == o2; 1010 } 1011 1012 @Run(test = "test36") 1013 @Warmup(10000) 1014 public void test36_verifier(RunInfo info) { 1015 test36(obj, otherObj); 1016 test36(otherObj, testValue1); 1017 test36(null, obj); 1018 if (!info.isWarmUp()) { 1019 Method m = info.getTest(); 1020 TestFramework.assertCompiledByC2(m); 1021 for (int i = 0; i < 10; i++) { 1022 test36(testValue1, obj); 1023 } 1024 if (WBFlags.UseACmpProfile) { 1025 TestFramework.assertDeoptimizedByC2(m); 1026 } 1027 } 1028 } 1029 1030 @Test 1031 @IR(applyIf = {"UseACmpProfile", "true"}, 1032 failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP}) 1033 @IR(applyIf = {"UseACmpProfile", "false"}, 1034 counts = {SUBSTITUTABILITY_TEST, "= 1"}) 1035 public boolean test37(Object o1, Object o2) { 1036 return o1 == o2; 1037 } 1038 1039 @Run(test = "test37") 1040 @Warmup(10000) 1041 public void test37_verifier(RunInfo info) { 1042 test37(otherObj, obj); 1043 test37(testValue1, otherObj); 1044 test37(obj, null); 1045 if (!info.isWarmUp()) { 1046 Method m = info.getTest(); 1047 TestFramework.assertCompiledByC2(m); 1048 for (int i = 0; i < 10; i++) { 1049 test37(obj, testValue1); 1050 } 1051 if (WBFlags.UseACmpProfile) { 1052 TestFramework.assertDeoptimizedByC2(m); 1053 } 1054 } 1055 } 1056 1057 // Test that acmp profile data that's unused at the acmp is fed to 1058 // speculation and leverage later 1059 @Test 1060 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 1061 failOn = {SUBSTITUTABILITY_TEST}, 1062 counts = {CLASS_CHECK_TRAP, "= 2"}) 1063 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 1064 counts = {SUBSTITUTABILITY_TEST, "= 2"}) 1065 public void test38(Object o1, Object o2, Object o3) { 1066 if (o1 == o2) { 1067 test38_helper2(); 1068 } 1069 test38_helper(o1, o3); 1070 } 1071 1072 public void test38_helper(Object o1, Object o2) { 1073 if (o1 == o2) { 1074 } 1075 } 1076 1077 public void test38_helper2() { 1078 } 1079 1080 @Run(test = "test38") 1081 @Warmup(10000) 1082 public void test38_verifier() { 1083 test38(obj, obj, obj); 1084 test38_helper(testValue1, testValue2); 1085 } 1086 1087 @Test 1088 @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"}, 1089 failOn = {SUBSTITUTABILITY_TEST}, 1090 counts = {CLASS_CHECK_TRAP, "= 2"}) 1091 @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"}, 1092 counts = {SUBSTITUTABILITY_TEST, "= 2"}) 1093 public void test39(Object o1, Object o2, Object o3) { 1094 if (o1 == o2) { 1095 test39_helper2(); 1096 } 1097 test39_helper(o2, o3); 1098 } 1099 1100 public void test39_helper(Object o1, Object o2) { 1101 if (o1 == o2) { 1102 } 1103 } 1104 1105 public void test39_helper2() { 1106 } 1107 1108 @Run(test = "test39") 1109 @Warmup(10000) 1110 public void test39_verifier() { 1111 test39(obj, obj, obj); 1112 test39_helper(testValue1, testValue2); 1113 } 1114 1115 // Test array access with polluted array type profile 1116 static abstract value class Test40Abstract { } 1117 static value class Test40Class extends Test40Abstract { } 1118 1119 @LooselyConsistentValue 1120 static value class Test40Inline extends Test40Abstract { } 1121 1122 @ForceInline 1123 public Object test40_access(Object[] array) { 1124 return array[0]; 1125 } 1126 1127 @Test 1128 public Object test40(Test40Abstract[] array) { 1129 return test40_access(array); 1130 } 1131 1132 @Run(test = "test40") 1133 @Warmup(10000) 1134 public void test40_verifier(RunInfo info) { 1135 // Make sure multiple implementors of Test40Abstract are loaded 1136 Test40Inline tmp1 = new Test40Inline(); 1137 Test40Class tmp2 = new Test40Class(); 1138 if (info.isWarmUp()) { 1139 // Pollute profile with Object[] (exact) 1140 test40_access(new Object[1]); 1141 } else { 1142 // When inlining test40_access, profiling contradicts actual type of array 1143 test40(new Test40Class[1]); 1144 } 1145 } 1146 1147 // Same as test40 but with array store 1148 @ForceInline 1149 public void test41_access(Object[] array, Object val) { 1150 array[0] = val; 1151 } 1152 1153 @Test 1154 public void test41(Test40Inline[] array, Object val) { 1155 test41_access(array, val); 1156 } 1157 1158 @Run(test = "test41") 1159 @Warmup(10000) 1160 public void test41_verifier(RunInfo info) { 1161 // Make sure multiple implementors of Test40Abstract are loaded 1162 Test40Inline tmp1 = new Test40Inline(); 1163 Test40Class tmp2 = new Test40Class(); 1164 if (info.isWarmUp()) { 1165 // Pollute profile with exact Object[] 1166 test41_access(new Object[1], new Object()); 1167 } else { 1168 // When inlining test41_access, profiling contradicts actual type of array 1169 Test40Inline[] array = (Test40Inline[])ValueClass.newNullRestrictedNonAtomicArray(Test40Inline.class, 1, new Test40Inline()); 1170 test41(array, new Test40Inline()); 1171 } 1172 } 1173 }