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  *                   -Djdk.lang.reflect.DVT=true compiler.valhalla.valuetypes.ValueTypeTestBench
  42  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  43  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:-UseCompressedOops
  44  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  45  *                   -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1

  46  *                   -Djdk.lang.reflect.DVT=true compiler.valhalla.valuetypes.ValueTypeTestBench
  47  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  48  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:-UseCompressedOops
  49  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  50  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0

  51  *                   -Djdk.lang.reflect.DVT=true -DVerifyIR=false compiler.valhalla.valuetypes.ValueTypeTestBench
  52  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  53  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+AlwaysIncrementalInline
  54  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten
  55  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0

  56  *                   -Djdk.lang.reflect.DVT=true -DVerifyIR=false compiler.valhalla.valuetypes.ValueTypeTestBench
  57  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  58  *                   -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation
  59  *                   -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten
  60  *                   -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1

  61  *                   -Djdk.lang.reflect.DVT=true -DVerifyIR=false compiler.valhalla.valuetypes.ValueTypeTestBench
  62  */


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