1 /*
   2  * Copyright (c) 2017, 2019, 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.valuetypes;
  25 
  26 import jdk.test.lib.Asserts;
  27 
  28 import java.lang.invoke.*;
  29 import java.lang.reflect.Method;
  30 
  31 /*
  32  * @test
  33  * @summary Test value type calling convention optimizations
  34  * @library /testlibrary /test/lib /compiler/whitebox /
  35  * @requires os.simpleArch == "x64"
  36  * @compile TestCallingConvention.java
  37  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  38  * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  39  *                               -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
  40  *                               compiler.valhalla.valuetypes.ValueTypeTest
  41  *                               compiler.valhalla.valuetypes.TestCallingConvention
  42  */
  43 public class TestCallingConvention extends ValueTypeTest {
  44     // Extra VM parameters for some test scenarios. See ValueTypeTest.getVMParameters()
  45     @Override
  46     public String[] getExtraVMParameters(int scenario) {
  47         switch (scenario) {
  48         case 0: return new String[] {"-Dsun.reflect.inflationThreshold=10000"}; // Don't generate bytecodes but call through runtime for reflective calls
  49         case 1: return new String[] {"-Dsun.reflect.inflationThreshold=10000"};
  50         case 3: return new String[] {"-XX:ValueArrayElemMaxFlatSize=0"};
  51         }
  52         return null;
  53     }
  54 
  55     static {
  56         try {
  57             Class<?> clazz = TestCallingConvention.class;
  58             ClassLoader loader = clazz.getClassLoader();
  59             MethodHandles.Lookup lookup = MethodHandles.lookup();
  60 
  61             MethodType mt32 = MethodType.methodType(MyValue2.class, boolean.class);
  62             test32_mh = lookup.findVirtual(clazz, "test32_interp", mt32);
  63 
  64             MethodType mt33 = MethodType.methodType(Object.class, boolean.class);
  65             test33_mh = lookup.findVirtual(clazz, "test33_interp", mt33);
  66         } catch (NoSuchMethodException | IllegalAccessException e) {
  67             e.printStackTrace();
  68             throw new RuntimeException("Method handle lookup failed");
  69         }
  70     }
  71 
  72     public static void main(String[] args) throws Throwable {
  73         TestCallingConvention test = new TestCallingConvention();
  74         test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue4.class, Test27Value1.class, Test27Value2.class, Test27Value3.class);
  75     }
  76 
  77     // Test interpreter to compiled code with various signatures
  78     @Test(failOn = ALLOC + STORE + TRAP)
  79     public long test1(MyValue2 v) {
  80         return v.hash();
  81     }
  82 
  83     @DontCompile
  84     public void test1_verifier(boolean warmup) {
  85         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
  86         long result = test1(v);
  87         Asserts.assertEQ(result, v.hashInterpreted());
  88     }
  89 
  90     @Test(failOn = ALLOC + STORE + TRAP)
  91     public long test2(int i1, MyValue2 v, int i2) {
  92         return v.hash() + i1 - i2;
  93     }
  94 
  95     @DontCompile
  96     public void test2_verifier(boolean warmup) {
  97         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
  98         long result = test2(rI, v, 2*rI);
  99         Asserts.assertEQ(result, v.hashInterpreted() - rI);
 100     }
 101 
 102     @Test(failOn = ALLOC + STORE + TRAP)
 103     public long test3(long l1, MyValue2 v, long l2) {
 104         return v.hash() + l1 - l2;
 105     }
 106 
 107     @DontCompile
 108     public void test3_verifier(boolean warmup) {
 109         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 110         long result = test3(rL, v, 2*rL);
 111         Asserts.assertEQ(result, v.hashInterpreted() - rL);
 112     }
 113 
 114     @Test(failOn = ALLOC + STORE + TRAP)
 115     public long test4(int i, MyValue2 v, long l) {
 116         return v.hash() + i + l;
 117     }
 118 
 119     @DontCompile
 120     public void test4_verifier(boolean warmup) {
 121         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 122         long result = test4(rI, v, rL);
 123         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 124     }
 125 
 126     @Test(failOn = ALLOC + STORE + TRAP)
 127     public long test5(long l, MyValue2 v, int i) {
 128         return v.hash() + i + l;
 129     }
 130 
 131     @DontCompile
 132     public void test5_verifier(boolean warmup) {
 133         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 134         long result = test5(rL, v, rI);
 135         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 136     }
 137 
 138     @Test(failOn = ALLOC + STORE + TRAP)
 139     public long test6(long l, MyValue1 v1, int i, MyValue2 v2) {
 140         return v1.hash() + i + l + v2.hash();
 141     }
 142 
 143     @DontCompile
 144     public void test6_verifier(boolean warmup) {
 145         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 146         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
 147         long result = test6(rL, v1, rI, v2);
 148         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
 149     }
 150 
 151     // Test compiled code to interpreter with various signatures
 152     @DontCompile
 153     public long test7_interp(MyValue2 v) {
 154         return v.hash();
 155     }
 156 
 157     @Test(failOn = ALLOC + STORE + TRAP)
 158     public long test7(MyValue2 v) {
 159         return test7_interp(v);
 160     }
 161 
 162     @DontCompile
 163     public void test7_verifier(boolean warmup) {
 164         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 165         long result = test7(v);
 166         Asserts.assertEQ(result, v.hashInterpreted());
 167     }
 168 
 169     @DontCompile
 170     public long test8_interp(int i1, MyValue2 v, int i2) {
 171         return v.hash() + i1 - i2;
 172     }
 173 
 174     @Test(failOn = ALLOC + STORE + TRAP)
 175     public long test8(int i1, MyValue2 v, int i2) {
 176         return test8_interp(i1, v, i2);
 177     }
 178 
 179     @DontCompile
 180     public void test8_verifier(boolean warmup) {
 181         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 182         long result = test8(rI, v, 2*rI);
 183         Asserts.assertEQ(result, v.hashInterpreted() - rI);
 184     }
 185 
 186     @DontCompile
 187     public long test9_interp(long l1, MyValue2 v, long l2) {
 188         return v.hash() + l1 - l2;
 189     }
 190 
 191     @Test(failOn = ALLOC + STORE + TRAP)
 192     public long test9(long l1, MyValue2 v, long l2) {
 193         return test9_interp(l1, v, l2);
 194     }
 195 
 196     @DontCompile
 197     public void test9_verifier(boolean warmup) {
 198         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 199         long result = test9(rL, v, 2*rL);
 200         Asserts.assertEQ(result, v.hashInterpreted() - rL);
 201     }
 202 
 203     @DontCompile
 204     public long test10_interp(int i, MyValue2 v, long l) {
 205         return v.hash() + i + l;
 206     }
 207 
 208     @Test(failOn = ALLOC + STORE + TRAP)
 209     public long test10(int i, MyValue2 v, long l) {
 210         return test10_interp(i, v, l);
 211     }
 212 
 213     @DontCompile
 214     public void test10_verifier(boolean warmup) {
 215         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 216         long result = test10(rI, v, rL);
 217         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 218     }
 219 
 220     @DontCompile
 221     public long test11_interp(long l, MyValue2 v, int i) {
 222         return v.hash() + i + l;
 223     }
 224 
 225     @Test(failOn = ALLOC + STORE + TRAP)
 226     public long test11(long l, MyValue2 v, int i) {
 227         return test11_interp(l, v, i);
 228     }
 229 
 230     @DontCompile
 231     public void test11_verifier(boolean warmup) {
 232         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 233         long result = test11(rL, v, rI);
 234         Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
 235     }
 236 
 237     @DontCompile
 238     public long test12_interp(long l, MyValue1 v1, int i, MyValue2 v2) {
 239         return v1.hash() + i + l + v2.hash();
 240     }
 241 
 242     @Test(failOn = ALLOC + STORE + TRAP)
 243     public long test12(long l, MyValue1 v1, int i, MyValue2 v2) {
 244         return test12_interp(l, v1, i, v2);
 245     }
 246 
 247     @DontCompile
 248     public void test12_verifier(boolean warmup) {
 249         MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
 250         MyValue2 v2 = MyValue2.createWithFieldsInline(rI, true);
 251         long result = test12(rL, v1, rI, v2);
 252         Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
 253     }
 254 
 255     // Test that debug info at a call is correct
 256     @DontCompile
 257     public long test13_interp(MyValue2 v, MyValue1[] va, boolean deopt) {
 258         if (deopt) {
 259             // uncommon trap
 260             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test13"));
 261         }
 262         return v.hash() + va[0].hash() + va[1].hash();
 263     }
 264 
 265     @Test(failOn = ALLOC + STORE + TRAP)
 266     public long test13(MyValue2 v, MyValue1[] va, boolean flag, long l) {
 267         return test13_interp(v, va, flag) + l;
 268     }
 269 
 270     @DontCompile
 271     public void test13_verifier(boolean warmup) {
 272         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 273         MyValue1[] va = new MyValue1[2];
 274         va[0] = MyValue1.createWithFieldsDontInline(rI, rL);
 275         va[1] = MyValue1.createWithFieldsDontInline(rI, rL);
 276         long result = test13(v, va, !warmup, rL);
 277         Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
 278     }
 279 
 280     // Test deoptimization at call return with return value in registers
 281     @DontCompile
 282     public MyValue2 test14_interp(boolean deopt) {
 283         if (deopt) {
 284             // uncommon trap
 285             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test14"));
 286         }
 287         return MyValue2.createWithFieldsInline(rI, true);
 288     }
 289 
 290     @Test()
 291     public MyValue2 test14(boolean flag) {
 292         return test14_interp(flag);
 293     }
 294 
 295     @DontCompile
 296     public void test14_verifier(boolean warmup) {
 297         MyValue2 result = test14(!warmup);
 298         MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
 299         Asserts.assertEQ(result.hash(), v.hash());
 300     }
 301 
 302     // Return value types in registers from interpreter -> compiled
 303     final MyValue3 test15_vt = MyValue3.create();
 304     @DontCompile
 305     public MyValue3 test15_interp() {
 306         return test15_vt;
 307     }
 308 
 309     MyValue3 test15_vt2;
 310     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
 311     @Test(valid = ValueTypeReturnedAsFieldsOff)
 312     public void test15() {
 313         test15_vt2 = test15_interp();
 314     }
 315 
 316     @DontCompile
 317     public void test15_verifier(boolean warmup) {
 318         test15();
 319         test15_vt.verify(test15_vt2);
 320     }
 321 
 322     // Return value types in registers from compiled -> interpreter
 323     final MyValue3 test16_vt = MyValue3.create();
 324     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + TRAP)
 325     @Test(valid = ValueTypeReturnedAsFieldsOff)
 326     public MyValue3 test16() {
 327         return test16_vt;
 328     }
 329 
 330     @DontCompile
 331     public void test16_verifier(boolean warmup) {
 332         MyValue3 vt = test16();
 333         test16_vt.verify(vt);
 334     }
 335 
 336     // Return value types in registers from compiled -> compiled
 337     final MyValue3 test17_vt = MyValue3.create();
 338     @DontInline
 339     public MyValue3 test17_comp() {
 340         return test17_vt;
 341     }
 342 
 343     MyValue3 test17_vt2;
 344     @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
 345     @Test(valid = ValueTypeReturnedAsFieldsOff)
 346     public void test17() {
 347         test17_vt2 = test17_comp();
 348     }
 349 
 350     @DontCompile
 351     public void test17_verifier(boolean warmup) throws Exception {
 352         Method helper_m = getClass().getDeclaredMethod("test17_comp");
 353         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
 354             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
 355             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test17_comp not compiled");
 356         }
 357         test17();
 358         test17_vt.verify(test17_vt2);
 359     }
 360 
 361     // Same tests as above but with a value type that cannot be returned in registers
 362 
 363     // Return value types in registers from interpreter -> compiled
 364     final MyValue4 test18_vt = MyValue4.create();
 365     @DontCompile
 366     public MyValue4 test18_interp() {
 367         return test18_vt;
 368     }
 369 
 370     MyValue4 test18_vt2;
 371     @Test
 372     public void test18() {
 373         test18_vt2 = test18_interp();
 374     }
 375 
 376     @DontCompile
 377     public void test18_verifier(boolean warmup) {
 378         test18();
 379         test18_vt.verify(test18_vt2);
 380     }
 381 
 382     // Return value types in registers from compiled -> interpreter
 383     final MyValue4 test19_vt = MyValue4.create();
 384     @Test
 385     public MyValue4 test19() {
 386         return test19_vt;
 387     }
 388 
 389     @DontCompile
 390     public void test19_verifier(boolean warmup) {
 391         MyValue4 vt = test19();
 392         test19_vt.verify(vt);
 393     }
 394 
 395     // Return value types in registers from compiled -> compiled
 396     final MyValue4 test20_vt = MyValue4.create();
 397     @DontInline
 398     public MyValue4 test20_comp() {
 399         return test20_vt;
 400     }
 401 
 402     MyValue4 test20_vt2;
 403     @Test
 404     public void test20() {
 405         test20_vt2 = test20_comp();
 406     }
 407 
 408     @DontCompile
 409     public void test20_verifier(boolean warmup) throws Exception {
 410         Method helper_m = getClass().getDeclaredMethod("test20_comp");
 411         if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
 412             WHITE_BOX.enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
 413             Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test20_comp not compiled");
 414         }
 415         test20();
 416         test20_vt.verify(test20_vt2);
 417     }
 418 
 419     // Test no result from inlined method for incremental inlining
 420     final MyValue3 test21_vt = MyValue3.create();
 421     public MyValue3 test21_inlined() {
 422         throw new RuntimeException();
 423     }
 424 
 425     @Test
 426     public MyValue3 test21() {
 427         try {
 428             return test21_inlined();
 429         } catch (RuntimeException ex) {
 430             return test21_vt;
 431         }
 432     }
 433 
 434     @DontCompile
 435     public void test21_verifier(boolean warmup) {
 436         MyValue3 vt = test21();
 437         test21_vt.verify(vt);
 438     }
 439 
 440     // Test returning a non-flattened value type as fields
 441     MyValue3? test22_vt = MyValue3.create();
 442 
 443     @Test
 444     public MyValue3 test22() {
 445         return (MyValue3) test22_vt;
 446     }
 447 
 448     @DontCompile
 449     public void test22_verifier(boolean warmup) {
 450         MyValue3 vt = test22();
 451         test22_vt.verify(vt);
 452     }
 453 
 454     // Test calling a method that has circular register/stack dependencies when unpacking value type arguments
 455     inline class TestValue23 {
 456         final double f1;
 457         TestValue23(double val) {
 458             f1 = val;
 459         }
 460     }
 461 
 462     static double test23Callee(int i1, int i2, int i3, int i4, int i5, int i6,
 463                                TestValue23 v1, TestValue23 v2, TestValue23 v3, TestValue23 v4, TestValue23 v5, TestValue23 v6, TestValue23 v7, TestValue23 v8,
 464                                double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8) {
 465         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;
 466     }
 467 
 468     @Test
 469     public double test23(int i1, int i2, int i3, int i4, int i5, int i6,
 470                          TestValue23 v1, TestValue23 v2, TestValue23 v3, TestValue23 v4, TestValue23 v5, TestValue23 v6, TestValue23 v7, TestValue23 v8,
 471                          double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8) {
 472         return test23Callee(i1, i2, i3, i4, i5, i6,
 473                             v1, v2, v3, v4, v5, v6, v7, v8,
 474                             d1, d2, d3, d4, d5, d6, d7, d8);
 475     }
 476 
 477     @DontCompile
 478     public void test23_verifier(boolean warmup) {
 479         TestValue23 vt = new TestValue23(rI);
 480         double res1 = test23(rI, rI, rI, rI, rI, rI,
 481                             vt, vt, vt, vt, vt, vt, vt, vt,
 482                             rI, rI, rI, rI, rI, rI, rI, rI);
 483         double res2 = test23Callee(rI, rI, rI, rI, rI, rI,
 484                                    vt, vt, vt, vt, vt, vt, vt, vt,
 485                                    rI, rI, rI, rI, rI, rI, rI, rI);
 486         double res3 = 6*rI + 8*rI + 8*rI;
 487         Asserts.assertEQ(res1, res2);
 488         Asserts.assertEQ(res2, res3);
 489     }
 490 
 491     // Should not return a nullable value type as fields
 492     @Test
 493     public MyValue2? test24() {
 494         return null;
 495     }
 496 
 497     @DontCompile
 498     public void test24_verifier(boolean warmup) {
 499         MyValue2? vt = test24();
 500         Asserts.assertEQ(vt, null);
 501     }
 502 
 503     // Same as test24 but with control flow and inlining
 504     @ForceInline
 505     public MyValue2? test26_callee(boolean b) {
 506         if (b) {
 507             return null;
 508         } else {
 509             return MyValue2.createWithFieldsInline(rI, true);
 510         }
 511     }
 512 
 513     @Test
 514     public MyValue2? test26(boolean b) {
 515         return test26_callee(b);
 516     }
 517 
 518     @DontCompile
 519     public void test26_verifier(boolean warmup) {
 520         MyValue2? vt = test26(true);
 521         Asserts.assertEQ(vt, null);
 522         vt = test26(false);
 523         Asserts.assertEQ(vt.hash(), MyValue2.createWithFieldsInline(rI, true).hash());
 524     }
 525 
 526     // Test calling convention with deep hierarchy of flattened fields
 527     final inline class Test27Value1 {
 528         final Test27Value2 valueField;
 529 
 530         private Test27Value1(Test27Value2 val2) {
 531             valueField = val2;
 532         }
 533 
 534         @DontInline
 535         public int test(Test27Value1 val1) {
 536             return valueField.test(valueField) + val1.valueField.test(valueField);
 537         }
 538     }
 539 
 540     final inline class Test27Value2 {
 541         final Test27Value3 valueField;
 542 
 543         private Test27Value2(Test27Value3 val3) {
 544             valueField = val3;
 545         }
 546 
 547         @DontInline
 548         public int test(Test27Value2 val2) {
 549             return valueField.test(valueField) + val2.valueField.test(valueField);
 550         }
 551     }
 552 
 553     final inline class Test27Value3 {
 554         final int x;
 555 
 556         private Test27Value3(int x) {
 557             this.x = x;
 558         }
 559 
 560         @DontInline
 561         public int test(Test27Value3 val3) {
 562             return x + val3.x;
 563         }
 564     }
 565 
 566     @Test
 567     public int test27(Test27Value1 val) {
 568         return val.test(val);
 569     }
 570 
 571     @DontCompile
 572     public void test27_verifier(boolean warmup) {
 573         Test27Value3 val3 = new Test27Value3(rI);
 574         Test27Value2 val2 = new Test27Value2(val3);
 575         Test27Value1 val1 = new Test27Value1(val2);
 576         int result = test27(val1);
 577         Asserts.assertEQ(result, 8*rI);
 578     }
 579 
 580     static final MyValue1? test28Val = MyValue1.createWithFieldsDontInline(rI, rL);
 581 
 582     @Test
 583     @Warmup(0)
 584     public String test28() {
 585         return test28Val.toString();
 586     }
 587 
 588     @DontCompile
 589     public void test28_verifier(boolean warmup) {
 590         String result = test28();
 591     }
 592 
 593     // Test calling a method returning a value type as fields via reflection
 594     MyValue3 test29_vt = MyValue3.create();
 595 
 596     @Test
 597     public MyValue3 test29() {
 598         return test29_vt;
 599     }
 600 
 601     @DontCompile
 602     public void test29_verifier(boolean warmup) throws Exception {
 603         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test29").invoke(this);
 604         test29_vt.verify(vt);
 605     }
 606 
 607     @Test
 608     public MyValue3 test30(MyValue3[] array) {
 609         MyValue3 result = MyValue3.create();
 610         array[0] = result;
 611         return result;
 612     }
 613 
 614     @DontCompile
 615     public void test30_verifier(boolean warmup) throws Exception {
 616         MyValue3[] array = new MyValue3[1];
 617         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test30", MyValue3[].class).invoke(this, (Object)array);
 618         array[0].verify(vt);
 619     }
 620 
 621     MyValue3 test31_vt;
 622 
 623     @Test
 624     public MyValue3 test31() {
 625         MyValue3 result = MyValue3.create();
 626         test31_vt = result;
 627         return result;
 628     }
 629 
 630     @DontCompile
 631     public void test31_verifier(boolean warmup) throws Exception {
 632         MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test31").invoke(this);
 633         test31_vt.verify(vt);
 634     }
 635 
 636     // Test deoptimization at call return with return value in registers. Same as test14, except the interpreted method
 637     // is called via a MethodHandle.
 638     static MethodHandle test32_mh;
 639 
 640     @DontCompile
 641     public MyValue2 test32_interp(boolean deopt) {
 642         if (deopt) {
 643             // uncommon trap
 644             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test32"));
 645         }
 646         return MyValue2.createWithFieldsInline(rI+32, true);
 647     }
 648 
 649     @Test()
 650     public MyValue2 test32(boolean flag) throws Throwable {
 651         return (MyValue2)test32_mh.invokeExact(this, flag);
 652     }
 653 
 654     @DontCompile
 655     public void test32_verifier(boolean warmup) throws Throwable {
 656         MyValue2 result = test32(!warmup);
 657         MyValue2 v = MyValue2.createWithFieldsInline(rI+32, true);
 658         Asserts.assertEQ(result.hash(), v.hash());
 659     }
 660 
 661     // Same as test32, except the return type is not flattenable.
 662     static MethodHandle test33_mh;
 663 
 664     @DontCompile
 665     public Object test33_interp(boolean deopt) {
 666         if (deopt) {
 667             // uncommon trap
 668             WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test33"));
 669         }
 670         return MyValue2.createWithFieldsInline(rI+33, true);
 671     }
 672 
 673     @Test()
 674     public MyValue2 test33(boolean flag) throws Throwable {
 675         Object o = test33_mh.invokeExact(this, flag);
 676         return (MyValue2)o;
 677     }
 678 
 679     @DontCompile
 680     public void test33_verifier(boolean warmup) throws Throwable {
 681         MyValue2 result = test33(!warmup);
 682         MyValue2 v = MyValue2.createWithFieldsInline(rI+33, true);
 683         Asserts.assertEQ(result.hash(), v.hash());
 684     }
 685 }