1 /*
   2  * Copyright (c) 2017, 2019, 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 -XDallowWithFieldOperator TestBasicFunctionality.java
  34  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  35  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -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     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC)
 142     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 143     public long test6() {
 144         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 145         // Pass to interpreter
 146         return v.hashInterpreted();
 147     }
 148 
 149     @DontCompile
 150     public void test6_verifier(boolean warmup) {
 151         long result = test6();
 152         Asserts.assertEQ(result, hash());
 153     }
 154 
 155     // Create a value type in compiled code and pass it to
 156     // the interpreter by returning.
 157     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 158     public MyValue1 test7(int x, long y) {
 159         return MyValue1.createWithFieldsInline(x, y);
 160     }
 161 
 162     @DontCompile
 163     public void test7_verifier(boolean warmup) {
 164         MyValue1 v = test7(rI, rL);
 165         Asserts.assertEQ(v.hash(), hash());
 166     }
 167 
 168     // Merge value types created from two branches
 169     @Test(failOn = ALLOC + STORE + TRAP)
 170     public long test8(boolean b) {
 171         MyValue1 v;
 172         if (b) {
 173             v = MyValue1.createWithFieldsInline(rI, rL);
 174         } else {
 175             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 176         }
 177         return v.hash();
 178     }
 179 
 180     @DontCompile
 181     public void test8_verifier(boolean warmup) {
 182         Asserts.assertEQ(test8(true), hash());
 183         Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
 184     }
 185 
 186     // Merge value types created from two branches
 187     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {12}, failOn = TRAP + ALLOC + STORE)
 188     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 5}, failOn = LOAD + TRAP)
 189     public MyValue1 test9(boolean b) {
 190         MyValue1 v;
 191         if (b) {
 192             // Value type is not allocated
 193             v = MyValue1.createWithFieldsInline(rI, rL);
 194         } else {
 195             // Value type is allocated by the callee
 196             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 197         }
 198         // Need to allocate value type if 'b' is true
 199         long sum = v.hashInterpreted();
 200         if (b) {
 201             v = MyValue1.createWithFieldsDontInline(rI, sum);
 202         } else {
 203             v = MyValue1.createWithFieldsDontInline(rI, sum + 1);
 204         }
 205         // Don't need to allocate value type because both branches allocate
 206         return v;
 207     }
 208 
 209     @DontCompile
 210     public void test9_verifier(boolean warmup) {
 211         MyValue1 v = test9(true);
 212         Asserts.assertEQ(v.x, rI);
 213         Asserts.assertEQ(v.y, hash());
 214         v = test9(false);
 215         Asserts.assertEQ(v.x, rI);
 216         Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
 217     }
 218 
 219     // Merge value types created in a loop (not inlined)
 220     @Test(failOn = ALLOC + STORE + TRAP)
 221     public long test10(int x, long y) {
 222         MyValue1 v = MyValue1.createWithFieldsDontInline(x, y);
 223         for (int i = 0; i < 10; ++i) {
 224             v = MyValue1.createWithFieldsDontInline(v.x + 1, v.y + 1);
 225         }
 226         return v.hash();
 227     }
 228 
 229     @DontCompile
 230     public void test10_verifier(boolean warmup) {
 231         long result = test10(rI, rL);
 232         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 233     }
 234 
 235     // Merge value types created in a loop (inlined)
 236     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 237     public long test11(int x, long y) {
 238         MyValue1 v = MyValue1.createWithFieldsInline(x, y);
 239         for (int i = 0; i < 10; ++i) {
 240             v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
 241         }
 242         return v.hash();
 243     }
 244 
 245     @DontCompile
 246     public void test11_verifier(boolean warmup) {
 247         long result = test11(rI, rL);
 248         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 249     }
 250 
 251     // Test loop with uncommon trap referencing a value type
 252     @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD)
 253     public long test12(boolean b) {
 254         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 255         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 256         for (int i = 0; i < va.length; ++i) {
 257             va[i] = MyValue1.createWithFieldsInline(rI, rL);
 258         }
 259         long result = rL;
 260         for (int i = 0; i < 1000; ++i) {
 261             if (b) {
 262                 result += v.x;
 263             } else {
 264                 // Uncommon trap referencing v. We delegate allocation to the
 265                 // interpreter by adding a SafePointScalarObjectNode.
 266                 result = v.hashInterpreted();
 267                 for (int j = 0; j < va.length; ++j) {
 268                     result += va[j].hash();
 269                 }
 270             }
 271         }
 272         return result;
 273     }
 274 
 275     @DontCompile
 276     public void test12_verifier(boolean warmup) {
 277         long result = test12(warmup);
 278         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 279     }
 280 
 281     // Test loop with uncommon trap referencing a value type
 282     @Test
 283     public long test13(boolean b) {
 284         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 285         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 286         for (int i = 0; i < va.length; ++i) {
 287             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
 288         }
 289         long result = rL;
 290         for (int i = 0; i < 1000; ++i) {
 291             if (b) {
 292                 result += v.x;
 293             } else {
 294                 // Uncommon trap referencing v. Should not allocate
 295                 // but just pass the existing oop to the uncommon trap.
 296                 result = v.hashInterpreted();
 297                 for (int j = 0; j < va.length; ++j) {
 298                     result += va[j].hashInterpreted();
 299                 }
 300             }
 301         }
 302         return result;
 303     }
 304 
 305     @DontCompile
 306     public void test13_verifier(boolean warmup) {
 307         long result = test13(warmup);
 308         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 309     }
 310 
 311     // Create a value type in a non-inlined method and then call a
 312     // non-inlined method on that value type.
 313     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {12})
 314     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
 315     public long test14() {
 316         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 317         return v.hashInterpreted();
 318     }
 319 
 320     @DontCompile
 321     public void test14_verifier(boolean b) {
 322         long result = test14();
 323         Asserts.assertEQ(result, hash());
 324     }
 325 
 326     // Create a value type in an inlined method and then call a
 327     // non-inlined method on that value type.
 328     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC))
 329     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
 330     public long test15() {
 331         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 332         return v.hashInterpreted();
 333     }
 334 
 335     @DontCompile
 336     public void test15_verifier(boolean b) {
 337         long result = test15();
 338         Asserts.assertEQ(result, hash());
 339     }
 340 
 341     // Create a value type in a non-inlined method and then call an
 342     // inlined method on that value type.
 343     @Test(failOn = (ALLOC + STORE + TRAP))
 344     public long test16() {
 345         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 346         return v.hash();
 347     }
 348 
 349     @DontCompile
 350     public void test16_verifier(boolean b) {
 351         long result = test16();
 352         Asserts.assertEQ(result, hash());
 353     }
 354 
 355     // Create a value type in an inlined method and then call an
 356     // inlined method on that value type.
 357     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
 358     public long test17() {
 359         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 360         return v.hash();
 361     }
 362 
 363     @DontCompile
 364     public void test17_verifier(boolean b) {
 365         long result = test17();
 366         Asserts.assertEQ(result, hash());
 367     }
 368 
 369     // Create a value type in compiled code and pass it to the
 370     // interpreter via a call. The value is live at the first call so
 371     // debug info should include a reference to all its fields.
 372     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 373     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 374     public long test18() {
 375         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 376         v.hashInterpreted();
 377         return v.hashInterpreted();
 378     }
 379 
 380     @DontCompile
 381     public void test18_verifier(boolean warmup) {
 382         long result = test18();
 383         Asserts.assertEQ(result, hash());
 384     }
 385 
 386     // Create a value type in compiled code and pass it to the
 387     // interpreter via a call. The value type is passed twice but
 388     // should only be allocated once.
 389     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 390     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 391     public long test19() {
 392         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 393         return sumValue(v, v);
 394     }
 395 
 396     @DontCompile
 397     public long sumValue(MyValue1 v, MyValue1 dummy) {
 398         return v.hash();
 399     }
 400 
 401     @DontCompile
 402     public void test19_verifier(boolean warmup) {
 403         long result = test19();
 404         Asserts.assertEQ(result, hash());
 405     }
 406 
 407     // Create a value type (array) in compiled code and pass it to the
 408     // interpreter via a call. The value type is live at the uncommon
 409     // trap: verify that deoptimization causes the value type to be
 410     // correctly allocated.
 411     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
 412     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD)
 413     public long test20(boolean deopt) {
 414         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 415         MyValue2[] va = new MyValue2[3];
 416         if (deopt) {
 417             // uncommon trap
 418             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test20"));
 419         }
 420         return v.hashInterpreted() + va[0].hashInterpreted() +
 421                 va[1].hashInterpreted() + va[2].hashInterpreted();
 422     }
 423 
 424     @DontCompile
 425     public void test20_verifier(boolean warmup) {
 426         MyValue2[] va = new MyValue2[42];
 427         long result = test20(!warmup);
 428         Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
 429     }
 430 
 431     // Value type fields in regular object
 432     MyValue1.val val1;
 433     MyValue2.val val2;
 434     final MyValue1.val val3 = MyValue1.createWithFieldsInline(rI, rL);
 435     static MyValue1.val val4;
 436     static final MyValue1.val val5 = MyValue1.createWithFieldsInline(rI, rL);
 437 
 438     // Test value type fields in objects
 439     @Test(match = {ALLOC}, matchCount = {1}, failOn = (TRAP))
 440     public long test21(int x, long y) {
 441         // Compute hash of value type fields
 442         long result = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 443         // Update fields
 444         val1 = MyValue1.createWithFieldsInline(x, y);
 445         val2 = MyValue2.createWithFieldsInline(x, true);
 446         val4 = MyValue1.createWithFieldsInline(x, y);
 447         return result;
 448     }
 449 
 450     @DontCompile
 451     public void test21_verifier(boolean warmup) {
 452         // Check if hash computed by test18 is correct
 453         val1 = MyValue1.createWithFieldsInline(rI, rL);
 454         val2 = val1.v2;
 455         // val3 is initialized in the constructor
 456         val4 = val1;
 457         // val5 is initialized in the static initializer
 458         long hash = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 459         long result = test21(rI + 1, rL + 1);
 460         Asserts.assertEQ(result, hash);
 461         // Check if value type fields were updated
 462         Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1));
 463         Asserts.assertEQ(val2.hash(), MyValue2.createWithFieldsInline(rI + 1, true).hash());
 464         Asserts.assertEQ(val4.hash(), hash(rI + 1, rL + 1));
 465     }
 466 
 467     // Test folding of constant value type fields
 468     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 469     public long test22() {
 470         // This should be constant folded
 471         return val5.hash() + val5.v3.hash();
 472     }
 473 
 474     @DontCompile
 475     public void test22_verifier(boolean warmup) {
 476         long result = test22();
 477         Asserts.assertEQ(result, val5.hash() + val5.v3.hash());
 478     }
 479 
 480     // Test defaultvalue
 481     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 482     public long test23() {
 483         MyValue2 v = MyValue2.createDefaultInline();
 484         return v.hash();
 485     }
 486 
 487     @DontCompile
 488     public void test23_verifier(boolean warmup) {
 489         long result = test23();
 490         Asserts.assertEQ(result, MyValue2.createDefaultInline().hash());
 491     }
 492 
 493     // Test defaultvalue
 494     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
 495     public long test24() {
 496         MyValue1 v1 = MyValue1.createDefaultInline();
 497         MyValue1 v2 = MyValue1.createDefaultDontInline();
 498         return v1.hashPrimitive() + v2.hashPrimitive();
 499     }
 500 
 501     @DontCompile
 502     public void test24_verifier(boolean warmup) {
 503         long result = test24();
 504         Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive());
 505     }
 506 
 507     // Test withfield
 508     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 509     public long test25() {
 510         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 511         return v.hash();
 512     }
 513 
 514     @DontCompile
 515     public void test25_verifier(boolean warmup) {
 516         long result = test25();
 517         Asserts.assertEQ(result, MyValue2.createWithFieldsInline(rI, true).hash());
 518     }
 519 
 520     // Test withfield
 521     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
 522     public long test26() {
 523         MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL);
 524         MyValue1 v2 = MyValue1.createWithFieldsDontInline(rI, rL);
 525         return v1.hash() + v2.hash();
 526     }
 527 
 528     @DontCompile
 529     public void test26_verifier(boolean warmup) {
 530         long result = test26();
 531         Asserts.assertEQ(result, 2 * hash());
 532     }
 533 
 534     class TestClass27 {
 535         public MyValue1.val v;
 536     }
 537 
 538     // Test allocation elimination of unused object with initialized value type field
 539     @Test(failOn = ALLOC + LOAD + STORE + LOOP)
 540     public void test27(boolean deopt) {
 541         TestClass27 unused = new TestClass27();
 542         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 543         unused.v = v;
 544         if (deopt) {
 545             // uncommon trap
 546             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test27"));
 547         }
 548     }
 549 
 550     @DontCompile
 551     public void test27_verifier(boolean warmup) {
 552         test27(!warmup);
 553     }
 554 
 555     static MyValue3.val staticVal3;
 556     static MyValue3.val staticVal3_copy;
 557 
 558     // Check elimination of redundant value type allocations
 559     @Test(match = {ALLOC}, matchCount = {1})
 560     public MyValue3 test28(MyValue3[] va) {
 561         // Create value type and force allocation
 562         MyValue3 vt = MyValue3.create();
 563         va[0] = vt;
 564         staticVal3 = vt;
 565         vt.verify(staticVal3);
 566 
 567         // Value type is now allocated, make a copy and force allocation.
 568         // Because copy is equal to vt, C2 should remove this redundant allocation.
 569         MyValue3 copy = MyValue3.setC(vt, vt.c);
 570         va[0] = copy;
 571         staticVal3_copy = copy;
 572         copy.verify(staticVal3_copy);
 573         return copy;
 574     }
 575 
 576     @DontCompile
 577     public void test28_verifier(boolean warmup) {
 578         MyValue3[] va = new MyValue3[1];
 579         MyValue3 vt = test28(va);
 580         staticVal3.verify(vt);
 581         staticVal3.verify(va[0]);
 582         staticVal3_copy.verify(vt);
 583         staticVal3_copy.verify(va[0]);
 584     }
 585 
 586     // Verify that only dominating allocations are re-used
 587     @Test()
 588     public MyValue3 test29(boolean warmup) {
 589         MyValue3 vt = MyValue3.create();
 590         if (warmup) {
 591             staticVal3 = vt; // Force allocation
 592         }
 593         // Force allocation to verify that above
 594         // non-dominating allocation is not re-used
 595         MyValue3 copy = MyValue3.setC(vt, vt.c);
 596         staticVal3_copy = copy;
 597         copy.verify(vt);
 598         return copy;
 599     }
 600 
 601     @DontCompile
 602     public void test29_verifier(boolean warmup) {
 603         MyValue3 vt = test29(warmup);
 604         if (warmup) {
 605             staticVal3.verify(vt);
 606         }
 607     }
 608 
 609     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
 610     @Test(failOn = ALLOC + ALLOCA + STORE)
 611     public MyValue3 test30(MyValue3[] va) {
 612         // C2 can re-use the oop of staticVal3 because staticVal3 is equal to copy
 613         MyValue3 copy = MyValue3.copy(staticVal3);
 614         va[0] = copy;
 615         staticVal3 = copy;
 616         copy.verify(staticVal3);
 617         return copy;
 618     }
 619 
 620     @DontCompile
 621     public void test30_verifier(boolean warmup) {
 622         staticVal3 = MyValue3.create();
 623         MyValue3[] va = new MyValue3[1];
 624         MyValue3 vt = test30(va);
 625         staticVal3.verify(vt);
 626         staticVal3.verify(va[0]);
 627     }
 628 
 629     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
 630     @Test(valid = ValueTypeReturnedAsFieldsOn)
 631     @Test(valid = ValueTypeReturnedAsFieldsOff, failOn = ALLOC + ALLOCA + STORE)
 632     public MyValue3 test31(MyValue3[] va) {
 633         // C2 can re-use the oop returned by createDontInline()
 634         // because the corresponding value type is equal to 'copy'.
 635         MyValue3 copy = MyValue3.copy(MyValue3.createDontInline());
 636         va[0] = copy;
 637         staticVal3 = copy;
 638         copy.verify(staticVal3);
 639         return copy;
 640     }
 641 
 642     @DontCompile
 643     public void test31_verifier(boolean warmup) {
 644         MyValue3[] va = new MyValue3[1];
 645         MyValue3 vt = test31(va);
 646         staticVal3.verify(vt);
 647         staticVal3.verify(va[0]);
 648     }
 649 
 650     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
 651     @Test(valid = ValueTypePassFieldsAsArgsOn)
 652     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + ALLOCA + STORE)
 653     public MyValue3 test32(MyValue3 vt, MyValue3[] va) {
 654         // C2 can re-use the oop of vt because vt is equal to 'copy'.
 655         MyValue3 copy = MyValue3.copy(vt);
 656         va[0] = copy;
 657         staticVal3 = copy;
 658         copy.verify(staticVal3);
 659         return copy;
 660     }
 661 
 662     @DontCompile
 663     public void test32_verifier(boolean warmup) {
 664         MyValue3 vt = MyValue3.create();
 665         MyValue3[] va = new MyValue3[1];
 666         MyValue3 result = test32(vt, va);
 667         staticVal3.verify(vt);
 668         va[0].verify(vt);
 669         result.verify(vt);
 670     }
 671 
 672     // Test correct identification of value type copies
 673     @Test()
 674     public MyValue3 test33(MyValue3[] va) {
 675         MyValue3 vt = MyValue3.copy(staticVal3);
 676         vt = MyValue3.setI(vt, vt.c);
 677         // vt is not equal to staticVal3, so C2 should not re-use the oop
 678         va[0] = vt;
 679         staticVal3 = vt;
 680         vt.verify(staticVal3);
 681         return vt;
 682     }
 683 
 684     @DontCompile
 685     public void test33_verifier(boolean warmup) {
 686         staticVal3 = MyValue3.create();
 687         MyValue3[] va = new MyValue3[1];
 688         MyValue3 vt = test33(va);
 689         Asserts.assertEQ(staticVal3.i, (int)staticVal3.c);
 690         Asserts.assertEQ(va[0].i, (int)staticVal3.c);
 691         Asserts.assertEQ(vt.i, (int)staticVal3.c);
 692     }
 693 
 694     // Verify that the default value type is never allocated.
 695     // C2 code should load and use the default oop from the java mirror.
 696     @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
 697     public MyValue3 test34(MyValue3[] va) {
 698         // Explicitly create default value
 699         MyValue3 vt = MyValue3.createDefault();
 700         va[0] = vt;
 701         staticVal3 = vt;
 702         vt.verify(vt);
 703 
 704         // Load default value from uninitialized value array
 705         MyValue3[] dva = new MyValue3[1];
 706         staticVal3_copy = dva[0];
 707         va[1] = dva[0];
 708         dva[0].verify(dva[0]);
 709         return vt;
 710     }
 711 
 712     @DontCompile
 713     public void test34_verifier(boolean warmup) {
 714         MyValue3 vt = MyValue3.createDefault();
 715         MyValue3[] va = new MyValue3[2];
 716         va[0] = MyValue3.create();
 717         va[1] = MyValue3.create();
 718         MyValue3 res = test34(va);
 719         res.verify(vt);
 720         staticVal3.verify(vt);
 721         staticVal3_copy.verify(vt);
 722         va[0].verify(vt);
 723         va[1].verify(vt);
 724     }
 725 
 726     // Same as above but manually initialize value type fields to default.
 727     @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
 728     public MyValue3 test35(MyValue3 vt, MyValue3[] va) {
 729         vt = MyValue3.setC(vt, (char)0);
 730         vt = MyValue3.setBB(vt, (byte)0);
 731         vt = MyValue3.setS(vt, (short)0);
 732         vt = MyValue3.setI(vt, 0);
 733         vt = MyValue3.setL(vt, 0);
 734         vt = MyValue3.setO(vt, null);
 735         vt = MyValue3.setF1(vt, 0);
 736         vt = MyValue3.setF2(vt, 0);
 737         vt = MyValue3.setF3(vt, 0);
 738         vt = MyValue3.setF4(vt, 0);
 739         vt = MyValue3.setF5(vt, 0);
 740         vt = MyValue3.setF6(vt, 0);
 741         vt = MyValue3.setV1(vt, MyValue3Inline.createDefault());
 742         va[0] = vt;
 743         staticVal3 = vt;
 744         vt.verify(vt);
 745         return vt;
 746     }
 747 
 748     @DontCompile
 749     public void test35_verifier(boolean warmup) {
 750         MyValue3 vt = MyValue3.createDefault();
 751         MyValue3[] va = new MyValue3[1];
 752         va[0] = MyValue3.create();
 753         MyValue3 res = test35(va[0], va);
 754         res.verify(vt);
 755         staticVal3.verify(vt);
 756         va[0].verify(vt);
 757     }
 758 
 759     // Merge value types created from two branches
 760 
 761     private Object test36_helper(Object v) {
 762         return v;
 763     }
 764 
 765     @Test(failOn = ALLOC + STORE + TRAP)
 766     public long test36(boolean b) {
 767         Object o;
 768         if (b) {
 769             o = test36_helper(MyValue1.createWithFieldsInline(rI, rL));
 770         } else {
 771             o = test36_helper(MyValue1.createWithFieldsDontInline(rI + 1, rL + 1));
 772         }
 773         MyValue1 v = (MyValue1)o;
 774         return v.hash();
 775     }
 776 
 777     @DontCompile
 778     public void test36_verifier(boolean warmup) {
 779         Asserts.assertEQ(test36(true), hash());
 780         Asserts.assertEQ(test36(false), hash(rI + 1, rL + 1));
 781     }
 782 }