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
  36  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  37  *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 -XX:+FullGCALotWithValueTypes
  38  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  39  * @run main/othervm -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  40  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation
  41  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  42  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  43  * @run main/othervm -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  44  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+AlwaysIncrementalInline
  45  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  46  *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1
  47  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  48  */
  49 
  50 package compiler.valhalla.valuetypes;
  51 
  52 import compiler.whitebox.CompilerWhiteBoxTest;
  53 import jdk.internal.misc.Unsafe;
  54 import jdk.test.lib.Asserts;
  55 import jdk.test.lib.management.InputArguments;
  56 import jdk.test.lib.Platform;
  57 import jdk.test.lib.process.ProcessTools;
  58 import jdk.test.lib.process.OutputAnalyzer;
  59 import jdk.test.lib.Utils;
  60 import sun.hotspot.WhiteBox;
  61 
  62 import java.lang.annotation.Retention;
  63 import java.lang.annotation.RetentionPolicy;
  64 import java.lang.annotation.Repeatable;
  65 import java.lang.invoke.*;
  66 import java.lang.reflect.Method;
  67 import java.util.ArrayList;
  68 import java.util.Arrays;
  69 import java.util.Hashtable;
  70 import java.util.LinkedHashMap;
  71 import java.util.List;
  72 import java.util.Map;
  73 import java.util.regex.Matcher;
  74 import java.util.regex.Pattern;
  75 import jdk.experimental.value.*;
  76 
  77 // Test value types
  78 __ByValue final class MyValue1 {
  79     static int s;
  80     static final long sf = ValueTypeTestBench.rL;
  81     final int x;
  82     final long y;
  83     final short z;
  84     final Integer o;
  85     final int[] oa;
  86     final MyValue2 v1;
  87     final MyValue2 v2;
  88     static final MyValue2 v3 = MyValue2.createWithFieldsInline(ValueTypeTestBench.rI, true);
  89     final int c;
  90 
  91     private MyValue1(int x, long y, short z, Integer o, int[] oa, MyValue2 v1, MyValue2 v2, int c) {
  92         s = x;
  93         this.x = x;
  94         this.y = y;
  95         this.z = z;
  96         this.o = o;
  97         this.oa = oa;
  98         this.v1 = v1;
  99         this.v2 = v2;
 100         this.c = c;
 101     }
 102 
 103     private MyValue1() {
 104         s = 0;
 105         this.x = 0;
 106         this.y = 0;
 107         this.z = 0;
 108         this.o = null;
 109         this.oa = null;
 110         this.v1 = MyValue2.createDefaultInline();
 111         this.v2 = MyValue2.createDefaultInline();
 112         this.c = 0;
 113     }
 114 
 115     @DontInline
 116     __ValueFactory static MyValue1 createDefaultDontInline() {
 117         return __MakeDefault MyValue1();
 118     }
 119 
 120     @ForceInline
 121     __ValueFactory static MyValue1 createDefaultInline() {
 122         return __MakeDefault MyValue1();
 123     }
 124 
 125     @DontInline
 126     static MyValue1 createWithFieldsDontInline(int x, long y) {
 127         MyValue1 v = createDefaultInline();
 128         v = setX(v, x);
 129         v = setY(v, y);
 130         v = setZ(v, (short)x);
 131         v = setO(v, new Integer(x));
 132         int[] oa = {x};
 133         v = setOA(v, oa);
 134         v = setV1(v, MyValue2.createWithFieldsInline(x, x < y));
 135         v = setV2(v, MyValue2.createWithFieldsInline(x, x > y));
 136         v = setC(v, ValueTypeTestBench.rI);
 137         return v;
 138     }
 139 
 140     @ForceInline
 141     static MyValue1 createWithFieldsInline(int x, long y) {
 142         MyValue1 v = createDefaultInline();
 143         v = setX(v, x);
 144         v = setY(v, y);
 145         v = setZ(v, (short)x);
 146         v = setO(v, new Integer(x));
 147         int[] oa = {x};
 148         v = setOA(v, oa);
 149         v = setV1(v, MyValue2.createWithFieldsInline(x, x < y));
 150         v = setV2(v, MyValue2.createWithFieldsInline(x, x > y));
 151         v = setC(v, ValueTypeTestBench.rI);
 152         return v;
 153     }
 154 
 155     // Hash only primitive and value type fields to avoid NullPointerException
 156     @ForceInline
 157     public long hashPrimitive() {
 158         return s + sf + x + y + z + c + v1.hash() + v2.hash() + v3.hash();
 159     }
 160 
 161     @ForceInline
 162     public long hash() {
 163         return hashPrimitive() + o + oa[0];
 164     }
 165 
 166     @DontCompile
 167     public long hashInterpreted() {
 168         return s + sf + x + y + z + o + oa[0] + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
 169     }
 170 
 171     @ForceInline
 172     public void print() {
 173         System.out.print("s=" + s + ", sf=" + sf + ", x=" + x + ", y=" + y + ", z=" + z + ", o=" + (o != null ? (Integer)o : "NULL") + ", v1[");
 174         v1.print();
 175         System.out.print("], v2[");
 176         v2.print();
 177         System.out.print("], v3[");
 178         v3.print();
 179         System.out.print("], c=" + c);
 180     }
 181 
 182     @ForceInline
 183     __ValueFactory static MyValue1 setX(MyValue1 v, int x) {
 184         v.x = x;
 185         return v;
 186     }
 187 
 188     @ForceInline
 189     __ValueFactory static MyValue1 setY(MyValue1 v, long y) {
 190         v.y = y;
 191         return v;
 192     }
 193 
 194     @ForceInline
 195     __ValueFactory static MyValue1 setZ(MyValue1 v, short z) {
 196         v.z = z;
 197         return v;
 198     }
 199 
 200     @ForceInline
 201     __ValueFactory static MyValue1 setO(MyValue1 v, Integer o) {
 202         v.o = o;
 203         return v;
 204     }
 205 
 206     @ForceInline
 207     __ValueFactory static MyValue1 setOA(MyValue1 v, int[] oa) {
 208         v.oa = oa;
 209         return v;
 210     }
 211 
 212     @ForceInline
 213     __ValueFactory static MyValue1 setC(MyValue1 v, int c) {
 214         v.c = c;
 215         return v;
 216     }
 217 
 218     @ForceInline
 219     __ValueFactory static MyValue1 setV1(MyValue1 v, MyValue2 v1) {
 220         v.v1 = v1;
 221         return v;
 222     }
 223 
 224     @ForceInline
 225     __ValueFactory static MyValue1 setV2(MyValue1 v, MyValue2 v2) {
 226         v.v2 = v2;
 227         return v;
 228     }
 229 }
 230 
 231 __ByValue final class MyValue2 {
 232     final int x;
 233     final byte y;
 234     final boolean b;
 235     final long c;
 236 
 237     private MyValue2(int x, byte y, boolean b, long c) {
 238         this.x = x;
 239         this.y = y;
 240         this.b = b;
 241         this.c = c;
 242     }
 243 
 244     private MyValue2() {
 245         this.x = 0;
 246         this.y = 0;
 247         this.b = false;
 248         this.c = 0;
 249     }
 250 
 251     @ForceInline
 252     __ValueFactory public static MyValue2 createDefaultInline() {
 253         return __MakeDefault MyValue2();
 254     }
 255 
 256     @ForceInline
 257     public static MyValue2 createWithFieldsInline(int x, boolean b) {
 258         MyValue2 v = createDefaultInline();
 259         v = setX(v, x);
 260         v = setY(v, (byte)x);
 261         v = setB(v, b);
 262         v = setC(v, ValueTypeTestBench.rL);
 263         return v;
 264     }
 265 
 266     @ForceInline
 267     public long hash() {
 268         return x + y + (b ? 0 : 1) + c;
 269     }
 270 
 271     @DontInline
 272     public long hashInterpreted() {
 273         return x + y + (b ? 0 : 1) + c;
 274     }
 275 
 276     @ForceInline
 277     public void print() {
 278         System.out.print("x=" + x + "y=" + y + ", b=" + b + ", c=" + c);
 279     }
 280 
 281     @ForceInline
 282     __ValueFactory static MyValue2 setX(MyValue2 v, int x) {
 283         v.x = x;
 284         return v;
 285     }
 286 
 287     @ForceInline
 288     __ValueFactory static MyValue2 setY(MyValue2 v, byte y) {
 289         v.y = y;
 290         return v;
 291     }
 292 
 293     @ForceInline
 294     __ValueFactory static MyValue2 setC(MyValue2 v, long c) {
 295         v.c = c;
 296         return v;
 297     }
 298 
 299     @ForceInline
 300     __ValueFactory static MyValue2 setB(MyValue2 v, boolean b) {
 301         v.b = b;
 302         return v;
 303     }
 304 }
 305 
 306 // Value type definition to stress test return of a value in registers
 307 // (uses all registers of calling convention on x86_64)
 308 __ByValue final class MyValue3 {
 309     final char c;
 310     final byte bb;
 311     final short s;
 312     final int i;
 313     final long l;
 314     final Object o;
 315     final float f1;
 316     final double f2;
 317     final float f3;
 318     final double f4;
 319     final float f5;
 320     final double f6;
 321     final float f7;
 322     final double f8;
 323 
 324     private MyValue3(char c,
 325                      byte bb,
 326                      short s,
 327                      int i,
 328                      long l,
 329                      Object o,
 330                      float f1,
 331                      double f2,
 332                      float f3,
 333                      double f4,
 334                      float f5,
 335                      double f6,
 336                      float f7,
 337                      double f8) {
 338         this.c = c;
 339         this.bb = bb;
 340         this.s = s;
 341         this.i = i;
 342         this.l = l;
 343         this.o = o;
 344         this.f1 = f1;
 345         this.f2 = f2;
 346         this.f3 = f3;
 347         this.f4 = f4;
 348         this.f5 = f5;
 349         this.f6 = f6;
 350         this.f7 = f7;
 351         this.f8 = f8;
 352     }
 353 
 354     private MyValue3() {
 355         this.c = 0;
 356         this.bb = 0;
 357         this.s = 0;
 358         this.i = 0;
 359         this.l = 0;
 360         this.o = null;
 361         this.f1 = 0;
 362         this.f2 = 0;
 363         this.f3 = 0;
 364         this.f4 = 0;
 365         this.f5 = 0;
 366         this.f6 = 0;
 367         this.f7 = 0;
 368         this.f8 = 0;
 369     }
 370 
 371     @ForceInline
 372     __ValueFactory static MyValue3 setC(MyValue3 v, char c) {
 373         v.c = c;
 374         return v;
 375     }
 376 
 377     @ForceInline
 378     __ValueFactory static MyValue3 setBB(MyValue3 v, byte bb) {
 379         v.bb = bb;
 380         return v;
 381     }
 382 
 383     @ForceInline
 384     __ValueFactory static MyValue3 setS(MyValue3 v, short s) {
 385         v.s = s;
 386         return v;
 387     }
 388 
 389     @ForceInline
 390     __ValueFactory static MyValue3 setI(MyValue3 v, int i) {
 391         v.i = i;
 392         return v;
 393     }
 394 
 395     @ForceInline
 396     __ValueFactory static MyValue3 setL(MyValue3 v, long l) {
 397         v.l = l;
 398         return v;
 399     }
 400 
 401     @ForceInline
 402     __ValueFactory static MyValue3 setO(MyValue3 v, Object o) {
 403         v.o = o;
 404         return v;
 405     }
 406 
 407     @ForceInline
 408     __ValueFactory static MyValue3 setF1(MyValue3 v, float f1) {
 409         v.f1 = f1;
 410         return v;
 411     }
 412 
 413     @ForceInline
 414     __ValueFactory static MyValue3 setF2(MyValue3 v, double f2) {
 415         v.f2 = f2;
 416         return v;
 417     }
 418 
 419     @ForceInline
 420     __ValueFactory static MyValue3 setF3(MyValue3 v, float f3) {
 421         v.f3 = f3;
 422         return v;
 423     }
 424 
 425     @ForceInline
 426     __ValueFactory static MyValue3 setF4(MyValue3 v, double f4) {
 427         v.f4 = f4;
 428         return v;
 429     }
 430 
 431     @ForceInline
 432     __ValueFactory static MyValue3 setF5(MyValue3 v, float f5) {
 433         v.f5 = f5;
 434         return v;
 435     }
 436 
 437     @ForceInline
 438     __ValueFactory static MyValue3 setF6(MyValue3 v, double f6) {
 439         v.f6 = f6;
 440         return v;
 441     }
 442 
 443     @ForceInline
 444     __ValueFactory static MyValue3 setF7(MyValue3 v, float f7) {
 445         v.f7 = f7;
 446         return v;
 447     }
 448 
 449     @ForceInline
 450     __ValueFactory static MyValue3 setF8(MyValue3 v, double f8) {
 451         v.f8 = f8;
 452         return v;
 453     }
 454 
 455     @ForceInline
 456     __ValueFactory public static MyValue3 createDefault() {
 457         return __MakeDefault MyValue3();
 458     }
 459 
 460     @ForceInline
 461     public static MyValue3 create() {
 462         java.util.Random r = Utils.getRandomInstance();
 463         MyValue3 v = createDefault();
 464         v = setC(v, (char)r.nextInt());
 465         v = setBB(v, (byte)r.nextInt());
 466         v = setS(v, (short)r.nextInt());
 467         v = setI(v, r.nextInt());
 468         v = setL(v, r.nextLong());
 469         v = setO(v, new Object());
 470         v = setF1(v, r.nextFloat());
 471         v = setF2(v, r.nextDouble());
 472         v = setF3(v, r.nextFloat());
 473         v = setF4(v, r.nextDouble());
 474         v = setF5(v, r.nextFloat());
 475         v = setF6(v, r.nextDouble());
 476         v = setF7(v, r.nextFloat());
 477         v = setF8(v, r.nextDouble());
 478         return v;
 479     }
 480 
 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 
 570     private static final ValueCapableClass1 vcc = ValueCapableClass1.create(rL, rI, (short)rI, (short)rI);
 571     private static final ValueCapableClass2 vcc2 = ValueCapableClass2.create(rL + 1);
 572 
 573     // ========== Helper methods ==========
 574 
 575     public long hash() {
 576         return hash(rI, rL);
 577     }
 578 
 579     public long hash(int x, long y) {
 580         return MyValue1.createWithFieldsInline(x, y).hash();
 581     }
 582 
 583     // ========== Test definitions ==========
 584 
 585     // Receive value type through call to interpreter
 586     @Test(failOn = ALLOC + STORE + TRAP)
 587     public long test1() {
 588         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 589         return v.hash();
 590     }
 591 
 592     @DontCompile
 593     public void test1_verifier(boolean warmup) {
 594         long result = test1();
 595         Asserts.assertEQ(result, hash());
 596     }
 597 
 598     // Receive value type from interpreter via parameter
 599     @Test(failOn = ALLOC + STORE + TRAP)
 600     public long test2(MyValue1 v) {
 601         return v.hash();
 602     }
 603 
 604     @DontCompile
 605     public void test2_verifier(boolean warmup) {
 606         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 607         long result = test2(v);
 608         Asserts.assertEQ(result, hash());
 609     }
 610 
 611     // Return incoming value type without accessing fields
 612     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount = {1, 11}, failOn = LOAD + TRAP)
 613     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = ALLOC + LOAD + STORE + TRAP)
 614     public MyValue1 test3(MyValue1 v) {
 615         return v;
 616     }
 617 
 618     @DontCompile
 619     public void test3_verifier(boolean warmup) {
 620         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 621         MyValue1 v2 = test3(v1);
 622         Asserts.assertEQ(v1.x, v2.x);
 623         Asserts.assertEQ(v1.y, v2.y);
 624     }
 625 
 626     // Create a value type in compiled code and only use fields.
 627     // Allocation should go away because value type does not escape.
 628     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 629     public long test4() {
 630         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 631         return v.hash();
 632     }
 633 
 634     @DontCompile
 635     public void test4_verifier(boolean warmup) {
 636         long result = test4();
 637         Asserts.assertEQ(result, hash());
 638     }
 639 
 640     // Create a value type in compiled code and pass it to
 641     // an inlined compiled method via a call.
 642     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 643     public long test5() {
 644         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 645         return test5Inline(v);
 646     }
 647 
 648     @ForceInline
 649     public long test5Inline(MyValue1 v) {
 650         return v.hash();
 651     }
 652 
 653     @DontCompile
 654     public void test5_verifier(boolean warmup) {
 655         long result = test5();
 656         Asserts.assertEQ(result, hash());
 657     }
 658 
 659     // Create a value type in compiled code and pass it to
 660     // the interpreter via a call.
 661     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC)
 662     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 663     public long test6() {
 664         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 665         // Pass to interpreter
 666         return v.hashInterpreted();
 667     }
 668 
 669     @DontCompile
 670     public void test6_verifier(boolean warmup) {
 671         long result = test6();
 672         Asserts.assertEQ(result, hash());
 673     }
 674 
 675     // Create a value type in compiled code and pass it to
 676     // the interpreter by returning.
 677     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 678     public MyValue1 test7(int x, long y) {
 679         return MyValue1.createWithFieldsInline(x, y);
 680     }
 681 
 682     @DontCompile
 683     public void test7_verifier(boolean warmup) {
 684         MyValue1 v = test7(rI, rL);
 685         Asserts.assertEQ(v.hash(), hash());
 686     }
 687 
 688     // Merge value types created from two branches
 689     @Test(failOn = ALLOC + STORE + TRAP)
 690     public long test8(boolean b) {
 691         MyValue1 v;
 692         if (b) {
 693             v = MyValue1.createWithFieldsInline(rI, rL);
 694         } else {
 695             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 696         }
 697         return v.hash();
 698     }
 699 
 700     @DontCompile
 701     public void test8_verifier(boolean warmup) {
 702         Asserts.assertEQ(test8(true), hash());
 703         Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
 704     }
 705 
 706     // Merge value types created from two branches
 707     @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {10}, failOn = TRAP + ALLOC + STORE)
 708     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 3}, failOn = LOAD + TRAP)
 709     public MyValue1 test9(boolean b) {
 710         MyValue1 v;
 711         if (b) {
 712             // Value type is not allocated
 713             v = MyValue1.createWithFieldsInline(rI, rL);
 714         } else {
 715             // Value type is allocated by the callee
 716             v = MyValue1.createWithFieldsDontInline(rI + 1, rL + 1);
 717         }
 718         // Need to allocate value type if 'b' is true
 719         long sum = v.hashInterpreted();
 720         if (b) {
 721             v = MyValue1.createWithFieldsDontInline(rI, sum);
 722         } else {
 723             v = MyValue1.createWithFieldsDontInline(rI, sum + 1);
 724         }
 725         // Don't need to allocate value type because both branches allocate
 726         return v;
 727     }
 728 
 729     @DontCompile
 730     public void test9_verifier(boolean warmup) {
 731         MyValue1 v = test9(true);
 732         Asserts.assertEQ(v.x, rI);
 733         Asserts.assertEQ(v.y, hash());
 734         v = test9(false);
 735         Asserts.assertEQ(v.x, rI);
 736         Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
 737     }
 738 
 739     // Merge value types created in a loop (not inlined)
 740     @Test(failOn = ALLOC + STORE + TRAP)
 741     public long test10(int x, long y) {
 742         MyValue1 v = MyValue1.createWithFieldsDontInline(x, y);
 743         for (int i = 0; i < 10; ++i) {
 744             v = MyValue1.createWithFieldsDontInline(v.x + 1, v.y + 1);
 745         }
 746         return v.hash();
 747     }
 748 
 749     @DontCompile
 750     public void test10_verifier(boolean warmup) {
 751         long result = test10(rI, rL);
 752         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 753     }
 754 
 755     // Merge value types created in a loop (inlined)
 756     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 757     public long test11(int x, long y) {
 758         MyValue1 v = MyValue1.createWithFieldsInline(x, y);
 759         for (int i = 0; i < 10; ++i) {
 760             v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
 761         }
 762         return v.hash();
 763     }
 764 
 765     @DontCompile
 766     public void test11_verifier(boolean warmup) {
 767         long result = test11(rI, rL);
 768         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 769     }
 770 
 771     // Test loop with uncommon trap referencing a value type
 772     @Test(match = {TRAP, SCOBJ}, matchCount = {1, -1 /* at least 1 */}, failOn = LOAD)
 773     public long test12(boolean b) {
 774         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 775         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 776         for (int i = 0; i < va.length; ++i) {
 777             va[i] = MyValue1.createWithFieldsInline(rI, rL);
 778         }
 779         long result = rL;
 780         for (int i = 0; i < 1000; ++i) {
 781             if (b) {
 782                 result += v.x;
 783             } else {
 784                 // Uncommon trap referencing v. We delegate allocation to the
 785                 // interpreter by adding a SafePointScalarObjectNode.
 786                 result = v.hashInterpreted();
 787                 for (int j = 0; j < va.length; ++j) {
 788                     result += va[j].hash();
 789                 }
 790             }
 791         }
 792         return result;
 793     }
 794 
 795     @DontCompile
 796     public void test12_verifier(boolean warmup) {
 797         long result = test12(warmup);
 798         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 799     }
 800 
 801     // Test loop with uncommon trap referencing a value type
 802     @Test(match = {TRAP}, matchCount = {1})
 803     public long test13(boolean b) {
 804         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 805         MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
 806         for (int i = 0; i < va.length; ++i) {
 807             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
 808         }
 809         long result = rL;
 810         for (int i = 0; i < 1000; ++i) {
 811             if (b) {
 812                 result += v.x;
 813             } else {
 814                 // Uncommon trap referencing v. Should not allocate
 815                 // but just pass the existing oop to the uncommon trap.
 816                 result = v.hashInterpreted();
 817                 for (int j = 0; j < va.length; ++j) {
 818                     result += va[j].hashInterpreted();
 819                 }
 820             }
 821         }
 822         return result;
 823     }
 824 
 825     @DontCompile
 826     public void test13_verifier(boolean warmup) {
 827         long result = test13(warmup);
 828         Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
 829     }
 830 
 831     // Create a value type in a non-inlined method and then call a
 832     // non-inlined method on that value type.
 833     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {10})
 834     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
 835     public long test14() {
 836         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 837         return v.hashInterpreted();
 838     }
 839 
 840     @DontCompile
 841     public void test14_verifier(boolean b) {
 842         long result = test14();
 843         Asserts.assertEQ(result, hash());
 844     }
 845 
 846     // Create a value type in an inlined method and then call a
 847     // non-inlined method on that value type.
 848     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC))
 849     @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
 850     public long test15() {
 851         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 852         return v.hashInterpreted();
 853     }
 854 
 855     @DontCompile
 856     public void test15_verifier(boolean b) {
 857         long result = test15();
 858         Asserts.assertEQ(result, hash());
 859     }
 860 
 861     // Create a value type in a non-inlined method and then call an
 862     // inlined method on that value type.
 863     @Test(failOn = (ALLOC + STORE + TRAP))
 864     public long test16() {
 865         MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
 866         return v.hash();
 867     }
 868 
 869     @DontCompile
 870     public void test16_verifier(boolean b) {
 871         long result = test16();
 872         Asserts.assertEQ(result, hash());
 873     }
 874 
 875     // Create a value type in an inlined method and then call an
 876     // inlined method on that value type.
 877     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
 878     public long test17() {
 879         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 880         return v.hash();
 881     }
 882 
 883     @DontCompile
 884     public void test17_verifier(boolean b) {
 885         long result = test17();
 886         Asserts.assertEQ(result, hash());
 887     }
 888 
 889     // Create a value type in compiled code and pass it to the
 890     // interpreter via a call. The value is live at the first call so
 891     // debug info should include a reference to all its fields.
 892     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 893     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 894     public long test18() {
 895         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 896         v.hashInterpreted();
 897         return v.hashInterpreted();
 898     }
 899 
 900     @DontCompile
 901     public void test18_verifier(boolean warmup) {
 902         long result = test18();
 903         Asserts.assertEQ(result, hash());
 904     }
 905 
 906     // Create a value type in compiled code and pass it to the
 907     // interpreter via a call. The value type is passed twice but
 908     // should only be allocated once.
 909     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
 910     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 911     public long test19() {
 912         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 913         return sumValue(v, v);
 914     }
 915 
 916     @DontCompile
 917     public long sumValue(MyValue1 v, MyValue1 dummy) {
 918         return v.hash();
 919     }
 920 
 921     @DontCompile
 922     public void test19_verifier(boolean warmup) {
 923         long result = test19();
 924         Asserts.assertEQ(result, hash());
 925     }
 926 
 927     // Create a value type (array) in compiled code and pass it to the
 928     // interpreter via a call. The value type is live at the uncommon
 929     // trap: verify that deoptimization causes the value type to be
 930     // correctly allocated.
 931     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
 932     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {2}, failOn = LOAD)
 933     public long test20(boolean deopt) {
 934         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
 935         MyValue2[] va = new MyValue2[3];
 936         if (deopt) {
 937             // uncommon trap
 938             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test20"));
 939         }
 940         return v.hashInterpreted() + va[0].hashInterpreted() +
 941                 va[1].hashInterpreted() + va[2].hashInterpreted();
 942     }
 943 
 944     @DontCompile
 945     public void test20_verifier(boolean warmup) {
 946         MyValue2[] va = new MyValue2[42];
 947         long result = test20(!warmup);
 948         Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
 949     }
 950 
 951     // Value type fields in regular object
 952     MyValue1 val1;
 953     MyValue2 val2;
 954     final MyValue1 val3;
 955     static MyValue1 val4;
 956     static final MyValue1 val5 = MyValue1.createWithFieldsInline(rI, rL);
 957 
 958     // Test value type fields in objects
 959     @Test(match = {ALLOC}, matchCount = {1}, failOn = (TRAP))
 960     public long test21(int x, long y) {
 961         // Compute hash of value type fields
 962         long result = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 963         // Update fields
 964         val1 = MyValue1.createWithFieldsInline(x, y);
 965         val2 = MyValue2.createWithFieldsInline(x, true);
 966         val4 = MyValue1.createWithFieldsInline(x, y);
 967         return result;
 968     }
 969 
 970     @DontCompile
 971     public void test21_verifier(boolean warmup) {
 972         // Check if hash computed by test18 is correct
 973         val1 = MyValue1.createWithFieldsInline(rI, rL);
 974         val2 = val1.v2;
 975         // val3 is initialized in the constructor
 976         val4 = val1;
 977         // val5 is initialized in the static initializer
 978         long hash = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
 979         long result = test21(rI + 1, rL + 1);
 980         Asserts.assertEQ(result, hash);
 981         // Check if value type fields were updated
 982         Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1));
 983         Asserts.assertEQ(val2.hash(), MyValue2.createWithFieldsInline(rI + 1, true).hash());
 984         Asserts.assertEQ(val4.hash(), hash(rI + 1, rL + 1));
 985     }
 986 
 987     // Test folding of constant value type fields
 988     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 989     public long test22() {
 990         // This should be constant folded
 991         return val5.hash() + val5.v3.hash();
 992     }
 993 
 994     @DontCompile
 995     public void test22_verifier(boolean warmup) {
 996         long result = test22();
 997         Asserts.assertEQ(result, val5.hash() + val5.v3.hash());
 998     }
 999 
