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