1 /*
   2  * Copyright (c) 2016, 2017, 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 // TODO add bugid and summary
  25 
  26 /*
  27  * @test
  28  * @library /testlibrary /test/lib /compiler/whitebox /
  29  * @requires os.simpleArch == "x64"
  30  * @modules java.base/jdk.experimental.value
  31  *          java.base/jdk.internal.misc:+open
  32  *          jdk.incubator.mvt
  33  * @compile -XDenableValueTypes ValueCapableClass1.java ValueCapableClass2.java ValueTypeTestBench.java
  34  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  35  * @run main ClassFileInstaller jdk.test.lib.Platform
  36  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  37  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+VerifyAdapterSharing -XX:+VerifyStack
  38  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  39  *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  40  *                   -Djdk.lang.reflect.DVT=true
  41  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  42  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  43  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+VerifyStack
  44  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  45  *                   -Djdk.lang.reflect.DVT=true
  46  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  47  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  48  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+AlwaysIncrementalInline
  49  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  50  *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  51  *                   -Djdk.lang.reflect.DVT=true
  52  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  53  */
  54 
  55 package compiler.valhalla.valuetypes;
  56 
  57 import compiler.whitebox.CompilerWhiteBoxTest;
  58 import jdk.experimental.value.MethodHandleBuilder;
  59 import jdk.incubator.mvt.ValueType;
  60 import jdk.test.lib.Asserts;
  61 import jdk.test.lib.management.InputArguments;
  62 import jdk.test.lib.Platform;
  63 import jdk.test.lib.process.ProcessTools;
  64 import jdk.test.lib.process.OutputAnalyzer;
  65 import jdk.test.lib.Utils;
  66 import sun.hotspot.WhiteBox;
  67 
  68 import java.lang.annotation.Retention;
  69 import java.lang.annotation.RetentionPolicy;
  70 import java.lang.annotation.Repeatable;
  71 import java.lang.invoke.*;
  72 import java.lang.reflect.Method;
  73 import java.util.ArrayList;
  74 import java.util.Arrays;
  75 import java.util.Hashtable;
  76 import java.util.LinkedHashMap;
  77 import java.util.List;
  78 import java.util.Map;
  79 import java.util.regex.Matcher;
  80 import java.util.regex.Pattern;
  81 
  82 // Test value types
  83 __ByValue final class MyValue1 {
  84     static int s;
  85     static final long sf = ValueTypeTestBench.rL;
  86     final int x;
  87     final long y;
  88     final short z;
  89     final Integer o;
  90     final int[] oa;
  91     final MyValue2 v1;
  92     final MyValue2 v2;
  93     static final MyValue2 v3 = MyValue2.createWithFieldsInline(ValueTypeTestBench.rI, true);
  94     final int c;
  95 
  96     private MyValue1() {
  97         s = 0;
  98         this.x = 0;
  99         this.y = 0;
 100         this.z = 0;
 101         this.o = null;
 102         this.oa = null;
 103         this.v1 = MyValue2.createDefaultInline();
 104         this.v2 = MyValue2.createDefaultInline();
 105         this.c = 0;
 106     }
 107 
 108     @DontInline
 109     __ValueFactory static MyValue1 createDefaultDontInline() {
 110         return createDefaultInline();
 111     }
 112 
 113     @ForceInline
 114     __ValueFactory static MyValue1 createDefaultInline() {
 115         return __MakeDefault MyValue1();
 116     }
 117 
 118     @DontInline
 119     static MyValue1 createWithFieldsDontInline(int x, long y) {
 120         return createWithFieldsInline(x, y);
 121     }
 122 
 123     @ForceInline
 124     static MyValue1 createWithFieldsInline(int x, long y) {
 125         MyValue1 v = createDefaultInline();
 126         v = setX(v, x);
 127         v = setY(v, y);
 128         v = setZ(v, (short)x);
 129         v = setO(v, new Integer(x));
 130         int[] oa = {x};
 131         v = setOA(v, oa);
 132         v = setV1(v, MyValue2.createWithFieldsInline(x, x < y));
 133         v = setV2(v, MyValue2.createWithFieldsInline(x, x > y));
 134         v = setC(v, ValueTypeTestBench.rI);
 135         return v;
 136     }
 137 
 138     // Hash only primitive and value type fields to avoid NullPointerException
 139     @ForceInline
 140     public long hashPrimitive() {
 141         return s + sf + x + y + z + c + v1.hash() + v2.hash() + v3.hash();
 142     }
 143 
 144     @ForceInline
 145     public long hash() {
 146         return hashPrimitive() + o + oa[0];
 147     }
 148 
 149     @DontCompile
 150     public long hashInterpreted() {
 151         return s + sf + x + y + z + o + oa[0] + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
 152     }
 153 
 154     @ForceInline
 155     public void print() {
 156         System.out.print("s=" + s + ", sf=" + sf + ", x=" + x + ", y=" + y + ", z=" + z + ", o=" + (o != null ? (Integer)o : "NULL") + ", v1[");
 157         v1.print();
 158         System.out.print("], v2[");
 159         v2.print();
 160         System.out.print("], v3[");
 161         v3.print();
 162         System.out.print("], c=" + c);
 163     }
 164 
 165     @ForceInline
 166     __ValueFactory static MyValue1 setX(MyValue1 v, int x) {
 167         v.x = x;
 168         return v;
 169     }
 170 
 171     @ForceInline
 172     __ValueFactory static MyValue1 setY(MyValue1 v, long y) {
 173         v.y = y;
 174         return v;
 175     }
 176 
 177     @ForceInline
 178     __ValueFactory static MyValue1 setZ(MyValue1 v, short z) {
 179         v.z = z;
 180         return v;
 181     }
 182 
 183     @ForceInline
 184     __ValueFactory static MyValue1 setO(MyValue1 v, Integer o) {
 185         v.o = o;
 186         return v;
 187     }
 188 
 189     @ForceInline
 190     __ValueFactory static MyValue1 setOA(MyValue1 v, int[] oa) {
 191         v.oa = oa;
 192         return v;
 193     }
 194 
 195     @ForceInline
 196     __ValueFactory static MyValue1 setC(MyValue1 v, int c) {
 197         v.c = c;
 198         return v;
 199     }
 200 
 201     @ForceInline
 202     __ValueFactory static MyValue1 setV1(MyValue1 v, MyValue2 v1) {
 203         v.v1 = v1;
 204         return v;
 205     }
 206 
 207     @ForceInline
 208     __ValueFactory static MyValue1 setV2(MyValue1 v, MyValue2 v2) {
 209         v.v2 = v2;
 210         return v;
 211     }
 212 }
 213 
 214 __ByValue final class MyValue2 {
 215     final int x;
 216     final byte y;
 217     final boolean b;
 218     final long c;
 219 
 220     private MyValue2() {
 221         this.x = 0;
 222         this.y = 0;
 223         this.b = false;
 224         this.c = 0;
 225     }
 226 
 227     @ForceInline
 228     __ValueFactory public static MyValue2 createDefaultInline() {
 229         return __MakeDefault MyValue2();
 230     }
 231 
 232     @ForceInline
 233     public static MyValue2 createWithFieldsInline(int x, boolean b) {
 234         MyValue2 v = createDefaultInline();
 235         v = setX(v, x);
 236         v = setY(v, (byte)x);
 237         v = setB(v, b);
 238         v = setC(v, ValueTypeTestBench.rL);
 239         return v;
 240     }
 241 
 242     @ForceInline
 243     public long hash() {
 244         return x + y + (b ? 0 : 1) + c;
 245     }
 246 
 247     @DontInline
 248     public long hashInterpreted() {
 249         return x + y + (b ? 0 : 1) + c;
 250     }
 251 
 252     @ForceInline
 253     public void print() {
 254         System.out.print("x=" + x + "y=" + y + ", b=" + b + ", c=" + c);
 255     }
 256 
 257     @ForceInline
 258     __ValueFactory static MyValue2 setX(MyValue2 v, int x) {
 259         v.x = x;
 260         return v;
 261     }
 262 
 263     @ForceInline
 264     __ValueFactory static MyValue2 setY(MyValue2 v, byte y) {
 265         v.y = y;
 266         return v;
 267     }
 268 
 269     @ForceInline
 270     __ValueFactory static MyValue2 setC(MyValue2 v, long c) {
 271         v.c = c;
 272         return v;
 273     }
 274 
 275     @ForceInline
 276     __ValueFactory static MyValue2 setB(MyValue2 v, boolean b) {
 277         v.b = b;
 278         return v;
 279     }
 280 }
 281 
 282 // Value type definition to stress test return of a value in registers
 283 // (uses all registers of calling convention on x86_64)
 284 __ByValue final class MyValue3 {
 285     final char c;
 286     final byte bb;
 287     final short s;
 288     final int i;
 289     final long l;
 290     final Object o;
 291     final float f1;
 292     final double f2;
 293     final float f3;
 294     final double f4;
 295     final float f5;
 296     final double f6;
 297     final float f7;
 298     final double f8;
 299 
 300     private MyValue3(char c,
 301             byte bb,
 302             short s,
 303             int i,
 304             long l,
 305             Object o,
 306             float f1,
 307             double f2,
 308             float f3,
 309             double f4,
 310             float f5,
 311             double f6,
 312             float f7,
 313             double f8) {
 314         this.c = c;
 315         this.bb = bb;
 316         this.s = s;
 317         this.i = i;
 318         this.l = l;
 319         this.o = o;
 320         this.f1 = f1;
 321         this.f2 = f2;
 322         this.f3 = f3;
 323         this.f4 = f4;
 324         this.f5 = f5;
 325         this.f6 = f6;
 326         this.f7 = f7;
 327         this.f8 = f8;
 328     }
 329 
 330     private MyValue3() {
 331         this.c = 0;
 332         this.bb = 0;
 333         this.s = 0;
 334         this.i = 0;
 335         this.l = 0;
 336         this.o = null;
 337         this.f1 = 0;
 338         this.f2 = 0;
 339         this.f3 = 0;
 340         this.f4 = 0;
 341         this.f5 = 0;
 342         this.f6 = 0;
 343         this.f7 = 0;
 344         this.f8 = 0;
 345     }
 346 
 347     @ForceInline
 348     __ValueFactory static MyValue3 setC(MyValue3 v, char c) {
 349         v.c = c;
 350         return v;
 351     }
 352 
 353     @ForceInline
 354     __ValueFactory static MyValue3 setBB(MyValue3 v, byte bb) {
 355         v.bb = bb;
 356         return v;
 357     }
 358 
 359     @ForceInline
 360     __ValueFactory static MyValue3 setS(MyValue3 v, short s) {
 361         v.s = s;
 362         return v;
 363     }
 364 
 365     @ForceInline
 366     __ValueFactory static MyValue3 setI(MyValue3 v, int i) {
 367         v.i = i;
 368         return v;
 369     }
 370 
 371     @ForceInline
 372     __ValueFactory static MyValue3 setL(MyValue3 v, long l) {
 373         v.l = l;
 374         return v;
 375     }
 376 
 377     @ForceInline
 378     __ValueFactory static MyValue3 setO(MyValue3 v, Object o) {
 379         v.o = o;
 380         return v;
 381     }
 382 
 383     @ForceInline
 384     __ValueFactory static MyValue3 setF1(MyValue3 v, float f1) {
 385         v.f1 = f1;
 386         return v;
 387     }
 388 
 389     @ForceInline
 390     __ValueFactory static MyValue3 setF2(MyValue3 v, double f2) {
 391         v.f2 = f2;
 392         return v;
 393     }
 394 
 395     @ForceInline
 396     __ValueFactory static MyValue3 setF3(MyValue3 v, float f3) {
 397         v.f3 = f3;
 398         return v;
 399     }
 400 
 401     @ForceInline
 402     __ValueFactory static MyValue3 setF4(MyValue3 v, double f4) {
 403         v.f4 = f4;
 404         return v;
 405     }
 406 
 407     @ForceInline
 408     __ValueFactory static MyValue3 setF5(MyValue3 v, float f5) {
 409         v.f5 = f5;
 410         return v;
 411     }
 412 
 413     @ForceInline
 414     __ValueFactory static MyValue3 setF6(MyValue3 v, double f6) {
 415         v.f6 = f6;
 416         return v;
 417     }
 418 
 419     @ForceInline
 420     __ValueFactory static MyValue3 setF7(MyValue3 v, float f7) {
 421         v.f7 = f7;
 422         return v;
 423     }
 424 
 425     @ForceInline
 426     __ValueFactory static MyValue3 setF8(MyValue3 v, double f8) {
 427         v.f8 = f8;
 428         return v;
 429     }
 430 
 431     @ForceInline
 432     __ValueFactory public static MyValue3 createDefault() {
 433         return __MakeDefault MyValue3();
 434     }
 435 
 436     @ForceInline
 437     public static MyValue3 create() {
 438         java.util.Random r = Utils.getRandomInstance();
 439         MyValue3 v = createDefault();
 440         v = setC(v, (char)r.nextInt());
 441         v = setBB(v, (byte)r.nextInt());
 442         v = setS(v, (short)r.nextInt());
 443         v = setI(v, r.nextInt());
 444         v = setL(v, r.nextLong());
 445         v = setO(v, new Object());
 446         v = setF1(v, r.nextFloat());
 447         v = setF2(v, r.nextDouble());
 448         v = setF3(v, r.nextFloat());
 449         v = setF4(v, r.nextDouble());
 450         v = setF5(v, r.nextFloat());
 451         v = setF6(v, r.nextDouble());
 452         v = setF7(v, r.nextFloat());
 453         v = setF8(v, r.nextDouble());
 454         return v;
 455     }
 456 
 457     @DontInline
 458     public static MyValue3 createDontInline() {
 459         return create();
 460     }
 461 
 462     @ForceInline
 463     public static MyValue3 copy(MyValue3 other) {
 464         MyValue3 v = createDefault();
 465         v = setC(v, other.c);
 466         v = setBB(v, other.bb);
 467         v = setS(v, other.s);
 468         v = setI(v, other.i);
 469         v = setL(v, other.l);
 470         v = setO(v, other.o);
 471         v = setF1(v, other.f1);
 472         v = setF2(v, other.f2);
 473         v = setF3(v, other.f3);
 474         v = setF4(v, other.f4);
 475         v = setF5(v, other.f5);
 476         v = setF6(v, other.f6);
 477         v = setF7(v, other.f7);
 478         v = setF8(v, other.f8);
 479         return v;
 480     }
 481 
 482     @DontInline
 483     public void verify(MyValue3 other) {
 484         Asserts.assertEQ(c, other.c);
 485         Asserts.assertEQ(bb, other.bb);
 486         Asserts.assertEQ(s, other.s);
 487         Asserts.assertEQ(i, other.i);
 488         Asserts.assertEQ(l, other.l);
 489         Asserts.assertEQ(o, other.o);
 490         Asserts.assertEQ(f1, other.f1);
 491         Asserts.assertEQ(f2, other.f2);
 492         Asserts.assertEQ(f3, other.f3);
 493         Asserts.assertEQ(f4, other.f4);
 494         Asserts.assertEQ(f5, other.f5);
 495         Asserts.assertEQ(f6, other.f6);
 496         Asserts.assertEQ(f7, other.f7);
 497         Asserts.assertEQ(f8, other.f8);
 498     }
 499 }
 500 
 501 // Value type definition with too many fields to return in registers
 502 __ByValue final class MyValue4 {
 503     final MyValue3 v1;
 504     final MyValue3 v2;
 505 
 506     private MyValue4(MyValue3 v1, MyValue3 v2) {
 507         this.v1 = v1;
 508         this.v2 = v2;
 509     }
 510 
 511     private MyValue4() {
 512         this.v1 = MyValue3.createDefault();
 513         this.v2 = MyValue3.createDefault();
 514     }
 515 
 516     @ForceInline
 517     __ValueFactory static MyValue4 setV1(MyValue4 v, MyValue3 v1) {
 518         v.v1 = v1;
 519         return v;
 520     }
 521 
 522     @ForceInline
 523     __ValueFactory static MyValue4 setV2(MyValue4 v, MyValue3 v2) {
 524         v.v2 = v2;
 525         return v;
 526     }
 527 
 528     @ForceInline
 529     __ValueFactory public static MyValue4 createDefault() {
 530         return __MakeDefault MyValue4();
 531     }
 532 
 533     @ForceInline
 534     public static MyValue4 create() {
 535         MyValue4 v = createDefault();
 536         MyValue3 v1 = MyValue3.create();
 537         v = setV1(v, v1);
 538         MyValue3 v2 = MyValue3.create();
 539         v = setV2(v, v2);
 540         return v;
 541     }
 542 
 543     public void verify(MyValue4 other) {
 544         v1.verify(other.v1);
 545         v2.verify(other.v2);
 546     }
 547 }
 548 
 549 
 550 public class ValueTypeTestBench {
 551     // Print ideal graph after execution of each test
 552     private static final boolean PRINT_GRAPH = true;
 553 
 554     // Random test values
 555     public static final int  rI = Utils.getRandomInstance().nextInt() % 1000;
 556     public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
 557 
 558     public ValueTypeTestBench() {
 559         val3 = MyValue1.createWithFieldsInline(rI, rL);
 560     }
 561 
 562     // MethodHandles and value-capable class instance needed for testing vbox/vunbox
 563     private static final MethodHandle vccUnboxLoadLongMH = generateVCCUnboxLoadLongMH();
 564     private static final MethodHandle vccUnboxLoadIntMH = generateVCCUnboxLoadIntMH();
 565     private static final MethodHandle vccUnboxBoxMH = generateVCCUnboxBoxMH();
 566     private static final MethodHandle vccUnboxBoxLoadIntMH = generateVCCUnboxBoxLoadIntMH();
 567     private static final MethodHandle nullvccUnboxLoadLongMH = generateNullVCCUnboxLoadLongMH();
 568     private static final MethodHandle objectUnboxLoadLongMH = generateObjectUnboxLoadLongMH();
 569     private static final MethodHandle objectBoxMH = generateObjectBoxMH();
 570     private static final MethodHandle checkedvccUnboxLoadLongMH = generateCheckedVCCUnboxLoadLongMH();
 571     private static final MethodHandle vastoreMH = generateVastore();
 572     private static final MethodHandle invalidVastoreMH = generateInvalidVastore();
 573 
 574     private static final ValueCapableClass1 vcc = ValueCapableClass1.create(rL, rI, (short)rI, (short)rI);
 575     private static final ValueCapableClass2 vcc2 = ValueCapableClass2.create(rL + 1);
 576 
 577     // ========== Helper methods ==========
 578 
 579     public long hash() {
 580         return hash(rI, rL);
 581     }
 582 
 583     public long hash(int x, long y) {
 584         return MyValue1.createWithFieldsInline(x, y).hash();
 585     }
 586 
 587     // ========== Test definitions ==========
 588 
 589     // Receive value type through call to interpreter
 590     @Test(failOn = ALLOC + STORE + TRAP)
 591     public long test1() {
 592         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 593         return v.hash();
 594     }
 595 
 596     @DontCompile
 597     public void test1_verifier(boolean warmup) {
 598         long result = test1();
 599         Asserts.assertEQ(result, hash());
 600     }
 601 
 602     // Receive value type from interpreter via parameter
 603     @Test(failOn = ALLOC + STORE + TRAP)
 604     public long test2(MyValue1 v) {
 605         return v.hash();
 606     }
 607 
 608     @DontCompile
 609     public void test2_verifier(boolean warmup) {
 610         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 611         long result = test2(v);
 612         Asserts.assertEQ(result, hash());
 613     }
 614 
 615     // Return incoming value type without accessing fields
 616     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount = {1, 11}, failOn = LOAD + TRAP)
 617     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + LOAD + STORE + TRAP)
 618     public MyValue1 test3(MyValue1 v) {
 619         return v;
 620     }
 621 
 622     @DontCompile
 623     public void test3_verifier(boolean warmup) {
 624         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 625         MyValue1 v2 = test3(v1);
 626         Asserts.assertEQ(v1.x, v2.x);
 627         Asserts.assertEQ(v1.y, v2.y);
 628     }
 629 
 630     // Create a value type in compiled code and only use fields.
 631     // Allocation should go away because value type does not escape.
 632     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 633     public long test4() {
 634         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 635         return v.hash();
 636     }
 637 
 638     @DontCompile
 639     public void test4_verifier(boolean warmup) {
 640         long result = test4();
 641         Asserts.assertEQ(result, hash());
 642     }
 643 
 644     // Create a value type in compiled code and pass it to
 645     // an inlined compiled method via a call.
 646     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 647     public long test5() {
 648         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 649         return test5Inline(v);
 650     }
 651 
 652     @ForceInline
 653     public long test5Inline(MyValue1 v) {
 654         return v.hash();
 655     }
 656 
 657     @DontCompile
 658     public void test5_verifier(boolean warmup) {
 659         long result = test5();
 660         Asserts.assertEQ(result, hash());
 661     }
 662 
 663     // Create a value type in compiled code and pass it to
 664     // the interpreter via a call.
 665     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC)
 666     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 667     public long test6() {
 668         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 669         // Pass to interpreter
 670         return v.hashInterpreted();
 671     }
 672 
 673     @DontCompile
 674     public void test6_verifier(boolean warmup) {
 675         long result = test6();
 676         Asserts.assertEQ(result, hash());
 677     }
 678 
 679     // Create a value type in compiled code and pass it to
 680     // the interpreter by returning.
 681     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 682     public MyValue1 test7(int x, long y) {
 683         return MyValue1.createWithFieldsInline(x, y);
 684     }
 685 
 686     @DontCompile
 687     public void test7_verifier(boolean warmup) {
 688         MyValue1 v = test7(rI, rL);
 689         Asserts.assertEQ(v.hash(), hash());
 690     }
 691 
 692     // Merge value types created from two branches
 693     @Test(failOn = ALLOC + STORE + TRAP)
 694     public long test8(boolean b) {
 695         MyValue1 v;
 696         if (b) {
 697             v = MyValue1.createWithFieldsInline(rI, rL);
 698         } else {
 699             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 700         }
 701         return v.hash();
 702     }
 703 
 704     @DontCompile
 705     public void test8_verifier(boolean warmup) {
 706         Asserts.assertEQ(test8(true), hash());
 707         Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
 708     }
 709 
 710     // Merge value types created from two branches
 711     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {10}, failOn = TRAP + ALLOC + STORE)
 712     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 3}, failOn = LOAD + TRAP)
 713     public MyValue1 test9(boolean b) {
 714         MyValue1 v;
 715         if (b) {
 716             // Value type is not allocated
 717             v = MyValue1.createWithFieldsInline(rI, rL);
 718         } else {
 719             // Value type is allocated by the callee
 720             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 721         }
 722         // Need to allocate value type if 'b' is true
 723         long sum = v.hashInterpreted();
 724         if (b) {
 725             v = MyValue1.createWithFieldsDontInline(rI, sum);
 726         } else {
 727             v = MyValue1.createWithFieldsDontInline(rI, sum + 1);
 728         }
 729         // Don't need to allocate value type because both branches allocate
 730         return v;
 731     }
 732 
 733     @DontCompile
 734     public void test9_verifier(boolean warmup) {
 735         MyValue1 v = test9(true);
 736         Asserts.assertEQ(v.x, rI);
 737         Asserts.assertEQ(v.y, hash());
 738         v = test9(false);
 739         Asserts.assertEQ(v.x, rI);
 740         Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
 741     }
 742 
 743     // Merge value types created in a loop (not inlined)
 744     @Test(failOn = ALLOC + STORE + TRAP)
 745     public long test10(int x, long y) {
 746         MyValue1 v = MyValue1.createWithFieldsDontInline(x, y);
 747         for (int i = 0; i < 10; ++i) {
 748             v = MyValue1.createWithFieldsDontInline(v.x + 1, v.y + 1);
 749         }
 750         return v.hash();
 751     }
 752 
 753     @DontCompile
 754     public void test10_verifier(boolean warmup) {
 755         long result = test10(rI, rL);
 756         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 757     }
 758 
 759     // Merge value types created in a loop (inlined)
 760     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 761     public long test11(int x, long y) {
 762         MyValue1 v = MyValue1.createWithFieldsInline(x, y);
 763         for (int i = 0; i < 10; ++i) {
 764             v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
 765         }
 766         return v.hash();
 767     }
 768 
 769     @DontCompile
 770     public void test11_verifier(boolean warmup) {
 771         long result = test11(rI, rL);
 772         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 773     }
 774 
 775     // Test loop with uncommon trap referencing a value type
 776     @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD)
 777     public long test12(boolean b) {
 778         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 779         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 780         for (int i = 0; i < va.length; ++i) {
 781             va[i] = MyValue1.createWithFieldsInline(rI, rL);
 782         }
 783         long result = rL;
 784         for (int i = 0; i < 1000; ++i) {
 785             if (b) {
 786                 result += v.x;
 787             } else {
 788                 // Uncommon trap referencing v. We delegate allocation to the
 789                 // interpreter by adding a SafePointScalarObjectNode.
 790                 result = v.hashInterpreted();
 791                 for (int j = 0; j < va.length; ++j) {
 792                     result += va[j].hash();
 793                 }
 794             }
 795         }
 796         return result;
 797     }
 798 
 799     @DontCompile
 800     public void test12_verifier(boolean warmup) {
 801         long result = test12(warmup);
 802         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 803     }
 804 
 805     // Test loop with uncommon trap referencing a value type
 806     @Test
 807     public long test13(boolean b) {
 808         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 809         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 810         for (int i = 0; i < va.length; ++i) {
 811             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
 812         }
 813         long result = rL;
 814         for (int i = 0; i < 1000; ++i) {
 815             if (b) {
 816                 result += v.x;
 817             } else {
 818                 // Uncommon trap referencing v. Should not allocate
 819                 // but just pass the existing oop to the uncommon trap.
 820                 result = v.hashInterpreted();
 821                 for (int j = 0; j < va.length; ++j) {
 822                     result += va[j].hashInterpreted();
 823                 }
 824             }
 825         }
 826         return result;
 827     }
 828 
 829     @DontCompile
 830     public void test13_verifier(boolean warmup) {
 831         long result = test13(warmup);
 832         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 833     }
 834 
 835     // Create a value type in a non-inlined method and then call a
 836     // non-inlined method on that value type.
 837     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {10})
 838     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
 839     public long test14() {
 840         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 841         return v.hashInterpreted();
 842     }
 843 
 844     @DontCompile
 845     public void test14_verifier(boolean b) {
 846         long result = test14();
 847         Asserts.assertEQ(result, hash());
 848     }
 849 
 850     // Create a value type in an inlined method and then call a
 851     // non-inlined method on that value type.
 852     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC))
 853     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
 854     public long test15() {
 855         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 856         return v.hashInterpreted();
 857     }
 858 
 859     @DontCompile
 860     public void test15_verifier(boolean b) {
 861         long result = test15();
 862         Asserts.assertEQ(result, hash());
 863     }
 864 
 865     // Create a value type in a non-inlined method and then call an
 866     // inlined method on that value type.
 867     @Test(failOn = (ALLOC + STORE + TRAP))
 868     public long test16() {
 869         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 870         return v.hash();
 871     }
 872 
 873     @DontCompile
 874     public void test16_verifier(boolean b) {
 875         long result = test16();
 876         Asserts.assertEQ(result, hash());
 877     }
 878 
 879     // Create a value type in an inlined method and then call an
 880     // inlined method on that value type.
 881     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
 882     public long test17() {
 883         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 884         return v.hash();
 885     }
 886 
 887     @DontCompile
 888     public void test17_verifier(boolean b) {
 889         long result = test17();
 890         Asserts.assertEQ(result, hash());
 891     }
 892 
 893     // Create a value type in compiled code and pass it to the
 894     // interpreter via a call. The value is live at the first call so
 895     // debug info should include a reference to all its fields.
 896     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 897     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 898     public long test18() {
 899         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 900         v.hashInterpreted();
 901         return v.hashInterpreted();
 902     }
 903 
 904     @DontCompile
 905     public void test18_verifier(boolean warmup) {
 906         long result = test18();
 907         Asserts.assertEQ(result, hash());
 908     }
 909 
 910     // Create a value type in compiled code and pass it to the
 911     // interpreter via a call. The value type is passed twice but
 912     // should only be allocated once.
 913     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 914     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 915     public long test19() {
 916         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 917         return sumValue(v, v);
 918     }
 919 
 920     @DontCompile
 921     public long sumValue(MyValue1 v, MyValue1 dummy) {
 922         return v.hash();
 923     }
 924 
 925     @DontCompile
 926     public void test19_verifier(boolean warmup) {
 927         long result = test19();
 928         Asserts.assertEQ(result, hash());
 929     }
 930 
 931     // Create a value type (array) in compiled code and pass it to the
 932     // interpreter via a call. The value type is live at the uncommon
 933     // trap: verify that deoptimization causes the value type to be
 934     // correctly allocated.
 935     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
 936     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {2}, failOn = LOAD)
 937     public long test20(boolean deopt) {
 938         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 939         MyValue2[] va = new MyValue2[3];
 940         if (deopt) {
 941             // uncommon trap
 942             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test20"));
 943         }
 944         return v.hashInterpreted() + va[0].hashInterpreted() +
 945                 va[1].hashInterpreted() + va[2].hashInterpreted();
 946     }
 947 
 948     @DontCompile
 949     public void test20_verifier(boolean warmup) {
 950         MyValue2[] va = new MyValue2[42];
 951         long result = test20(!warmup);
 952         Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
 953     }
 954 
 955     // Value type fields in regular object
 956     MyValue1 val1;
 957     MyValue2 val2;
 958     final MyValue1 val3;
 959     static MyValue1 val4;
 960     static final MyValue1 val5 = MyValue1.createWithFieldsInline(rI, rL);
 961 
 962     // Test value type fields in objects
 963     @Test(match = {ALLOC}, matchCount = {1}, failOn = (TRAP))
 964     public long test21(int x, long y) {
 965         // Compute hash of value type fields
 966         long result = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 967         // Update fields
 968         val1 = MyValue1.createWithFieldsInline(x, y);
 969         val2 = MyValue2.createWithFieldsInline(x, true);
 970         val4 = MyValue1.createWithFieldsInline(x, y);
 971         return result;
 972     }
 973 
 974     @DontCompile
 975     public void test21_verifier(boolean warmup) {
 976         // Check if hash computed by test18 is correct
 977         val1 = MyValue1.createWithFieldsInline(rI, rL);
 978         val2 = val1.v2;
 979         // val3 is initialized in the constructor
 980         val4 = val1;
 981         // val5 is initialized in the static initializer
 982         long hash = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 983         long result = test21(rI + 1, rL + 1);
 984         Asserts.assertEQ(result, hash);
 985         // Check if value type fields were updated
 986         Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1));
 987         Asserts.assertEQ(val2.hash(), MyValue2.createWithFieldsInline(rI + 1, true).hash());
 988         Asserts.assertEQ(val4.hash(), hash(rI + 1, rL + 1));
 989     }
 990 
 991     // Test folding of constant value type fields
 992     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 993     public long test22() {
 994         // This should be constant folded
 995         return val5.hash() + val5.v3.hash();
 996     }
 997 
 998     @DontCompile
 999     public void test22_verifier(boolean warmup) {
1000         long result = test22();
1001         Asserts.assertEQ(result, val5.hash() + val5.v3.hash());
1002     }
1003 
1004     // Test OSR compilation
1005     @Test()
1006     public long test23() {
1007         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1008         MyValue1[] va = new MyValue1[Math.abs(rI) % 3];
1009         for (int i = 0; i < va.length; ++i) {
1010             va[i] = MyValue1.createWithFieldsInline(rI, rL);
1011         }
1012         long result = 0;
1013         // Long loop to trigger OSR compilation
1014         for (int i = 0 ; i < 100_000; ++i) {
1015             // Reference local value type in interpreter state
1016             result = v.hash();
1017             for (int j = 0; j < va.length; ++j) {
1018                 result += va[j].hash();
1019             }
1020         }
1021         return result;
1022     }
1023 
1024     @DontCompile
1025     public void test23_verifier(boolean warmup) {
1026         long result = test23();
1027         Asserts.assertEQ(result, ((Math.abs(rI) % 3) + 1) * hash());
1028     }
1029 
1030     // Test interpreter to compiled code with various signatures
1031     @Test(failOn = ALLOC + STORE + TRAP)
1032     public long test24(MyValue2 v) {
1033         return v.hash();
1034     }
1035 
1036     @DontCompile
1037     public void test24_verifier(boolean warmup) {
1038         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1039         long result = test24(v);
1040         Asserts.assertEQ(result, v.hashInterpreted());
1041     }
1042 
1043     @Test(failOn = ALLOC + STORE + TRAP)
1044     public long test25(int i1, MyValue2 v, int i2) {
1045         return v.hash() + i1 - i2;
1046     }
1047 
1048     @DontCompile
1049     public void test25_verifier(boolean warmup) {
1050         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1051         long result = test25(rI, v, 2*rI);
1052         Asserts.assertEQ(result, v.hashInterpreted() - rI);
1053     }
1054 
1055     @Test(failOn = ALLOC + STORE + TRAP)
1056     public long test26(long l1, MyValue2 v, long l2) {
1057         return v.hash() + l1 - l2;
1058     }
1059 
1060     @DontCompile
1061     public void test26_verifier(boolean warmup) {
1062         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1063         long result = test26(rL, v, 2*rL);
1064         Asserts.assertEQ(result, v.hashInterpreted() - rL);
1065     }
1066 
1067     @Test(failOn = ALLOC + STORE + TRAP)
1068     public long test27(int i, MyValue2 v, long l) {
1069         return v.hash() + i + l;
1070     }
1071 
1072     @DontCompile
1073     public void test27_verifier(boolean warmup) {
1074         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1075         long result = test27(rI, v, rL);
1076         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1077     }
1078 
1079     @Test(failOn = ALLOC + STORE + TRAP)
1080     public long test28(long l, MyValue2 v, int i) {
1081         return v.hash() + i + l;
1082     }
1083 
1084     @DontCompile
1085     public void test28_verifier(boolean warmup) {
1086         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1087         long result = test28(rL, v, rI);
1088         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1089     }
1090 
1091     @Test(failOn = ALLOC + STORE + TRAP)
1092     public long test29(long l, MyValue1 v1, int i, MyValue2 v2) {
1093         return v1.hash() + i + l + v2.hash();
1094     }
1095 
1096     @DontCompile
1097     public void test29_verifier(boolean warmup) {
1098         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
1099         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
1100         long result = test29(rL, v1, rI, v2);
1101         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
1102     }
1103 
1104     // Test compiled code to interpreter with various signatures
1105     @DontCompile
1106     public long test30_interp(MyValue2 v) {
1107         return v.hash();
1108     }
1109 
1110     @Test(failOn = ALLOC + STORE + TRAP)
1111     public long test30(MyValue2 v) {
1112         return test30_interp(v);
1113     }
1114 
1115     @DontCompile
1116     public void test30_verifier(boolean warmup) {
1117         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1118         long result = test30(v);
1119         Asserts.assertEQ(result, v.hashInterpreted());
1120     }
1121 
1122     @DontCompile
1123     public long test31_interp(int i1, MyValue2 v, int i2) {
1124         return v.hash() + i1 - i2;
1125     }
1126 
1127     @Test(failOn = ALLOC + STORE + TRAP)
1128     public long test31(int i1, MyValue2 v, int i2) {
1129         return test31_interp(i1, v, i2);
1130     }
1131 
1132     @DontCompile
1133     public void test31_verifier(boolean warmup) {
1134         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1135         long result = test31(rI, v, 2*rI);
1136         Asserts.assertEQ(result, v.hashInterpreted() - rI);
1137     }
1138 
1139     @DontCompile
1140     public long test32_interp(long l1, MyValue2 v, long l2) {
1141         return v.hash() + l1 - l2;
1142     }
1143 
1144     @Test(failOn = ALLOC + STORE + TRAP)
1145     public long test32(long l1, MyValue2 v, long l2) {
1146         return test32_interp(l1, v, l2);
1147     }
1148 
1149     @DontCompile
1150     public void test32_verifier(boolean warmup) {
1151         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1152         long result = test32(rL, v, 2*rL);
1153         Asserts.assertEQ(result, v.hashInterpreted() - rL);
1154     }
1155 
1156     @DontCompile
1157     public long test33_interp(int i, MyValue2 v, long l) {
1158         return v.hash() + i + l;
1159     }
1160 
1161     @Test(failOn = ALLOC + STORE + TRAP)
1162     public long test33(int i, MyValue2 v, long l) {
1163         return test33_interp(i, v, l);
1164     }
1165 
1166     @DontCompile
1167     public void test33_verifier(boolean warmup) {
1168         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1169         long result = test33(rI, v, rL);
1170         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1171     }
1172 
1173     @DontCompile
1174     public long test34_interp(long l, MyValue2 v, int i) {
1175         return v.hash() + i + l;
1176     }
1177 
1178     @Test(failOn = ALLOC + STORE + TRAP)
1179     public long test34(long l, MyValue2 v, int i) {
1180         return test34_interp(l, v, i);
1181     }
1182 
1183     @DontCompile
1184     public void test34_verifier(boolean warmup) {
1185         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1186         long result = test34(rL, v, rI);
1187         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1188     }
1189 
1190     @DontCompile
1191     public long test35_interp(long l, MyValue1 v1, int i, MyValue2 v2) {
1192         return v1.hash() + i + l + v2.hash();
1193     }
1194 
1195     @Test(failOn = ALLOC + STORE + TRAP)
1196     public long test35(long l, MyValue1 v1, int i, MyValue2 v2) {
1197         return test35_interp(l, v1, i, v2);
1198     }
1199 
1200     @DontCompile
1201     public void test35_verifier(boolean warmup) {
1202         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
1203         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
1204         long result = test35(rL, v1, rI, v2);
1205         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
1206     }
1207 
1208     // test that debug info at a call is correct
1209     @DontCompile
1210     public long test36_interp(MyValue2 v, MyValue1[] va, boolean deopt) {
1211         if (deopt) {
1212             // uncommon trap
1213             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test36"));
1214         }
1215         return v.hash() + va[0].hash() + va[1].hash();
1216     }
1217 
1218     @Test(failOn = ALLOC + STORE + TRAP)
1219     public long test36(MyValue2 v, MyValue1[] va, boolean flag, long l) {
1220         return test36_interp(v, va, flag) + l;
1221     }
1222 
1223     @DontCompile
1224     public void test36_verifier(boolean warmup) {
1225         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1226         MyValue1[] va = new MyValue1[2];
1227         va[0] = MyValue1.createWithFieldsDontInline(rI, rL);
1228         va[1] = MyValue1.createWithFieldsDontInline(rI, rL);
1229         long result = test36(v, va, !warmup, rL);
1230         Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
1231     }
1232 
1233     // Test vbox and vunbox
1234     @Test
1235     public long test37() throws Throwable {
1236         return (long)vccUnboxLoadLongMH.invokeExact(vcc);
1237     }
1238 
1239     @DontCompile
1240     public void test37_verifier(boolean warmup) {
1241         try {
1242             long result = test37();
1243             Asserts.assertEQ(vcc.t, result, "Field t of input and result must be equal.");
1244         } catch (Throwable t) {
1245             throw new RuntimeException("test 37 failed", t);
1246         }
1247     }
1248 
1249     // Generate a MethodHandle that obtains field t of the
1250     // derived value type
1251     private static MethodHandle generateVCCUnboxLoadLongMH() {
1252         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1253                 "vccUnboxLoadLong",
1254                 MethodType.methodType(long.class, ValueCapableClass1.class),
1255                 CODE -> {
1256                     CODE.
1257                     aload_0().
1258                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1259                     getfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1260                     lreturn();
1261                 }
1262                 );
1263     }
1264 
1265     @Test
1266     public int test38() throws Throwable {
1267         return (int)vccUnboxLoadIntMH.invokeExact(vcc);
1268     }
1269 
1270     @DontCompile
1271     public void test38_verifier(boolean warmup) {
1272         try {
1273             int result = test38();
1274             Asserts.assertEQ(vcc.x, result, "Field x of input and result must be equal.");
1275         } catch (Throwable t) {
1276             throw new RuntimeException("test 38 failed", t);
1277         }
1278     }
1279 
1280     // Generate a MethodHandle that obtains field x of the
1281     // derived value type
1282     private static MethodHandle generateVCCUnboxLoadIntMH() {
1283         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1284                 "vccUnboxLoadInt",
1285                 MethodType.methodType(int.class, ValueCapableClass1.class),
1286                 CODE -> {
1287                     CODE.
1288                     aload_0().
1289                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1290                     getfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "x", "I").
1291                     ireturn();
1292                 }
1293                 );
1294     }
1295 
1296     @Test
1297     public ValueCapableClass1 test39() throws Throwable {
1298         return (ValueCapableClass1)vccUnboxBoxMH.invokeExact(vcc);
1299     }
1300 
1301     @DontCompile
1302     public void test39_verifier(boolean warmup) {
1303         try {
1304             ValueCapableClass1 result = test39();
1305             Asserts.assertEQ(vcc.value(), result.value(), "Value of VCC and returned VCC must be equal");
1306         } catch (Throwable t) {
1307             throw new RuntimeException("test 39 failed", t);
1308         }
1309     }
1310 
1311     // Generate a MethodHandle that takes a value-capable class,
1312     // unboxes it, then boxes it again and returns it.
1313     private static MethodHandle generateVCCUnboxBoxMH() {
1314         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1315                 "vccUnboxBox",
1316                 MethodType.methodType(ValueCapableClass1.class, ValueCapableClass1.class),
1317                 CODE -> {
1318                     CODE.
1319                     aload_0().
1320                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1321                     vbox(ValueCapableClass1.class).
1322                     areturn();
1323                 }
1324                 );
1325     }
1326 
1327     @Test
1328     public int test40() throws Throwable {
1329         return (int)vccUnboxBoxLoadIntMH.invokeExact(vcc);
1330     }
1331 
1332     @DontCompile
1333     public void test40_verifier(boolean warmup) {
1334         try {
1335             int result = test40();
1336             Asserts.assertEQ(vcc.x, result, "Field x of VCC and result must be equal");
1337         } catch (Throwable t) {
1338             throw new RuntimeException("Test failed in the interpeter", t);
1339         }
1340     }
1341 
1342     // Generate a MethodHandle that takes a value-capable class,
1343     // unboxes it, boxes it, reads a field from it, and returns the
1344     // field.
1345     private static MethodHandle generateVCCUnboxBoxLoadIntMH() {
1346         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1347                 "vccUnboxBoxLoadInt",
1348                 MethodType.methodType(int.class, ValueCapableClass1.class),
1349                 CODE -> {
1350                     CODE.
1351                     aload_0().
1352                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1353                     vbox(ValueCapableClass1.class).
1354                     getfield(ValueCapableClass1.class, "x", "I").
1355                     ireturn();
1356                 }
1357                 );
1358 
1359     }
1360 
1361     // Test value type array creation and initialization
1362     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD))
1363     @Test(valid = ValueTypeArrayFlattenOn)
1364     public MyValue1[] test41(int len) {
1365         MyValue1[] va = new MyValue1[len];
1366         for (int i = 0; i < len; ++i) {
1367             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
1368         }
1369         return va;
1370     }
1371 
1372     @DontCompile
1373     public void test41_verifier(boolean warmup) {
1374         int len = Math.abs(rI % 10);
1375         MyValue1[] va = test41(len);
1376         for (int i = 0; i < len; ++i) {
1377             Asserts.assertEQ(va[i].hash(), hash());
1378         }
1379     }
1380 
1381     // Test creation of a value type array and element access
1382     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOOP + TRAP))
1383     @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOC + ALLOCA + LOOP + LOAD + LOADP + STORE + TRAP))
1384     public long test42() {
1385         MyValue1[] va = new MyValue1[1];
1386         va[0] = MyValue1.createWithFieldsInline(rI, rL);
1387         return va[0].hash();
1388     }
1389 
1390     @DontCompile
1391     public void test42_verifier(boolean warmup) {
1392         long result = test42();
1393         Asserts.assertEQ(result, hash());
1394     }
1395 
1396     // Test receiving a value type array from the interpreter,
1397     // updating its elements in a loop and computing a hash.
1398     @Test(failOn = (ALLOCA))
1399     public long test43(MyValue1[] va) {
1400         long result = 0;
1401         for (int i = 0; i < 10; ++i) {
1402             result += va[i].hash();
1403             va[i] = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
1404         }
1405         return result;
1406     }
1407 
1408     @DontCompile
1409     public void test43_verifier(boolean warmup) {
1410         MyValue1[] va = new MyValue1[10];
1411         long expected = 0;
1412         for (int i = 0; i < 10; ++i) {
1413             va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1414             expected += va[i].hash();
1415         }
1416         long result = test43(va);
1417         Asserts.assertEQ(expected, result);
1418         for (int i = 0; i < 10; ++i) {
1419             if (va[i].hash() != hash(rI + 1, rL + 1)) {
1420                 Asserts.assertEQ(va[i].hash(), hash(rI + 1, rL + 1));
1421             }
1422         }
1423     }
1424 
1425     // Test returning a value type array received from the interpreter
1426     @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP)
1427     public MyValue1[] test44(MyValue1[] va) {
1428         return va;
1429     }
1430 
1431     @DontCompile
1432     public void test44_verifier(boolean warmup) {
1433         MyValue1[] va = new MyValue1[10];
1434         for (int i = 0; i < 10; ++i) {
1435             va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1436         }
1437         va = test44(va);
1438         for (int i = 0; i < 10; ++i) {
1439             Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1440         }
1441     }
1442 
1443     // Merge value type arrays created from two branches
1444     @Test
1445     public MyValue1[] test45(boolean b) {
1446         MyValue1[] va;
1447         if (b) {
1448             va = new MyValue1[5];
1449             for (int i = 0; i < 5; ++i) {
1450                 va[i] = MyValue1.createWithFieldsInline(rI, rL);
1451             }
1452         } else {
1453             va = new MyValue1[10];
1454             for (int i = 0; i < 10; ++i) {
1455                 va[i] = MyValue1.createWithFieldsInline(rI + i, rL + i);
1456             }
1457         }
1458         long sum = va[0].hashInterpreted();
1459         if (b) {
1460             va[0] = MyValue1.createWithFieldsDontInline(rI, sum);
1461         } else {
1462             va[0] = MyValue1.createWithFieldsDontInline(rI + 1, sum + 1);
1463         }
1464         return va;
1465     }
1466 
1467     @DontCompile
1468     public void test45_verifier(boolean warmup) {
1469         MyValue1[] va = test45(true);
1470         Asserts.assertEQ(va.length, 5);
1471         Asserts.assertEQ(va[0].hash(), hash(rI, hash()));
1472         for (int i = 1; i < 5; ++i) {
1473             Asserts.assertEQ(va[i].hash(), hash());
1474         }
1475         va = test45(false);
1476         Asserts.assertEQ(va.length, 10);
1477         Asserts.assertEQ(va[0].hash(), hash(rI + 1, hash(rI, rL) + 1));
1478         for (int i = 1; i < 10; ++i) {
1479             Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1480         }
1481     }
1482 
1483     // Test creation of value type array with single element
1484     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD + LOOP + TRAP))
1485     @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOCA + LOAD + LOOP + TRAP))
1486     public MyValue1 test46() {
1487         MyValue1[] va = new MyValue1[1];
1488         return va[0];
1489     }
1490 
1491     @DontCompile
1492     public void test46_verifier(boolean warmup) {
1493         MyValue1[] va = new MyValue1[1];
1494         MyValue1 v = test46();
1495         Asserts.assertEQ(v.hashPrimitive(), va[0].hashPrimitive());
1496     }
1497 
1498     // Test default initialization of value type arrays
1499     @Test(failOn = LOAD)
1500     public MyValue1[] test47(int len) {
1501         return new MyValue1[len];
1502     }
1503 
1504     @DontCompile
1505     public void test47_verifier(boolean warmup) {
1506         int len = Math.abs(rI % 10);
1507         MyValue1[] va = new MyValue1[len];
1508         MyValue1[] var = test47(len);
1509         for (int i = 0; i < len; ++i) {
1510             Asserts.assertEQ(va[i].hashPrimitive(), var[i].hashPrimitive());
1511         }
1512     }
1513 
1514     // Test creation of value type array with zero length
1515     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
1516     public MyValue1[] test48() {
1517         return new MyValue1[0];
1518     }
1519 
1520     @DontCompile
1521     public void test48_verifier(boolean warmup) {
1522         MyValue1[] va = test48();
1523         Asserts.assertEQ(va.length, 0);
1524     }
1525 
1526     static MyValue1[] test49_va;
1527 
1528     // Test that value type array loaded from field has correct type
1529     @Test(failOn = (LOOP))
1530     public long test49() {
1531         return test49_va[0].hash();
1532     }
1533 
1534     @DontCompile
1535     public void test49_verifier(boolean warmup) {
1536         test49_va = new MyValue1[1];
1537         test49_va[0] = MyValue1.createWithFieldsInline(rI, rL);
1538         long result = test49();
1539         Asserts.assertEQ(result, hash());
1540     }
1541 
1542     // test vdefault
1543     @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
1544     public long test50() {
1545         MyValue2 v = MyValue2.createDefaultInline();
1546         return v.hash();
1547     }
1548 
1549     @DontCompile
1550     public void test50_verifier(boolean warmup) {
1551         long result = test50();
1552         Asserts.assertEQ(result, MyValue2.createDefaultInline().hash());
1553     }
1554 
1555     // test vdefault
1556     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
1557     public long test51() {
1558         MyValue1 v1 = MyValue1.createDefaultInline();
1559         MyValue1 v2 = MyValue1.createDefaultDontInline();
1560         return v1.hashPrimitive() + v2.hashPrimitive();
1561     }
1562 
1563     @DontCompile
1564     public void test51_verifier(boolean warmup) {
1565         long result = test51();
1566         Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive());
1567     }
1568 
1569     // test vwithfield
1570     @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
1571     public long test52() {
1572         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1573         return v.hash();
1574     }
1575 
1576     @DontCompile
1577     public void test52_verifier(boolean warmup) {
1578         long result = test52();
1579         Asserts.assertEQ(result, MyValue2.createWithFieldsInline(rI, true).hash());
1580     }
1581 
1582     // test vwithfield
1583     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
1584     public long test53() {
1585         MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL);
1586         MyValue1 v2 = MyValue1.createWithFieldsDontInline(rI, rL);
1587         return v1.hash() + v2.hash();
1588     }
1589 
1590     @DontCompile
1591     public void test53_verifier(boolean warmup) {
1592         long result = test53();
1593         Asserts.assertEQ(result, 2 * hash());
1594     }
1595 
1596     // multi-dimensional arrays
1597     @Test
1598     public MyValue1[][][] test54(int len1, int len2, int len3) {
1599         MyValue1[][][] arr = new MyValue1[len1][len2][len3];
1600         for (int i = 0; i < len1; i++) {
1601             for (int j = 0; j < len2; j++) {
1602                 for (int k = 0; k < len3; k++) {
1603                     arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i , rL + j + k);
1604                 }
1605             }
1606         }
1607         return arr;
1608     }
1609 
1610     @DontCompile
1611     public void test54_verifier(boolean warmup) {
1612         MyValue1[][][] arr = test54(2, 3, 4);
1613         for (int i = 0; i < 2; i++) {
1614             for (int j = 0; j < 3; j++) {
1615                 for (int k = 0; k < 4; k++) {
1616                     Asserts.assertEQ(arr[i][j][k].hash(), MyValue1.createWithFieldsDontInline(rI + i , rL + j + k).hash());
1617                 }
1618             }
1619         }
1620     }
1621 
1622     @Test
1623     public void test55(MyValue1[][][] arr, long[] res) {
1624         int l = 0;
1625         for (int i = 0; i < arr.length; i++) {
1626             for (int j = 0; j < arr[i].length; j++) {
1627                 for (int k = 0; k < arr[i][j].length; k++) {
1628                     res[l] = arr[i][j][k].hash();
1629                     l++;
1630                 }
1631             }
1632         }
1633     }
1634 
1635     @DontCompile
1636     public void test55_verifier(boolean warmup) {
1637         MyValue1[][][] arr = new MyValue1[2][3][4];
1638         long[] res = new long[2*3*4];
1639         long[] verif = new long[2*3*4];
1640         int l = 0;
1641         for (int i = 0; i < 2; i++) {
1642             for (int j = 0; j < 3; j++) {
1643                 for (int k = 0; k < 4; k++) {
1644                     arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i, rL + j + k);
1645                     verif[l] = arr[i][j][k].hash();
1646                     l++;
1647                 }
1648             }
1649         }
1650         test55(arr, res);
1651         for (int i = 0; i < verif.length; i++) {
1652             Asserts.assertEQ(res[i], verif[i]);
1653         }
1654     }
1655 
1656     class TestClass56 {
1657         public MyValue1 v;
1658     }
1659 
1660     // Test allocation elimination of unused object with initialized value type field
1661     @Test(failOn = ALLOC + LOAD + STORE + LOOP)
1662     public void test56(boolean deopt) {
1663         TestClass56 unused = new TestClass56();
1664         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1665         unused.v = v;
1666         if (deopt) {
1667             // uncommon trap
1668             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test56"));
1669         }
1670     }
1671 
1672     @DontCompile
1673     public void test56_verifier(boolean warmup) {
1674         test56(!warmup);
1675     }
1676 
1677     // Test loop peeling
1678     @Test(failOn = ALLOC + LOAD + STORE)
1679     public void test57() {
1680         MyValue1 v = MyValue1.createWithFieldsInline(0, 1);
1681         // Trigger OSR compilation and loop peeling
1682         for (int i = 0; i < 100_000; ++i) {
1683             if (v.x != i || v.y != i + 1) {
1684                 // Uncommon trap
1685                 throw new RuntimeException("test57 failed");
1686             }
1687             v = MyValue1.createWithFieldsInline(i + 1, i + 2);
1688         }
1689     }
1690 
1691     @DontCompile
1692     public void test57_verifier(boolean warmup) {
1693         test57();
1694     }
1695 
1696     // Test loop peeling and unrolling
1697     @Test()
1698     public void test58() {
1699         MyValue1 v1 = MyValue1.createWithFieldsInline(0, 0);
1700         MyValue1 v2 = MyValue1.createWithFieldsInline(1, 1);
1701         // Trigger OSR compilation and loop peeling
1702         for (int i = 0; i < 100_000; ++i) {
1703             if (v1.x != 2*i || v2.x != i+1 || v2.y != i+1) {
1704                 // Uncommon trap
1705                 throw new RuntimeException("test58 failed");
1706             }
1707             v1 = MyValue1.createWithFieldsInline(2*(i+1), 0);
1708             v2 = MyValue1.createWithFieldsInline(i+2, i+2);
1709         }
1710     }
1711 
1712     @DontCompile
1713     public void test58_verifier(boolean warmup) {
1714         test58();
1715     }
1716 
1717     // When calling a method on __Value, passing fields as arguments is impossible
1718     @Test(failOn = ALLOC + STORE + LOAD)
1719     public String test59(MyValue1 v) {
1720         return v.toString();
1721     }
1722 
1723     @DontCompile
1724     public void test59_verifier(boolean warmup) {
1725         boolean failed = false;
1726         try {
1727             test59(val1);
1728             failed = true;
1729         } catch (UnsupportedOperationException uoe) {
1730         }
1731         Asserts.assertFalse(failed);
1732     }
1733 
1734     // Same as above, but the method on __Value is inlined
1735     // hashCode allocates an exception so can't really check the graph shape
1736     @Test()
1737     public int test60(MyValue1 v) {
1738         return v.hashCode();
1739     }
1740 
1741     @DontCompile
1742     public void test60_verifier(boolean warmup) {
1743         boolean failed = false;
1744         try {
1745             test60(val1);
1746             failed = true;
1747         } catch (UnsupportedOperationException uoe) {
1748         }
1749         Asserts.assertFalse(failed);
1750     }
1751 
1752     /* The compiler is supposed to determine that the value to be
1753      * unboxed in nullcvvUnboxLoadLong is always null. Therefore, the
1754      * compiler generates only the path leading to the corresponding
1755      * uncommon trap. */
1756     @Test(failOn = RETURN)
1757     public long test61() throws Throwable {
1758         return (long)nullvccUnboxLoadLongMH.invokeExact();
1759     }
1760 
1761     @DontCompile
1762     public void test61_verifier(boolean warmup) throws Throwable {
1763         try {
1764             long result = test61();
1765             throw new RuntimeException("Test failed because no exception was thrown");
1766         } catch (NullPointerException e) {
1767         }
1768     }
1769 
1770     public static MethodHandle generateNullVCCUnboxLoadLongMH() {
1771         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1772                 "nullvccUnboxLoadLong",
1773                 MethodType.methodType(long.class),
1774                 CODE -> {
1775                     CODE.
1776                     aconst_null().
1777                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1778                     getfield(ValueCapableClass1.class, "t", "J").
1779                     lreturn();
1780                 }
1781                 );
1782     }
1783 
1784     /* The compiler is supposed to determine that the allocated
1785      * ValueCapableClass1 instance is never null (and therefore not
1786      * generate a null check). Also, the source and target type match
1787      * (known at compile time), so no type check is needed either.*/
1788     @Test(failOn = NPE)
1789     public long test62() throws Throwable {
1790         return (long)checkedvccUnboxLoadLongMH.invokeExact();
1791     }
1792 
1793     @DontCompile
1794     public void test62_verifier(boolean warmup) throws Throwable {
1795         long result = test62();
1796         Asserts.assertEQ(result, 17L);
1797     }
1798 
1799     public static MethodHandle generateCheckedVCCUnboxLoadLongMH() {
1800         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1801                 "checkedVCCUnboxLoadLongMH",
1802                 MethodType.methodType(long.class),
1803                 CODE -> {
1804                     CODE.
1805                     invokestatic(ValueCapableClass1.class, "createInline", "()Lcompiler/valhalla/valuetypes/ValueCapableClass1;", false).
1806                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1807                     getfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1808                     lreturn();
1809                 }
1810                 );
1811     }
1812 
1813     /* The compiler is supposed to emit a runtime null check because
1814      * it does not have enough information to determine that the value
1815      * to be unboxed is not null (and either that it is null). The
1816      * declared type of the */
1817     @Test(match = {NPE}, matchCount = {1})
1818     public long test63(ValueCapableClass1 vcc) throws Throwable {
1819         return (long)vccUnboxLoadLongMH.invokeExact(vcc);
1820     }
1821 
1822     @DontCompile
1823     public void test63_verifier(boolean warmup) throws Throwable {
1824         try {
1825             long result = test63(null);
1826             throw new RuntimeException("Test failed because no exception was thrown");
1827         } catch (NullPointerException e) {
1828         }
1829     }
1830 
1831     /* Attempt to unbox an object that is not a subclass of the
1832      * value-capable class derived from the value type specified in
1833      * the vunbox bytecode. */
1834     @Test(match = {NPE,CCE}, matchCount = {1,1})
1835     public long test64(Object vcc) throws Throwable {
1836         return (long)objectUnboxLoadLongMH.invokeExact(vcc);
1837     }
1838 
1839     @DontCompile
1840     public void test64_verifier(boolean warmup) throws Throwable {
1841         try {
1842             long result = test64(new Object());
1843             throw new RuntimeException("Test failed because no exception was thrown");
1844         } catch (ClassCastException e) {
1845         }
1846 
1847         try {
1848             long result = test64(vcc2);
1849             throw new RuntimeException("Test failed because no exception was thrown");
1850         } catch (ClassCastException e) {
1851         }
1852 
1853         Asserts.assertEQ(test64(vcc), rL);
1854     }
1855 
1856     private static MethodHandle generateObjectUnboxLoadLongMH() {
1857         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1858                 "ObjectUnboxLoadLong",
1859                 MethodType.methodType(long.class, Object.class),
1860                 CODE -> {
1861                     CODE.
1862                     aload_0().
1863                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1864                     getfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1865                     lreturn();
1866                 }
1867                 );
1868     }
1869 
1870     /* Generate an if-then-else construct with one path that contains
1871      * an invalid boxing operation (boxing of a value-type to a
1872      * non-matching value-capable class).*/
1873     @Test(match = {NPE, CCE}, matchCount = {2, 2})
1874     public long test65(Object obj, boolean warmup) throws Throwable {
1875         return (long)objectBoxMH.invokeExact(obj, warmup);
1876     }
1877 
1878     @DontCompile
1879     public void test65_verifier(boolean warmup) throws Throwable {
1880         try {
1881             long result = test65(vcc2, true);
1882             throw new RuntimeException("Test failed because no exception was thrown");
1883         } catch (ClassCastException e) {
1884         }
1885 
1886         Asserts.assertEQ(test65(vcc, true), rL);
1887 
1888         try {
1889             long result = test65(vcc2, false);
1890             throw new RuntimeException("Test failed because no exception was thrown");
1891         } catch (ClassCastException e) {
1892         }
1893 
1894         try {
1895             long result = test65(vcc, false);
1896             throw new RuntimeException("Test failed because no exception was thrown");
1897         } catch (ClassCastException e) {
1898         }
1899     }
1900 
1901     private static MethodHandle generateObjectBoxMH() {
1902         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1903                 "ObjectBox",
1904                 MethodType.methodType(long.class, Object.class, boolean.class),
1905                 CODE -> {
1906                     CODE.
1907                     iload_1().
1908                     iconst_1().
1909                     if_icmpne((short)14).
1910                     aload_0().
1911                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1912                     vbox(ValueCapableClass1.class).
1913                     getfield(ValueCapableClass1.class, "t", "J").
1914                     lreturn().
1915                     aload_0().
1916                     vunbox(ValueType.forClass(ValueCapableClass2.class).valueClass()).
1917                     vbox(ValueCapableClass1.class).
1918                     getfield(ValueCapableClass1.class, "t", "J").
1919                     lreturn();
1920                 }
1921                 );
1922     }
1923 
1924     // Test deoptimization at call return with return value in registers
1925     @DontCompile
1926     public MyValue2 test66_interp(boolean deopt) {
1927         if (deopt) {
1928             // uncommon trap
1929             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test66"));
1930         }
1931         return MyValue2.createWithFieldsInline(rI, true);
1932     }
1933 
1934     @Test()
1935     public MyValue2 test66(boolean flag) {
1936         return test66_interp(flag);
1937     }
1938 
1939     @DontCompile
1940     public void test66_verifier(boolean warmup) {
1941         MyValue2 result = test66(!warmup);
1942         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1943         Asserts.assertEQ(result.hash(), v.hash());
1944     }
1945 
1946     // Return value types in registers from interpreter -> compiled
1947     final MyValue3 test67_vt = MyValue3.create();
1948     @DontCompile
1949     public MyValue3 test67_interp() {
1950         return test67_vt;
1951     }
1952 
1953     MyValue3 test67_vt2;
1954     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
1955     @Test(valid = ValueTypeReturnedAsFieldsOff)
1956     public void test67() {
1957         test67_vt2 = test67_interp();
1958     }
1959 
1960     @DontCompile
1961     public void test67_verifier(boolean warmup) {
1962         test67();
1963         test67_vt.verify(test67_vt2);
1964     }
1965 
1966     // Return value types in registers from compiled -> interpreter
1967     final MyValue3 test68_vt = MyValue3.create();
1968     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + TRAP)
1969     @Test(valid = ValueTypeReturnedAsFieldsOff)
1970     public MyValue3 test68() {
1971         return test68_vt;
1972     }
1973 
1974     @DontCompile
1975     public void test68_verifier(boolean warmup) {
1976         MyValue3 vt = test68();
1977         test68_vt.verify(vt);
1978     }
1979 
1980     // Return value types in registers from compiled -> compiled
1981     final MyValue3 test69_vt = MyValue3.create();
1982     @DontInline
1983     public MyValue3 test69_comp() {
1984         return test69_vt;
1985     }
1986 
1987     MyValue3 test69_vt2;
1988     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
1989     @Test(valid = ValueTypeReturnedAsFieldsOff)
1990     public void test69() {
1991         test69_vt2 = test69_comp();
1992     }
1993 
1994     @DontCompile
1995     public void test69_verifier(boolean warmup) throws Exception {
1996         Method helper_m = getClass().getDeclaredMethod("test69_comp");
1997         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
1998             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
1999             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test69_comp not compiled");
2000         }
2001         test69();
2002         test69_vt.verify(test69_vt2);
2003     }
2004 
2005     // Same tests as above but with a value type that cannot be returned in registers
2006 
2007     // Return value types in registers from interpreter -> compiled
2008     final MyValue4 test70_vt = MyValue4.create();
2009     @DontCompile
2010     public MyValue4 test70_interp() {
2011         return test70_vt;
2012     }
2013 
2014     MyValue4 test70_vt2;
2015     @Test
2016     public void test70() {
2017         test70_vt2 = test70_interp();
2018     }
2019 
2020     @DontCompile
2021     public void test70_verifier(boolean warmup) {
2022         test70();
2023         test70_vt.verify(test70_vt2);
2024     }
2025 
2026     // Return value types in registers from compiled -> interpreter
2027     final MyValue4 test71_vt = MyValue4.create();
2028     @Test
2029     public MyValue4 test71() {
2030         return test71_vt;
2031     }
2032 
2033     @DontCompile
2034     public void test71_verifier(boolean warmup) {
2035         MyValue4 vt = test71();
2036         test71_vt.verify(vt);
2037     }
2038 
2039     // Return value types in registers from compiled -> compiled
2040     final MyValue4 test72_vt = MyValue4.create();
2041     @DontInline
2042     public MyValue4 test72_comp() {
2043         return test72_vt;
2044     }
2045 
2046     MyValue4 test72_vt2;
2047     @Test
2048     public void test72() {
2049         test72_vt2 = test72_comp();
2050     }
2051 
2052     @DontCompile
2053     public void test72_verifier(boolean warmup) throws Exception {
2054         Method helper_m = getClass().getDeclaredMethod("test72_comp");
2055         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
2056             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
2057             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test72_comp not compiled");
2058         }
2059         test72();
2060         test72_vt.verify(test72_vt2);
2061     }
2062 
2063     // Return values and method handles tests
2064 
2065     // Everything inlined
2066     final MyValue3 test73_vt = MyValue3.create();
2067     @ForceInline
2068     MyValue3 test73_target() {
2069         return test73_vt;
2070     }
2071 
2072     static final MethodHandle test73_mh;
2073 
2074     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + CALL)
2075     @Test(valid = ValueTypeReturnedAsFieldsOff, match = { ALLOC, STORE }, matchCount = { 1, 11 })
2076     MyValue3 test73() throws Throwable {
2077         return (MyValue3)test73_mh.invokeExact(this);
2078     }
2079 
2080     @DontCompile
2081     public void test73_verifier(boolean warmup) throws Throwable {
2082         MyValue3 vt = test73();
2083         test73_vt.verify(vt);
2084     }
2085 
2086     // Leaf method not inlined but returned type is known
2087     final MyValue3 test74_vt = MyValue3.create();
2088     @DontInline
2089     MyValue3 test74_target() {
2090         return test74_vt;
2091     }
2092 
2093     static final MethodHandle test74_mh;
2094 
2095     @Test
2096     MyValue3 test74() throws Throwable {
2097         return (MyValue3)test74_mh.invokeExact(this);
2098     }
2099 
2100     @DontCompile
2101     public void test74_verifier(boolean warmup) throws Throwable {
2102         Method helper_m = getClass().getDeclaredMethod("test74_target");
2103         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
2104             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
2105             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test74_target not compiled");
2106         }
2107         MyValue3 vt = test74();
2108         test74_vt.verify(vt);
2109     }
2110 
2111     // Leaf method not inlined and returned type not known
2112     final MyValue3 test75_vt = MyValue3.create();
2113     @DontInline
2114     MyValue3 test75_target() {
2115         return test75_vt;
2116     }
2117 
2118     static final MethodHandle test75_mh;
2119 
2120     @Test
2121     MyValue3 test75() throws Throwable {
2122         return (MyValue3)test75_mh.invokeExact(this);
2123     }
2124 
2125     @DontCompile
2126     public void test75_verifier(boolean warmup) throws Throwable {
2127         // hack so C2 doesn't know the target of the invoke call
2128         Class c = Class.forName("java.lang.invoke.DirectMethodHandle");
2129         Method m = c.getDeclaredMethod("internalMemberName", Object.class);
2130         WHITE_BOX.testSetDontInlineMethod(m, warmup);
2131         MyValue3 vt = test75();
2132         test75_vt.verify(vt);
2133     }
2134 
2135     // Test no result from inlined method for incremental inlining
2136     final MyValue3 test76_vt = MyValue3.create();
2137     public MyValue3 test76_inlined() {
2138         throw new RuntimeException();
2139     }
2140 
2141     @Test
2142     public MyValue3 test76() {
2143         try {
2144             return test76_inlined();
2145         } catch (RuntimeException ex) {
2146             return test76_vt;
2147         }
2148     }
2149 
2150     @DontCompile
2151     public void test76_verifier(boolean warmup) {
2152         MyValue3 vt = test76();
2153         test76_vt.verify(vt);
2154     }
2155 
2156     static {
2157         try {
2158             MethodHandles.Lookup lookup = MethodHandles.lookup();
2159             MethodType mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2160             test73_mh = lookup.findVirtual(ValueTypeTestBench.class, "test73_target", mt);
2161             test74_mh = lookup.findVirtual(ValueTypeTestBench.class, "test74_target", mt);
2162             test75_mh = lookup.findVirtual(ValueTypeTestBench.class, "test75_target", mt);
2163         } catch (NoSuchMethodException|IllegalAccessException e) {
2164             throw new RuntimeException("method handle lookup fails");
2165         }
2166     }
2167 
2168     /* Array load out of bounds (upper bound) at compile time.*/
2169     @Test
2170     public int test77() {
2171         int arraySize = Math.abs(rI) % 10;;
2172         MyValue1[] va = new MyValue1[arraySize];
2173 
2174         for (int i = 0; i < arraySize; i++) {
2175             va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2176         }
2177 
2178         try {
2179             return va[arraySize + 1].x;
2180         } catch (ArrayIndexOutOfBoundsException e) {
2181             return rI;
2182         }
2183     }
2184 
2185     public void test77_verifier(boolean warmup) {
2186         Asserts.assertEQ(test77(), rI);
2187     }
2188 
2189     /* Array load  out of bounds (lower bound) at compile time.*/
2190     @Test
2191     public int test78() {
2192         int arraySize = Math.abs(rI) % 10;;
2193         MyValue1[] va = new MyValue1[arraySize];
2194 
2195         for (int i = 0; i < arraySize; i++) {
2196             va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL);
2197         }
2198 
2199         try {
2200             return va[-arraySize].x;
2201         } catch (ArrayIndexOutOfBoundsException e) {
2202             return rI;
2203         }
2204     }
2205 
2206     public void test78_verifier(boolean warmup) {
2207         Asserts.assertEQ(test78(), rI);
2208     }
2209 
2210     /* Array load out of bound not known to compiler (both lower and upper bound). */
2211     @Test
2212     public int test79(MyValue1[] va, int index)  {
2213         return va[index].x;
2214     }
2215 
2216     public void test79_verifier(boolean warmup) {
2217         int arraySize = Math.abs(rI) % 10;
2218         MyValue1[] va = new MyValue1[arraySize];
2219 
2220         for (int i = 0; i < arraySize; i++) {
2221             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
2222         }
2223 
2224         int result;
2225         for (int i = -20; i < 20; i++) {
2226             try {
2227                 result = test79(va, i);
2228             } catch (ArrayIndexOutOfBoundsException e) {
2229                 result = rI;
2230             }
2231             Asserts.assertEQ(result, rI);
2232         }
2233     }
2234 
2235     /* Array store out of bounds (upper bound) at compile time.*/
2236     @Test
2237     public int test80() {
2238         int arraySize = Math.abs(rI) % 10;;
2239         MyValue1[] va = new MyValue1[arraySize];
2240 
2241         try {
2242             for (int i = 0; i <= arraySize; i++) {
2243                 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2244             }
2245             return rI - 1;
2246         } catch (ArrayIndexOutOfBoundsException e) {
2247             return rI;
2248         }
2249     }
2250 
2251     public void test80_verifier(boolean warmup) {
2252         Asserts.assertEQ(test80(), rI);
2253     }
2254 
2255     /* Array store out of bounds (lower bound) at compile time.*/
2256     @Test
2257     public int test81() {
2258         int arraySize = Math.abs(rI) % 10;;
2259         MyValue1[] va = new MyValue1[arraySize];
2260 
2261         try {
2262             for (int i = -1; i <= arraySize; i++) {
2263                 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2264             }
2265             return rI - 1;
2266         } catch (ArrayIndexOutOfBoundsException e) {
2267             return rI;
2268         }
2269     }
2270 
2271     public void test81_verifier(boolean warmup) {
2272         Asserts.assertEQ(test81(), rI);
2273     }
2274 
2275     /* Array store out of bound not known to compiler (both lower and upper bound). */
2276     @Test
2277     public int test82(MyValue1[] va, int index, MyValue1 vt)  {
2278         va[index] = vt;
2279         return va[index].x;
2280     }
2281 
2282     @DontCompile
2283     public void test82_verifier(boolean warmup) {
2284         int arraySize = Math.abs(rI) % 10;
2285         MyValue1[] va = new MyValue1[arraySize];
2286 
2287         for (int i = 0; i < arraySize; i++) {
2288             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
2289         }
2290 
2291         MyValue1 vt = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2292         int result;
2293         for (int i = -20; i < 20; i++) {
2294             try {
2295                 result = test82(va, i, vt);
2296             } catch (ArrayIndexOutOfBoundsException e) {
2297                 result = rI + 1;
2298             }
2299             Asserts.assertEQ(result, rI + 1);
2300         }
2301 
2302         for (int i = 0; i < arraySize; i++) {
2303             Asserts.assertEQ(va[i].x, rI + 1);
2304         }
2305     }
2306 
2307     /* Create a new value type array and store a value type into
2308      * it. The test should pass without throwing an exception. */
2309     @Test
2310     public void test83() throws Throwable {
2311         vastoreMH.invokeExact(vcc);
2312     }
2313 
2314     public void test83_verifier(boolean warmup) throws Throwable {
2315         test83();
2316     }
2317 
2318     private static MethodHandle generateVastore() {
2319         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
2320                 "Vastore",
2321                 MethodType.methodType(void.class, ValueCapableClass1.class),
2322                 CODE -> {
2323                     CODE.
2324                     iconst_1().
2325                     anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2326                     iconst_0().
2327                     aload_0().
2328                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2329                     vastore().
2330                     return_();
2331                 }
2332                 );
2333     }
2334 
2335     /* Create a new value type array with element type
2336      * ValueCapableClass1 and attempt to store a value type of type
2337      * ValueCapableClass2 into it. */
2338     @Test
2339     public void test84() throws Throwable {
2340         invalidVastoreMH.invokeExact(vcc2);
2341     }
2342 
2343     public void test84_verifier(boolean warmup) throws Throwable {
2344         boolean exceptionThrown = false;
2345         try {
2346             test84();
2347         } catch (ArrayStoreException e) {
2348             exceptionThrown = true;
2349         }
2350         Asserts.assertTrue(exceptionThrown, "ArrayStoreException must be thrown");
2351     }
2352 
2353     private static MethodHandle generateInvalidVastore() {
2354         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
2355                 "Vastore",
2356                 MethodType.methodType(void.class, ValueCapableClass2.class),
2357                 CODE -> {
2358                     CODE.
2359                     iconst_1().
2360                     anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2361                     iconst_0().
2362                     aload_0().
2363                     vunbox(ValueType.forClass(ValueCapableClass2.class).valueClass()).
2364                     vastore().
2365                     return_();
2366                 }
2367                 );
2368     }
2369 
2370     // When test85_helper1 is inlined in test85, the method handle
2371     // linker that called it is passed a pointer to a copy of vt
2372     // stored in memory. The method handle linker needs to load the
2373     // fields from memory before it inlines test85_helper1.
2374     static public int test85_helper1(MyValue1 vt) {
2375         return vt.x;
2376     }
2377 
2378     static MyValue1 test85_vt = MyValue1.createWithFieldsInline(rI, rL);
2379     static public MyValue1 test85_helper2() {
2380         return test85_vt;
2381     }
2382 
2383     static final MethodHandle test85_mh;
2384 
2385     @Test
2386     public int test85() throws Throwable {
2387         return (int)test85_mh.invokeExact();
2388     }
2389 
2390     @DontCompile
2391     public void test85_verifier(boolean warmup) throws Throwable {
2392         int i = test85();
2393         Asserts.assertEQ(i, test85_vt.x);
2394     }
2395 
2396     // Test method handle call with value type argument
2397     public int test86_target(MyValue1 vt) {
2398         return vt.x;
2399     }
2400 
2401     static final MethodHandle test86_mh;
2402     MyValue1 test86_vt = MyValue1.createWithFieldsInline(rI, rL);
2403 
2404     @Test
2405     public int test86() throws Throwable {
2406         return (int)test86_mh.invokeExact(this, test86_vt);
2407     }
2408 
2409     @DontCompile
2410     public void test86_verifier(boolean warmup) throws Throwable {
2411         int i = test86();
2412         Asserts.assertEQ(i, test86_vt.x);
2413     }
2414 
2415     static {
2416         try {
2417             MethodHandles.Lookup lookup = MethodHandles.lookup();
2418 
2419             MethodType test85_mt1 = MethodType.fromMethodDescriptorString("(Qcompiler/valhalla/valuetypes/MyValue1;)I", ValueTypeTestBench.class.getClassLoader());
2420             MethodType test85_mt2 = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue1;", ValueTypeTestBench.class.getClassLoader());
2421             MethodHandle test85_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test85_helper1", test85_mt1);
2422             MethodHandle test85_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test85_helper2", test85_mt2);
2423             test85_mh = MethodHandles.filterReturnValue(test85_mh2, test85_mh1);
2424 
2425             MethodType test86_mt = MethodType.fromMethodDescriptorString("(Qcompiler/valhalla/valuetypes/MyValue1;)I", ValueTypeTestBench.class.getClassLoader());
2426             test86_mh = lookup.findVirtual(ValueTypeTestBench.class, "test86_target", test86_mt);
2427         } catch (NoSuchMethodException|IllegalAccessException e) {
2428             throw new RuntimeException("method handle lookup fails");
2429         }
2430     }
2431 
2432     static MyValue3 staticVal3;
2433     static MyValue3 staticVal3_copy;
2434 
2435     // Check elimination of redundant value type allocations
2436     @Test(match = {ALLOC}, matchCount = {1})
2437     public MyValue3 test87(MyValue3[] va) {
2438         // Create value type and force allocation
2439         MyValue3 vt = MyValue3.create();
2440         va[0] = vt;
2441         staticVal3 = vt;
2442         vt.verify(staticVal3);
2443 
2444         // Value type is now allocated, make a copy and force allocation.
2445         // Because copy is equal to vt, C2 should remove this redundant allocation.
2446         MyValue3 copy = MyValue3.setC(vt, vt.c);
2447         va[0] = copy;
2448         staticVal3_copy = copy;
2449         copy.verify(staticVal3_copy);
2450         return copy;
2451     }
2452 
2453     @DontCompile
2454     public void test87_verifier(boolean warmup) {
2455         MyValue3[] va = new MyValue3[1];
2456         MyValue3 vt = test87(va);
2457         staticVal3.verify(vt);
2458         staticVal3.verify(va[0]);
2459         staticVal3_copy.verify(vt);
2460         staticVal3_copy.verify(va[0]);
2461     }
2462 
2463     // Verify that only dominating allocations are re-used
2464     @Test()
2465     public MyValue3 test88(boolean warmup) {
2466         MyValue3 vt = MyValue3.create();
2467         if (warmup) {
2468             staticVal3 = vt; // Force allocation
2469         }
2470         // Force allocation to verify that above
2471         // non-dominating allocation is not re-used
2472         MyValue3 copy = MyValue3.setC(vt, vt.c);
2473         staticVal3_copy = copy;
2474         copy.verify(vt);
2475         return copy;
2476     }
2477 
2478     @DontCompile
2479     public void test88_verifier(boolean warmup) {
2480         MyValue3 vt = test88(warmup);
2481         if (warmup) {
2482             staticVal3.verify(vt);
2483         }
2484     }
2485 
2486     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
2487     @Test(failOn = ALLOC + ALLOCA + STORE)
2488     public MyValue3 test89(MyValue3[] va) {
2489         // C2 can re-use the oop of staticVal3 because staticVal3 is equal to copy
2490         MyValue3 copy = MyValue3.copy(staticVal3);
2491         va[0] = copy;
2492         staticVal3 = copy;
2493         copy.verify(staticVal3);
2494         return copy;
2495     }
2496 
2497     @DontCompile
2498     public void test89_verifier(boolean warmup) {
2499         staticVal3 = MyValue3.create();
2500         MyValue3[] va = new MyValue3[1];
2501         MyValue3 vt = test89(va);
2502         staticVal3.verify(vt);
2503         staticVal3.verify(va[0]);
2504     }
2505 
2506     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
2507     @Test(valid = ValueTypeReturnedAsFieldsOff, failOn = ALLOC + ALLOCA + STORE)
2508     @Test(valid = ValueTypeReturnedAsFieldsOn)
2509     public MyValue3 test90(MyValue3[] va) {
2510         // C2 can re-use the oop returned by createDontInline()
2511         // because the corresponding value type is equal to 'copy'.
2512         MyValue3 copy = MyValue3.copy(MyValue3.createDontInline());
2513         va[0] = copy;
2514         staticVal3 = copy;
2515         copy.verify(staticVal3);
2516         return copy;
2517     }
2518 
2519     @DontCompile
2520     public void test90_verifier(boolean warmup) {
2521         MyValue3[] va = new MyValue3[1];
2522         MyValue3 vt = test90(va);
2523         staticVal3.verify(vt);
2524         staticVal3.verify(va[0]);
2525     }
2526 
2527     // Verify that C2 recognizes value type loads and re-uses the oop to avoid allocations
2528     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + ALLOCA + STORE)
2529     @Test(valid = ValueTypePassFieldsAsArgsOn)
2530     public MyValue3 test91(MyValue3 vt, MyValue3[] va) {
2531         // C2 can re-use the oop of vt because vt is equal to 'copy'.
2532         MyValue3 copy = MyValue3.copy(vt);
2533         va[0] = copy;
2534         staticVal3 = copy;
2535         copy.verify(staticVal3);
2536         return copy;
2537     }
2538 
2539     @DontCompile
2540     public void test91_verifier(boolean warmup) {
2541         MyValue3 vt = MyValue3.create();
2542         MyValue3[] va = new MyValue3[1];
2543         MyValue3 result = test91(vt, va);
2544         staticVal3.verify(vt);
2545         va[0].verify(vt);
2546         result.verify(vt);
2547     }
2548 
2549     // Test correct identification of value type copies
2550     @Test()
2551     public MyValue3 test92(MyValue3[] va) {
2552         MyValue3 vt = MyValue3.copy(staticVal3);
2553         vt = MyValue3.setI(vt, (int)vt.c);
2554         // vt is not equal to staticVal3, so C2 should not re-use the oop
2555         va[0] = vt;
2556         staticVal3 = vt;
2557         vt.verify(staticVal3);
2558         return vt;
2559     }
2560 
2561     @DontCompile
2562     public void test92_verifier(boolean warmup) {
2563         staticVal3 = MyValue3.create();
2564         MyValue3[] va = new MyValue3[1];
2565         MyValue3 vt = test92(va);
2566         Asserts.assertEQ(staticVal3.i, (int)staticVal3.c);
2567         Asserts.assertEQ(va[0].i, (int)staticVal3.c);
2568         Asserts.assertEQ(vt.i, (int)staticVal3.c);
2569     }
2570 
2571     // Test correct handling of __Value merges through PhiNodes
2572     @Test()
2573     public long test93() throws Throwable {
2574         // Create a new value type
2575         final MethodHandle dvt = MethodHandleBuilder.loadCode(MethodHandles.lookup(), "createValueType",
2576                                      MethodType.methodType(ValueType.forClass(ValueCapableClass1.class).valueClass()),
2577                                      CODE -> {
2578                                          CODE.
2579                                          iconst_1().
2580                                          anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2581                                          iconst_0().
2582                                          vaload().
2583                                          vreturn();
2584                                      });
2585         // Box the value type
2586         final MethodHandle box = MethodHandleBuilder.loadCode(MethodHandles.lookup(), "boxValueType",
2587                                      MethodType.methodType(ValueCapableClass1.class, ValueType.forClass(ValueCapableClass1.class).valueClass()),
2588                                      CODE -> {
2589                                          CODE.
2590                                          vload(0).
2591                                          vbox(ValueCapableClass1.class).
2592                                          areturn();
2593                                      });
2594         long result = 0;
2595         for (int i = 0; i < 10_000; ++i) {
2596             // Merge __Value (ValueCapableClass1) from the two GWT branches, box to the VCC and access field
2597             MethodHandle gwt = MethodHandles.guardWithTest(MethodHandles.constant(boolean.class, i % 2 == 0), dvt, dvt);
2598             ValueCapableClass1 vcc = (ValueCapableClass1) MethodHandles.filterReturnValue(gwt, box).invokeExact();
2599             result += vcc.t;
2600         }
2601         return result;
2602     }
2603 
2604     @DontCompile
2605     public void test93_verifier(boolean warmup) throws Throwable {
2606         long result = test93();
2607         Asserts.assertEQ(result, 0L);
2608     }
2609 
2610     // Test correctness of the Class::isAssignableFrom intrinsic
2611     @Test()
2612     public boolean test94(Class<?> supercls, Class<?> subcls) {
2613         return supercls.isAssignableFrom(subcls);
2614     }
2615 
2616     public void test94_verifier(boolean warmup) {
2617         Asserts.assertTrue(test94(__Value.class, MyValue1.class), "test94_1 failed");
2618         Asserts.assertTrue(test94(MyValue1.class, MyValue1.class), "test94_2 failed");
2619         Asserts.assertTrue(test94(Object.class, java.util.ArrayList.class), "test94_3 failed");
2620         Asserts.assertTrue(test94(java.util.ArrayList.class, java.util.ArrayList.class), "test94_4 failed");
2621         Asserts.assertTrue(!test94(Object.class, MyValue1.class), "test94_5 failed");
2622         Asserts.assertTrue(!test94(__Value.class, java.util.ArrayList.class), "test94_6 failed");
2623     }
2624 
2625     // Verify that Class::isAssignableFrom checks with statically known classes are folded
2626     @Test(failOn = LOADK)
2627     public boolean test95() {
2628         boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class);
2629         boolean check2 = MyValue1.class.isAssignableFrom(MyValue1.class);
2630         boolean check3 = Object.class.isAssignableFrom(java.util.ArrayList.class);
2631         boolean check4 = java.lang.__Value.class.isAssignableFrom(MyValue1.class);
2632         boolean check5 = !Object.class.isAssignableFrom(MyValue1.class);
2633         boolean check6 = !MyValue1.class.isAssignableFrom(Object.class);
2634         return check1 && check2 && check3 && check4 && check5 && check6;
2635     }
2636 
2637     public void test95_verifier(boolean warmup) {
2638         Asserts.assertTrue(test95(), "test95 failed");
2639     }
2640 
2641     // Test correctness of the Class::getSuperclass intrinsic
2642     @Test()
2643     public Class<?> test96(Class<?> cls) {
2644         return cls.getSuperclass();
2645     }
2646 
2647     public void test96_verifier(boolean warmup) {
2648         Asserts.assertTrue(test96(__Value.class) == null, "test94_1 failed");
2649         Asserts.assertTrue(test96(Object.class) == null, "test94_2 failed");
2650         Asserts.assertTrue(test96(MyValue1.class) == __Value.class, "test94_3 failed");
2651         Asserts.assertTrue(test96(Class.class) == Object.class, "test94_4 failed");
2652     }
2653 
2654     // Verify that Class::getSuperclass checks with statically known classes are folded
2655     @Test(failOn = LOADK)
2656     public boolean test97() {
2657         boolean check1 = __Value.class.getSuperclass() == null;
2658         boolean check2 = Object.class.getSuperclass() == null;
2659         boolean check3 = MyValue1.class.getSuperclass() == __Value.class;
2660         boolean check4 = Class.class.getSuperclass() == Object.class;
2661         return check1 && check2 && check3 && check4;
2662     }
2663 
2664     public void test97_verifier(boolean warmup) {
2665         Asserts.assertTrue(test97(), "test97 failed");
2666     }
2667 
2668     // Test Class::cast intrinsic
2669     @Test()
2670     public Object test98(Class<?> cls, Object o) throws ClassCastException {
2671         return cls.cast(o);
2672     }
2673 
2674     public void test98_verifier(boolean warmup) {
2675         try {
2676             test98(ValueCapableClass1.class, vcc);
2677         } catch (ClassCastException e) {
2678             throw new RuntimeException("test98_1 failed");
2679         }
2680         try {
2681             test98(__Value.class, new Object());
2682             throw new RuntimeException("test98_2 failed");
2683         } catch (ClassCastException e) {
2684             // Expected
2685         }
2686     }
2687 
2688     // method handle combinators
2689     static {
2690         try {
2691             MethodHandles.Lookup lookup = MethodHandles.lookup();
2692 
2693             MethodType test99_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2694             MethodHandle test99_mh1 = lookup.findVirtual(ValueTypeTestBench.class, "test99_target1", test99_mt);
2695             MethodHandle test99_mh2 = lookup.findVirtual(ValueTypeTestBench.class, "test99_target2", test99_mt);
2696             MethodType boolean_mt = MethodType.methodType(boolean.class);
2697             MethodHandle test99_mh_test = lookup.findVirtual(ValueTypeTestBench.class, "test99_test", boolean_mt);
2698             test99_mh = MethodHandles.guardWithTest(test99_mh_test, test99_mh1, test99_mh2);
2699 
2700             MethodType myvalue2_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue2;", ValueTypeTestBench.class.getClassLoader());
2701             test100_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test100_target1", myvalue2_mt);
2702             MethodHandle test100_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test100_target2", myvalue2_mt);
2703             MethodHandle test100_mh_test = lookup.findStatic(ValueTypeTestBench.class, "test100_test", boolean_mt);
2704             test100_mh = MethodHandles.guardWithTest(test100_mh_test,
2705                                                     MethodHandles.invoker(myvalue2_mt),
2706                                                     MethodHandles.dropArguments(test100_mh2, 0, MethodHandle.class));
2707 
2708             MethodHandle test101_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test101_target1", myvalue2_mt);
2709             test101_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test101_target2", myvalue2_mt);
2710             MethodHandle test101_mh_test = lookup.findStatic(ValueTypeTestBench.class, "test101_test", boolean_mt);
2711             test101_mh = MethodHandles.guardWithTest(test101_mh_test,
2712                                                     MethodHandles.dropArguments(test101_mh1, 0, MethodHandle.class),
2713                                                     MethodHandles.invoker(myvalue2_mt));
2714 
2715             MethodHandle test102_count = MethodHandles.constant(int.class, 100);
2716             ValueType<?> test102_VT = ValueType.forClass(ValueCapableClass2.class);
2717             MethodHandle test102_init = test102_VT.defaultValueConstant();
2718             MethodHandle test102_getfield = test102_VT.findGetter(lookup, "u", long.class);
2719             MethodHandle test102_add = lookup.findStatic(Long.class, "sum", MethodType.methodType(long.class, long.class, long.class));
2720             MethodHandle test102_body = MethodHandles.collectArguments(ValueCapableClass2.FACTORY,
2721                                                                       0,
2722                                                                       MethodHandles.dropArguments(MethodHandles.collectArguments(MethodHandles.insertArguments(test102_add,
2723                                                                                                                                                                0,
2724                                                                                                                                                                1L),
2725                                                                                                                                  0,
2726                                                                                                                                  test102_getfield),
2727                                                                                                   1,
2728                                                                                                   int.class));
2729             test102_mh = MethodHandles.collectArguments(test102_getfield,
2730                                                        0,
2731                                                        MethodHandles.countedLoop(test102_count, test102_init, test102_body));
2732 
2733             MethodType test103_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2734             MethodHandle test103_mh1 = lookup.findVirtual(ValueTypeTestBench.class, "test103_target1", test103_mt);
2735             MethodHandle test103_mh2 = lookup.findVirtual(ValueTypeTestBench.class, "test103_target2", test103_mt);
2736             MethodHandle test103_mh3 = lookup.findVirtual(ValueTypeTestBench.class, "test103_target3", test103_mt);
2737             MethodType test103_mt2 = MethodType.methodType(boolean.class);
2738             MethodHandle test103_mh_test1 = lookup.findVirtual(ValueTypeTestBench.class, "test103_test1", test103_mt2);
2739             MethodHandle test103_mh_test2 = lookup.findVirtual(ValueTypeTestBench.class, "test103_test2", test103_mt2);
2740             test103_mh = MethodHandles.guardWithTest(test103_mh_test1,
2741                                                     test103_mh1,
2742                                                     MethodHandles.guardWithTest(test103_mh_test2, test103_mh2, test103_mh3));
2743 
2744             MethodType test104_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue2;", ValueTypeTestBench.class.getClassLoader());
2745             MethodHandle test104_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test104_target1", test104_mt);
2746             test104_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test104_target2", test104_mt);
2747             test104_mh3 = lookup.findStatic(ValueTypeTestBench.class, "test104_target3", test104_mt);
2748             MethodType test104_mt2 = MethodType.methodType(boolean.class);
2749             MethodType test104_mt3 = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue2;", ValueTypeTestBench.class.getClassLoader());
2750             MethodHandle test104_mh_test1 = lookup.findStatic(ValueTypeTestBench.class, "test104_test1", test104_mt2);
2751             MethodHandle test104_mh_test2 = lookup.findStatic(ValueTypeTestBench.class, "test104_test2", test104_mt2);
2752             test104_mh = MethodHandles.guardWithTest(test104_mh_test1,
2753                                                     MethodHandles.dropArguments(test104_mh1, 0, MethodHandle.class, MethodHandle.class),
2754                                                     MethodHandles.guardWithTest(test104_mh_test2,
2755                                                                                 MethodHandles.dropArguments(MethodHandles.invoker(test104_mt3), 1, MethodHandle.class),
2756                                                                                 MethodHandles.dropArguments(MethodHandles.invoker(test104_mt3), 0, MethodHandle.class))
2757                                                     );
2758 
2759             MethodHandle test105_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test105_target1", myvalue2_mt);
2760             test105_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test105_target2", myvalue2_mt);
2761             MethodHandle test105_mh_test = lookup.findStatic(ValueTypeTestBench.class, "test105_test", boolean_mt);
2762             test105_mh = MethodHandles.guardWithTest(test105_mh_test,
2763                                                     MethodHandles.dropArguments(test105_mh1, 0, MethodHandle.class),
2764                                                     MethodHandles.invoker(myvalue2_mt));
2765         } catch (NoSuchMethodException|IllegalAccessException|NoSuchFieldException e) {
2766             e.printStackTrace();
2767             throw new RuntimeException("method handle lookup fails");
2768         }
2769     }
2770 
2771     // Return of target1 and target2 merged in a Lambda Form as an
2772     // __Value. Shouldn't cause any allocation
2773     final MyValue3 test99_vt1 = MyValue3.create();
2774     @ForceInline
2775     MyValue3 test99_target1() {
2776         return test99_vt1;
2777     }
2778 
2779     final MyValue3 test99_vt2 = MyValue3.create();
2780     @ForceInline
2781     MyValue3 test99_target2() {
2782         return test99_vt2;
2783     }
2784 
2785     boolean test99_bool = true;
2786     @ForceInline
2787     boolean test99_test() {
2788         return test99_bool;
2789     }
2790 
2791     static final MethodHandle test99_mh;
2792 
2793     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
2794     @Test(valid = ValueTypeReturnedAsFieldsOff)
2795     MyValue3 test99() throws Throwable {
2796         return (MyValue3)test99_mh.invokeExact(this);
2797     }
2798 
2799     @DontCompile
2800     public void test99_verifier(boolean warmup) throws Throwable {
2801         test99_bool = !test99_bool;
2802         MyValue3 vt = test99();
2803         vt.verify(test99_bool ? test99_vt1 : test99_vt2);
2804     }
2805 
2806     // Similar as above but with the method handle for target1 not
2807     // constant. Shouldn't cause any allocation.
2808     @ForceInline
2809     static MyValue2 test100_target1() {
2810         return MyValue2.createWithFieldsInline(rI, true);
2811     }
2812 
2813     @ForceInline
2814     static MyValue2 test100_target2() {
2815         return MyValue2.createWithFieldsInline(rI+1, false);
2816     }
2817 
2818     static boolean test100_bool = true;
2819     @ForceInline
2820     static boolean test100_test() {
2821         return test100_bool;
2822     }
2823 
2824     static final MethodHandle test100_mh;
2825     static MethodHandle test100_mh1;
2826 
2827     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
2828     @Test(valid = ValueTypeReturnedAsFieldsOff)
2829     long test100() throws Throwable {
2830         return ((MyValue2)test100_mh.invokeExact(test100_mh1)).hash();
2831     }
2832 
2833     @DontCompile
2834     public void test100_verifier(boolean warmup) throws Throwable {
2835         test100_bool = !test100_bool;
2836         long hash = test100();
2837         Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(rI+(test100_bool ? 0 : 1), test100_bool).hash());
2838     }
2839 
2840     // Same as above but with the method handle for target2 not
2841     // constant. Shouldn't cause any allocation.
2842     @ForceInline
2843     static MyValue2 test101_target1() {
2844         return MyValue2.createWithFieldsInline(rI, true);
2845     }
2846 
2847     @ForceInline
2848     static MyValue2 test101_target2() {
2849         return MyValue2.createWithFieldsInline(rI+1, false);
2850     }
2851 
2852     static boolean test101_bool = true;
2853     @ForceInline
2854     static boolean test101_test() {
2855         return test101_bool;
2856     }
2857 
2858     static final MethodHandle test101_mh;
2859     static MethodHandle test101_mh2;
2860 
2861     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
2862     @Test(valid = ValueTypeReturnedAsFieldsOff)
2863     long test101() throws Throwable {
2864         return ((MyValue2)test101_mh.invokeExact(test101_mh2)).hash();
2865     }
2866 
2867     @DontCompile
2868     public void test101_verifier(boolean warmup) throws Throwable {
2869         test101_bool = !test101_bool;
2870         long hash = test101();
2871         Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(rI+(test101_bool ? 0 : 1), test101_bool).hash());
2872     }
2873 
2874     // Simple reduction with intermediate result merged in a Lambda
2875     // Form as an __Value. Shouldn't cause any allocations. The entire
2876     // loop should go away as the result is a constant.
2877     static final MethodHandle test102_mh;
2878 
2879     @Test(failOn = ALLOC + STORE + LOOP + STOREVALUETYPEFIELDS)
2880     long test102() throws Throwable {
2881         return (long)test102_mh.invokeExact();
2882     }
2883 
2884     @DontCompile
2885     public void test102_verifier(boolean warmup) throws Throwable {
2886         long v = test102();
2887         Asserts.assertEQ(v, 100L);
2888     }
2889 
2890     // Return of target1, target2 and target3 merged in Lambda Forms
2891     // as an __Value. Shouldn't cause any allocation
2892     final MyValue3 test103_vt1 = MyValue3.create();
2893     @ForceInline
2894     MyValue3 test103_target1() {
2895         return test103_vt1;
2896     }
2897 
2898     final MyValue3 test103_vt2 = MyValue3.create();
2899     @ForceInline
2900     MyValue3 test103_target2() {
2901         return test103_vt2;
2902     }
2903 
2904     final MyValue3 test103_vt3 = MyValue3.create();
2905     @ForceInline
2906     MyValue3 test103_target3() {
2907         return test103_vt3;
2908     }
2909 
2910     boolean test103_bool1 = true;
2911     @ForceInline
2912     boolean test103_test1() {
2913         return test103_bool1;
2914     }
2915 
2916     boolean test103_bool2 = true;
2917     @ForceInline
2918     boolean test103_test2() {
2919         return test103_bool2;
2920     }
2921 
2922     static final MethodHandle test103_mh;
2923 
2924     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
2925     @Test(valid = ValueTypeReturnedAsFieldsOff)
2926     MyValue3 test103() throws Throwable {
2927         return (MyValue3)test103_mh.invokeExact(this);
2928     }
2929 
2930     static int test103_i = 0;
2931     @DontCompile
2932     public void test103_verifier(boolean warmup) throws Throwable {
2933         test103_i++;
2934         test103_bool1 = (test103_i % 2) == 0;
2935         test103_bool2 = (test103_i % 3) == 0;
2936         MyValue3 vt = test103();
2937         vt.verify(test103_bool1 ? test103_vt1 : (test103_bool2 ? test103_vt2 : test103_vt3));
2938     }
2939 
2940     // Same as above but with non constant target2 and target3
2941     @ForceInline
2942     static MyValue2 test104_target1() {
2943         return MyValue2.createWithFieldsInline(rI, true);
2944     }
2945 
2946     @ForceInline
2947     static MyValue2 test104_target2() {
2948         return MyValue2.createWithFieldsInline(rI+1, false);
2949     }
2950 
2951     @ForceInline
2952     static MyValue2 test104_target3() {
2953         return MyValue2.createWithFieldsInline(rI+2, true);
2954     }
2955 
2956     static boolean test104_bool1 = true;
2957     @ForceInline
2958     static boolean test104_test1() {
2959         return test104_bool1;
2960     }
2961 
2962     static boolean test104_bool2 = true;
2963     @ForceInline
2964     static boolean test104_test2() {
2965         return test104_bool2;
2966     }
2967 
2968     static final MethodHandle test104_mh;
2969     static MethodHandle test104_mh2;
2970     static MethodHandle test104_mh3;
2971 
2972     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
2973     @Test(valid = ValueTypeReturnedAsFieldsOff)
2974     long test104() throws Throwable {
2975         return ((MyValue2)test104_mh.invokeExact(test104_mh2, test104_mh3)).hash();
2976     }
2977 
2978     static int test104_i = 0;
2979     @DontCompile
2980     public void test104_verifier(boolean warmup) throws Throwable {
2981         test104_i++;
2982         test104_bool1 = (test104_i % 2) == 0;
2983         test104_bool2 = (test104_i % 3) == 0;
2984         long hash = test104();
2985         int i = rI+(test104_bool1 ? 0 : (test104_bool2 ? 1 : 2));
2986         boolean b = test104_bool1 ? true : (test104_bool2 ? false : true);
2987         Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(i, b).hash());
2988     }
2989 
2990     @ForceInline
2991     static MyValue2 test105_target1() {
2992         return MyValue2.createWithFieldsInline(rI+test105_i, true);
2993     }
2994 
2995     @ForceInline
2996     static MyValue2 test105_target2() {
2997         return MyValue2.createWithFieldsInline(rI-test105_i, false);
2998     }
2999 
3000     static int test105_i = 0;
3001     @ForceInline
3002     static boolean test105_test() {
3003         return (test105_i % 100) == 0;
3004     }
3005 
3006     static final MethodHandle test105_mh;
3007     static MethodHandle test105_mh2;
3008 
3009     // Check that a buffered value returned by a compiled lambda form
3010     // is properly handled by the caller.
3011     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STOREVALUETYPEFIELDS)
3012     @Test(valid = ValueTypeReturnedAsFieldsOff)
3013     @Warmup(11000)
3014     long test105() throws Throwable {
3015         return ((MyValue2)test105_mh.invokeExact(test105_mh2)).hash();
3016     }
3017 
3018     @DontCompile
3019     public void test105_verifier(boolean warmup) throws Throwable {
3020         test105_i++;
3021         long hash = test105();
3022         boolean b = (test105_i % 100) == 0;
3023         Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(rI+test105_i * (b ? 1 : -1), b).hash());
3024     }
3025 
3026 
3027     // OSR compilation with __Value local
3028     @DontCompile
3029     public __Value test106_init() {
3030         return MyValue1.createWithFieldsInline(rI, rL);
3031     }
3032 
3033     @DontCompile
3034     public __Value test106_body() {
3035         return MyValue1.createWithFieldsInline(rI, rL);
3036     }
3037 
3038     @Test()
3039     public __Value test106() throws Throwable {
3040         __Value vt = test106_init();
3041         for (int i = 0; i < 50_000; i++) {
3042             if (i % 2 == 1) {
3043                 vt = test106_body();
3044             }
3045         }
3046         return vt;
3047     }
3048 
3049     @DontCompile
3050     public void test106_verifier(boolean warmup) throws Throwable {
3051         test106();
3052     }
3053 
3054     // ========== Test infrastructure ==========
3055 
3056     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
3057     private static final int ValueTypePassFieldsAsArgsOn = 0x1;
3058     private static final int ValueTypePassFieldsAsArgsOff = 0x2;
3059     private static final int ValueTypeArrayFlattenOn = 0x4;
3060     private static final int ValueTypeArrayFlattenOff = 0x8;
3061     private static final int ValueTypeReturnedAsFieldsOn = 0x10;
3062     private static final int ValueTypeReturnedAsFieldsOff = 0x20;
3063     static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff | ValueTypeReturnedAsFieldsOn;
3064     private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
3065     private static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten");
3066     private static final boolean ValueTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("ValueTypeReturnedAsFields");
3067     private static final int COMP_LEVEL_ANY = -2;
3068     private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
3069     private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
3070     private static final int WARMUP = 251;
3071     private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
3072     private static boolean PRINT_IDEAL  = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
3073     private static boolean XCOMP = Platform.isComp();
3074 
3075     // Regular expressions used to match nodes in the PrintIdeal output
3076     private static final String START = "(\\d+\\t(.*";
3077     private static final String MID = ".*)+\\t===.*";
3078     private static final String END = ")|";
3079     private static final String ALLOC  = "(.*precise klass compiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_instance_Java" + END;
3080     private static final String ALLOCA = "(.*precise klass \\[Qcompiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_array_Java" + END;
3081     private static final String LOAD   = START + "Load(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
3082     private static final String LOADP  = START + "Load(P|N)" + MID + "valuetype\\*" + END;
3083     private static final String LOADK  = START + "LoadK" + MID + END;
3084     private static final String STORE  = START + "Store(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
3085     private static final String STOREP = START + "Store(P|N)" + MID + "valuetype\\*" + END;
3086     private static final String LOOP   = START + "Loop" + MID + "" + END;
3087     private static final String TRAP   = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END;
3088     private static final String RETURN = START + "Return" + MID + "returns" + END;
3089     private static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END;
3090     private static final String NPE = START + "CallStaticJava" + MID + "null_check" + END;
3091     private static final String CCE = START + "CallStaticJava" + MID + "class_check" + END;
3092     private static final String CALL = START + "CallStaticJava" + MID + END;
3093     private static final String STOREVALUETYPEFIELDS = START + "CallStaticJava" + MID + "store_value_type_fields" + END;
3094     private static final String SCOBJ = "(.*# ScObj.*" + END;
3095 
3096     static {
3097         // Gather all test methods and put them in Hashtable
3098         for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
3099             Test[] annos = m.getAnnotationsByType(Test.class);
3100             if (annos.length != 0) {
3101                 tests.put("ValueTypeTestBench::" + m.getName(), m);
3102             }
3103         }
3104     }
3105 
3106     private static void execute_vm(String... args) throws Throwable {
3107         Asserts.assertFalse(tests.isEmpty(), "no tests to execute");
3108         ArrayList<String> all_args = new ArrayList(List.of(args));
3109         // Run tests in own process and verify output
3110         all_args.add(ValueTypeTestBench.class.getName());
3111         all_args.add("run");
3112         // Spawn process with default JVM options from the test's run command
3113         String[] vmInputArgs = InputArguments.getVmInputArgs();
3114         String[] cmds = Arrays.copyOf(vmInputArgs, vmInputArgs.length + all_args.size());
3115         System.arraycopy(all_args.toArray(), 0, cmds, vmInputArgs.length, all_args.size());
3116         OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);
3117         // If ideal graph printing is enabled/supported, verify output
3118         String output = oa.getOutput();
3119         oa.shouldHaveExitValue(0);
3120         boolean verifyIR = output.contains("PrintIdeal enabled") &&
3121                 !output.contains("ValueTypePassFieldsAsArgs is not supported on this platform");
3122         if (verifyIR) {
3123             parseOutput(output);
3124         } else {
3125             System.out.println("WARNING: IR verification disabled! Running with -Xint, -Xcomp or release build?");
3126         }
3127     }
3128 
3129     public static void main(String[] args) throws Throwable {
3130         //tests.values().removeIf(p -> !p.getName().equals("test106")); // Run single test
3131         if (args.length == 0) {
3132             execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation",
3133                     "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
3134                     "-XX:CICompilerCount=1",
3135                     "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
3136                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*",
3137                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*",
3138                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue3::*",
3139                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue4::*",
3140                     "-XX:CompileCommand=compileonly,java.lang.Object::<init>",
3141                     "-XX:CompileCommand=inline,java.lang.__Value::hashCode",
3142                     "-XX:CompileCommand=compileonly,java.lang.invoke.*::*",
3143                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueCapableClass2_*::*",
3144                     "-XX:CompileCommand=compileonly,java.lang.Long::sum");
3145         } else {
3146             // Execute tests
3147             ValueTypeTestBench bench = new ValueTypeTestBench();
3148             bench.run();
3149         }
3150     }
3151 
3152     public static void parseOutput(String output) throws Exception {
3153         Pattern comp_re = Pattern.compile("\\n\\s+\\d+\\s+\\d+\\s+(%| )(s| )(!| )b(n| )\\s+\\S+\\.(?<name>[^.]+::\\S+)\\s+(?<osr>@ \\d+\\s+)?[(]\\d+ bytes[)]\\n");
3154         Matcher m = comp_re.matcher(output);
3155         Map<String,String> compilations = new LinkedHashMap<>();
3156         int prev = 0;
3157         String methodName = null;
3158         while (m.find()) {
3159             if (prev == 0) {
3160                 // Print header
3161                 System.out.print(output.substring(0, m.start()+1));
3162             } else if (methodName != null) {
3163                 compilations.put(methodName, output.substring(prev, m.start()+1));
3164             }
3165             if (m.group("osr") != null) {
3166                 methodName = null;
3167             } else {
3168                 methodName = m.group("name");
3169             }
3170             prev = m.end();
3171         }
3172         if (prev == 0) {
3173             // Print header
3174             System.out.print(output);
3175         } else if (methodName != null) {
3176             compilations.put(methodName, output.substring(prev));
3177         }
3178         // Iterate over compilation output
3179         for (String testName : compilations.keySet()) {
3180             Method test = tests.get(testName);
3181             if (test == null) {
3182                 // Skip helper methods
3183                 continue;
3184             }
3185             String graph = compilations.get(testName);
3186             if (PRINT_GRAPH) {
3187                 System.out.println("\nGraph for " + testName + "\n" + graph);
3188             }
3189             // Parse graph using regular expressions to determine if it contains forbidden nodes
3190             Test[] annos = test.getAnnotationsByType(Test.class);
3191             Test anno = null;
3192             for (Test a : annos) {
3193                 if ((a.valid() & ValueTypePassFieldsAsArgsOn) != 0 && ValueTypePassFieldsAsArgs) {
3194                     assert anno == null;
3195                     anno = a;
3196                 } else if ((a.valid() & ValueTypePassFieldsAsArgsOff) != 0 && !ValueTypePassFieldsAsArgs) {
3197                     assert anno == null;
3198                     anno = a;
3199                 } else if ((a.valid() & ValueTypeArrayFlattenOn) != 0 && ValueTypeArrayFlatten) {
3200                     assert anno == null;
3201                     anno = a;
3202                 } else if ((a.valid() & ValueTypeArrayFlattenOff) != 0 && !ValueTypeArrayFlatten) {
3203                     assert anno == null;
3204                     anno = a;
3205                 } else if ((a.valid() & ValueTypeReturnedAsFieldsOn) != 0 && ValueTypeReturnedAsFields) {
3206                     assert anno == null;
3207                     anno = a;
3208                 } else if ((a.valid() & ValueTypeReturnedAsFieldsOff) != 0 && !ValueTypeReturnedAsFields) {
3209                     assert anno == null;
3210                     anno = a;
3211                 }
3212             }
3213             assert anno != null;
3214             String regexFail = anno.failOn();
3215             if (!regexFail.isEmpty()) {
3216                 Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1));
3217                 Matcher matcher = pattern.matcher(graph);
3218                 boolean found = matcher.find();
3219                 Asserts.assertFalse(found, "Graph for '" + testName + "' contains forbidden node:\n" + (found ? matcher.group() : ""));
3220             }
3221             String[] regexMatch = anno.match();
3222             int[] matchCount = anno.matchCount();
3223             for (int i = 0; i < regexMatch.length; ++i) {
3224                 Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1));
3225                 Matcher matcher = pattern.matcher(graph);
3226                 int count = 0;
3227                 String nodes = "";
3228                 while (matcher.find()) {
3229                     count++;
3230                     nodes += matcher.group() + "\n";
3231                 }
3232                 if (matchCount[i] < 0) {
3233                     Asserts.assertLTE(Math.abs(matchCount[i]), count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
3234                 } else {
3235                     Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
3236                 }
3237             }
3238             tests.remove(testName);
3239             System.out.println(testName + " passed");
3240         }
3241         // Check if all tests were compiled
3242         if (tests.size() != 0) {
3243             for (String name : tests.keySet()) {
3244                 System.out.println("Test '" + name + "' not compiled!");
3245             }
3246             throw new RuntimeException("Not all tests were compiled");
3247         }
3248     }
3249 
3250     public void setup(Method[] methods) {
3251         if (XCOMP) {
3252             // Don't control compilation if -Xcomp is enabled
3253             return;
3254         }
3255         for (Method m : methods) {
3256             if (m.isAnnotationPresent(Test.class)) {
3257                 // Don't inline tests
3258                 WHITE_BOX.testSetDontInlineMethod(m, true);
3259             }
3260             if (m.isAnnotationPresent(DontCompile.class)) {
3261                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true);
3262                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false);
3263                 WHITE_BOX.testSetDontInlineMethod(m, true);
3264             }
3265             if (m.isAnnotationPresent(ForceInline.class)) {
3266                 WHITE_BOX.testSetForceInlineMethod(m, true);
3267             } else if (m.isAnnotationPresent(DontInline.class)) {
3268                 WHITE_BOX.testSetDontInlineMethod(m, true);
3269             }
3270         }
3271     }
3272 
3273     public void run() throws Exception {
3274         if (USE_COMPILER && PRINT_IDEAL && !XCOMP) {
3275             System.out.println("PrintIdeal enabled");
3276         }
3277         System.out.format("rI = %d, rL = %d\n", rI, rL);
3278         setup(this.getClass().getDeclaredMethods());
3279         setup(MyValue1.class.getDeclaredMethods());
3280         setup(MyValue2.class.getDeclaredMethods());
3281         setup(MyValue3.class.getDeclaredMethods());
3282         setup(MyValue4.class.getDeclaredMethods());
3283 
3284         // Compile class initializers
3285         WHITE_BOX.enqueueInitializerForCompilation(this.getClass(), COMP_LEVEL_FULL_OPTIMIZATION);
3286         WHITE_BOX.enqueueInitializerForCompilation(MyValue1.class, COMP_LEVEL_FULL_OPTIMIZATION);
3287         WHITE_BOX.enqueueInitializerForCompilation(MyValue2.class, COMP_LEVEL_FULL_OPTIMIZATION);
3288         WHITE_BOX.enqueueInitializerForCompilation(MyValue3.class, COMP_LEVEL_FULL_OPTIMIZATION);
3289         WHITE_BOX.enqueueInitializerForCompilation(MyValue4.class, COMP_LEVEL_FULL_OPTIMIZATION);
3290 
3291         // Execute tests
3292         for (Method test : tests.values()) {
3293             Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier", boolean.class);
3294             // Warmup using verifier method
3295             Warmup anno = test.getAnnotation(Warmup.class);
3296             int warmup = anno == null ? WARMUP : anno.value();
3297             for (int i = 0; i < warmup; ++i) {
3298                 verifier.invoke(this, true);
3299             }
3300             // Trigger compilation
3301             WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION);
3302             Asserts.assertTrue(!USE_COMPILER || WHITE_BOX.isMethodCompiled(test, false), test + " not compiled");
3303             // Check result
3304             verifier.invoke(this, false);
3305         }
3306     }
3307 }
3308 
3309 // Mark method as test
3310 @Retention(RetentionPolicy.RUNTIME)
3311 @Repeatable(Tests.class)
3312 @interface Test {
3313     // Regular expression used to match forbidden IR nodes
3314     // in the C2 IR emitted for this test.
3315     String failOn() default "";
3316     // Regular expressions used to match and count IR nodes.
3317     String[] match() default { };
3318     int[] matchCount() default { };
3319     int valid() default ValueTypeTestBench.AllFlags;
3320 }
3321 
3322 @Retention(RetentionPolicy.RUNTIME)
3323 @interface Tests {
3324     Test[] value();
3325 }
3326 
3327 // Force method inlining during compilation
3328 @Retention(RetentionPolicy.RUNTIME)
3329 @interface ForceInline { }
3330 
3331 // Prevent method inlining during compilation
3332 @Retention(RetentionPolicy.RUNTIME)
3333 @interface DontInline { }
3334 
3335 // Prevent method compilation
3336 @Retention(RetentionPolicy.RUNTIME)
3337 @interface DontCompile { }
3338 
3339 @Retention(RetentionPolicy.RUNTIME)
3340 @interface Warmup {
3341     int value();
3342 }