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