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