1000     // Test OSR compilation
1001     @Test()
1002     public long test23() {
1003         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1004         MyValue1[] va = new MyValue1[Math.abs(rI) % 3];
1005         for (int i = 0; i < va.length; ++i) {
1006             va[i] = MyValue1.createWithFieldsInline(rI, rL);
1007         }
1008         long result = 0;
1009         // Long loop to trigger OSR compilation
1010         for (int i = 0 ; i < 100_000; ++i) {
1011             // Reference local value type in interpreter state
1012             result = v.hash();
1013             for (int j = 0; j < va.length; ++j) {
1014                 result += va[j].hash();
1015             }
1016         }
1017         return result;
1018     }
1019 
1020     @DontCompile
1021     public void test23_verifier(boolean warmup) {
1022         long result = test23();
1023         Asserts.assertEQ(result, ((Math.abs(rI) % 3) + 1) * hash());
1024     }
1025 
1026     // Test interpreter to compiled code with various signatures
1027     @Test(failOn = ALLOC + STORE + TRAP)
1028     public long test24(MyValue2 v) {
1029         return v.hash();
1030     }
1031 
1032     @DontCompile
1033     public void test24_verifier(boolean warmup) {
1034         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1035         long result = test24(v);
1036         Asserts.assertEQ(result, v.hashInterpreted());
1037     }
1038 
1039     @Test(failOn = ALLOC + STORE + TRAP)
1040     public long test25(int i1, MyValue2 v, int i2) {
1041         return v.hash() + i1 - i2;
1042     }
1043 
1044     @DontCompile
1045     public void test25_verifier(boolean warmup) {
1046         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1047         long result = test25(rI, v, 2*rI);
1048         Asserts.assertEQ(result, v.hashInterpreted() - rI);
1049     }
1050 
1051     @Test(failOn = ALLOC + STORE + TRAP)
1052     public long test26(long l1, MyValue2 v, long l2) {
1053         return v.hash() + l1 - l2;
1054     }
1055 
1056     @DontCompile
1057     public void test26_verifier(boolean warmup) {
1058         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1059         long result = test26(rL, v, 2*rL);
1060         Asserts.assertEQ(result, v.hashInterpreted() - rL);
1061     }
1062 
1063     @Test(failOn = ALLOC + STORE + TRAP)
1064     public long test27(int i, MyValue2 v, long l) {
1065         return v.hash() + i + l;
1066     }
1067 
1068     @DontCompile
1069     public void test27_verifier(boolean warmup) {
1070         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1071         long result = test27(rI, v, rL);
1072         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1073     }
1074 
1075     @Test(failOn = ALLOC + STORE + TRAP)
1076     public long test28(long l, MyValue2 v, int i) {
1077         return v.hash() + i + l;
1078     }
1079 
1080     @DontCompile
1081     public void test28_verifier(boolean warmup) {
1082         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1083         long result = test28(rL, v, rI);
1084         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1085     }
1086 
1087     @Test(failOn = ALLOC + STORE + TRAP)
1088     public long test29(long l, MyValue1 v1, int i, MyValue2 v2) {
1089         return v1.hash() + i + l + v2.hash();
1090     }
1091 
1092     @DontCompile
1093     public void test29_verifier(boolean warmup) {
1094         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
1095         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
1096         long result = test29(rL, v1, rI, v2);
1097         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
1098     }
1099 
1100     // Test compiled code to interpreter with various signatures
1101     @DontCompile
1102     public long test30_interp(MyValue2 v) {
1103         return v.hash();
1104     }
1105 
1106     @Test(failOn = ALLOC + STORE + TRAP)
1107     public long test30(MyValue2 v) {
1108         return test30_interp(v);
1109     }
1110 
1111     @DontCompile
1112     public void test30_verifier(boolean warmup) {
1113         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1114         long result = test30(v);
1115         Asserts.assertEQ(result, v.hashInterpreted());
1116     }
1117 
1118     @DontCompile
1119     public long test31_interp(int i1, MyValue2 v, int i2) {
1120         return v.hash() + i1 - i2;
1121     }
1122 
1123     @Test(failOn = ALLOC + STORE + TRAP)
1124     public long test31(int i1, MyValue2 v, int i2) {
1125         return test31_interp(i1, v, i2);
1126     }
1127 
1128     @DontCompile
1129     public void test31_verifier(boolean warmup) {
1130         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1131         long result = test31(rI, v, 2*rI);
1132         Asserts.assertEQ(result, v.hashInterpreted() - rI);
1133     }
1134 
1135     @DontCompile
1136     public long test32_interp(long l1, MyValue2 v, long l2) {
1137         return v.hash() + l1 - l2;
1138     }
1139 
1140     @Test(failOn = ALLOC + STORE + TRAP)
1141     public long test32(long l1, MyValue2 v, long l2) {
1142         return test32_interp(l1, v, l2);
1143     }
1144 
1145     @DontCompile
1146     public void test32_verifier(boolean warmup) {
1147         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1148         long result = test32(rL, v, 2*rL);
1149         Asserts.assertEQ(result, v.hashInterpreted() - rL);
1150     }
1151 
1152     @DontCompile
1153     public long test33_interp(int i, MyValue2 v, long l) {
1154         return v.hash() + i + l;
1155     }
1156 
1157     @Test(failOn = ALLOC + STORE + TRAP)
1158     public long test33(int i, MyValue2 v, long l) {
1159         return test33_interp(i, v, l);
1160     }
1161 
1162     @DontCompile
1163     public void test33_verifier(boolean warmup) {
1164         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1165         long result = test33(rI, v, rL);
1166         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1167     }
1168 
1169     @DontCompile
1170     public long test34_interp(long l, MyValue2 v, int i) {
1171         return v.hash() + i + l;
1172     }
1173 
1174     @Test(failOn = ALLOC + STORE + TRAP)
1175     public long test34(long l, MyValue2 v, int i) {
1176         return test34_interp(l, v, i);
1177     }
1178 
1179     @DontCompile
1180     public void test34_verifier(boolean warmup) {
1181         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1182         long result = test34(rL, v, rI);
1183         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
1184     }
1185 
1186     @DontCompile
1187     public long test35_interp(long l, MyValue1 v1, int i, MyValue2 v2) {
1188         return v1.hash() + i + l + v2.hash();
1189     }
1190 
1191     @Test(failOn = ALLOC + STORE + TRAP)
1192     public long test35(long l, MyValue1 v1, int i, MyValue2 v2) {
1193         return test35_interp(l, v1, i, v2);
1194     }
1195 
1196     @DontCompile
1197     public void test35_verifier(boolean warmup) {
1198         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
1199         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
1200         long result = test35(rL, v1, rI, v2);
1201         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
1202     }
1203 
1204     // test that debug info at a call is correct
1205     @DontCompile
1206     public long test36_interp(MyValue2 v, MyValue1[] va, boolean deopt) {
1207         if (deopt) {
1208             // uncommon trap
1209             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test36"));
1210         }
1211         return v.hash() + va[0].hash() + va[1].hash();
1212     }
1213 
1214     @Test(failOn = ALLOC + STORE + TRAP)
1215     public long test36(MyValue2 v, MyValue1[] va, boolean flag, long l) {
1216         return test36_interp(v, va, flag) + l;
1217     }
1218 
1219     @DontCompile
1220     public void test36_verifier(boolean warmup) {
1221         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1222         MyValue1[] va = new MyValue1[2];
1223         va[0] = MyValue1.createWithFieldsDontInline(rI, rL);
1224         va[1] = MyValue1.createWithFieldsDontInline(rI, rL);
1225         long result = test36(v, va, !warmup, rL);
1226         Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
1227     }
1228 
1229     // Test vbox and vunbox
1230     @Test
1231     public long test37() throws Throwable {
1232         return (long)vccUnboxLoadLongMH.invokeExact(vcc);
1233     }
1234 
1235     @DontCompile
1236     public void test37_verifier(boolean warmup) {
1237         try {
1238             long result = test37();
1239             Asserts.assertEQ(vcc.t, result, "Field t of input and result must be equal.");
1240         } catch (Throwable t) {
1241             throw new RuntimeException("test 37 failed", t);
1242         }
1243     }
1244 
1245     // Generate a MethodHandle that obtains field t of the
1246     // derived value type
1247     private static MethodHandle generateVCCUnboxLoadLongMH() {
1248         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1249                 "vccUnboxLoadLong",
1250                 MethodType.methodType(long.class, ValueCapableClass1.class),
1251                 CODE -> {
1252                     CODE.
1253                     aload_0().
1254                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1255                     vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1256                     lreturn();
1257                 }
1258                 );
1259     }
1260 
1261     @Test
1262     public int test38() throws Throwable {
1263         return (int)vccUnboxLoadIntMH.invokeExact(vcc);
1264     }
1265 
1266     @DontCompile
1267     public void test38_verifier(boolean warmup) {
1268         try {
1269             int result = test38();
1270             Asserts.assertEQ(vcc.x, result, "Field x of input and result must be equal.");
1271         } catch (Throwable t) {
1272             throw new RuntimeException("test 38 failed", t);
1273         }
1274     }
1275 
1276     // Generate a MethodHandle that obtains field x of the
1277     // derived value type
1278     private static MethodHandle generateVCCUnboxLoadIntMH() {
1279         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1280                 "vccUnboxLoadInt",
1281                 MethodType.methodType(int.class, ValueCapableClass1.class),
1282                 CODE -> {
1283                     CODE.
1284                     aload_0().
1285                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1286                     vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "x", "I").
1287                     ireturn();
1288                 }
1289                 );
1290     }
1291 
1292     @Test
1293     public ValueCapableClass1 test39() throws Throwable {
1294         return (ValueCapableClass1)vccUnboxBoxMH.invokeExact(vcc);
1295     }
1296 
1297     @DontCompile
1298     public void test39_verifier(boolean warmup) {
1299         try {
1300             ValueCapableClass1 result = test39();
1301             Asserts.assertEQ(vcc.value(), result.value(), "Value of VCC and returned VCC must be equal");
1302         } catch (Throwable t) {
1303             throw new RuntimeException("test 39 failed", t);
1304         }
1305     }
1306 
1307     // Generate a MethodHandle that takes a value-capable class,
1308     // unboxes it, then boxes it again and returns it.
1309     private static MethodHandle generateVCCUnboxBoxMH() {
1310         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1311                 "vccUnboxBox",
1312                 MethodType.methodType(ValueCapableClass1.class, ValueCapableClass1.class),
1313                 CODE -> {
1314                     CODE.
1315                     aload_0().
1316                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1317                     vbox(ValueCapableClass1.class).
1318                     areturn();
1319                 }
1320                 );
1321     }
1322 
1323     @Test
1324     public int test40() throws Throwable {
1325         return (int)vccUnboxBoxLoadIntMH.invokeExact(vcc);
1326     }
1327 
1328     @DontCompile
1329     public void test40_verifier(boolean warmup) {
1330         try {
1331             int result = test40();
1332             Asserts.assertEQ(vcc.x, result, "Field x of VCC and result must be equal");
1333         } catch (Throwable t) {
1334             throw new RuntimeException("Test failed in the interpeter", t);
1335         }
1336     }
1337 
1338     // Generate a MethodHandle that takes a value-capable class,
1339     // unboxes it, boxes it, reads a field from it, and returns the
1340     // field.
1341     private static MethodHandle generateVCCUnboxBoxLoadIntMH() {
1342         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1343                 "vccUnboxBoxLoadInt",
1344                 MethodType.methodType(int.class, ValueCapableClass1.class),
1345                 CODE -> {
1346                     CODE.
1347                     aload_0().
1348                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1349                     vbox(ValueCapableClass1.class).
1350                     getfield(ValueCapableClass1.class, "x", "I").
1351                     ireturn();
1352                 }
1353                 );
1354 
1355     }
1356 
1357     // Test value type array creation and initialization
1358     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD))
1359     @Test(valid = ValueTypeArrayFlattenOn)
1360     public MyValue1[] test41(int len) {
1361         MyValue1[] va = new MyValue1[len];
1362         for (int i = 0; i < len; ++i) {
1363             va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
1364         }
1365         return va;
1366     }
1367 
1368     @DontCompile
1369     public void test41_verifier(boolean warmup) {
1370         int len = Math.abs(rI % 10);
1371         MyValue1[] va = test41(len);
1372         for (int i = 0; i < len; ++i) {
1373             Asserts.assertEQ(va[i].hash(), hash());
1374         }
1375     }
1376 
1377     // Test creation of a value type array and element access
1378     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOOP + TRAP))
1379     @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOC + ALLOCA + LOOP + LOAD + LOADP + STORE + TRAP))
1380     public long test42() {
1381         MyValue1[] va = new MyValue1[1];
1382         va[0] = MyValue1.createWithFieldsInline(rI, rL);
1383         return va[0].hash();
1384     }
1385 
1386     @DontCompile
1387     public void test42_verifier(boolean warmup) {
1388         long result = test42();
1389         Asserts.assertEQ(result, hash());
1390     }
1391 
1392     // Test receiving a value type array from the interpreter,
1393     // updating its elements in a loop and computing a hash.
1394     @Test(failOn = (ALLOCA))
1395     public long test43(MyValue1[] va) {
1396         long result = 0;
1397         for (int i = 0; i < 10; ++i) {
1398             result += va[i].hash();
1399             va[i] = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
1400         }
1401         return result;
1402     }
1403 
1404     @DontCompile
1405     public void test43_verifier(boolean warmup) {
1406         MyValue1[] va = new MyValue1[10];
1407         long expected = 0;
1408         for (int i = 0; i < 10; ++i) {
1409             va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1410             expected += va[i].hash();
1411         }
1412         long result = test43(va);
1413         Asserts.assertEQ(expected, result);
1414         for (int i = 0; i < 10; ++i) {
1415             if (va[i].hash() != hash(rI + 1, rL + 1)) {
1416                 Asserts.assertEQ(va[i].hash(), hash(rI + 1, rL + 1));
1417             }
1418         }
1419     }
1420 
1421     // Test returning a value type array received from the interpreter
1422     @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP)
1423     public MyValue1[] test44(MyValue1[] va) {
1424         return va;
1425     }
1426 
1427     @DontCompile
1428     public void test44_verifier(boolean warmup) {
1429         MyValue1[] va = new MyValue1[10];
1430         for (int i = 0; i < 10; ++i) {
1431             va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1432         }
1433         va = test44(va);
1434         for (int i = 0; i < 10; ++i) {
1435             Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1436         }
1437     }
1438 
1439     // Merge value type arrays created from two branches
1440     @Test(failOn = (TRAP))
1441     public MyValue1[] test45(boolean b) {
1442         MyValue1[] va;
1443         if (b) {
1444             va = new MyValue1[5];
1445             for (int i = 0; i < 5; ++i) {
1446                 va[i] = MyValue1.createWithFieldsInline(rI, rL);
1447             }
1448         } else {
1449             va = new MyValue1[10];
1450             for (int i = 0; i < 10; ++i) {
1451                 va[i] = MyValue1.createWithFieldsInline(rI + i, rL + i);
1452             }
1453         }
1454         long sum = va[0].hashInterpreted();
1455         if (b) {
1456             va[0] = MyValue1.createWithFieldsDontInline(rI, sum);
1457         } else {
1458             va[0] = MyValue1.createWithFieldsDontInline(rI + 1, sum + 1);
1459         }
1460         return va;
1461     }
1462 
1463     @DontCompile
1464     public void test45_verifier(boolean warmup) {
1465         MyValue1[] va = test45(true);
1466         Asserts.assertEQ(va.length, 5);
1467         Asserts.assertEQ(va[0].hash(), hash(rI, hash()));
1468         for (int i = 1; i < 5; ++i) {
1469             Asserts.assertEQ(va[i].hash(), hash());
1470         }
1471         va = test45(false);
1472         Asserts.assertEQ(va.length, 10);
1473         Asserts.assertEQ(va[0].hash(), hash(rI + 1, hash(rI, rL) + 1));
1474         for (int i = 1; i < 10; ++i) {
1475             Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1476         }
1477     }
1478 
1479     // Test creation of value type array with single element
1480     @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD + LOOP + TRAP))
1481     @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOCA + LOAD + LOOP + TRAP))
1482     public MyValue1 test46() {
1483         MyValue1[] va = new MyValue1[1];
1484         return va[0];
1485     }
1486 
1487     @DontCompile
1488     public void test46_verifier(boolean warmup) {
1489         MyValue1[] va = new MyValue1[1];
1490         MyValue1 v = test46();
1491         Asserts.assertEQ(v.hashPrimitive(), va[0].hashPrimitive());
1492     }
1493 
1494     // Test default initialization of value type arrays
1495     @Test(failOn = LOAD)
1496     public MyValue1[] test47(int len) {
1497         return new MyValue1[len];
1498     }
1499 
1500     @DontCompile
1501     public void test47_verifier(boolean warmup) {
1502         int len = Math.abs(rI % 10);
1503         MyValue1[] va = new MyValue1[len];
1504         MyValue1[] var = test47(len);
1505         for (int i = 0; i < len; ++i) {
1506             Asserts.assertEQ(va[i].hashPrimitive(), var[i].hashPrimitive());
1507         }
1508     }
1509 
1510     // Test creation of value type array with zero length
1511     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
1512     public MyValue1[] test48() {
1513         return new MyValue1[0];
1514     }
1515 
1516     @DontCompile
1517     public void test48_verifier(boolean warmup) {
1518         MyValue1[] va = test48();
1519         Asserts.assertEQ(va.length, 0);
1520     }
1521 
1522     static MyValue1[] test49_va;
1523 
1524     // Test that value type array loaded from field has correct type
1525     @Test(failOn = (LOOP))
1526     public long test49() {
1527         return test49_va[0].hash();
1528     }
1529 
1530     @DontCompile
1531     public void test49_verifier(boolean warmup) {
1532         test49_va = new MyValue1[1];
1533         test49_va[0] = MyValue1.createWithFieldsInline(rI, rL);
1534         long result = test49();
1535         Asserts.assertEQ(result, hash());
1536     }
1537 
1538     // test vdefault
1539     @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
1540     public long test50() {
1541         MyValue2 v = MyValue2.createDefaultInline();
1542         return v.hash();
1543     }
1544 
1545     @DontCompile
1546     public void test50_verifier(boolean warmup) {
1547         long result = test50();
1548         Asserts.assertEQ(result, MyValue2.createDefaultInline().hash());
1549     }
1550 
1551     // test vdefault
1552     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
1553     public long test51() {
1554         MyValue1 v1 = MyValue1.createDefaultInline();
1555         MyValue1 v2 = MyValue1.createDefaultDontInline();
1556         return v1.hashPrimitive() + v2.hashPrimitive();
1557     }
1558 
1559     @DontCompile
1560     public void test51_verifier(boolean warmup) {
1561         long result = test51();
1562         Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive());
1563     }
1564 
1565     // test vwithfield
1566     @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
1567     public long test52() {
1568         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1569         return v.hash();
1570     }
1571 
1572     @DontCompile
1573     public void test52_verifier(boolean warmup) {
1574         long result = test52();
1575         Asserts.assertEQ(result, MyValue2.createWithFieldsInline(rI, true).hash());
1576     }
1577 
1578     // test vwithfield
1579     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
1580     public long test53() {
1581         MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL);
1582         MyValue1 v2 = MyValue1.createWithFieldsDontInline(rI, rL);
1583         return v1.hash() + v2.hash();
1584     }
1585 
1586     @DontCompile
1587     public void test53_verifier(boolean warmup) {
1588         long result = test53();
1589         Asserts.assertEQ(result, 2 * hash());
1590     }
1591 
1592     // multi-dimensional arrays
1593     @Test
1594     public MyValue1[][][] test54(int len1, int len2, int len3) {
1595         MyValue1[][][] arr = new MyValue1[len1][len2][len3];
1596         for (int i = 0; i < len1; i++) {
1597             for (int j = 0; j < len2; j++) {
1598                 for (int k = 0; k < len3; k++) {
1599                     arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i , rL + j + k);
1600                 }
1601             }
1602         }
1603         return arr;
1604     }
1605 
1606     @DontCompile
1607     public void test54_verifier(boolean warmup) {
1608         MyValue1[][][] arr = test54(2, 3, 4);
1609         for (int i = 0; i < 2; i++) {
1610             for (int j = 0; j < 3; j++) {
1611                 for (int k = 0; k < 4; k++) {
1612                     Asserts.assertEQ(arr[i][j][k].hash(), MyValue1.createWithFieldsDontInline(rI + i , rL + j + k).hash());
1613                 }
1614             }
1615         }
1616     }
1617 
1618     @Test
1619     public void test55(MyValue1[][][] arr, long[] res) {
1620         int l = 0;
1621         for (int i = 0; i < arr.length; i++) {
1622             for (int j = 0; j < arr[i].length; j++) {
1623                 for (int k = 0; k < arr[i][j].length; k++) {
1624                     res[l] = arr[i][j][k].hash();
1625                     l++;
1626                 }
1627             }
1628         }
1629     }
1630 
1631     @DontCompile
1632     public void test55_verifier(boolean warmup) {
1633         MyValue1[][][] arr = new MyValue1[2][3][4];
1634         long[] res = new long[2*3*4];
1635         long[] verif = new long[2*3*4];
1636         int l = 0;
1637         for (int i = 0; i < 2; i++) {
1638             for (int j = 0; j < 3; j++) {
1639                 for (int k = 0; k < 4; k++) {
1640                     arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i, rL + j + k);
1641                     verif[l] = arr[i][j][k].hash();
1642                     l++;
1643                 }
1644             }
1645         }
1646         test55(arr, res);
1647         for (int i = 0; i < verif.length; i++) {
1648             Asserts.assertEQ(res[i], verif[i]);
1649         }
1650     }
1651 
1652     class TestClass56 {
1653         public MyValue1 v;
1654     }
1655 
1656     // Test allocation elimination of unused object with initialized value type field
1657     @Test(failOn = ALLOC + LOAD + STORE + LOOP)
1658     public void test56(boolean deopt) {
1659         TestClass56 unused = new TestClass56();
1660         MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
1661         unused.v = v;
1662         if (deopt) {
1663             // uncommon trap
1664             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test56"));
1665         }
1666     }
1667 
1668     @DontCompile
1669     public void test56_verifier(boolean warmup) {
1670         test56(!warmup);
1671     }
1672 
1673     // Test loop peeling
1674     @Test(failOn = ALLOC + LOAD + STORE)
1675     public void test57() {
1676         MyValue1 v = MyValue1.createWithFieldsInline(0, 1);
1677         // Trigger OSR compilation and loop peeling
1678         for (int i = 0; i < 100_000; ++i) {
1679             if (v.x != i || v.y != i + 1) {
1680                 // Uncommon trap
1681                 throw new RuntimeException("test57 failed");
1682             }
1683             v = MyValue1.createWithFieldsInline(i + 1, i + 2);
1684         }
1685     }
1686 
1687     @DontCompile
1688     public void test57_verifier(boolean warmup) {
1689         test57();
1690     }
1691 
1692     // Test loop peeling and unrolling
1693     @Test()
1694     public void test58() {
1695         MyValue1 v1 = MyValue1.createWithFieldsInline(0, 0);
1696         MyValue1 v2 = MyValue1.createWithFieldsInline(1, 1);
1697         // Trigger OSR compilation and loop peeling
1698         for (int i = 0; i < 100_000; ++i) {
1699             if (v1.x != 2*i || v2.x != i+1 || v2.y != i+1) {
1700                 // Uncommon trap
1701                 throw new RuntimeException("test58 failed");
1702             }
1703             v1 = MyValue1.createWithFieldsInline(2*(i+1), 0);
1704             v2 = MyValue1.createWithFieldsInline(i+2, i+2);
1705         }
1706     }
1707 
1708     @DontCompile
1709     public void test58_verifier(boolean warmup) {
1710         test58();
1711     }
1712 
1713     // When calling a method on __Value, passing fields as arguments is impossible
1714     @Test(failOn = ALLOC + STORE + LOAD)
1715     public String test59(MyValue1 v) {
1716         return v.toString();
1717     }
1718 
1719     @DontCompile
1720     public void test59_verifier(boolean warmup) {
1721         boolean failed = false;
1722         try {
1723             test59(val1);
1724             failed = true;
1725         } catch (UnsupportedOperationException uoe) {
1726         }
1727         Asserts.assertFalse(failed);
1728     }
1729 
1730     // Same as above, but the method on __Value is inlined
1731     // hashCode allocates an exception so can't really check the graph shape
1732     @Test()
1733     public int test60(MyValue1 v) {
1734         return v.hashCode();
1735     }
1736 
1737     @DontCompile
1738     public void test60_verifier(boolean warmup) {
1739         boolean failed = false;
1740         try {
1741             test60(val1);
1742             failed = true;
1743         } catch (UnsupportedOperationException uoe) {
1744         }
1745         Asserts.assertFalse(failed);
1746     }
1747 
1748     /* The compiler is supposed to determine that the value to be
1749      * unboxed in nullcvvUnboxLoadLong is always null. Therefore, the
1750      * compiler generates only the path leading to the corresponding
1751      * uncommon trap. */
1752     @Test(failOn = RETURN)
1753     public long test61() throws Throwable {
1754         return (long)nullvccUnboxLoadLongMH.invokeExact();
1755     }
1756 
1757     @DontCompile
1758     public void test61_verifier(boolean warmup) throws Throwable {
1759         try {
1760             long result = test61();
1761             throw new RuntimeException("Test failed because no exception was thrown");
1762         } catch (NullPointerException e) {
1763         }
1764     }
1765 
1766     public static MethodHandle generateNullVCCUnboxLoadLongMH() {
1767         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1768                 "nullvccUnboxLoadLong",
1769                 MethodType.methodType(long.class),
1770                 CODE -> {
1771                     CODE.
1772                     aconst_null().
1773                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1774                     vgetfield(ValueCapableClass1.class, "t", "J").
1775                     lreturn();
1776                 }
1777                 );
1778     }
1779 
1780     /* The compiler is supposed to determine that the allocated
1781      * ValueCapableClass1 instance is never null (and therefore not
1782      * generate a null check). Also, the source and target type match
1783      * (known at compile time), so no type check is needed either.*/
1784     @Test(failOn = NPE)
1785     public long test62() throws Throwable {
1786         return (long)checkedvccUnboxLoadLongMH.invokeExact();
1787     }
1788 
1789     @DontCompile
1790     public void test62_verifier(boolean warmup) throws Throwable {
1791         long result = test62();
1792         Asserts.assertEQ(result, 17L);
1793     }
1794 
1795     public static MethodHandle generateCheckedVCCUnboxLoadLongMH() {
1796         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1797                 "checkedVCCUnboxLoadLongMH",
1798                 MethodType.methodType(long.class),
1799                 CODE -> {
1800                     CODE.
1801                     invokestatic(ValueCapableClass1.class, "createInline", "()Lcompiler/valhalla/valuetypes/ValueCapableClass1;", false).
1802                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1803                     vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1804                     lreturn();
1805                 }
1806                 );
1807     }
1808 
1809     /* The compiler is supposed to emit a runtime null check because
1810      * it does not have enough information to determine that the value
1811      * to be unboxed is not null (and either that it is null). The
1812      * declared type of the */
1813     @Test(match = {NPE}, matchCount = {1})
1814     public long test63(ValueCapableClass1 vcc) throws Throwable {
1815         return (long)vccUnboxLoadLongMH.invokeExact(vcc);
1816     }
1817 
1818     @DontCompile
1819     public void test63_verifier(boolean warmup) throws Throwable {
1820         try {
1821             long result = test63(null);
1822             throw new RuntimeException("Test failed because no exception was thrown");
1823         } catch (NullPointerException e) {
1824         }
1825     }
1826 
1827     /* Attempt to unbox an object that is not a subclass of the
1828      * value-capable class derived from the value type specified in
1829      * the vunbox bytecode. */
1830     @Test(match = {NPE,CCE}, matchCount = {1,1})
1831     public long test64(Object vcc) throws Throwable {
1832         return (long)objectUnboxLoadLongMH.invokeExact(vcc);
1833     }
1834 
1835     @DontCompile
1836     public void test64_verifier(boolean warmup) throws Throwable {
1837         try {
1838             long result = test64(new Object());
1839             throw new RuntimeException("Test failed because no exception was thrown");
1840         } catch (ClassCastException e) {
1841         }
1842 
1843         try {
1844             long result = test64(vcc2);
1845             throw new RuntimeException("Test failed because no exception was thrown");
1846         } catch (ClassCastException e) {
1847         }
1848 
1849         Asserts.assertEQ(test64(vcc), rL);
1850     }
1851 
1852     private static MethodHandle generateObjectUnboxLoadLongMH() {
1853         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1854                 "ObjectUnboxLoadLong",
1855                 MethodType.methodType(long.class, Object.class),
1856                 CODE -> {
1857                     CODE.
1858                     aload_0().
1859                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1860                     vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
1861                     lreturn();
1862                 }
1863                 );
1864     }
1865 
1866     /* Generate an if-then-else construct with one path that contains
1867      * an invalid boxing operation (boxing of a value-type to a
1868      * non-matching value-capable class).*/
1869     @Test(match = {NPE, CCE}, matchCount = {2, 2})
1870     public long test65(Object obj, boolean warmup) throws Throwable {
1871         return (long)objectBoxMH.invokeExact(obj, warmup);
1872     }
1873 
1874     @DontCompile
1875     public void test65_verifier(boolean warmup) throws Throwable {
1876         try {
1877             long result = test65(vcc2, true);
1878             throw new RuntimeException("Test failed because no exception was thrown");
1879         } catch (ClassCastException e) {
1880         }
1881 
1882         Asserts.assertEQ(test65(vcc, true), rL);
1883 
1884         try {
1885             long result = test65(vcc2, false);
1886             throw new RuntimeException("Test failed because no exception was thrown");
1887         } catch (ClassCastException e) {
1888         }
1889 
1890         try {
1891             long result = test65(vcc, false);
1892             throw new RuntimeException("Test failed because no exception was thrown");
1893         } catch (ClassCastException e) {
1894         }
1895     }
1896 
1897     private static MethodHandle generateObjectBoxMH() {
1898         return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
1899                 "ObjectBox",
1900                 MethodType.methodType(long.class, Object.class, boolean.class),
1901                 CODE -> {
1902                     CODE.
1903                     iload_1().
1904                     iconst_1().
1905                     if_icmpne((short)14).
1906                     aload_0().
1907                     vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
1908                     vbox(ValueCapableClass1.class).
1909                     getfield(ValueCapableClass1.class, "t", "J").
1910                     lreturn().
1911                     aload_0().
1912                     vunbox(ValueType.forClass(ValueCapableClass2.class).valueClass()).
1913                     vbox(ValueCapableClass1.class).
1914                     getfield(ValueCapableClass1.class, "t", "J").
1915                     lreturn();
1916                 }
1917                 );
1918     }
1919 
1920     // Test deoptimization at call return with return value in registers
1921     @DontCompile
1922     public MyValue2 test66_interp(boolean deopt) {
1923         if (deopt) {
1924             // uncommon trap
1925             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test66"));
1926         }
1927         return MyValue2.createWithFieldsInline(rI, true);
1928     }
1929 
1930     @Test()
1931     public MyValue2 test66(boolean flag) {
1932         return test66_interp(flag);
1933     }
1934 
1935     @DontCompile
1936     public void test66_verifier(boolean warmup) {
1937         MyValue2 result = test66(!warmup);
1938         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
1939         Asserts.assertEQ(result.hash(), v.hash());
1940     }
1941 
1942     // Return value types in registers from interpreter -> compiled
1943     final MyValue3 test67_vt = MyValue3.create();
1944     @DontCompile
1945     public MyValue3 test67_interp() {
1946         return test67_vt;
1947     }
1948 
1949     MyValue3 test67_vt2;
1950     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
1951     @Test(valid = ValueTypeReturnedAsFieldsOff)
1952     public void test67() {
1953         test67_vt2 = test67_interp();
1954     }
1955 
1956     @DontCompile
1957     public void test67_verifier(boolean warmup) {
1958         test67();
1959         test67_vt.verify(test67_vt2);
1960     }
1961 
1962     // Return value types in registers from compiled -> interpreter
1963     final MyValue3 test68_vt = MyValue3.create();
1964     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + TRAP)
1965     @Test(valid = ValueTypeReturnedAsFieldsOff)
1966     public MyValue3 test68() {
1967         return test68_vt;
1968     }
1969 
1970     @DontCompile
1971     public void test68_verifier(boolean warmup) {
1972         MyValue3 vt = test68();
1973         test68_vt.verify(vt);
1974     }
1975 
1976     // Return value types in registers from compiled -> compiled
1977     final MyValue3 test69_vt = MyValue3.create();
1978     @DontInline
1979     public MyValue3 test69_comp() {
1980         return test69_vt;
1981     }
1982 
1983     MyValue3 test69_vt2;
1984     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
1985     @Test(valid = ValueTypeReturnedAsFieldsOff)
1986     public void test69() {
1987         test69_vt2 = test69_comp();
1988     }
1989 
1990     @DontCompile
1991     public void test69_verifier(boolean warmup) throws Exception {
1992         Method helper_m = getClass().getDeclaredMethod("test69_comp");
1993         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
1994             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
1995             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test69_comp not compiled");
1996         }
1997         test69();
1998         test69_vt.verify(test69_vt2);
1999     }
2000 
2001     // Same tests as above but with a value type that cannot be returned in registers
2002 
2003     // Return value types in registers from interpreter -> compiled
2004     final MyValue4 test70_vt = MyValue4.create();
2005     @DontCompile
2006     public MyValue4 test70_interp() {
2007         return test70_vt;
2008     }
2009 
2010     MyValue4 test70_vt2;
2011     @Test
2012     public void test70() {
2013         test70_vt2 = test70_interp();
2014     }
2015 
2016     @DontCompile
2017     public void test70_verifier(boolean warmup) {
2018         test70();
2019         test70_vt.verify(test70_vt2);
2020     }
2021 
2022     // Return value types in registers from compiled -> interpreter
2023     final MyValue4 test71_vt = MyValue4.create();
2024     @Test
2025     public MyValue4 test71() {
2026         return test71_vt;
2027     }
2028 
2029     @DontCompile
2030     public void test71_verifier(boolean warmup) {
2031         MyValue4 vt = test71();
2032         test71_vt.verify(vt);
2033     }
2034 
2035     // Return value types in registers from compiled -> compiled
2036     final MyValue4 test72_vt = MyValue4.create();
2037     @DontInline
2038     public MyValue4 test72_comp() {
2039         return test72_vt;
2040     }
2041 
2042     MyValue4 test72_vt2;
2043     @Test
2044     public void test72() {
2045         test72_vt2 = test72_comp();
2046     }
2047 
2048     @DontCompile
2049     public void test72_verifier(boolean warmup) throws Exception {
2050         Method helper_m = getClass().getDeclaredMethod("test72_comp");
2051         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
2052             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
2053             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test72_comp not compiled");
2054         }
2055         test72();
2056         test72_vt.verify(test72_vt2);
2057     }
2058 
2059     // Return values and method handles tests
2060 
2061     // Everything inlined
2062     final MyValue3 test73_vt = MyValue3.create();
2063     @ForceInline
2064     MyValue3 test73_target() {
2065         return test73_vt;
2066     }
2067 
2068     static final MethodHandle test73_mh;
2069 
2070     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + CALL)
2071     @Test(valid = ValueTypeReturnedAsFieldsOff, match = { ALLOC, STORE }, matchCount = { 1, 11 })
2072     MyValue3 test73() throws Throwable {
2073         return (MyValue3)test73_mh.invokeExact(this);
2074     }
2075 
2076     @DontCompile
2077     public void test73_verifier(boolean warmup) throws Throwable {
2078         MyValue3 vt = test73();
2079         test73_vt.verify(vt);
2080     }
2081 
2082     // Leaf method not inlined but returned type is known
2083     final MyValue3 test74_vt = MyValue3.create();
2084     @DontInline
2085     MyValue3 test74_target() {
2086         return test74_vt;
2087     }
2088 
2089     static final MethodHandle test74_mh;
2090 
2091     @Test
2092     MyValue3 test74() throws Throwable {
2093         return (MyValue3)test74_mh.invokeExact(this);
2094     }
2095 
2096     @DontCompile
2097     public void test74_verifier(boolean warmup) throws Throwable {
2098         Method helper_m = getClass().getDeclaredMethod("test74_target");
2099         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
2100             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
2101             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test74_target not compiled");
2102         }
2103         MyValue3 vt = test74();
2104         test74_vt.verify(vt);
2105     }
2106 
2107     // Leaf method not inlined and returned type not known
2108     final MyValue3 test75_vt = MyValue3.create();
2109     @DontInline
2110     MyValue3 test75_target() {
2111         return test75_vt;
2112     }
2113 
2114     static final MethodHandle test75_mh;
2115 
2116     @Test
2117     MyValue3 test75() throws Throwable {
2118         return (MyValue3)test75_mh.invokeExact(this);
2119     }
2120 
2121     @DontCompile
2122     public void test75_verifier(boolean warmup) throws Throwable {
2123         // hack so C2 doesn't know the target of the invoke call
2124         Class c = Class.forName("java.lang.invoke.DirectMethodHandle");
2125         Method m = c.getDeclaredMethod("internalMemberName", Object.class);
2126         WHITE_BOX.testSetDontInlineMethod(m, warmup);
2127         MyValue3 vt = test75();
2128         test75_vt.verify(vt);
2129     }
2130 
2131     // Test no result from inlined method for incremental inlining
2132     final MyValue3 test76_vt = MyValue3.create();
2133     public MyValue3 test76_inlined() {
2134         throw new RuntimeException();
2135     }
2136 
2137     @Test
2138     public MyValue3 test76() {
2139         try {
2140             return test76_inlined();
2141         } catch (RuntimeException ex) {
2142             return test76_vt;
2143         }
2144     }
2145 
2146     @DontCompile
2147     public void test76_verifier(boolean warmup) throws Exception {
2148         MyValue3 vt = test76();
2149         test76_vt.verify(vt);
2150     }
2151 
2152     static {
2153         try {
2154             MethodHandles.Lookup lookup = MethodHandles.lookup();
2155             MethodType mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2156             test73_mh = lookup.findVirtual(ValueTypeTestBench.class, "test73_target", mt);
2157             test74_mh = lookup.findVirtual(ValueTypeTestBench.class, "test74_target", mt);
2158             test75_mh = lookup.findVirtual(ValueTypeTestBench.class, "test75_target", mt);
2159         } catch (NoSuchMethodException|IllegalAccessException e) {
2160             throw new RuntimeException("method handle lookup fails");
2161         }
2162     }
2163 
2164     // ========== Test infrastructure ==========
2165 
2166     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
2167     private static final int ValueTypePassFieldsAsArgsOn = 0x1;
2168     private static final int ValueTypePassFieldsAsArgsOff = 0x2;
2169     private static final int ValueTypeArrayFlattenOn = 0x4;
2170     private static final int ValueTypeArrayFlattenOff = 0x8;
2171     private static final int ValueTypeReturnedAsFieldsOn = 0x10;
2172     private static final int ValueTypeReturnedAsFieldsOff = 0x20;
2173     static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff | ValueTypeReturnedAsFieldsOn;
2174     private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
2175     private static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten");
2176     private static final boolean ValueTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("ValueTypeReturnedAsFields");
2177     private static final int COMP_LEVEL_ANY = -1;
2178     private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
2179     private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
2180     private static final int WARMUP = 251;
2181     private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
2182     private static boolean PRINT_IDEAL  = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
2183     private static boolean XCOMP = Platform.isComp();
2184 
2185     // Regular expressions used to match nodes in the PrintIdeal output
2186     private static final String START = "(\\d+\\t(.*";
2187     private static final String MID = ".*)+\\t===.*";
2188     private static final String END = ")|";
2189     private static final String ALLOC  = "(.*precise klass compiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_instance_Java" + END;
2190     private static final String ALLOCA = "(.*precise klass \\[Qcompiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_array_Java" + END;
2191     private static final String LOAD   = START + "Load(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
2192     private static final String LOADP  = START + "Load(P|N)" + MID + "valuetype\\*" + END;
2193     private static final String STORE  = START + "Store(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
2194     private static final String STOREP = START + "Store(P|N)" + MID + "valuetype\\*" + END;
2195     private static final String LOOP   = START + "Loop" + MID + "" + END;
2196     private static final String TRAP   = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END;
2197     private static final String RETURN = START + "Return" + MID + "returns" + END;
2198     private static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END;
2199     private static final String NPE = START + "CallStaticJava" + MID + "null_check" + END;
2200     private static final String CCE = START + "CallStaticJava" + MID + "class_check" + END;
2201     private static final String CALL = START + "CallStaticJava" + MID + END;
2202     private static final String SCOBJ = "(.*# ScObj.*" + END;
2203 
2204     static {
2205         // Gather all test methods and put them in Hashtable
2206         for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
2207             Test[] annos = m.getAnnotationsByType(Test.class);
2208             if (annos.length != 0) {
2209                 tests.put("ValueTypeTestBench::" + m.getName(), m);
2210             }
2211         }
2212     }
2213 
2214     private static void execute_vm(String... args) throws Throwable {
2215         Asserts.assertFalse(tests.isEmpty(), "no tests to execute");
2216         ArrayList<String> all_args = new ArrayList(List.of(args));
2217         // Run tests in own process and verify output
2218         all_args.add(ValueTypeTestBench.class.getName());
2219         all_args.add("run");
2220         // Spawn process with default JVM options from the test's run command
2221         String[] vmInputArgs = InputArguments.getVmInputArgs();
2222         String[] cmds = Arrays.copyOf(vmInputArgs, vmInputArgs.length + all_args.size());
2223         System.arraycopy(all_args.toArray(), 0, cmds, vmInputArgs.length, all_args.size());
2224         OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);
2225         // If ideal graph printing is enabled/supported, verify output
2226         String output = oa.getOutput();
2227         oa.shouldHaveExitValue(0);
2228         boolean verifyIR = output.contains("PrintIdeal enabled") &&
2229                 !output.contains("ValueTypePassFieldsAsArgs is not supported on this platform");
2230         if (verifyIR) {
2231             parseOutput(output);
2232         } else {
2233             System.out.println("WARNING: IR verification disabled! Running with -Xint, -Xcomp or release build?");
2234         }
2235     }
2236 
2237     public static void main(String[] args) throws Throwable {
2238         //tests.values().removeIf(p -> !p.getName().equals("test74")); // Run single test
2239         if (args.length == 0) {
2240             execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation",
2241                     "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
2242                     "-XX:CICompilerCount=1",
2243                     "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
2244                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*",
2245                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*",
2246                     "-XX:CompileCommand=compileonly,java.lang.Object::<init>",
2247                     "-XX:CompileCommand=inline,java.lang.__Value::hashCode",
2248                     "-XX:CompileCommand=compileonly,java.lang.invoke.*::*");
2249         } else {
2250             // Execute tests
2251             ValueTypeTestBench bench = new ValueTypeTestBench();
2252             bench.run();
2253         }
2254     }
2255 
2256     public static void parseOutput(String output) throws Exception {
2257         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");
2258         Matcher m = comp_re.matcher(output);
2259         Map<String,String> compilations = new LinkedHashMap<>();
2260         int prev = 0;
2261         String methodName = null;
2262         while (m.find()) {
2263             if (prev == 0) {
2264                 // Print header
2265                 System.out.print(output.substring(0, m.start()+1));
2266             } else if (methodName != null) {
2267                 compilations.put(methodName, output.substring(prev, m.start()+1));
2268             }
2269             if (m.group("osr") != null) {
2270                 methodName = null;
2271             } else {
2272                 methodName = m.group("name");
2273             }
2274             prev = m.end();
2275         }
2276         if (prev == 0) {
2277             // Print header
2278             System.out.print(output);
2279         } else if (methodName != null) {
2280             compilations.put(methodName, output.substring(prev));
2281         }
2282         // Iterate over compilation output
2283         for (String testName : compilations.keySet()) {
2284             Method test = tests.get(testName);
2285             if (test == null) {
2286                 // Skip helper methods
2287                 continue;
2288             }
2289             String graph = compilations.get(testName);
2290             if (PRINT_GRAPH) {
2291                 System.out.println("\nGraph for " + testName + "\n" + graph);
2292             }
2293             // Parse graph using regular expressions to determine if it contains forbidden nodes
2294             Test[] annos = test.getAnnotationsByType(Test.class);
2295             Test anno = null;
2296             for (Test a : annos) {
2297                 if ((a.valid() & ValueTypePassFieldsAsArgsOn) != 0 && ValueTypePassFieldsAsArgs) {
2298                     assert anno == null;
2299                     anno = a;
2300                 } else if ((a.valid() & ValueTypePassFieldsAsArgsOff) != 0 && !ValueTypePassFieldsAsArgs) {
2301                     assert anno == null;
2302                     anno = a;
2303                 } else if ((a.valid() & ValueTypeArrayFlattenOn) != 0 && ValueTypeArrayFlatten) {
2304                     assert anno == null;
2305                     anno = a;
2306                 } else if ((a.valid() & ValueTypeArrayFlattenOff) != 0 && !ValueTypeArrayFlatten) {
2307                     assert anno == null;
2308                     anno = a;
2309                 } else if ((a.valid() & ValueTypeReturnedAsFieldsOn) != 0 && ValueTypeReturnedAsFields) {
2310                     assert anno == null;
2311                     anno = a;
2312                 } else if ((a.valid() & ValueTypeReturnedAsFieldsOff) != 0 && !ValueTypeReturnedAsFields) {
2313                     assert anno == null;
2314                     anno = a;
2315                 }
2316             }
2317             assert anno != null;
2318             String regexFail = anno.failOn();
2319             if (!regexFail.isEmpty()) {
2320                 Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1));
2321                 Matcher matcher = pattern.matcher(graph);
2322                 boolean found = matcher.find();
2323                 Asserts.assertFalse(found, "Graph for '" + testName + "' contains forbidden node:\n" + (found ? matcher.group() : ""));
2324             }
2325             String[] regexMatch = anno.match();
2326             int[] matchCount = anno.matchCount();
2327             for (int i = 0; i < regexMatch.length; ++i) {
2328                 Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1));
2329                 Matcher matcher = pattern.matcher(graph);
2330                 int count = 0;
2331                 String nodes = "";
2332                 while (matcher.find()) {
2333                     count++;
2334                     nodes += matcher.group() + "\n";
2335                 }
2336                 if (matchCount[i] < 0) {
2337                     Asserts.assertLTE(Math.abs(matchCount[i]), count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
2338                 } else {
2339                     Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
2340                 }
2341             }
2342             tests.remove(testName);
2343             System.out.println(testName + " passed");
2344         }
2345         // Check if all tests were compiled
2346         if (tests.size() != 0) {
2347             for (String name : tests.keySet()) {
2348                 System.out.println("Test '" + name + "' not compiled!");
2349             }
2350             throw new RuntimeException("Not all tests were compiled");
2351         }
2352     }
2353 
2354     public void setup(Method[] methods) {
2355         if (XCOMP) {
2356           // Don't control compilation if -Xcomp is enabled
2357           return;
2358         }
2359         for (Method m : methods) {
2360             if (m.isAnnotationPresent(Test.class)) {
2361                 // Don't inline tests
2362                 WHITE_BOX.testSetDontInlineMethod(m, true);
2363             }
2364             if (m.isAnnotationPresent(DontCompile.class)) {
2365                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true);
2366                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false);
2367                 WHITE_BOX.testSetDontInlineMethod(m, true);
2368             }
2369             if (m.isAnnotationPresent(ForceInline.class)) {
2370                 WHITE_BOX.testSetForceInlineMethod(m, true);
2371             } else if (m.isAnnotationPresent(DontInline.class)) {
2372                 WHITE_BOX.testSetDontInlineMethod(m, true);
2373             }
2374         }
2375     }
2376 
2377     public void run() throws Exception {
2378         if (USE_COMPILER && PRINT_IDEAL && !XCOMP) {
2379             System.out.println("PrintIdeal enabled");
2380         }
2381         System.out.format("rI = %d, rL = %d\n", rI, rL);
2382         setup(this.getClass().getDeclaredMethods());
2383         setup(MyValue1.class.getDeclaredMethods());
2384         setup(MyValue2.class.getDeclaredMethods());
2385 
2386         // Compile class initializers
2387         WHITE_BOX.enqueueInitializerForCompilation(this.getClass(), COMP_LEVEL_FULL_OPTIMIZATION);
2388         WHITE_BOX.enqueueInitializerForCompilation(MyValue1.class, COMP_LEVEL_FULL_OPTIMIZATION);
2389         WHITE_BOX.enqueueInitializerForCompilation(MyValue2.class, COMP_LEVEL_FULL_OPTIMIZATION);
2390 
2391         // Execute tests
2392         for (Method test : tests.values()) {
2393             Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier", boolean.class);
2394             // Warmup using verifier method
2395             for (int i = 0; i < WARMUP; ++i) {
2396                 verifier.invoke(this, true);
2397             }
2398             // Trigger compilation
2399             WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION);
2400             Asserts.assertTrue(!USE_COMPILER || WHITE_BOX.isMethodCompiled(test, false), test + " not compiled");
2401             // Check result
2402             verifier.invoke(this, false);
2403         }
2404     }
2405 }
2406 
2407 // Mark method as test
2408 @Retention(RetentionPolicy.RUNTIME)
2409 @Repeatable(Tests.class)
2410 @interface Test {
2411     // Regular expression used to match forbidden IR nodes
2412     // in the C2 IR emitted for this test.
2413     String failOn() default "";
2414     // Regular expressions used to match and count IR nodes.
2415     String[] match() default { };
2416     int[] matchCount() default { };
2417     int valid() default ValueTypeTestBench.AllFlags;
2418 }
2419 
2420 @Retention(RetentionPolicy.RUNTIME)
2421 @interface Tests {
2422     Test[] value();
2423 }
2424 
2425 // Force method inlining during compilation
2426 @Retention(RetentionPolicy.RUNTIME)
2427 @interface ForceInline { }
2428 
2429 // Prevent method inlining during compilation
2430 @Retention(RetentionPolicy.RUNTIME)
2431 @interface DontInline { }
2432 
2433 // Prevent method compilation
2434 @Retention(RetentionPolicy.RUNTIME)
2435 @interface DontCompile { }