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