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 -XDemitQtypes -XDenableValueTypes -XDallowWithFieldOperator -XDallowFlattenabilityModifiers 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:+EnableValhalla
  37  *                               compiler.valhalla.valuetypes.ValueTypeTest
  38  *                               compiler.valhalla.valuetypes.TestBasicFunctionality
  39  */
  40 public class TestBasicFunctionality extends ValueTypeTest {
  41     // Extra VM parameters for some test scenarios. See ValueTypeTest.getVMParameters()
  42     @Override
  43     public String[] getExtraVMParameters(int scenario) {
  44         switch (scenario) {
  45         case 3: return new String[] {"-XX:-ValueArrayFlatten"};
  46         }
  47         return null;
  48     }
  49 
  50     public static void main(String[] args) throws Throwable {
  51         TestBasicFunctionality test = new TestBasicFunctionality();
  52         test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class);
  53     }
  54 
  55     // Helper methods
  56 
  57     protected long hash() {
  58         return hash(rI, rL);
  59     }
  60 
  61     protected long hash(int x, long y) {
  62         return MyValue1.createWithFieldsInline(x, y).hash();
  63     }
  64 
  65     // Receive value type through call to interpreter
  66     @Test(failOn = ALLOC + STORE + TRAP)
  67     public long test1() {
  68         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
  69         return v.hash();
  70     }
  71 
  72     @DontCompile
  73     public void test1_verifier(boolean warmup) {
  74         long result = test1();
  75         Asserts.assertEQ(result, hash());
  76     }
  77 
  78     // Receive value type from interpreter via parameter
  79     @Test(failOn = ALLOC + STORE + TRAP)
  80     public long test2(MyValue1 v) {
  81         return v.hash();
  82     }
  83 
  84     @DontCompile
  85     public void test2_verifier(boolean warmup) {
  86         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
  87         long result = test2(v);
  88         Asserts.assertEQ(result, hash());
  89     }
  90 
  91     // Return incoming value type without accessing fields
  92     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount = {1, 14}, failOn = LOAD + TRAP)
  93     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + LOAD + STORE + TRAP)
  94     public MyValue1 test3(MyValue1 v) {
  95         return v;
  96     }
  97 
  98     @DontCompile
  99     public void test3_verifier(boolean warmup) {
 100         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 101         MyValue1 v2 = test3(v1);
 102         Asserts.assertEQ(v1.x, v2.x);
 103         Asserts.assertEQ(v1.y, v2.y);
 104     }
 105 
 106     // Create a value type in compiled code and only use fields.
 107     // Allocation should go away because value type does not escape.
 108     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 109     public long test4() {
 110         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 111         return v.hash();
 112     }
 113 
 114     @DontCompile
 115     public void test4_verifier(boolean warmup) {
 116         long result = test4();
 117         Asserts.assertEQ(result, hash());
 118     }
 119 
 120     // Create a value type in compiled code and pass it to
 121     // an inlined compiled method via a call.
 122     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 123     public long test5() {
 124         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 125         return test5Inline(v);
 126     }
 127 
 128     @ForceInline
 129     public long test5Inline(MyValue1 v) {
 130         return v.hash();
 131     }
 132 
 133     @DontCompile
 134     public void test5_verifier(boolean warmup) {
 135         long result = test5();
 136         Asserts.assertEQ(result, hash());
 137     }
 138 
 139     // Create a value type in compiled code and pass it to
 140     // the interpreter via a call.
 141 // TODO enable once receiver is scalarized
 142 //    @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC)
 143     @Test(valid = ValueTypePassFieldsAsArgsOn)
 144     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 145     public long test6() {
 146         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 147         // Pass to interpreter
 148         return v.hashInterpreted();
 149     }
 150 
 151     @DontCompile
 152     public void test6_verifier(boolean warmup) {
 153         long result = test6();
 154         Asserts.assertEQ(result, hash());
 155     }
 156 
 157     // Create a value type in compiled code and pass it to
 158     // the interpreter by returning.
 159     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 160     public MyValue1 test7(int x, long y) {
 161         return MyValue1.createWithFieldsInline(x, y);
 162     }
 163 
 164     @DontCompile
 165     public void test7_verifier(boolean warmup) {
 166         MyValue1 v = test7(rI, rL);
 167         Asserts.assertEQ(v.hash(), hash());
 168     }
 169 
 170     // Merge value types created from two branches
 171     @Test(valid = AlwaysIncrementalInlineOn, match = {ALLOC, STORE, LOAD}, matchCount = {1, 5, 12}, failOn = TRAP)
 172     @Test(valid = AlwaysIncrementalInlineOff, failOn = ALLOC + STORE + TRAP)
 173     public long test8(boolean b) {
 174         MyValue1 v;
 175         if (b) {
 176             v = MyValue1.createWithFieldsInline(rI, rL);
 177         } else {
 178             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 179         }
 180         return v.hash();
 181     }
 182 
 183     @DontCompile
 184     public void test8_verifier(boolean warmup) {
 185         Asserts.assertEQ(test8(true), hash());
 186         Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
 187     }
 188 
 189     // Merge value types created from two branches
 190 // TODO enable once receiver is scalarized
 191 //    @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {10}, failOn = TRAP + ALLOC + STORE)
 192     @Test(valid = ValueTypePassFieldsAsArgsOn)
 193     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 5}, failOn = LOAD + TRAP)
 194     public MyValue1 test9(boolean b) {
 195         MyValue1 v;
 196         if (b) {
 197             // Value type is not allocated
 198             v = MyValue1.createWithFieldsInline(rI, rL);
 199         } else {
 200             // Value type is allocated by the callee
 201             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 202         }
 203         // Need to allocate value type if 'b' is true
 204         long sum = v.hashInterpreted();
 205         if (b) {
 206             v = MyValue1.createWithFieldsDontInline(rI, sum);
 207         } else {
 208             v = MyValue1.createWithFieldsDontInline(rI, sum + 1);
 209         }
 210         // Don't need to allocate value type because both branches allocate
 211         return v;
 212     }
 213 
 214     @DontCompile
 215     public void test9_verifier(boolean warmup) {
 216         MyValue1 v = test9(true);
 217         Asserts.assertEQ(v.x, rI);
 218         Asserts.assertEQ(v.y, hash());
 219         v = test9(false);
 220         Asserts.assertEQ(v.x, rI);
 221         Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
 222     }
 223 
 224     // Merge value types created in a loop (not inlined)
 225     @Test(failOn = ALLOC + STORE + TRAP)
 226     public long test10(int x, long y) {
 227         MyValue1 v = MyValue1.createWithFieldsDontInline(x, y);
 228         for (int i = 0; i < 10; ++i) {
 229             v = MyValue1.createWithFieldsDontInline(v.x + 1, v.y + 1);
 230         }
 231         return v.hash();
 232     }
 233 
 234     @DontCompile
 235     public void test10_verifier(boolean warmup) {
 236         long result = test10(rI, rL);
 237         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 238     }
 239 
 240     // Merge value types created in a loop (inlined)
 241     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 242     public long test11(int x, long y) {
 243         MyValue1 v = MyValue1.createWithFieldsInline(x, y);
 244         for (int i = 0; i < 10; ++i) {
 245             v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
 246         }
 247         return v.hash();
 248     }
 249 
 250     @DontCompile
 251     public void test11_verifier(boolean warmup) {
 252         long result = test11(rI, rL);
 253         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 254     }
 255 
 256     // Test loop with uncommon trap referencing a value type
 257     @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD)
 258     public long test12(boolean b) {
 259         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 260         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 261         for (int i = 0; i < va.length; ++i) {
 262             va[i] = MyValue1.createWithFieldsInline(rI, rL);
 263         }
 264         long result = rL;
 265         for (int i = 0; i < 1000; ++i) {
 266             if (b) {
 267                 result += v.x;
 268             } else {
 269                 // Uncommon trap referencing v. We delegate allocation to the
 270                 // interpreter by adding a SafePointScalarObjectNode.
 271                 result = v.hashInterpreted();
 272                 for (int j = 0; j < va.length; ++j) {
 273                     result += va[j].hash();
 274                 }
 275             }
 276         }
 277         return result;
 278     }
 279 
 280     @DontCompile
 281     public void test12_verifier(boolean warmup) {
 282         long result = test12(warmup);
 283         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 284     }
 285 
 286     // Test loop with uncommon trap referencing a value type
 287     @Test
 288     public long test13(boolean b) {
 289         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 290         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 291         for (int i = 0; i < va.length; ++i) {
 292             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
 293         }
 294         long result = rL;
 295         for (int i = 0; i < 1000; ++i) {
 296             if (b) {
 297                 result += v.x;
 298             } else {
 299                 // Uncommon trap referencing v. Should not allocate
 300                 // but just pass the existing oop to the uncommon trap.
 301                 result = v.hashInterpreted();
 302                 for (int j = 0; j < va.length; ++j) {
 303                     result += va[j].hashInterpreted();
 304                 }
 305             }
 306         }
 307         return result;
 308     }
 309 
 310     @DontCompile
 311     public void test13_verifier(boolean warmup) {
 312         long result = test13(warmup);
 313         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 314     }
 315 
 316     // Create a value type in a non-inlined method and then call a
 317     // non-inlined method on that value type.
 318 // TODO enable once receiver is scalarized
 319 //    @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {10})
 320     @Test(valid = ValueTypePassFieldsAsArgsOn)
 321     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
 322     public long test14() {
 323         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 324         return v.hashInterpreted();
 325     }
 326 
 327     @DontCompile
 328     public void test14_verifier(boolean b) {
 329         long result = test14();
 330         Asserts.assertEQ(result, hash());
 331     }
 332 
 333     // Create a value type in an inlined method and then call a
 334     // non-inlined method on that value type.
 335 // TODO enable once receiver is scalarized
 336 //    @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC))
 337     @Test(valid = ValueTypePassFieldsAsArgsOn)
 338     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
 339     public long test15() {
 340         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 341         return v.hashInterpreted();
 342     }
 343 
 344     @DontCompile
 345     public void test15_verifier(boolean b) {
 346         long result = test15();
 347         Asserts.assertEQ(result, hash());
 348     }
 349 
 350     // Create a value type in a non-inlined method and then call an
 351     // inlined method on that value type.
 352     @Test(failOn = (ALLOC + STORE + TRAP))
 353     public long test16() {
 354         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 355         return v.hash();
 356     }
 357 
 358     @DontCompile
 359     public void test16_verifier(boolean b) {
 360         long result = test16();
 361         Asserts.assertEQ(result, hash());
 362     }
 363 
 364     // Create a value type in an inlined method and then call an
 365     // inlined method on that value type.
 366     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
 367     public long test17() {
 368         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 369         return v.hash();
 370     }
 371 
 372     @DontCompile
 373     public void test17_verifier(boolean b) {
 374         long result = test17();
 375         Asserts.assertEQ(result, hash());
 376     }
 377 
 378     // Create a value type in compiled code and pass it to the
 379     // interpreter via a call. The value is live at the first call so
 380     // debug info should include a reference to all its fields.
 381 // TODO enable once receiver is scalarized
 382 //    @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 383     @Test(valid = ValueTypePassFieldsAsArgsOn)
 384     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 385     public long test18() {
 386         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 387         v.hashInterpreted();
 388         return v.hashInterpreted();
 389     }
 390 
 391     @DontCompile
 392     public void test18_verifier(boolean warmup) {
 393         long result = test18();
 394         Asserts.assertEQ(result, hash());
 395     }
 396 
 397     // Create a value type in compiled code and pass it to the
 398     // interpreter via a call. The value type is passed twice but
 399     // should only be allocated once.
 400     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 401     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 402     public long test19() {
 403         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 404         return sumValue(v, v);
 405     }
 406 
 407     @DontCompile
 408     public long sumValue(MyValue1 v, MyValue1 dummy) {
 409         return v.hash();
 410     }
 411 
 412     @DontCompile
 413     public void test19_verifier(boolean warmup) {
 414         long result = test19();
 415         Asserts.assertEQ(result, hash());
 416     }
 417 
 418     // Create a value type (array) in compiled code and pass it to the
 419     // interpreter via a call. The value type is live at the uncommon
 420     // trap: verify that deoptimization causes the value type to be
 421     // correctly allocated.
 422 // TODO enable once receiver is scalarized
 423 //    @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
 424     @Test(valid = ValueTypePassFieldsAsArgsOn)
 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     MyValue1.val val1;
 446     MyValue2.val val2;
 447     final MyValue1.val val3 = MyValue1.createWithFieldsInline(rI, rL);
 448     static MyValue1.val val4;
 449     static final MyValue1.val 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         public MyValue1.val 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     static MyValue3.val staticVal3;
 569     static MyValue3.val 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 = ValueTypeReturnedAsFieldsOn)
 644     @Test(valid = ValueTypeReturnedAsFieldsOff, failOn = ALLOC + ALLOCA + STORE)
 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 = ValueTypePassFieldsAsArgsOn)
 665     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + ALLOCA + STORE)
 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 }