1 /*
   2  * Copyright (c) 2017, 2024, 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 package compiler.valhalla.inlinetypes;
  25 
  26 import compiler.lib.ir_framework.*;
  27 import jdk.test.lib.Asserts;
  28 
  29 import java.lang.invoke.MethodHandle;
  30 import java.lang.invoke.MethodHandles;
  31 import java.lang.invoke.MethodType;
  32 import java.lang.reflect.Method;
  33 
  34 import static compiler.valhalla.inlinetypes.InlineTypeIRNode.*;
  35 import static compiler.valhalla.inlinetypes.InlineTypes.*;
  36 
  37 import jdk.internal.value.ValueClass;
  38 import jdk.internal.vm.annotation.ImplicitlyConstructible;
  39 import jdk.internal.vm.annotation.LooselyConsistentValue;
  40 import jdk.internal.vm.annotation.NullRestricted;
  41 
  42 /*
  43  * @test
  44  * @key randomness
  45  * @summary Test value class calling convention optimizations.
  46  * @library /test/lib /
  47  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  48  * @enablePreview
  49  * @modules java.base/jdk.internal.value
  50  *          java.base/jdk.internal.vm.annotation
  51  * @run main/othervm/timeout=450 compiler.valhalla.inlinetypes.TestCallingConvention
  52  */
  53 
  54 @ForceCompileClassInitializer
  55 public class TestCallingConvention {
  56 
  57     static {
  58         try {
  59             Class<?> clazz = TestCallingConvention.class;
  60             MethodHandles.Lookup lookup = MethodHandles.lookup();
  61 
  62             MethodType mt = MethodType.methodType(MyValue2.class, boolean.class);
  63             test32_mh = lookup.findVirtual(clazz, "test32_interp", mt);
  64 
  65             mt = MethodType.methodType(Object.class, boolean.class);
  66             test33_mh = lookup.findVirtual(clazz, "test33_interp", mt);
  67 
  68             mt = MethodType.methodType(int.class);
  69             test37_mh = lookup.findVirtual(Test37Value.class, "test", mt);
  70 
  71             mt = MethodType.methodType(MyValue2.class);
  72             test54_mh = lookup.findVirtual(clazz, "test54_callee", mt);
  73 
  74             mt = MethodType.methodType(MyValue2.class, boolean.class);
  75             test56_mh = lookup.findVirtual(clazz, "test56_callee", mt);
  76         } catch (NoSuchMethodException | IllegalAccessException e) {
  77             e.printStackTrace();
  78             throw new RuntimeException("Method handle lookup failed");
  79         }
  80     }
  81 
  82     public static void main(String[] args) {
  83 
  84         Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
  85         // Don't generate bytecodes but call through runtime for reflective calls
  86         scenarios[0].addFlags("-Dsun.reflect.inflationThreshold=10000");
  87         scenarios[1].addFlags("-Dsun.reflect.inflationThreshold=10000");
  88         scenarios[3].addFlags("-XX:FlatArrayElementMaxSize=0");
  89         scenarios[4].addFlags("-XX:-UseTLAB");
  90 
  91         InlineTypes.getFramework()
  92                    .addScenarios(scenarios)
  93                    .addHelperClasses(MyValue1.class,
  94                                      MyValue2.class,
  95                                      MyValue2Inline.class,
  96                                      MyValue3.class,
  97                                      MyValue3Inline.class,
  98                                      MyValue4.class)
  99                    .start();
 100     }
 101 
 102     // Helper methods and classes
 103 
 104     private void deoptimize(String name, Class<?>... params) {
 105         try {
 106             TestFramework.deoptimize(getClass().getDeclaredMethod(name, params));
 107         } catch (NoSuchMethodException e) {
 108             throw new RuntimeException(e);
 109         }
 110     }
 111 
 112     // Test interpreter to compiled code with various signatures
 113     @Test
 114     @IR(failOn = {ALLOC, STORE, TRAP})
 115     public long test1(MyValue2 v) {
 116         return v.hash();
 117     }
 118 
 119     @Run(test = "test1")
 120     public void test1_verifier() {
 121         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 122         long result = test1(v);
 123         Asserts.assertEQ(result, v.hashInterpreted());
 124     }
 125 
 126     @Test
 127     @IR(failOn = {ALLOC, STORE, TRAP})
 128     public long test2(int i1, MyValue2 v, int i2) {
 129         return v.hash() + i1 - i2;
 130     }
 131 
 132     @Run(test = "test2")
 133     public void test2_verifier() {
 134         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 135         long result = test2(rI, v, 2*rI);
 136         Asserts.assertEQ(result, v.hashInterpreted() - rI);
 137     }
 138 
 139     @Test
 140     @IR(failOn = {ALLOC, STORE, TRAP})
 141     public long test3(long l1, MyValue2 v, long l2) {
 142         return v.hash() + l1 - l2;
 143     }
 144 
 145     @Run(test = "test3")
 146     public void test3_verifier() {
 147         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 148         long result = test3(rL, v, 2*rL);
 149         Asserts.assertEQ(result, v.hashInterpreted() - rL);
 150     }
 151 
 152     @Test
 153     @IR(failOn = {ALLOC, STORE, TRAP})
 154     public long test4(int i, MyValue2 v, long l) {
 155         return v.hash() + i + l;
 156     }
 157 
 158     @Run(test = "test4")
 159     public void test4_verifier() {
 160         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 161         long result = test4(rI, v, rL);
 162         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 163     }
 164 
 165     @Test
 166     @IR(failOn = {ALLOC, STORE, TRAP})
 167     public long test5(long l, MyValue2 v, int i) {
 168         return v.hash() + i + l;
 169     }
 170 
 171     @Run(test = "test5")
 172     public void test5_verifier() {
 173         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 174         long result = test5(rL, v, rI);
 175         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 176     }
 177 
 178     @Test
 179     @IR(failOn = {ALLOC, STORE, TRAP})
 180     public long test6(long l, MyValue1 v1, int i, MyValue2 v2) {
 181         return v1.hash() + i + l + v2.hash();
 182     }
 183 
 184     @Run(test = "test6")
 185     public void test6_verifier() {
 186         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 187         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, rD);
 188         long result = test6(rL, v1, rI, v2);
 189         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
 190     }
 191 
 192     // Test compiled code to interpreter with various signatures
 193     @DontCompile
 194     public long test7_interp(MyValue2 v) {
 195         return v.hash();
 196     }
 197 
 198     @Test
 199     @IR(failOn = {ALLOC, STORE, TRAP})
 200     public long test7(MyValue2 v) {
 201         return test7_interp(v);
 202     }
 203 
 204     @Run(test = "test7")
 205     public void test7_verifier() {
 206         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 207         long result = test7(v);
 208         Asserts.assertEQ(result, v.hashInterpreted());
 209     }
 210 
 211     @DontCompile
 212     public long test8_interp(int i1, MyValue2 v, int i2) {
 213         return v.hash() + i1 - i2;
 214     }
 215 
 216     @Test
 217     @IR(failOn = {ALLOC, STORE, TRAP})
 218     public long test8(int i1, MyValue2 v, int i2) {
 219         return test8_interp(i1, v, i2);
 220     }
 221 
 222     @Run(test = "test8")
 223     public void test8_verifier() {
 224         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 225         long result = test8(rI, v, 2*rI);
 226         Asserts.assertEQ(result, v.hashInterpreted() - rI);
 227     }
 228 
 229     @DontCompile
 230     public long test9_interp(long l1, MyValue2 v, long l2) {
 231         return v.hash() + l1 - l2;
 232     }
 233 
 234     @Test
 235     @IR(failOn = {ALLOC, STORE, TRAP})
 236     public long test9(long l1, MyValue2 v, long l2) {
 237         return test9_interp(l1, v, l2);
 238     }
 239 
 240     @Run(test = "test9")
 241     public void test9_verifier() {
 242         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 243         long result = test9(rL, v, 2*rL);
 244         Asserts.assertEQ(result, v.hashInterpreted() - rL);
 245     }
 246 
 247     @DontCompile
 248     public long test10_interp(int i, MyValue2 v, long l) {
 249         return v.hash() + i + l;
 250     }
 251 
 252     @Test
 253     @IR(failOn = {ALLOC, STORE, TRAP})
 254     public long test10(int i, MyValue2 v, long l) {
 255         return test10_interp(i, v, l);
 256     }
 257 
 258     @Run(test = "test10")
 259     public void test10_verifier() {
 260         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 261         long result = test10(rI, v, rL);
 262         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 263     }
 264 
 265     @DontCompile
 266     public long test11_interp(long l, MyValue2 v, int i) {
 267         return v.hash() + i + l;
 268     }
 269 
 270     @Test
 271     @IR(failOn = {ALLOC, STORE, TRAP})
 272     public long test11(long l, MyValue2 v, int i) {
 273         return test11_interp(l, v, i);
 274     }
 275 
 276     @Run(test = "test11")
 277     public void test11_verifier() {
 278         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 279         long result = test11(rL, v, rI);
 280         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 281     }
 282 
 283     @DontCompile
 284     public long test12_interp(long l, MyValue1 v1, int i, MyValue2 v2) {
 285         return v1.hash() + i + l + v2.hash();
 286     }
 287 
 288     @Test
 289     @IR(failOn = {ALLOC, STORE, TRAP})
 290     public long test12(long l, MyValue1 v1, int i, MyValue2 v2) {
 291         return test12_interp(l, v1, i, v2);
 292     }
 293 
 294     @Run(test = "test12")
 295     public void test12_verifier() {
 296         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 297         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, rD);
 298         long result = test12(rL, v1, rI, v2);
 299         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
 300     }
 301 
 302     // Test that debug info at a call is correct
 303     @DontCompile
 304     public long test13_interp(MyValue2 v, MyValue1[] va, boolean deopt) {
 305         if (deopt) {
 306             // uncommon trap
 307             deoptimize("test13", MyValue2.class, MyValue1[].class, boolean.class, long.class);
 308         }
 309         return v.hash() + va[0].hash() + va[1].hash();
 310     }
 311 
 312     @Test
 313     @IR(failOn = {ALLOC, STORE, TRAP})
 314     public long test13(MyValue2 v, MyValue1[] va, boolean flag, long l) {
 315         return test13_interp(v, va, flag) + l;
 316     }
 317 
 318     @Run(test = "test13")
 319     public void test13_verifier(RunInfo info) {
 320         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 321         MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 2);
 322         va[0] = MyValue1.createWithFieldsDontInline(rI, rL);
 323         va[1] = MyValue1.createWithFieldsDontInline(rI, rL);
 324         long result = test13(v, va, !info.isWarmUp(), rL);
 325         Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
 326     }
 327 
 328     // Test deoptimization at call return with value object returned in registers
 329     @DontCompile
 330     public MyValue2 test14_interp(boolean deopt) {
 331         if (deopt) {
 332             // uncommon trap
 333             deoptimize("test14", boolean.class);
 334         }
 335         return MyValue2.createWithFieldsInline(rI, rD);
 336     }
 337 
 338     @Test
 339     public MyValue2 test14(boolean flag) {
 340         return test14_interp(flag);
 341     }
 342 
 343     @Run(test = "test14")
 344     public void test14_verifier(RunInfo info) {
 345         MyValue2 result = test14(!info.isWarmUp());
 346         MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
 347         Asserts.assertEQ(result.hash(), v.hash());
 348     }
 349 
 350     // Return value objects in registers from interpreter -> compiled
 351     @NullRestricted
 352     final MyValue3 test15_vt = MyValue3.create();
 353 
 354     @DontCompile
 355     public MyValue3 test15_interp() {
 356         return test15_vt;
 357     }
 358 
 359     @NullRestricted
 360     MyValue3 test15_vt2;
 361 
 362     @Test
 363     @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
 364         failOn = {ALLOC, TRAP})
 365     public void test15() {
 366         test15_vt2 = test15_interp();
 367     }
 368 
 369     @Run(test = "test15")
 370     public void test15_verifier() {
 371         test15();
 372         test15_vt.verify(test15_vt2);
 373     }
 374 
 375     // Return value objects in registers from compiled -> interpreter
 376     @NullRestricted
 377     final MyValue3 test16_vt = MyValue3.create();
 378 
 379     @Test
 380     @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
 381         failOn = {ALLOC, STORE, TRAP})
 382     public MyValue3 test16() {
 383         return test16_vt;
 384     }
 385 
 386     @Run(test = "test16")
 387     public void test16_verifier() {
 388         MyValue3 vt = test16();
 389         test16_vt.verify(vt);
 390     }
 391 
 392     // Return value objects in registers from compiled -> compiled
 393     @NullRestricted
 394     final MyValue3 test17_vt = MyValue3.create();
 395 
 396     @DontInline
 397     public MyValue3 test17_comp() {
 398         return test17_vt;
 399     }
 400 
 401     @NullRestricted
 402     MyValue3 test17_vt2;
 403 
 404     @Test
 405     @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
 406         failOn = {ALLOC, TRAP})
 407     public void test17() {
 408         test17_vt2 = test17_comp();
 409     }
 410 
 411     @Run(test = "test17")
 412     public void test17_verifier(RunInfo info) throws Exception {
 413         Method helper_m = getClass().getDeclaredMethod("test17_comp");
 414         if (!info.isWarmUp() && TestFramework.isCompiled(helper_m)) {
 415             TestFramework.compile(helper_m, CompLevel.C2);
 416             TestFramework.assertCompiledByC2(helper_m);
 417         }
 418 
 419         test17();
 420         test17_vt.verify(test17_vt2);
 421     }
 422 
 423     // Same tests as above but with a value class that cannot be returned in registers
 424 
 425     // Return value objects in registers from interpreter -> compiled
 426     @NullRestricted
 427     final MyValue4 test18_vt = MyValue4.create();
 428 
 429     @DontCompile
 430     public MyValue4 test18_interp() {
 431         return test18_vt;
 432     }
 433 
 434     @NullRestricted
 435     MyValue4 test18_vt2;
 436 
 437     @Test
 438     public void test18() {
 439         test18_vt2 = test18_interp();
 440     }
 441 
 442     @Run(test = "test18")
 443     public void test18_verifier() {
 444         test18();
 445         test18_vt.verify(test18_vt2);
 446     }
 447 
 448     // Return value objects in registers from compiled -> interpreter
 449     @NullRestricted
 450     final MyValue4 test19_vt = MyValue4.create();
 451 
 452     @Test
 453     public MyValue4 test19() {
 454         return test19_vt;
 455     }
 456 
 457     @Run(test = "test19")
 458     public void test19_verifier() {
 459         MyValue4 vt = test19();
 460         test19_vt.verify(vt);
 461     }
 462 
 463     // Return value objects in registers from compiled -> compiled
 464     @NullRestricted
 465     final MyValue4 test20_vt = MyValue4.create();
 466 
 467     @DontInline
 468     public MyValue4 test20_comp() {
 469         return test20_vt;
 470     }
 471 
 472     @NullRestricted
 473     MyValue4 test20_vt2;
 474 
 475     @Test
 476     public void test20() {
 477         test20_vt2 = test20_comp();
 478     }
 479 
 480     @Run(test = "test20")
 481     public void test20_verifier(RunInfo info) throws Exception {
 482         Method helper_m = getClass().getDeclaredMethod("test20_comp");
 483         if (!info.isWarmUp() && TestFramework.isCompiled(helper_m)) {
 484             TestFramework.compile(helper_m, CompLevel.C2);
 485             TestFramework.assertCompiledByC2(helper_m);
 486         }
 487         test20();
 488         test20_vt.verify(test20_vt2);
 489     }
 490 
 491     // Test no result from inlined method for incremental inlining
 492     @NullRestricted
 493     final MyValue3 test21_vt = MyValue3.create();
 494 
 495     public MyValue3 test21_inlined() {
 496         throw new RuntimeException();
 497     }
 498 
 499     @Test
 500     public MyValue3 test21() {
 501         try {
 502             return test21_inlined();
 503         } catch (RuntimeException ex) {
 504             return test21_vt;
 505         }
 506     }
 507 
 508     @Run(test = "test21")
 509     public void test21_verifier() {
 510         MyValue3 vt = test21();
 511         test21_vt.verify(vt);
 512     }
 513 
 514     // Test returning a non-flattened value object as fields
 515     MyValue3 test22_vt = MyValue3.create();
 516 
 517     @Test
 518     public MyValue3 test22() {
 519         return (MyValue3) test22_vt;
 520     }
 521 
 522     @Run(test = "test22")
 523     public void test22_verifier() {
 524         MyValue3 vt = test22();
 525         test22_vt.verify(vt);
 526     }
 527 
 528     // Test calling a method that has circular register/stack dependencies when unpacking value class arguments
 529     @ImplicitlyConstructible
 530     @LooselyConsistentValue
 531     value class TestValue23 {
 532         double f1;
 533 
 534         TestValue23(double val) {
 535             f1 = val;
 536         }
 537     }
 538 
 539     static double test23Callee(int i1, int i2, int i3, int i4, int i5, int i6,
 540                                TestValue23 v1, TestValue23 v2, TestValue23 v3, TestValue23 v4, TestValue23 v5, TestValue23 v6, TestValue23 v7, TestValue23 v8,
 541                                double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8) {
 542         return i1 + i2 + i3 + i4 + i5 + i6 + v1.f1 + v2.f1 + v3.f1 + v4.f1 + v5.f1 + v6.f1 + v7.f1 + v8.f1 + d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8;
 543     }
 544 
 545     @Test
 546     public double test23(int i1, int i2, int i3, int i4, int i5, int i6,
 547                          TestValue23 v1, TestValue23 v2, TestValue23 v3, TestValue23 v4, TestValue23 v5, TestValue23 v6, TestValue23 v7, TestValue23 v8,
 548                          double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8) {
 549         return test23Callee(i1, i2, i3, i4, i5, i6,
 550                             v1, v2, v3, v4, v5, v6, v7, v8,
 551                             d1, d2, d3, d4, d5, d6, d7, d8);
 552     }
 553 
 554     @Run(test = "test23")
 555     public void test23_verifier() {
 556         TestValue23 vt = new TestValue23(rI);
 557         double res1 = test23(rI, rI, rI, rI, rI, rI,
 558                             vt, vt, vt, vt, vt, vt, vt, vt,
 559                             rI, rI, rI, rI, rI, rI, rI, rI);
 560         double res2 = test23Callee(rI, rI, rI, rI, rI, rI,
 561                                    vt, vt, vt, vt, vt, vt, vt, vt,
 562                                    rI, rI, rI, rI, rI, rI, rI, rI);
 563         double res3 = 6*rI + 8*rI + 8*rI;
 564         Asserts.assertEQ(res1, res2);
 565         Asserts.assertEQ(res2, res3);
 566     }
 567 
 568     // Should not return a nullable value object as fields
 569     @Test
 570     public MyValue2 test24() {
 571         return null;
 572     }
 573 
 574     @Run(test = "test24")
 575     public void test24_verifier() {
 576         MyValue2 vt = test24();
 577         Asserts.assertEQ(vt, null);
 578     }
 579 
 580     // Same as test24 but with control flow and inlining
 581     @ForceInline
 582     public MyValue2 test26_callee(boolean b) {
 583         if (b) {
 584             return null;
 585         } else {
 586             return MyValue2.createWithFieldsInline(rI, rD);
 587         }
 588     }
 589 
 590     @Test
 591     public MyValue2 test26(boolean b) {
 592         return test26_callee(b);
 593     }
 594 
 595     @Run(test = "test26")
 596     public void test26_verifier() {
 597         MyValue2 vt = test26(true);
 598         Asserts.assertEQ(vt, null);
 599         vt = test26(false);
 600         Asserts.assertEQ(vt.hash(), MyValue2.createWithFieldsInline(rI, rD).hash());
 601     }
 602 
 603     // Test calling convention with deep hierarchy of flattened fields
 604     @ImplicitlyConstructible
 605     @LooselyConsistentValue
 606     value class Test27Value1 {
 607         Test27Value2 valueField;
 608 
 609         private Test27Value1(Test27Value2 val2) {
 610             valueField = val2;
 611         }
 612 
 613         @DontInline
 614         public int test(Test27Value1 val1) {
 615             return valueField.test(valueField) + val1.valueField.test(valueField);
 616         }
 617     }
 618 
 619     @ImplicitlyConstructible
 620     @LooselyConsistentValue
 621     value class Test27Value2 {
 622         Test27Value3 valueField;
 623 
 624         private Test27Value2(Test27Value3 val3) {
 625             valueField = val3;
 626         }
 627 
 628         @DontInline
 629         public int test(Test27Value2 val2) {
 630             return valueField.test(valueField) + val2.valueField.test(valueField);
 631         }
 632     }
 633 
 634     @ImplicitlyConstructible
 635     @LooselyConsistentValue
 636     value class Test27Value3 {
 637         int x;
 638 
 639         private Test27Value3(int x) {
 640             this.x = x;
 641         }
 642 
 643         @DontInline
 644         public int test(Test27Value3 val3) {
 645             return x + val3.x;
 646         }
 647     }
 648 
 649     @Test
 650     public int test27(Test27Value1 val) {
 651         return val.test(val);
 652     }
 653 
 654     @Run(test = "test27")
 655     public void test27_verifier() {
 656         Test27Value3 val3 = new Test27Value3(rI);
 657         Test27Value2 val2 = new Test27Value2(val3);
 658         Test27Value1 val1 = new Test27Value1(val2);
 659         int result = test27(val1);
 660         Asserts.assertEQ(result, 8*rI);
 661     }
 662 
 663     static final MyValue1 test28Val = MyValue1.createWithFieldsDontInline(rI, rL);
 664 
 665     @Test
 666     public String test28() {
 667         return test28Val.toString();
 668     }
 669 
 670     @Run(test = "test28")
 671     @Warmup(0)
 672     public void test28_verifier() {
 673         String result = test28();
 674     }
 675 
 676     // Test calling a method returning a value object as fields via reflection
 677     @NullRestricted
 678     MyValue3 test29_vt = MyValue3.create();
 679 
 680     @Test
 681     public MyValue3 test29() {
 682         return test29_vt;
 683     }
 684 
 685     @Run(test = "test29")
 686     public void test29_verifier() throws Exception {
 687         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test29").invoke(this);
 688         test29_vt.verify(vt);
 689     }
 690 
 691     @Test
 692     public MyValue3 test30(MyValue3[] array) {
 693         MyValue3 result = MyValue3.create();
 694         array[0] = result;
 695         return result;
 696     }
 697 
 698     @Run(test = "test30")
 699     public void test30_verifier() throws Exception {
 700         MyValue3[] array = (MyValue3[])ValueClass.newNullRestrictedArray(MyValue3.class, 1);
 701         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test30", MyValue3[].class).invoke(this, (Object)array);
 702         array[0].verify(vt);
 703     }
 704 
 705     @NullRestricted
 706     MyValue3 test31_vt;
 707 
 708     @Test
 709     public MyValue3 test31() {
 710         MyValue3 result = MyValue3.create();
 711         test31_vt = result;
 712         return result;
 713     }
 714 
 715     @Run(test = "test31")
 716     public void test31_verifier() throws Exception {
 717         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test31").invoke(this);
 718         test31_vt.verify(vt);
 719     }
 720 
 721     // Test deoptimization at call return with value object returned in registers.
 722     // Same as test14, except the interpreted method is called via a MethodHandle.
 723     static MethodHandle test32_mh;
 724 
 725     @DontCompile
 726     public MyValue2 test32_interp(boolean deopt) {
 727         if (deopt) {
 728             // uncommon trap
 729             deoptimize("test32", boolean.class);
 730         }
 731         return MyValue2.createWithFieldsInline(rI+32, rD);
 732     }
 733 
 734     @Test
 735     public MyValue2 test32(boolean flag) throws Throwable {
 736         return (MyValue2)test32_mh.invokeExact(this, flag);
 737     }
 738 
 739     @Run(test = "test32")
 740     public void test32_verifier(RunInfo info) throws Throwable {
 741         MyValue2 result = test32(!info.isWarmUp());
 742         MyValue2 v = MyValue2.createWithFieldsInline(rI+32, rD);
 743         Asserts.assertEQ(result.hash(), v.hash());
 744     }
 745 
 746     // Same as test32, except the return type is not flattenable.
 747     static MethodHandle test33_mh;
 748 
 749     @DontCompile
 750     public Object test33_interp(boolean deopt) {
 751         if (deopt) {
 752             // uncommon trap
 753             deoptimize("test33", boolean.class);
 754         }
 755         return MyValue2.createWithFieldsInline(rI+33, rD);
 756     }
 757 
 758     @Test
 759     public MyValue2 test33(boolean flag) throws Throwable {
 760         Object o = test33_mh.invokeExact(this, flag);
 761         return (MyValue2)o;
 762     }
 763 
 764     @Run(test = "test33")
 765     public void test33_verifier(RunInfo info) throws Throwable {
 766         MyValue2 result = test33(!info.isWarmUp());
 767         MyValue2 v = MyValue2.createWithFieldsInline(rI+33, rD);
 768         Asserts.assertEQ(result.hash(), v.hash());
 769     }
 770 
 771     // Test selection of correct entry point in SharedRuntime::handle_wrong_method
 772     static boolean test34_deopt = false;
 773 
 774     @DontInline
 775     public static long test34_callee(MyValue2 vt, int i1, int i2, int i3, int i4) {
 776         Asserts.assertEQ(i1, rI);
 777         Asserts.assertEQ(i2, rI);
 778         Asserts.assertEQ(i3, rI);
 779         Asserts.assertEQ(i4, rI);
 780 
 781         if (test34_deopt) {
 782             // uncommon trap
 783             int result = 0;
 784             for (int i = 0; i < 10; ++i) {
 785                 result += rL;
 786             }
 787             return vt.hash() + i1 + i2 + i3 + i4 + result;
 788         }
 789         return vt.hash() + i1 + i2 + i3 + i4;
 790     }
 791 
 792     @Test
 793     public static long test34(MyValue2 vt, int i1, int i2, int i3, int i4) {
 794         return test34_callee(vt, i1, i2, i3, i4);
 795     }
 796 
 797     @Run(test = "test34")
 798     @Warmup(10000) // Make sure test34_callee is compiled
 799     public void test34_verifier(RunInfo info) {
 800         MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
 801         long result = test34(vt, rI, rI, rI, rI);
 802         Asserts.assertEQ(result, vt.hash()+4*rI);
 803         if (!info.isWarmUp()) {
 804             test34_deopt = true;
 805             for (int i = 0; i < 100; ++i) {
 806                 result = test34(vt, rI, rI, rI, rI);
 807                 Asserts.assertEQ(result, vt.hash()+4*rI+10*rL);
 808             }
 809         }
 810     }
 811 
 812     // Test OSR compilation of method with scalarized argument
 813     @Test
 814     public static long test35(MyValue2 vt, int i1, int i2, int i3, int i4) {
 815         int result = 0;
 816         // Trigger OSR compilation
 817         for (int i = 0; i < 10_000; ++i) {
 818             result += i1;
 819         }
 820         return vt.hash() + i1 + i2 + i3 + i4 + result;
 821     }
 822 
 823     @Run(test = "test35")
 824     public void test35_verifier() {
 825         MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
 826         long result = test35(vt, rI, rI, rI, rI);
 827         Asserts.assertEQ(result, vt.hash()+10004*rI);
 828     }
 829 
 830     // Same as test31 but with GC in callee to verify that the
 831     // pre-allocated buffer for the returned value object remains valid.
 832     @NullRestricted
 833     MyValue3 test36_vt;
 834 
 835     @Test
 836     public MyValue3 test36() {
 837         MyValue3 result = MyValue3.create();
 838         test36_vt = result;
 839         System.gc();
 840         return result;
 841     }
 842 
 843     @Run(test = "test36")
 844     public void test36_verifier() throws Exception {
 845         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test36").invoke(this);
 846         test36_vt.verify(vt);
 847     }
 848 
 849     // Test method resolution with scalarized value object receiver at invokespecial
 850     static final MethodHandle test37_mh;
 851 
 852     @ImplicitlyConstructible
 853     @LooselyConsistentValue
 854     value class Test37Value {
 855         int x = rI;
 856 
 857         @DontInline
 858         public int test() {
 859             return x;
 860         }
 861     }
 862 
 863     @Test
 864     public int test37(Test37Value vt) throws Throwable {
 865         // Generates invokespecial call of Test37Value::test
 866         return (int)test37_mh.invokeExact(vt);
 867     }
 868 
 869     @Run(test = "test37")
 870     public void test37_verifier() throws Throwable {
 871         Test37Value vt = new Test37Value();
 872         int res = test37(vt);
 873         Asserts.assertEQ(res, rI);
 874     }
 875 
 876     // Test passing/returning an empty value object
 877     @Test
 878     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
 879     public MyValueEmpty test38(MyValueEmpty vt) {
 880         return vt.copy(vt);
 881     }
 882 
 883     @Run(test = "test38")
 884     public void test38_verifier() {
 885         MyValueEmpty vt = new MyValueEmpty();
 886         MyValueEmpty res = test38(vt);
 887         Asserts.assertEQ(res, vt);
 888     }
 889 
 890     @ImplicitlyConstructible
 891     @LooselyConsistentValue
 892     static value class LargeValueWithOops {
 893         // Use all 6 int registers + 50/2 on stack = 29
 894         Object o1 = null;
 895         Object o2 = null;
 896         Object o3 = null;
 897         Object o4 = null;
 898         Object o5 = null;
 899         Object o6 = null;
 900         Object o7 = null;
 901         Object o8 = null;
 902         Object o9 = null;
 903         Object o10 = null;
 904         Object o11 = null;
 905         Object o12 = null;
 906         Object o13 = null;
 907         Object o14 = null;
 908         Object o15 = null;
 909         Object o16 = null;
 910         Object o17 = null;
 911         Object o18 = null;
 912         Object o19 = null;
 913         Object o20 = null;
 914         Object o21 = null;
 915         Object o22 = null;
 916         Object o23 = null;
 917         Object o24 = null;
 918         Object o25 = null;
 919         Object o26 = null;
 920         Object o27 = null;
 921         Object o28 = null;
 922         Object o29 = null;
 923     }
 924 
 925     @ImplicitlyConstructible
 926     @LooselyConsistentValue
 927     static value class LargeValueWithoutOops {
 928         // Use all 6 int registers + 50/2 on stack = 29
 929         int i1 = 0;
 930         int i2 = 0;
 931         int i3 = 0;
 932         int i4 = 0;
 933         int i5 = 0;
 934         int i6 = 0;
 935         int i7 = 0;
 936         int i8 = 0;
 937         int i9 = 0;
 938         int i10 = 0;
 939         int i11 = 0;
 940         int i12 = 0;
 941         int i13 = 0;
 942         int i14 = 0;
 943         int i15 = 0;
 944         int i16 = 0;
 945         int i17 = 0;
 946         int i18 = 0;
 947         int i19 = 0;
 948         int i20 = 0;
 949         int i21 = 0;
 950         int i22 = 0;
 951         int i23 = 0;
 952         int i24 = 0;
 953         int i25 = 0;
 954         int i26 = 0;
 955         int i27 = 0;
 956         int i28 = 0;
 957         int i29 = 0;
 958         // Use all 7 float registers
 959         double d1 = 0;
 960         double d2 = 0;
 961         double d3 = 0;
 962         double d4 = 0;
 963         double d5 = 0;
 964         double d6 = 0;
 965         double d7 = 0;
 966         double d8 = 0;
 967     }
 968 
 969     // Test passing/returning a large value object with oop fields
 970     @Test
 971     public static LargeValueWithOops test39(LargeValueWithOops vt) {
 972         return vt;
 973     }
 974 
 975     @Run(test = "test39")
 976     public void test39_verifier() {
 977         LargeValueWithOops vt = new LargeValueWithOops();
 978         LargeValueWithOops res = test39(vt);
 979         Asserts.assertEQ(res, vt);
 980     }
 981 
 982     // Test passing/returning a large value object with only int/float fields
 983     @Test
 984     public static LargeValueWithoutOops test40(LargeValueWithoutOops vt) {
 985         return vt;
 986     }
 987 
 988     @Run(test = "test40")
 989     public void test40_verifier() {
 990         LargeValueWithoutOops vt = new LargeValueWithoutOops();
 991         LargeValueWithoutOops res = test40(vt);
 992         Asserts.assertEQ(res, vt);
 993     }
 994 
 995     // Test passing/returning an empty value object together with non-empty
 996     // value objects such that only some value class arguments are scalarized.
 997     @Test
 998     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
 999     public MyValueEmpty test41(MyValue1 vt1, MyValueEmpty vt2, MyValue1 vt3) {
1000         return vt2.copy(vt2);
1001     }
1002 
1003     @Run(test = "test41")
1004     public void test41_verifier() {
1005         MyValueEmpty res = test41(MyValue1.createDefaultInline(), new MyValueEmpty(), MyValue1.createDefaultInline());
1006         Asserts.assertEQ(res, new MyValueEmpty());
1007     }
1008 
1009     // More empty value class tests with containers
1010 
1011     @ImplicitlyConstructible
1012     @LooselyConsistentValue
1013     static value class EmptyContainer {
1014         @NullRestricted
1015         private MyValueEmpty empty;
1016 
1017         @ForceInline
1018         EmptyContainer(MyValueEmpty empty) {
1019             this.empty = empty;
1020         }
1021 
1022         @ForceInline
1023         MyValueEmpty getInline() { return empty; }
1024 
1025         @DontInline
1026         MyValueEmpty getNoInline() { return empty; }
1027     }
1028 
1029     @ImplicitlyConstructible
1030     @LooselyConsistentValue
1031     static value class MixedContainer {
1032         public int val;
1033         @NullRestricted
1034         private EmptyContainer empty;
1035 
1036         @ForceInline
1037         MixedContainer(int val, EmptyContainer empty) {
1038             this.val = val;
1039             this.empty = empty;
1040         }
1041 
1042         @ForceInline
1043         EmptyContainer getInline() { return empty; }
1044 
1045         @DontInline
1046         EmptyContainer getNoInline() { return empty; }
1047     }
1048 
1049     // Empty value object return
1050     @Test
1051     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1052     public MyValueEmpty test42() {
1053         EmptyContainer c = new EmptyContainer(new MyValueEmpty());
1054         return c.getInline();
1055     }
1056 
1057     @Run(test = "test42")
1058     public void test42_verifier() {
1059         MyValueEmpty empty = test42();
1060         Asserts.assertEquals(empty, new MyValueEmpty());
1061     }
1062 
1063     // Empty value class container return
1064     @Test
1065     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1066     public EmptyContainer test43(EmptyContainer c) {
1067         return c;
1068     }
1069 
1070     @Run(test = "test43")
1071     public void test43_verifier() {
1072         EmptyContainer empty = new EmptyContainer(new MyValueEmpty());
1073         EmptyContainer c = test43(empty);
1074         Asserts.assertEquals(c, empty);
1075     }
1076 
1077     // Empty value class container (mixed) return
1078     @Test
1079     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1080     public MixedContainer test44() {
1081         MixedContainer c = new MixedContainer(rI, new EmptyContainer(new MyValueEmpty()));
1082         c = new MixedContainer(rI, c.getInline());
1083         return c;
1084     }
1085 
1086     @Run(test = "test44")
1087     public void test44_verifier() {
1088         MixedContainer c = test44();
1089         Asserts.assertEquals(c, new MixedContainer(rI, new EmptyContainer(new MyValueEmpty())));
1090     }
1091 
1092     // Empty value class container argument
1093     @Test
1094     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1095     public EmptyContainer test45(EmptyContainer c) {
1096         return new EmptyContainer(c.getInline());
1097     }
1098 
1099     @Run(test = "test45")
1100     public void test45_verifier() {
1101         EmptyContainer empty = new EmptyContainer(new MyValueEmpty());
1102         EmptyContainer c = test45(empty);
1103         Asserts.assertEquals(c, empty);
1104     }
1105 
1106     // Empty value class container and mixed container arguments
1107     @Test
1108 // TODO 8325106
1109 //    @IR(failOn = {ALLOC, STORE, TRAP})
1110     public MyValueEmpty test46(EmptyContainer c1, MixedContainer c2, MyValueEmpty empty) {
1111         c2 = new MixedContainer(c2.val, c1);
1112         return c2.getNoInline().getNoInline();
1113     }
1114 
1115     @Run(test = "test46")
1116     public void test46_verifier() {
1117         MyValueEmpty empty = test46(new EmptyContainer(new MyValueEmpty()), new MixedContainer(0, new EmptyContainer(new MyValueEmpty())), new MyValueEmpty());
1118         Asserts.assertEquals(empty, new MyValueEmpty());
1119     }
1120 
1121     // No receiver and only empty argument
1122     @Test
1123     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1124     public static MyValueEmpty test47(MyValueEmpty empty) {
1125         return empty;
1126     }
1127 
1128     @Run(test = "test47")
1129     public void test47_verifier() {
1130         MyValueEmpty empty = test47(new MyValueEmpty());
1131         Asserts.assertEquals(empty,new MyValueEmpty());
1132     }
1133 
1134     // No receiver and only empty container argument
1135     @Test
1136     @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
1137     public static MyValueEmpty test48(EmptyContainer empty) {
1138         return empty.getNoInline();
1139     }
1140 
1141     @Run(test = "test48")
1142     public void test48_verifier() {
1143         MyValueEmpty empty = test48(new EmptyContainer(new MyValueEmpty()));
1144         Asserts.assertEquals(empty, new MyValueEmpty());
1145     }
1146 
1147     // Test conditional value class return with incremental inlining
1148     public MyValue3 test49_inlined1(boolean b) {
1149         if (b) {
1150             return MyValue3.create();
1151         } else {
1152             return MyValue3.create();
1153         }
1154     }
1155 
1156     public MyValue3 test49_inlined2(boolean b) {
1157         return test49_inlined1(b);
1158     }
1159 
1160     @Test
1161     public void test49(boolean b) {
1162         test49_inlined2(b);
1163     }
1164 
1165     @Run(test = "test49")
1166     public void test49_verifier() {
1167         test49(true);
1168         test49(false);
1169     }
1170 
1171     // Variant of test49 with result verification (triggered different failure mode)
1172     @NullRestricted
1173     final MyValue3 test50_vt = MyValue3.create();
1174     @NullRestricted
1175     final MyValue3 test50_vt2 = test50_vt;
1176 
1177     public MyValue3 test50_inlined1(boolean b) {
1178         if (b) {
1179             return test50_vt;
1180         } else {
1181             return test50_vt2;
1182         }
1183     }
1184 
1185     public MyValue3 test50_inlined2(boolean b) {
1186         return test50_inlined1(b);
1187     }
1188 
1189     @Test
1190     public void test50(boolean b) {
1191         MyValue3 vt = test50_inlined2(b);
1192         test50_vt.verify(vt);
1193     }
1194 
1195     @Run(test = "test50")
1196     public void test50_verifier() {
1197         test50(true);
1198         test50(false);
1199     }
1200 
1201     // Test stack repair with stack slots reserved for monitors
1202     private static final Object lock1 = new Object();
1203     private static final Object lock2 = new Object();
1204     private static final Object lock3 = new Object();
1205 
1206     @DontInline
1207     static void test51_callee() { }
1208 
1209     @Test
1210     public void test51(MyValue1 val) {
1211         synchronized (lock1) {
1212             test51_callee();
1213         }
1214     }
1215 
1216     @Run(test = "test51")
1217     public void test51_verifier() {
1218         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1219         test51(vt);
1220     }
1221 
1222     @DontInline
1223     static void test52_callee() { }
1224 
1225     @Test
1226     public void test52(MyValue1 val) {
1227         synchronized (lock1) {
1228             synchronized (lock2) {
1229                 test52_callee();
1230             }
1231         }
1232     }
1233 
1234     @Run(test = "test52")
1235     public void test52_verifier() {
1236         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1237         test52(vt);
1238     }
1239 
1240     @DontInline
1241     static void test53_callee() { }
1242 
1243     @Test
1244     public void test53(MyValue1 val) {
1245         synchronized (lock1) {
1246             synchronized (lock2) {
1247                 synchronized (lock3) {
1248                     test53_callee();
1249                 }
1250             }
1251         }
1252     }
1253 
1254     @Run(test = "test53")
1255     public void test53_verifier() {
1256         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1257         test53(vt);
1258     }
1259 
1260     static MethodHandle test54_mh;
1261 
1262     @DontInline
1263     public MyValue2 test54_callee() {
1264         return MyValue2.createWithFieldsInline(rI, rD);
1265     }
1266 
1267     // Test that method handle invocation does not block scalarization of return value
1268     @Test
1269     @IR(failOn = {ALLOC_G, STORE})
1270     public long test54(Method m, boolean b1, boolean b2) throws Throwable {
1271         MyInterface obj = MyValue2.createWithFieldsInline(rI, rD);
1272         if (b1) {
1273             obj = (MyValue2)test54_mh.invokeExact(this);
1274         }
1275         if (b2) {
1276             // Uncommon trap
1277             TestFramework.deoptimize(m);
1278             return obj.hash();
1279         }
1280         return -1;
1281     }
1282 
1283     @Run(test = "test54")
1284     @Warmup(10000)
1285     public void test54_verifier(RunInfo info) throws Throwable {
1286         Asserts.assertEQ(test54(info.getTest(), true, false), -1L);
1287         Asserts.assertEQ(test54(info.getTest(), false, false), -1L);
1288         if (!info.isWarmUp()) {
1289             MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
1290             Asserts.assertEQ(test54(info.getTest(), true, true), v.hash());
1291         }
1292     }
1293 
1294     @DontInline
1295     public MyValue2 test55_callee() {
1296         return MyValue2.createWithFieldsInline(rI, rD);
1297     }
1298 
1299     // Test scalarization of nullable return value that is unused
1300     @Test
1301     public void test55() {
1302         test55_callee();
1303     }
1304 
1305     @Run(test = "test55")
1306     public void test55_verifier() {
1307         test55();
1308     }
1309 
1310     static MethodHandle test56_mh;
1311 
1312     @DontInline
1313     public MyValue2 test56_callee(boolean b) {
1314         return b ? MyValue2.createWithFieldsInline(rI, rD) : null;
1315     }
1316 
1317     // Test that scalarization of nullable return works properly for method handle calls
1318     @Test
1319     public MyValue2 test56(boolean b) throws Throwable {
1320         return (MyValue2)test56_mh.invokeExact(this, b);
1321     }
1322 
1323     @Run(test = "test56")
1324     @Warmup(10000)
1325     public void test56_verifier(RunInfo info) throws Throwable {
1326         MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
1327         Asserts.assertEQ(test56(true).hash(), vt.hash());
1328         if (!info.isWarmUp()) {
1329             Asserts.assertEQ(test56(false), null);
1330         }
1331     }
1332 }