1 /* 2 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package compiler.valhalla.valuetypes; 25 26 import jdk.test.lib.Asserts; 27 28 /* 29 * @test 30 * @summary Test the basic value type implementation in C2 31 * @library /testlibrary /test/lib /compiler/whitebox / 32 * @requires os.simpleArch == "x64" 33 * @compile -XDenableValueTypes TestBasicFunctionality.java 34 * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform 35 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 36 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline 37 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 38 * -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 39 * compiler.valhalla.valuetypes.TestBasicFunctionality 40 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 41 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops 42 * -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 43 * -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 44 * compiler.valhalla.valuetypes.TestBasicFunctionality 45 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 46 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops 47 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:-ValueArrayFlatten 48 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0 49 * -DVerifyIR=false compiler.valhalla.valuetypes.TestBasicFunctionality 50 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 51 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline 52 * -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten 53 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0 54 * -DVerifyIR=false compiler.valhalla.valuetypes.TestBasicFunctionality 55 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 56 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI 57 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 58 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 59 * -DVerifyIR=false compiler.valhalla.valuetypes.TestBasicFunctionality 60 */ 61 public class TestBasicFunctionality extends ValueTypeTest { 62 63 public static void main(String[] args) throws Throwable { 64 TestBasicFunctionality test = new TestBasicFunctionality(); 65 test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class); 66 } 67 68 // Helper methods 69 70 protected long hash() { 71 return hash(rI, rL); 72 } 73 74 protected long hash(int x, long y) { 75 return MyValue1.createWithFieldsInline(x, y).hash(); 76 } 77 78 // Receive value type through call to interpreter 79 @Test(failOn = ALLOC + STORE + TRAP) 80 public long test1() { 81 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); 82 return v.hash(); 83 } 84 85 @DontCompile 86 public void test1_verifier(boolean warmup) { 87 long result = test1(); 88 Asserts.assertEQ(result, hash()); 89 } 90 91 // Receive value type from interpreter via parameter 92 @Test(failOn = ALLOC + STORE + TRAP) 93 public long test2(MyValue1 v) { 94 return v.hash(); 95 } 96 97 @DontCompile 98 public void test2_verifier(boolean warmup) { 99 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); 100 long result = test2(v); 101 Asserts.assertEQ(result, hash()); 102 } 103 104 // Return incoming value type without accessing fields 105 @Test(valid = ValueTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount = {1, 11}, failOn = LOAD + TRAP) 106 @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + LOAD + STORE + TRAP) 107 public MyValue1 test3(MyValue1 v) { 108 return v; 109 } 110 111 @DontCompile 112 public void test3_verifier(boolean warmup) { 113 MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL); 114 MyValue1 v2 = test3(v1); 115 Asserts.assertEQ(v1.x, v2.x); 116 Asserts.assertEQ(v1.y, v2.y); 117 } 118 119 // Create a value type in compiled code and only use fields. 120 // Allocation should go away because value type does not escape. 121 @Test(failOn = ALLOC + LOAD + STORE + TRAP) 122 public long test4() { 123 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 124 return v.hash(); 125 } 126 127 @DontCompile 128 public void test4_verifier(boolean warmup) { 129 long result = test4(); 130 Asserts.assertEQ(result, hash()); 131 } 132 133 // Create a value type in compiled code and pass it to 134 // an inlined compiled method via a call. 135 @Test(failOn = ALLOC + LOAD + STORE + TRAP) 136 public long test5() { 137 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 138 return test5Inline(v); 139 } 140 141 @ForceInline 142 public long test5Inline(MyValue1 v) { 143 return v.hash(); 144 } 145 146 @DontCompile 147 public void test5_verifier(boolean warmup) { 148 long result = test5(); 149 Asserts.assertEQ(result, hash()); 150 } 151 152 // Create a value type in compiled code and pass it to 153 // the interpreter via a call. 154 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC) 155 @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP) 156 public long test6() { 157 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 158 // Pass to interpreter 159 return v.hashInterpreted(); 160 } 161 162 @DontCompile 163 public void test6_verifier(boolean warmup) { 164 long result = test6(); 165 Asserts.assertEQ(result, hash()); 166 } 167 168 // Create a value type in compiled code and pass it to 169 // the interpreter by returning. 170 @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP) 171 public MyValue1 test7(int x, long y) { 172 return MyValue1.createWithFieldsInline(x, y); 173 } 174 175 @DontCompile 176 public void test7_verifier(boolean warmup) { 177 MyValue1 v = test7(rI, rL); 178 Asserts.assertEQ(v.hash(), hash()); 179 } 180 181 // Merge value types created from two branches 182 @Test(failOn = ALLOC + STORE + TRAP) 183 public long test8(boolean b) { 184 MyValue1 v; 185 if (b) { 186 v = MyValue1.createWithFieldsInline(rI, rL); 187 } else { 188 v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1); 189 } 190 return v.hash(); 191 } 192 193 @DontCompile 194 public void test8_verifier(boolean warmup) { 195 Asserts.assertEQ(test8(true), hash()); 196 Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1)); 197 } 198 199 // Merge value types created from two branches 200 @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {10}, failOn = TRAP + ALLOC + STORE) 201 @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 5}, failOn = LOAD + TRAP) 202 public MyValue1 test9(boolean b) { 203 MyValue1 v; 204 if (b) { 205 // Value type is not allocated 206 v = MyValue1.createWithFieldsInline(rI, rL); 207 } else { 208 // Value type is allocated by the callee 209 v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1); 210 } 211 // Need to allocate value type if 'b' is true 212 long sum = v.hashInterpreted(); 213 if (b) { 214 v = MyValue1.createWithFieldsDontInline(rI, sum); 215 } else { 216 v = MyValue1.createWithFieldsDontInline(rI, sum + 1); 217 } 218 // Don't need to allocate value type because both branches allocate 219 return v; 220 } 221 222 @DontCompile 223 public void test9_verifier(boolean warmup) { 224 MyValue1 v = test9(true); 225 Asserts.assertEQ(v.x, rI); 226 Asserts.assertEQ(v.y, hash()); 227 v = test9(false); 228 Asserts.assertEQ(v.x, rI); 229 Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1); 230 } 231 232 // Merge value types created in a loop (not inlined) 233 @Test(failOn = ALLOC + STORE + TRAP) 234 public long test10(int x, long y) { 235 MyValue1 v = MyValue1.createWithFieldsDontInline(x, y); 236 for (int i = 0; i < 10; ++i) { 237 v = MyValue1.createWithFieldsDontInline(v.x + 1, v.y + 1); 238 } 239 return v.hash(); 240 } 241 242 @DontCompile 243 public void test10_verifier(boolean warmup) { 244 long result = test10(rI, rL); 245 Asserts.assertEQ(result, hash(rI + 10, rL + 10)); 246 } 247 248 // Merge value types created in a loop (inlined) 249 @Test(failOn = ALLOC + LOAD + STORE + TRAP) 250 public long test11(int x, long y) { 251 MyValue1 v = MyValue1.createWithFieldsInline(x, y); 252 for (int i = 0; i < 10; ++i) { 253 v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1); 254 } 255 return v.hash(); 256 } 257 258 @DontCompile 259 public void test11_verifier(boolean warmup) { 260 long result = test11(rI, rL); 261 Asserts.assertEQ(result, hash(rI + 10, rL + 10)); 262 } 263 264 // Test loop with uncommon trap referencing a value type 265 @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD) 266 public long test12(boolean b) { 267 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 268 MyValue1[] va = new MyValue1[Math.abs(rI) % 10]; 269 for (int i = 0; i < va.length; ++i) { 270 va[i] = MyValue1.createWithFieldsInline(rI, rL); 271 } 272 long result = rL; 273 for (int i = 0; i < 1000; ++i) { 274 if (b) { 275 result += v.x; 276 } else { 277 // Uncommon trap referencing v. We delegate allocation to the 278 // interpreter by adding a SafePointScalarObjectNode. 279 result = v.hashInterpreted(); 280 for (int j = 0; j < va.length; ++j) { 281 result += va[j].hash(); 282 } 283 } 284 } 285 return result; 286 } 287 288 @DontCompile 289 public void test12_verifier(boolean warmup) { 290 long result = test12(warmup); 291 Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash()); 292 } 293 294 // Test loop with uncommon trap referencing a value type 295 @Test 296 public long test13(boolean b) { 297 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); 298 MyValue1[] va = new MyValue1[Math.abs(rI) % 10]; 299 for (int i = 0; i < va.length; ++i) { 300 va[i] = MyValue1.createWithFieldsDontInline(rI, rL); 301 } 302 long result = rL; 303 for (int i = 0; i < 1000; ++i) { 304 if (b) { 305 result += v.x; 306 } else { 307 // Uncommon trap referencing v. Should not allocate 308 // but just pass the existing oop to the uncommon trap. 309 result = v.hashInterpreted(); 310 for (int j = 0; j < va.length; ++j) { 311 result += va[j].hashInterpreted(); 312 } 313 } 314 } 315 return result; 316 } 317 318 @DontCompile 319 public void test13_verifier(boolean warmup) { 320 long result = test13(warmup); 321 Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash()); 322 } 323 324 // Create a value type in a non-inlined method and then call a 325 // non-inlined method on that value type. 326 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {10}) 327 @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP)) 328 public long test14() { 329 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); 330 return v.hashInterpreted(); 331 } 332 333 @DontCompile 334 public void test14_verifier(boolean b) { 335 long result = test14(); 336 Asserts.assertEQ(result, hash()); 337 } 338 339 // Create a value type in an inlined method and then call a 340 // non-inlined method on that value type. 341 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC)) 342 @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1}) 343 public long test15() { 344 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 345 return v.hashInterpreted(); 346 } 347 348 @DontCompile 349 public void test15_verifier(boolean b) { 350 long result = test15(); 351 Asserts.assertEQ(result, hash()); 352 } 353 354 // Create a value type in a non-inlined method and then call an 355 // inlined method on that value type. 356 @Test(failOn = (ALLOC + STORE + TRAP)) 357 public long test16() { 358 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); 359 return v.hash(); 360 } 361 362 @DontCompile 363 public void test16_verifier(boolean b) { 364 long result = test16(); 365 Asserts.assertEQ(result, hash()); 366 } 367 368 // Create a value type in an inlined method and then call an 369 // inlined method on that value type. 370 @Test(failOn = (ALLOC + LOAD + STORE + TRAP)) 371 public long test17() { 372 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 373 return v.hash(); 374 } 375 376 @DontCompile 377 public void test17_verifier(boolean b) { 378 long result = test17(); 379 Asserts.assertEQ(result, hash()); 380 } 381 382 // Create a value type in compiled code and pass it to the 383 // interpreter via a call. The value is live at the first call so 384 // debug info should include a reference to all its fields. 385 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP) 386 @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP) 387 public long test18() { 388 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 389 v.hashInterpreted(); 390 return v.hashInterpreted(); 391 } 392 393 @DontCompile 394 public void test18_verifier(boolean warmup) { 395 long result = test18(); 396 Asserts.assertEQ(result, hash()); 397 } 398 399 // Create a value type in compiled code and pass it to the 400 // interpreter via a call. The value type is passed twice but 401 // should only be allocated once. 402 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP) 403 @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP) 404 public long test19() { 405 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 406 return sumValue(v, v); 407 } 408 409 @DontCompile 410 public long sumValue(MyValue1 v, MyValue1 dummy) { 411 return v.hash(); 412 } 413 414 @DontCompile 415 public void test19_verifier(boolean warmup) { 416 long result = test19(); 417 Asserts.assertEQ(result, hash()); 418 } 419 420 // Create a value type (array) in compiled code and pass it to the 421 // interpreter via a call. The value type is live at the uncommon 422 // trap: verify that deoptimization causes the value type to be 423 // correctly allocated. 424 @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE) 425 @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD) 426 public long test20(boolean deopt) { 427 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 428 MyValue2[] va = new MyValue2[3]; 429 if (deopt) { 430 // uncommon trap 431 WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test20")); 432 } 433 return v.hashInterpreted() + va[0].hashInterpreted() + 434 va[1].hashInterpreted() + va[2].hashInterpreted(); 435 } 436 437 @DontCompile 438 public void test20_verifier(boolean warmup) { 439 MyValue2[] va = new MyValue2[42]; 440 long result = test20(!warmup); 441 Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash()); 442 } 443 444 // Value type fields in regular object 445 __Flattenable MyValue1 val1; 446 __Flattenable MyValue2 val2; 447 __Flattenable final MyValue1 val3 = MyValue1.createWithFieldsInline(rI, rL); 448 __Flattenable static MyValue1 val4; 449 __Flattenable static final MyValue1 val5 = MyValue1.createWithFieldsInline(rI, rL); 450 451 // Test value type fields in objects 452 @Test(match = {ALLOC}, matchCount = {1}, failOn = (TRAP)) 453 public long test21(int x, long y) { 454 // Compute hash of value type fields 455 long result = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash(); 456 // Update fields 457 val1 = MyValue1.createWithFieldsInline(x, y); 458 val2 = MyValue2.createWithFieldsInline(x, true); 459 val4 = MyValue1.createWithFieldsInline(x, y); 460 return result; 461 } 462 463 @DontCompile 464 public void test21_verifier(boolean warmup) { 465 // Check if hash computed by test18 is correct 466 val1 = MyValue1.createWithFieldsInline(rI, rL); 467 val2 = val1.v2; 468 // val3 is initialized in the constructor 469 val4 = val1; 470 // val5 is initialized in the static initializer 471 long hash = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash(); 472 long result = test21(rI + 1, rL + 1); 473 Asserts.assertEQ(result, hash); 474 // Check if value type fields were updated 475 Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1)); 476 Asserts.assertEQ(val2.hash(), MyValue2.createWithFieldsInline(rI + 1, true).hash()); 477 Asserts.assertEQ(val4.hash(), hash(rI + 1, rL + 1)); 478 } 479 480 // Test folding of constant value type fields 481 @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP) 482 public long test22() { 483 // This should be constant folded 484 return val5.hash() + val5.v3.hash(); 485 } 486 487 @DontCompile 488 public void test22_verifier(boolean warmup) { 489 long result = test22(); 490 Asserts.assertEQ(result, val5.hash() + val5.v3.hash()); 491 } 492 493 // Test defaultvalue 494 @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP) 495 public long test23() { 496 MyValue2 v = MyValue2.createDefaultInline(); 497 return v.hash(); 498 } 499 500 @DontCompile 501 public void test23_verifier(boolean warmup) { 502 long result = test23(); 503 Asserts.assertEQ(result, MyValue2.createDefaultInline().hash()); 504 } 505 506 // Test defaultvalue 507 @Test(failOn = ALLOC + STORE + LOOP + TRAP) 508 public long test24() { 509 MyValue1 v1 = MyValue1.createDefaultInline(); 510 MyValue1 v2 = MyValue1.createDefaultDontInline(); 511 return v1.hashPrimitive() + v2.hashPrimitive(); 512 } 513 514 @DontCompile 515 public void test24_verifier(boolean warmup) { 516 long result = test24(); 517 Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive()); 518 } 519 520 // Test withfield 521 @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP) 522 public long test25() { 523 MyValue2 v = MyValue2.createWithFieldsInline(rI, true); 524 return v.hash(); 525 } 526 527 @DontCompile 528 public void test25_verifier(boolean warmup) { 529 long result = test25(); 530 Asserts.assertEQ(result, MyValue2.createWithFieldsInline(rI, true).hash()); 531 } 532 533 // Test withfield 534 @Test(failOn = ALLOC + STORE + LOOP + TRAP) 535 public long test26() { 536 MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL); 537 MyValue1 v2 = MyValue1.createWithFieldsDontInline(rI, rL); 538 return v1.hash() + v2.hash(); 539 } 540 541 @DontCompile 542 public void test26_verifier(boolean warmup) { 543 long result = test26(); 544 Asserts.assertEQ(result, 2 * hash()); 545 } 546 547 class TestClass27 { 548 __Flattenable public MyValue1 v; 549 } 550 551 // Test allocation elimination of unused object with initialized value type field 552 @Test(failOn = ALLOC + LOAD + STORE + LOOP) 553 public void test27(boolean deopt) { 554 TestClass27 unused = new TestClass27(); 555 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 556 unused.v = v; 557 if (deopt) { 558 // uncommon trap 559 WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test27")); 560 } 561 } 562 563 @DontCompile 564 public void test27_verifier(boolean warmup) { 565 test27(!warmup); 566 } 567 568 __Flattenable static MyValue3 staticVal3; 569 __Flattenable static MyValue3 staticVal3_copy; 570 571 // Check elimination of redundant value type allocations 572 @Test(match = {ALLOC}, matchCount = {1}) 573 public MyValue3 test28(MyValue3[] va) { 574 // Create value type and force allocation 575 MyValue3 vt = MyValue3.create(); 576 va[0] = vt; 577 staticVal3 = vt; 578 vt.verify(staticVal3); 579 580 // Value type is now allocated, make a copy and force allocation. 581 // Because copy is equal to vt, C2 should remove this redundant allocation. 582 MyValue3 copy = MyValue3.setC(vt, vt.c); 583 va[0] = copy; 584 staticVal3_copy = copy; 585 copy.verify(staticVal3_copy); 586 return copy; 587 } 588 589 @DontCompile 590 public void test28_verifier(boolean warmup) { 591 MyValue3[] va = new MyValue3[1]; 592 MyValue3 vt = test28(va); 593 staticVal3.verify(vt); 594 staticVal3.verify(va[0]); 595 staticVal3_copy.verify(vt); 596 staticVal3_copy.verify(va[0]); 597 } 598 599 // Verify that only dominating allocations are re-used 600 @Test() 601 public MyValue3 test29(boolean warmup) { 602 MyValue3 vt = MyValue3.create(); 603 if (warmup) { 604 staticVal3 = vt; // Force allocation 605 } 606 // Force allocation to verify that above 607 // non-dominating allocation is not re-used 608 MyValue3 copy = MyValue3.setC(vt, vt.c); 609 staticVal3_copy = copy; 610 copy.verify(vt); 611 return copy; 612 } 613 614 @DontCompile 615 public void test29_verifier(boolean warmup) { 616 MyValue3 vt = test29(warmup); 617 if (warmup) { 618 staticVal3.verify(vt); 619 } 620 } 621 622 // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations 623 @Test(failOn = ALLOC + ALLOCA + STORE) 624 public MyValue3 test30(MyValue3[] va) { 625 // C2 can re-use the oop of staticVal3 because staticVal3 is equal to copy 626 MyValue3 copy = MyValue3.copy(staticVal3); 627 va[0] = copy; 628 staticVal3 = copy; 629 copy.verify(staticVal3); 630 return copy; 631 } 632 633 @DontCompile 634 public void test30_verifier(boolean warmup) { 635 staticVal3 = MyValue3.create(); 636 MyValue3[] va = new MyValue3[1]; 637 MyValue3 vt = test30(va); 638 staticVal3.verify(vt); 639 staticVal3.verify(va[0]); 640 } 641 642 // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations 643 @Test(valid = ValueTypeReturnedAsFieldsOff, failOn = ALLOC + ALLOCA + STORE) 644 @Test(valid = ValueTypeReturnedAsFieldsOn) 645 public MyValue3 test31(MyValue3[] va) { 646 // C2 can re-use the oop returned by createDontInline() 647 // because the corresponding value type is equal to 'copy'. 648 MyValue3 copy = MyValue3.copy(MyValue3.createDontInline()); 649 va[0] = copy; 650 staticVal3 = copy; 651 copy.verify(staticVal3); 652 return copy; 653 } 654 655 @DontCompile 656 public void test31_verifier(boolean warmup) { 657 MyValue3[] va = new MyValue3[1]; 658 MyValue3 vt = test31(va); 659 staticVal3.verify(vt); 660 staticVal3.verify(va[0]); 661 } 662 663 // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations 664 @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + ALLOCA + STORE) 665 @Test(valid = ValueTypePassFieldsAsArgsOn) 666 public MyValue3 test32(MyValue3 vt, MyValue3[] va) { 667 // C2 can re-use the oop of vt because vt is equal to 'copy'. 668 MyValue3 copy = MyValue3.copy(vt); 669 va[0] = copy; 670 staticVal3 = copy; 671 copy.verify(staticVal3); 672 return copy; 673 } 674 675 @DontCompile 676 public void test32_verifier(boolean warmup) { 677 MyValue3 vt = MyValue3.create(); 678 MyValue3[] va = new MyValue3[1]; 679 MyValue3 result = test32(vt, va); 680 staticVal3.verify(vt); 681 va[0].verify(vt); 682 result.verify(vt); 683 } 684 685 // Test correct identification of value type copies 686 @Test() 687 public MyValue3 test33(MyValue3[] va) { 688 MyValue3 vt = MyValue3.copy(staticVal3); 689 vt = MyValue3.setI(vt, vt.c); 690 // vt is not equal to staticVal3, so C2 should not re-use the oop 691 va[0] = vt; 692 staticVal3 = vt; 693 vt.verify(staticVal3); 694 return vt; 695 } 696 697 @DontCompile 698 public void test33_verifier(boolean warmup) { 699 staticVal3 = MyValue3.create(); 700 MyValue3[] va = new MyValue3[1]; 701 MyValue3 vt = test33(va); 702 Asserts.assertEQ(staticVal3.i, (int)staticVal3.c); 703 Asserts.assertEQ(va[0].i, (int)staticVal3.c); 704 Asserts.assertEQ(vt.i, (int)staticVal3.c); 705 } 706 707 // Verify that the default value type is never allocated. 708 // C2 code should load and use the default oop from the java mirror. 709 @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP) 710 public MyValue3 test34(MyValue3[] va) { 711 // Explicitly create default value 712 MyValue3 vt = MyValue3.createDefault(); 713 va[0] = vt; 714 staticVal3 = vt; 715 vt.verify(vt); 716 717 // Load default value from uninitialized value array 718 MyValue3[] dva = new MyValue3[1]; 719 staticVal3_copy = dva[0]; 720 va[1] = dva[0]; 721 dva[0].verify(dva[0]); 722 return vt; 723 } 724 725 @DontCompile 726 public void test34_verifier(boolean warmup) { 727 MyValue3 vt = MyValue3.createDefault(); 728 MyValue3[] va = new MyValue3[2]; 729 va[0] = MyValue3.create(); 730 va[1] = MyValue3.create(); 731 MyValue3 res = test34(va); 732 res.verify(vt); 733 staticVal3.verify(vt); 734 staticVal3_copy.verify(vt); 735 va[0].verify(vt); 736 va[1].verify(vt); 737 } 738 739 // Same as above but manually initialize value type fields to default. 740 @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP) 741 public MyValue3 test35(MyValue3 vt, MyValue3[] va) { 742 vt = MyValue3.setC(vt, (char)0); 743 vt = MyValue3.setBB(vt, (byte)0); 744 vt = MyValue3.setS(vt, (short)0); 745 vt = MyValue3.setI(vt, 0); 746 vt = MyValue3.setL(vt, 0); 747 vt = MyValue3.setO(vt, null); 748 vt = MyValue3.setF1(vt, 0); 749 vt = MyValue3.setF2(vt, 0); 750 vt = MyValue3.setF3(vt, 0); 751 vt = MyValue3.setF4(vt, 0); 752 vt = MyValue3.setF5(vt, 0); 753 vt = MyValue3.setF6(vt, 0); 754 vt = MyValue3.setV1(vt, MyValue3Inline.createDefault()); 755 va[0] = vt; 756 staticVal3 = vt; 757 vt.verify(vt); 758 return vt; 759 } 760 761 @DontCompile 762 public void test35_verifier(boolean warmup) { 763 MyValue3 vt = MyValue3.createDefault(); 764 MyValue3[] va = new MyValue3[1]; 765 va[0] = MyValue3.create(); 766 MyValue3 res = test35(va[0], va); 767 res.verify(vt); 768 staticVal3.verify(vt); 769 va[0].verify(vt); 770 } 771 }