1 /*
   2  * Copyright (c) 2019, 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 test.java.lang.invoke.lib.InstructionHelper;
  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 import java.util.Arrays;
  35 import java.util.Objects;
  36 
  37 import jdk.internal.value.ValueClass;
  38 import jdk.internal.vm.annotation.LooselyConsistentValue;
  39 import jdk.internal.vm.annotation.NullRestricted;
  40 import jdk.internal.vm.annotation.Strict;
  41 
  42 import static compiler.valhalla.inlinetypes.InlineTypeIRNode.*;
  43 import static compiler.valhalla.inlinetypes.InlineTypes.*;
  44 
  45 /*
  46  * @test
  47  * @key randomness
  48  * @summary Test inline types in LWorld.
  49  * @library /test/lib /test/jdk/java/lang/invoke/common /
  50  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  51  * @enablePreview
  52  * @modules java.base/jdk.internal.value
  53  *          java.base/jdk.internal.vm.annotation
  54  * @build test.java.lang.invoke.lib.InstructionHelper
  55  * @run main/othervm/timeout=450 compiler.valhalla.inlinetypes.TestLWorld
  56  */
  57 
  58 @ForceCompileClassInitializer
  59 public class TestLWorld {
  60 
  61     public static void main(String[] args) {
  62         // Make sure Test140Value is loaded but not linked
  63         Class<?> class1 = Test140Value.class;
  64         // Make sure Test141Value is linked but not initialized
  65         Class<?> class2 = Test141Value.class;
  66         class2.getDeclaredFields();
  67 
  68         Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
  69         scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:+UseArrayFlattening");
  70         scenarios[4].addFlags("-XX:-MonomorphicArrayCheck");
  71 
  72         InlineTypes.getFramework()
  73                    .addScenarios(scenarios)
  74                    .addHelperClasses(MyValue1.class,
  75                                      MyValue2.class,
  76                                      MyValue2Inline.class,
  77                                      MyValue3.class,
  78                                      MyValue3Inline.class)
  79                    .start();
  80     }
  81 
  82     static {
  83         // Make sure RuntimeException is loaded to prevent uncommon traps in IR verified tests
  84         RuntimeException tmp = new RuntimeException("42");
  85     }
  86 
  87     // Helper methods
  88 
  89     @Strict
  90     @NullRestricted
  91     private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL);
  92     @Strict
  93     @NullRestricted
  94     private static final MyValue2 testValue2 = MyValue2.createWithFieldsInline(rI, rD);
  95 
  96     protected long hash() {
  97         return testValue1.hash();
  98     }
  99 
 100     // Test passing an inline type as an Object
 101     @DontInline
 102     public Object test1_dontinline1(Object o) {
 103         return o;
 104     }
 105 
 106     @DontInline
 107     public MyValue1 test1_dontinline2(Object o) {
 108         return (MyValue1)o;
 109     }
 110 
 111     @ForceInline
 112     public Object test1_inline1(Object o) {
 113         return o;
 114     }
 115 
 116     @ForceInline
 117     public MyValue1 test1_inline2(Object o) {
 118         return (MyValue1)o;
 119     }
 120 
 121     @Test
 122     @IR(failOn = {ALLOC_G})
 123     public MyValue1 test1() {
 124         MyValue1 vt = testValue1;
 125         vt = (MyValue1)test1_dontinline1(vt);
 126         vt =           test1_dontinline2(vt);
 127         vt = (MyValue1)test1_inline1(vt);
 128         vt =           test1_inline2(vt);
 129         return vt;
 130     }
 131 
 132     @Run(test = "test1")
 133     public void test1_verifier() {
 134         Asserts.assertEQ(test1().hash(), hash());
 135     }
 136 
 137     // Test storing/loading inline types to/from Object and inline type fields
 138     Object objectField1 = null;
 139     Object objectField2 = null;
 140     Object objectField3 = null;
 141     Object objectField4 = null;
 142     Object objectField5 = null;
 143     Object objectField6 = null;
 144 
 145     @Strict
 146     @NullRestricted
 147     MyValue1 valueField1 = testValue1;
 148     @Strict
 149     @NullRestricted
 150     MyValue1 valueField2 = testValue1;
 151     MyValue1 valueField3 = testValue1;
 152     @Strict
 153     @NullRestricted
 154     MyValue1 valueField4 = MyValue1.DEFAULT;
 155     MyValue1 valueField5;
 156 
 157     static MyValue1 staticValueField1 = testValue1;
 158     @Strict
 159     @NullRestricted
 160     static MyValue1 staticValueField2 = testValue1;
 161     @Strict
 162     @NullRestricted
 163     static MyValue1 staticValueField3 = MyValue1.DEFAULT;
 164     static MyValue1 staticValueField4;
 165 
 166     @DontInline
 167     public Object readValueField5() {
 168         return (Object)valueField5;
 169     }
 170 
 171     @DontInline
 172     public Object readStaticValueField4() {
 173         return (Object)staticValueField4;
 174     }
 175 
 176     @Test
 177     public long test2(MyValue1 vt1, Object vt2) {
 178         objectField1 = vt1;
 179         objectField2 = (MyValue1)vt2;
 180         objectField3 = testValue1;
 181         objectField4 = MyValue1.createWithFieldsDontInline(rI, rL);
 182         objectField5 = valueField1;
 183         objectField6 = valueField3;
 184         valueField1 = (MyValue1)objectField1;
 185         valueField2 = (MyValue1)vt2;
 186         valueField3 = (MyValue1)vt2;
 187         staticValueField1 = (MyValue1)objectField1;
 188         staticValueField2 = (MyValue1)vt1;
 189         // Don't inline these methods because reading NULL will trigger a deoptimization
 190         if (readValueField5() != null || readStaticValueField4() != null) {
 191             throw new RuntimeException("Should be null");
 192         }
 193         return ((MyValue1)objectField1).hash() + ((MyValue1)objectField2).hash() +
 194                ((MyValue1)objectField3).hash() + ((MyValue1)objectField4).hash() +
 195                ((MyValue1)objectField5).hash() + ((MyValue1)objectField6).hash() +
 196                 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() +
 197                 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
 198     }
 199 
 200     @Run(test = "test2")
 201     public void test2_verifier() {
 202         MyValue1 vt = testValue1;
 203         MyValue1 def = MyValue1.createDefaultDontInline();
 204         long result = test2(vt, vt);
 205         Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive());
 206     }
 207 
 208     // Test merging inline types and objects
 209     @Test
 210     public Object test3(int state) {
 211         Object res = null;
 212         if (state == 0) {
 213             res = new NonValueClass(rI);
 214         } else if (state == 1) {
 215             res = MyValue1.createWithFieldsInline(rI, rL);
 216         } else if (state == 2) {
 217             res = MyValue1.createWithFieldsDontInline(rI, rL);
 218         } else if (state == 3) {
 219             res = (MyValue1)objectField1;
 220         } else if (state == 4) {
 221             res = valueField1;
 222         } else if (state == 5) {
 223             res = null;
 224         } else if (state == 6) {
 225             res = MyValue2.createWithFieldsInline(rI, rD);
 226         } else if (state == 7) {
 227             res = testValue2;
 228         }
 229         return res;
 230     }
 231 
 232     @Run(test = "test3")
 233     public void test3_verifier() {
 234         objectField1 = valueField1;
 235         Object result = null;
 236         result = test3(0);
 237         Asserts.assertEQ(((NonValueClass)result).x, rI);
 238         result = test3(1);
 239         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 240         result = test3(2);
 241         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 242         result = test3(3);
 243         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 244         result = test3(4);
 245         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 246         result = test3(5);
 247         Asserts.assertEQ(result, null);
 248         result = test3(6);
 249         Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash());
 250         result = test3(7);
 251         Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash());
 252     }
 253 
 254     // Test merging inline types and objects in loops
 255     @Test
 256     public Object test4(int iters) {
 257         Object res = new NonValueClass(rI);
 258         for (int i = 0; i < iters; ++i) {
 259             if (res instanceof NonValueClass) {
 260                 res = MyValue1.createWithFieldsInline(rI, rL);
 261             } else {
 262                 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL);
 263             }
 264         }
 265         return res;
 266     }
 267 
 268     @Run(test = "test4")
 269     public void test4_verifier() {
 270         NonValueClass result1 = (NonValueClass)test4(0);
 271         Asserts.assertEQ(result1.x, rI);
 272         int iters = (Math.abs(rI) % 10) + 1;
 273         MyValue1 result2 = (MyValue1)test4(iters);
 274         MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL);
 275         Asserts.assertEQ(result2.hash(), vt.hash());
 276     }
 277 
 278     // Test inline types in object variables that are live at safepoint
 279     @Test
 280     @IR(failOn = {ALLOC, STORE, LOOP})
 281     public long test5(MyValue1 arg, boolean deopt, Method m) {
 282         Object vt1 = MyValue1.createWithFieldsInline(rI, rL);
 283         Object vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
 284         Object vt3 = arg;
 285         Object vt4 = valueField1;
 286         if (deopt) {
 287             // uncommon trap
 288             TestFramework.deoptimize(m);
 289         }
 290         return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
 291                ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
 292     }
 293 
 294     @Run(test = "test5")
 295     public void test5_verifier(RunInfo info) {
 296         long result = test5(valueField1, !info.isWarmUp(), info.getTest());
 297         Asserts.assertEQ(result, 4*hash());
 298     }
 299 
 300     // Test comparing inline types with objects
 301     @Test
 302     public boolean test6(Object arg) {
 303         Object vt = MyValue1.createWithFieldsInline(rI, rL);
 304         if (vt == arg || vt == (Object)valueField1 || vt == objectField1 || vt == null ||
 305             arg == vt || (Object)valueField1 == vt || objectField1 == vt || null == vt) {
 306             return true;
 307         }
 308         return false;
 309     }
 310 
 311     @Run(test = "test6")
 312     public void test6_verifier() {
 313         boolean result = test6(null);
 314         Asserts.assertFalse(result);
 315     }
 316 
 317     // merge of inline type and non-inline type
 318     @Test
 319     public Object test7(boolean flag) {
 320         Object res = null;
 321         if (flag) {
 322             res = valueField1;
 323         } else {
 324             res = objectField1;
 325         }
 326         return res;
 327     }
 328 
 329     @Run(test = "test7")
 330     public void test7_verifier() {
 331         Asserts.assertEQ(test7(true), valueField1);
 332         Asserts.assertEQ(test7(false), objectField1);
 333     }
 334 
 335     @Test
 336     public Object test8(boolean flag) {
 337         Object res = null;
 338         if (flag) {
 339             res = objectField1;
 340         } else {
 341             res = valueField1;
 342         }
 343         return res;
 344     }
 345 
 346     @Run(test = "test8")
 347     public void test8_verifier() {
 348         Asserts.assertEQ(test8(true), objectField1);
 349         Asserts.assertEQ(test8(false), valueField1);
 350     }
 351 
 352     // merge of inline types in a loop, stored in an object local
 353     @Test
 354     public Object test9() {
 355         Object o = valueField1;
 356         for (int i = 1; i < 100; i *= 2) {
 357             MyValue1 v = (MyValue1)o;
 358             o = MyValue1.setX(v, v.x + 1);
 359         }
 360         return o;
 361     }
 362 
 363     @Run(test = "test9")
 364     public void test9_verifier() {
 365         Asserts.assertEQ(test9(), MyValue1.setX(valueField1, valueField1.x + 7));
 366     }
 367 
 368     // merge of inline types in an object local
 369     @ForceInline
 370     public Object test10_helper() {
 371         return valueField1;
 372     }
 373 
 374     @Test
 375     @IR(failOn = {ALLOC_G})
 376     public void test10(boolean flag) {
 377         Object o = null;
 378         if (flag) {
 379             o = valueField1;
 380         } else {
 381             o = test10_helper();
 382         }
 383         valueField1 = (MyValue1)o;
 384     }
 385 
 386     @Run(test = "test10")
 387     public void test10_verifier() {
 388         test10(true);
 389         test10(false);
 390     }
 391 
 392     // Interface tests
 393 
 394     @DontInline
 395     public MyInterface test11_dontinline1(MyInterface o) {
 396         return o;
 397     }
 398 
 399     @DontInline
 400     public MyValue1 test11_dontinline2(MyInterface o) {
 401         return (MyValue1)o;
 402     }
 403 
 404     @ForceInline
 405     public MyInterface test11_inline1(MyInterface o) {
 406         return o;
 407     }
 408 
 409     @ForceInline
 410     public MyValue1 test11_inline2(MyInterface o) {
 411         return (MyValue1)o;
 412     }
 413 
 414     @Test
 415     public MyValue1 test11() {
 416         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 417         vt = (MyValue1)test11_dontinline1(vt);
 418         vt =           test11_dontinline2(vt);
 419         vt = (MyValue1)test11_inline1(vt);
 420         vt =           test11_inline2(vt);
 421         return vt;
 422     }
 423 
 424     @Run(test = "test11")
 425     public void test11_verifier() {
 426         Asserts.assertEQ(test11().hash(), hash());
 427     }
 428 
 429     // Test storing/loading inline types to/from interface and inline type fields
 430     MyInterface interfaceField1 = null;
 431     MyInterface interfaceField2 = null;
 432     MyInterface interfaceField3 = null;
 433     MyInterface interfaceField4 = null;
 434     MyInterface interfaceField5 = null;
 435     MyInterface interfaceField6 = null;
 436 
 437     @DontInline
 438     public MyInterface readValueField5AsInterface() {
 439         return (MyInterface)valueField5;
 440     }
 441 
 442     @DontInline
 443     public MyInterface readStaticValueField4AsInterface() {
 444         return (MyInterface)staticValueField4;
 445     }
 446 
 447     @Test
 448     public long test12(MyValue1 vt1, MyInterface vt2) {
 449         interfaceField1 = vt1;
 450         interfaceField2 = (MyValue1)vt2;
 451         interfaceField3 = MyValue1.createWithFieldsInline(rI, rL);
 452         interfaceField4 = MyValue1.createWithFieldsDontInline(rI, rL);
 453         interfaceField5 = valueField1;
 454         interfaceField6 = valueField3;
 455         valueField1 = (MyValue1)interfaceField1;
 456         valueField2 = (MyValue1)vt2;
 457         valueField3 = (MyValue1)vt2;
 458         staticValueField1 = (MyValue1)interfaceField1;
 459         staticValueField2 = (MyValue1)vt1;
 460         // Don't inline these methods because reading NULL will trigger a deoptimization
 461         if (readValueField5AsInterface() != null || readStaticValueField4AsInterface() != null) {
 462             throw new RuntimeException("Should be null");
 463         }
 464         return ((MyValue1)interfaceField1).hash() + ((MyValue1)interfaceField2).hash() +
 465                ((MyValue1)interfaceField3).hash() + ((MyValue1)interfaceField4).hash() +
 466                ((MyValue1)interfaceField5).hash() + ((MyValue1)interfaceField6).hash() +
 467                 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() +
 468                 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
 469     }
 470 
 471     @Run(test = "test12")
 472     public void test12_verifier() {
 473         MyValue1 vt = testValue1;
 474         MyValue1 def = MyValue1.createDefaultDontInline();
 475         long result = test12(vt, vt);
 476         Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive());
 477     }
 478 
 479     class MyObject1 implements MyInterface {
 480         public int x;
 481 
 482         public MyObject1(int x) {
 483             this.x = x;
 484         }
 485 
 486         @ForceInline
 487         public long hash() {
 488             return x;
 489         }
 490     }
 491 
 492     // Test merging inline types and interfaces
 493     @Test
 494     public MyInterface test13(int state) {
 495         MyInterface res = null;
 496         if (state == 0) {
 497             res = new MyObject1(rI);
 498         } else if (state == 1) {
 499             res = MyValue1.createWithFieldsInline(rI, rL);
 500         } else if (state == 2) {
 501             res = MyValue1.createWithFieldsDontInline(rI, rL);
 502         } else if (state == 3) {
 503             res = (MyValue1)objectField1;
 504         } else if (state == 4) {
 505             res = valueField1;
 506         } else if (state == 5) {
 507             res = null;
 508         }
 509         return res;
 510     }
 511 
 512     @Run(test = "test13")
 513     public void test13_verifier() {
 514         objectField1 = valueField1;
 515         MyInterface result = null;
 516         result = test13(0);
 517         Asserts.assertEQ(((MyObject1)result).x, rI);
 518         result = test13(1);
 519         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 520         result = test13(2);
 521         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 522         result = test13(3);
 523         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 524         result = test13(4);
 525         Asserts.assertEQ(((MyValue1)result).hash(), hash());
 526         result = test13(5);
 527         Asserts.assertEQ(result, null);
 528     }
 529 
 530     // Test merging inline types and interfaces in loops
 531     @Test
 532     public MyInterface test14(int iters) {
 533         MyInterface res = new MyObject1(rI);
 534         for (int i = 0; i < iters; ++i) {
 535             if (res instanceof MyObject1) {
 536                 res = MyValue1.createWithFieldsInline(rI, rL);
 537             } else {
 538                 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL);
 539             }
 540         }
 541         return res;
 542     }
 543 
 544     @Run(test = "test14")
 545     public void test14_verifier() {
 546         MyObject1 result1 = (MyObject1)test14(0);
 547         Asserts.assertEQ(result1.x, rI);
 548         int iters = (Math.abs(rI) % 10) + 1;
 549         MyValue1 result2 = (MyValue1)test14(iters);
 550         MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL);
 551         Asserts.assertEQ(result2.hash(), vt.hash());
 552     }
 553 
 554     // Test inline types in interface variables that are live at safepoint
 555     @Test
 556     @IR(failOn = {ALLOC, STORE, LOOP})
 557     public long test15(MyValue1 arg, boolean deopt, Method m) {
 558         MyInterface vt1 = MyValue1.createWithFieldsInline(rI, rL);
 559         MyInterface vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
 560         MyInterface vt3 = arg;
 561         MyInterface vt4 = valueField1;
 562         return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
 563                ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
 564     }
 565 
 566     @Run(test = "test15")
 567     public void test15_verifier(RunInfo info) {
 568         long result = test15(valueField1, !info.isWarmUp(), info.getTest());
 569         Asserts.assertEQ(result, 4*hash());
 570     }
 571 
 572     // Test comparing inline types with interfaces
 573     @Test
 574     public boolean test16(Object arg) {
 575         MyInterface vt = MyValue1.createWithFieldsInline(rI, rL);
 576         if (vt == arg || vt == (MyInterface)valueField1 || vt == interfaceField1 || vt == null ||
 577             arg == vt || (MyInterface)valueField1 == vt || interfaceField1 == vt || null == vt) {
 578             return true;
 579         }
 580         return false;
 581     }
 582 
 583     @Run(test = "test16")
 584     public void test16_verifier() {
 585         boolean result = test16(null);
 586         Asserts.assertFalse(result);
 587     }
 588 
 589     // Test subtype check when casting to inline type
 590     @Test
 591     @IR(failOn = {ALLOC})
 592     public MyValue1 test17(MyValue1 vt, Object obj) {
 593         try {
 594             vt = (MyValue1)obj;
 595             throw new RuntimeException("ClassCastException expected");
 596         } catch (ClassCastException e) {
 597             // Expected
 598         }
 599         return vt;
 600     }
 601 
 602     @Run(test = "test17")
 603     public void test17_verifier() {
 604         MyValue1 vt = testValue1;
 605         MyValue1 result = test17(vt, new NonValueClass(rI));
 606         Asserts.assertEquals(result.hash(), vt.hash());
 607     }
 608 
 609     @Test
 610     public MyValue1 test18(MyValue1 vt) {
 611         Object obj = vt;
 612         vt = (MyValue1)obj;
 613         return vt;
 614     }
 615 
 616     @Run(test = "test18")
 617     public void test18_verifier() {
 618         MyValue1 vt = testValue1;
 619         MyValue1 result = test18(vt);
 620         Asserts.assertEquals(result.hash(), vt.hash());
 621     }
 622 
 623     @Test
 624     @IR(failOn = {ALLOC_G})
 625     public void test19(MyValue1 vt) {
 626         if (vt == null) {
 627             return;
 628         }
 629         Object obj = vt;
 630         try {
 631             MyValue2 vt2 = (MyValue2)obj;
 632             throw new RuntimeException("ClassCastException expected");
 633         } catch (ClassCastException e) {
 634             // Expected
 635         }
 636     }
 637 
 638     @Run(test = "test19")
 639     public void test19_verifier() {
 640         test19(valueField1);
 641     }
 642 
 643     @Test
 644     @IR(failOn = {ALLOC_G})
 645     public void test20(MyValue1 vt) {
 646         if (vt == null) {
 647             return;
 648         }
 649         Object obj = vt;
 650         try {
 651             NonValueClass i = (NonValueClass)obj;
 652             throw new RuntimeException("ClassCastException expected");
 653         } catch (ClassCastException e) {
 654             // Expected
 655         }
 656     }
 657 
 658     @Run(test = "test20")
 659     public void test20_verifier() {
 660         test20(valueField1);
 661     }
 662 
 663     // Array tests
 664 
 665     private static final MyValue1[] testValue1Array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 3, MyValue1.DEFAULT);
 666     static {
 667         for (int i = 0; i < 3; ++i) {
 668             testValue1Array[i] = testValue1;
 669         }
 670     }
 671 
 672     private static final MyValue1[][] testValue1Array2 = new MyValue1[][] {testValue1Array,
 673                                                                            testValue1Array,
 674                                                                            testValue1Array};
 675 
 676     private static final MyValue2[] testValue2Array = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 3, MyValue2.DEFAULT);
 677     static {
 678         for (int i = 0; i < 3; ++i) {
 679             testValue2Array[i] = testValue2;
 680         }
 681     }
 682 
 683     private static final NonValueClass[] testNonValueArray = new NonValueClass[42];
 684 
 685     // Test load from (flattened) inline type array disguised as object array
 686     @Test
 687     public Object test21(Object[] oa, int index) {
 688         return oa[index];
 689     }
 690 
 691     @Run(test = "test21")
 692     public void test21_verifier() {
 693         MyValue1 result = (MyValue1)test21(testValue1Array, Math.abs(rI) % 3);
 694         Asserts.assertEQ(result.hash(), hash());
 695     }
 696 
 697     // Test load from (flattened) inline type array disguised as interface array
 698     @Test
 699     public Object test22Interface(MyInterface[] ia, int index) {
 700         return ia[index];
 701     }
 702 
 703     @Run(test = "test22Interface")
 704     public void test22Interface_verifier() {
 705         MyValue1 result = (MyValue1)test22Interface(testValue1Array, Math.abs(rI) % 3);
 706         Asserts.assertEQ(result.hash(), hash());
 707     }
 708 
 709     // Test load from (flattened) inline type array disguised as abstract array
 710     @Test
 711     public Object test22Abstract(MyAbstract[] ia, int index) {
 712         return ia[index];
 713     }
 714 
 715     @Run(test = "test22Abstract")
 716     public void test22Abstract_verifier() {
 717         MyValue1 result = (MyValue1)test22Abstract(testValue1Array, Math.abs(rI) % 3);
 718         Asserts.assertEQ(result.hash(), hash());
 719     }
 720 
 721     // Test inline store to (flattened) inline type array disguised as object array
 722     @ForceInline
 723     public void test23_inline(Object[] oa, Object o, int index) {
 724         oa[index] = o;
 725     }
 726 
 727     @Test
 728     public void test23(Object[] oa, MyValue1 vt, int index) {
 729         test23_inline(oa, vt, index);
 730     }
 731 
 732     @Run(test = "test23")
 733     public void test23_verifier() {
 734         int index = Math.abs(rI) % 3;
 735         MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
 736         test23(testValue1Array, vt, index);
 737         Asserts.assertEQ(testValue1Array[index].hash(), vt.hash());
 738         testValue1Array[index] = testValue1;
 739         try {
 740             test23(testValue2Array, vt, index);
 741             throw new RuntimeException("No ArrayStoreException thrown");
 742         } catch (ArrayStoreException e) {
 743             // Expected
 744         }
 745         Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash());
 746     }
 747 
 748     @ForceInline
 749     public void test24_inline(Object[] oa, Object o, int index) {
 750         oa[index] = o;
 751     }
 752 
 753     @Test
 754     public void test24(Object[] oa, MyValue1 vt, int index) {
 755         test24_inline(oa, vt, index);
 756     }
 757 
 758     @Run(test = "test24")
 759     public void test24_verifier() {
 760         int index = Math.abs(rI) % 3;
 761         try {
 762             test24(testNonValueArray, testValue1, index);
 763             throw new RuntimeException("No ArrayStoreException thrown");
 764         } catch (ArrayStoreException e) {
 765             // Expected
 766         }
 767     }
 768 
 769     @ForceInline
 770     public void test25_inline(Object[] oa, Object o, int index) {
 771         oa[index] = o;
 772     }
 773 
 774     @Test
 775     public void test25(Object[] oa, MyValue1 vt, int index) {
 776         test25_inline(oa, vt, index);
 777     }
 778 
 779     @Run(test = "test25")
 780     public void test25_verifier() {
 781         int index = Math.abs(rI) % 3;
 782         try {
 783             test25(null, testValue1, index);
 784             throw new RuntimeException("No NPE thrown");
 785         } catch (NullPointerException e) {
 786             // Expected
 787         }
 788     }
 789 
 790     // Test inline store to (flattened) inline type array disguised as interface array
 791     @ForceInline
 792     public void test26Interface_inline(MyInterface[] ia, MyInterface i, int index) {
 793         ia[index] = i;
 794     }
 795 
 796     @Test
 797     public void test26Interface(MyInterface[] ia, MyValue1 vt, int index) {
 798       test26Interface_inline(ia, vt, index);
 799     }
 800 
 801     @Run(test = "test26Interface")
 802     public void test26Interface_verifier() {
 803         int index = Math.abs(rI) % 3;
 804         MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
 805         test26Interface(testValue1Array, vt, index);
 806         Asserts.assertEQ(testValue1Array[index].hash(), vt.hash());
 807         testValue1Array[index] = testValue1;
 808         try {
 809             test26Interface(testValue2Array, vt, index);
 810             throw new RuntimeException("No ArrayStoreException thrown");
 811         } catch (ArrayStoreException e) {
 812             // Expected
 813         }
 814         Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash());
 815     }
 816 
 817     @ForceInline
 818     public void test27Interface_inline(MyInterface[] ia, MyInterface i, int index) {
 819         ia[index] = i;
 820     }
 821 
 822     @Test
 823     public void test27Interface(MyInterface[] ia, MyValue1 vt, int index) {
 824         test27Interface_inline(ia, vt, index);
 825     }
 826 
 827     @Run(test = "test27Interface")
 828     public void test27Interface_verifier() {
 829         int index = Math.abs(rI) % 3;
 830         try {
 831             test27Interface(null, testValue1, index);
 832             throw new RuntimeException("No NPE thrown");
 833         } catch (NullPointerException e) {
 834             // Expected
 835         }
 836     }
 837 
 838     // Test inline store to (flattened) inline type array disguised as abstract array
 839     @ForceInline
 840     public void test26Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
 841         ia[index] = i;
 842     }
 843 
 844     @Test
 845     public void test26Abstract(MyAbstract[] ia, MyValue1 vt, int index) {
 846       test26Abstract_inline(ia, vt, index);
 847     }
 848 
 849     @Run(test = "test26Abstract")
 850     public void test26Abstract_verifier() {
 851         int index = Math.abs(rI) % 3;
 852         MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
 853         test26Abstract(testValue1Array, vt, index);
 854         Asserts.assertEQ(testValue1Array[index].hash(), vt.hash());
 855         testValue1Array[index] = testValue1;
 856         try {
 857             test26Abstract(testValue2Array, vt, index);
 858             throw new RuntimeException("No ArrayStoreException thrown");
 859         } catch (ArrayStoreException e) {
 860             // Expected
 861         }
 862         Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash());
 863     }
 864 
 865     @ForceInline
 866     public void test27Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
 867         ia[index] = i;
 868     }
 869 
 870     @Test
 871     public void test27Abstract(MyAbstract[] ia, MyValue1 vt, int index) {
 872         test27Abstract_inline(ia, vt, index);
 873     }
 874 
 875     @Run(test = "test27Abstract")
 876     public void test27Abstract_verifier() {
 877         int index = Math.abs(rI) % 3;
 878         try {
 879             test27Abstract(null, testValue1, index);
 880             throw new RuntimeException("No NPE thrown");
 881         } catch (NullPointerException e) {
 882             // Expected
 883         }
 884     }
 885 
 886     // Test object store to (flattened) inline type array disguised as object array
 887     @ForceInline
 888     public void test28_inline(Object[] oa, Object o, int index) {
 889         oa[index] = o;
 890     }
 891 
 892     @Test
 893     public void test28(Object[] oa, Object o, int index) {
 894         test28_inline(oa, o, index);
 895     }
 896 
 897     @Run(test = "test28")
 898     public void test28_verifier() {
 899         int index = Math.abs(rI) % 3;
 900         MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
 901         test28(testValue1Array, vt1, index);
 902         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
 903         try {
 904             test28(testValue1Array, testValue2, index);
 905             throw new RuntimeException("No ArrayStoreException thrown");
 906         } catch (ArrayStoreException e) {
 907             // Expected
 908         }
 909         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
 910         testValue1Array[index] = testValue1;
 911     }
 912 
 913     @ForceInline
 914     public void test29_inline(Object[] oa, Object o, int index) {
 915         oa[index] = o;
 916     }
 917 
 918     @Test
 919     public void test29(Object[] oa, Object o, int index) {
 920         test29_inline(oa, o, index);
 921     }
 922 
 923     @Run(test = "test29")
 924     public void test29_verifier() {
 925         int index = Math.abs(rI) % 3;
 926         try {
 927             test29(testValue2Array, testValue1, index);
 928             throw new RuntimeException("No ArrayStoreException thrown");
 929         } catch (ArrayStoreException e) {
 930             // Expected
 931         }
 932         Asserts.assertEQ(testValue2Array[index].hash(), testValue2.hash());
 933     }
 934 
 935     @ForceInline
 936     public void test30_inline(Object[] oa, Object o, int index) {
 937         oa[index] = o;
 938     }
 939 
 940     @Test
 941     public void test30(Object[] oa, Object o, int index) {
 942         test30_inline(oa, o, index);
 943     }
 944 
 945     @Run(test = "test30")
 946     public void test30_verifier() {
 947         int index = Math.abs(rI) % 3;
 948         try {
 949             test30(testNonValueArray, testValue1, index);
 950             throw new RuntimeException("No ArrayStoreException thrown");
 951         } catch (ArrayStoreException e) {
 952             // Expected
 953         }
 954     }
 955 
 956     // Test inline store to (flattened) inline type array disguised as interface array
 957     @ForceInline
 958     public void test31Interface_inline(MyInterface[] ia, MyInterface i, int index) {
 959         ia[index] = i;
 960     }
 961 
 962     @Test
 963     public void test31Interface(MyInterface[] ia, MyInterface i, int index) {
 964         test31Interface_inline(ia, i, index);
 965     }
 966 
 967     @Run(test = "test31Interface")
 968     public void test31Interface_verifier() {
 969         int index = Math.abs(rI) % 3;
 970         MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
 971         test31Interface(testValue1Array, vt1, index);
 972         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
 973         try {
 974             test31Interface(testValue1Array, testValue2, index);
 975             throw new RuntimeException("No ArrayStoreException thrown");
 976         } catch (ArrayStoreException e) {
 977             // Expected
 978         }
 979         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
 980         testValue1Array[index] = testValue1;
 981     }
 982 
 983     @ForceInline
 984     public void test32Interface_inline(MyInterface[] ia, MyInterface i, int index) {
 985         ia[index] = i;
 986     }
 987 
 988     @Test
 989     public void test32Interface(MyInterface[] ia, MyInterface i, int index) {
 990         test32Interface_inline(ia, i, index);
 991     }
 992 
 993     @Run(test = "test32Interface")
 994     public void test32Interface_verifier() {
 995         int index = Math.abs(rI) % 3;
 996         try {
 997             test32Interface(testValue2Array, testValue1, index);
 998             throw new RuntimeException("No ArrayStoreException thrown");
 999         } catch (ArrayStoreException e) {
1000             // Expected
1001         }
1002     }
1003 
1004     // Test inline store to (flattened) inline type array disguised as abstract array
1005     @ForceInline
1006     public void test31Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
1007         ia[index] = i;
1008     }
1009 
1010     @Test
1011     public void test31Abstract(MyAbstract[] ia, MyAbstract i, int index) {
1012         test31Abstract_inline(ia, i, index);
1013     }
1014 
1015     @Run(test = "test31Abstract")
1016     public void test31Abstract_verifier() {
1017         int index = Math.abs(rI) % 3;
1018         MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
1019         test31Abstract(testValue1Array, vt1, index);
1020         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
1021         try {
1022             test31Abstract(testValue1Array, testValue2, index);
1023             throw new RuntimeException("No ArrayStoreException thrown");
1024         } catch (ArrayStoreException e) {
1025             // Expected
1026         }
1027         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
1028         testValue1Array[index] = testValue1;
1029     }
1030 
1031     @ForceInline
1032     public void test32Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
1033         ia[index] = i;
1034     }
1035 
1036     @Test
1037     public void test32Abstract(MyAbstract[] ia, MyAbstract i, int index) {
1038         test32Abstract_inline(ia, i, index);
1039     }
1040 
1041     @Run(test = "test32Abstract")
1042     public void test32Abstract_verifier() {
1043         int index = Math.abs(rI) % 3;
1044         try {
1045             test32Abstract(testValue2Array, testValue1, index);
1046             throw new RuntimeException("No ArrayStoreException thrown");
1047         } catch (ArrayStoreException e) {
1048             // Expected
1049         }
1050     }
1051 
1052     // Test writing null to a (flattened) inline type array disguised as object array
1053     @ForceInline
1054     public void test33_inline(Object[] oa, Object o, int index) {
1055         oa[index] = o;
1056     }
1057 
1058     @Test
1059     public void test33(Object[] oa, Object o, int index) {
1060         test33_inline(oa, o, index);
1061     }
1062 
1063     @Run(test = "test33")
1064     public void test33_verifier() {
1065         int index = Math.abs(rI) % 3;
1066         try {
1067             test33(testValue1Array, null, index);
1068             throw new RuntimeException("No NPE thrown");
1069         } catch (NullPointerException e) {
1070             // Expected
1071         }
1072         Asserts.assertEQ(testValue1Array[index].hash(), hash());
1073     }
1074 
1075     // Test writing constant null to a (flattened) inline type array disguised as object array
1076 
1077     @ForceInline
1078     public void test34_inline(Object[] oa, Object o, int index) {
1079         oa[index] = o;
1080     }
1081 
1082     @Test
1083     public void test34(Object[] oa, int index) {
1084         test34_inline(oa, null, index);
1085     }
1086 
1087     @Run(test = "test34")
1088     public void test34_verifier() {
1089         int index = Math.abs(rI) % 3;
1090         try {
1091             test34(testValue1Array, index);
1092             throw new RuntimeException("No NPE thrown");
1093         } catch (NullPointerException e) {
1094             // Expected
1095         }
1096         Asserts.assertEQ(testValue1Array[index].hash(), hash());
1097     }
1098 
1099     // Test writing constant null to a (flattened) inline type array
1100 
1101     private static final MethodHandle setArrayElementNull = InstructionHelper.buildMethodHandle(MethodHandles.lookup(),
1102         "setArrayElementNull",
1103         MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class),
1104         CODE -> {
1105             CODE.
1106             aload(1).
1107             iload(2).
1108             aconst_null().
1109             aastore().
1110             return_();
1111         });
1112 
1113     @Test
1114     public void test35(MyValue1[] va, int index) throws Throwable {
1115         setArrayElementNull.invoke(this, va, index);
1116     }
1117 
1118     @Run(test = "test35")
1119     @Warmup(10000)
1120     public void test35_verifier() throws Throwable {
1121         int index = Math.abs(rI) % 3;
1122         try {
1123             test35(testValue1Array, index);
1124             throw new RuntimeException("No NPE thrown");
1125         } catch (NullPointerException e) {
1126             // Expected
1127         }
1128         Asserts.assertEQ(testValue1Array[index].hash(), hash());
1129     }
1130 
1131     // Test writing an inline type to a null inline type array
1132     @Test
1133     public void test36(MyValue1[] va, MyValue1 vt, int index) {
1134         va[index] = vt;
1135     }
1136 
1137     @Run(test = "test36")
1138     public void test36_verifier() {
1139         int index = Math.abs(rI) % 3;
1140         try {
1141             test36(null, testValue1Array[index], index);
1142             throw new RuntimeException("No NPE thrown");
1143         } catch (NullPointerException e) {
1144             // Expected
1145         }
1146     }
1147 
1148     // Test incremental inlining
1149     @ForceInline
1150     public void test37_inline(Object[] oa, Object o, int index) {
1151         oa[index] = o;
1152     }
1153 
1154     @Test
1155     @IR(failOn = {ALLOC_G})
1156     public void test37(MyValue1[] va, Object o, int index) {
1157         test37_inline(va, o, index);
1158     }
1159 
1160     @Run(test = "test37")
1161     public void test37_verifier() {
1162         int index = Math.abs(rI) % 3;
1163         MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
1164         test37(testValue1Array, vt1, index);
1165         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
1166         try {
1167             test37(testValue1Array, testValue2, index);
1168             throw new RuntimeException("No ArrayStoreException thrown");
1169         } catch (ArrayStoreException e) {
1170             // Expected
1171         }
1172         Asserts.assertEQ(testValue1Array[index].hash(), vt1.hash());
1173         testValue1Array[index] = testValue1;
1174     }
1175 
1176     // Test merging of inline type arrays
1177 
1178     @ForceInline
1179     public Object[] test38_inline() {
1180         return (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT);
1181     }
1182 
1183     @Test
1184     @IR(failOn = {ALLOC})
1185     public Object[] test38(Object[] oa, Object o, int i1, int i2, int num) {
1186         Object[] result = null;
1187         switch (num) {
1188         case 0:
1189             result = test38_inline();
1190             break;
1191         case 1:
1192             result = oa;
1193             break;
1194         case 2:
1195             result = testValue1Array;
1196             break;
1197         case 3:
1198             result = testValue2Array;
1199             break;
1200         case 4:
1201             result = testNonValueArray;
1202             break;
1203         case 5:
1204             result = null;
1205             break;
1206         case 6:
1207             result = testValue1Array2;
1208             break;
1209         }
1210         result[i1] = result[i2];
1211         result[i2] = o;
1212         return result;
1213     }
1214 
1215     @Run(test = "test38")
1216     public void test38_verifier() {
1217         int index = Math.abs(rI) % 3;
1218         MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT);
1219         Object[] result = test38(null, testValue1, index, index, 0);
1220         Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash());
1221         result = test38(testValue1Array, testValue1, index, index, 1);
1222         Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash());
1223         result = test38(null, testValue1, index, index, 2);
1224         Asserts.assertEQ(((MyValue1)result[index]).hash(), testValue1.hash());
1225         result = test38(null, testValue2, index, index, 3);
1226         Asserts.assertEQ(((MyValue2)result[index]).hash(), testValue2.hash());
1227         try {
1228             result = test38(null, null, index, index, 3);
1229             throw new RuntimeException("No NPE thrown");
1230         } catch (NullPointerException e) {
1231             // Expected
1232         }
1233         result = test38(null, null, index, index, 4);
1234         try {
1235             result = test38(null, testValue1, index, index, 4);
1236             throw new RuntimeException("No ArrayStoreException thrown");
1237         } catch (ArrayStoreException e) {
1238             // Expected
1239         }
1240         try {
1241             result = test38(null, testValue1, index, index, 5);
1242             throw new RuntimeException("No NPE thrown");
1243         } catch (NullPointerException e) {
1244             // Expected
1245         }
1246         result = test38(null, testValue1Array, index, index, 6);
1247         Asserts.assertEQ(((MyValue1[][])result)[index][index].hash(), testValue1.hash());
1248     }
1249 
1250     @ForceInline
1251     public Object test39_inline() {
1252         return (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT);
1253     }
1254 
1255     // Same as above but merging into Object instead of Object[]
1256     @Test
1257     public Object test39(Object oa, Object o, int i1, int i2, int num) {
1258         Object result = null;
1259         switch (num) {
1260         case 0:
1261             result = test39_inline();
1262             break;
1263         case 1:
1264             result = oa;
1265             break;
1266         case 2:
1267             result = testValue1Array;
1268             break;
1269         case 3:
1270             result = testValue2Array;
1271             break;
1272         case 4:
1273             result = testNonValueArray;
1274             break;
1275         case 5:
1276             result = null;
1277             break;
1278         case 6:
1279             result = testValue1;
1280             break;
1281         case 7:
1282             result = testValue2;
1283             break;
1284         case 8:
1285             result = MyValue1.createWithFieldsInline(rI, rL);
1286             break;
1287         case 9:
1288             result = new NonValueClass(42);
1289             break;
1290         case 10:
1291             result = testValue1Array2;
1292             break;
1293         }
1294         if (result instanceof Object[]) {
1295             ((Object[])result)[i1] = ((Object[])result)[i2];
1296             ((Object[])result)[i2] = o;
1297         }
1298         return result;
1299     }
1300 
1301     @Run(test = "test39")
1302     public void test39_verifier() {
1303         int index = Math.abs(rI) % 3;
1304         MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 42, MyValue1.DEFAULT);
1305         Object result = test39(null, testValue1, index, index, 0);
1306         Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash());
1307         result = test39(testValue1Array, testValue1, index, index, 1);
1308         Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash());
1309         result = test39(null, testValue1, index, index, 2);
1310         Asserts.assertEQ(((MyValue1[])result)[index].hash(), testValue1.hash());
1311         result = test39(null, testValue2, index, index, 3);
1312         Asserts.assertEQ(((MyValue2[])result)[index].hash(), testValue2.hash());
1313         try {
1314             result = test39(null, null, index, index, 3);
1315             throw new RuntimeException("No NPE thrown");
1316         } catch (NullPointerException e) {
1317             // Expected
1318         }
1319         result = test39(null, null, index, index, 4);
1320         try {
1321             result = test39(null, testValue1, index, index, 4);
1322             throw new RuntimeException("No ArrayStoreException thrown");
1323         } catch (ArrayStoreException e) {
1324             // Expected
1325         }
1326         result = test39(null, testValue1, index, index, 5);
1327         Asserts.assertEQ(result, null);
1328         result = test39(null, testValue1, index, index, 6);
1329         Asserts.assertEQ(((MyValue1)result).hash(), testValue1.hash());
1330         result = test39(null, testValue1, index, index, 7);
1331         Asserts.assertEQ(((MyValue2)result).hash(), testValue2.hash());
1332         result = test39(null, testValue1, index, index, 8);
1333         Asserts.assertEQ(((MyValue1)result).hash(), testValue1.hash());
1334         result = test39(null, testValue1, index, index, 9);
1335         Asserts.assertEQ(((NonValueClass)result).x, 42);
1336         result = test39(null, testValue1Array, index, index, 10);
1337         Asserts.assertEQ(((MyValue1[][])result)[index][index].hash(), testValue1.hash());
1338     }
1339 
1340     // Test instanceof with inline types and arrays
1341     @Test
1342     @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
1343         failOn = {ALLOC_G})
1344     public long test40(Object o, int index) {
1345         if (o instanceof MyValue1) {
1346           return ((MyValue1)o).hashInterpreted();
1347         } else if (o instanceof MyValue1[]) {
1348           return ((MyValue1[])o)[index].hashInterpreted();
1349         } else if (o instanceof MyValue2) {
1350           return ((MyValue2)o).hash();
1351         } else if (o instanceof MyValue2[]) {
1352           return ((MyValue2[])o)[index].hash();
1353         } else if (o instanceof MyValue1[][]) {
1354           return ((MyValue1[][])o)[index][index].hash();
1355         } else if (o instanceof Long) {
1356           return (long)o;
1357         }
1358         return 0;
1359     }
1360 
1361     @Run(test = "test40")
1362     public void test40_verifier() {
1363         int index = Math.abs(rI) % 3;
1364         long result = test40(testValue1, 0);
1365         Asserts.assertEQ(result, testValue1.hashInterpreted());
1366         result = test40(testValue1Array, index);
1367         Asserts.assertEQ(result, testValue1.hashInterpreted());
1368         result = test40(testValue2, index);
1369         Asserts.assertEQ(result, testValue2.hash());
1370         result = test40(testValue2Array, index);
1371         Asserts.assertEQ(result, testValue2.hash());
1372         result = test40(testValue1Array2, index);
1373         Asserts.assertEQ(result, testValue1.hash());
1374         result = test40(Long.valueOf(42), index);
1375         Asserts.assertEQ(result, 42L);
1376     }
1377 
1378     // Test for bug in Escape Analysis
1379     @DontInline
1380     public void test41_dontinline(Object o) {
1381         Asserts.assertEQ(o, rI);
1382     }
1383 
1384     @Test
1385     @IR(failOn = {ALLOC})
1386     public void test41() {
1387         MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT);
1388         vals[0] = testValue1;
1389         test41_dontinline(vals[0].oa[0]);
1390         test41_dontinline(vals[0].oa[0]);
1391     }
1392 
1393     @Run(test = "test41")
1394     public void test41_verifier() {
1395         test41();
1396     }
1397 
1398     // Test for bug in Escape Analysis
1399     private static final MyValue1 test42VT1 = MyValue1.createWithFieldsInline(rI, rL);
1400     private static final MyValue1 test42VT2 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
1401 
1402     @Test
1403     @IR(failOn = {ALLOC})
1404     public void test42() {
1405         MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 2, MyValue1.DEFAULT);
1406         vals[0] = test42VT1;
1407         vals[1] = test42VT2;
1408         Asserts.assertEQ(vals[0].hash(), test42VT1.hash());
1409         Asserts.assertEQ(vals[1].hash(), test42VT2.hash());
1410     }
1411 
1412     @Run(test = "test42")
1413     public void test42_verifier(RunInfo info) {
1414         if (!info.isWarmUp()) test42(); // We need -Xcomp behavior
1415     }
1416 
1417     // Test for bug in Escape Analysis
1418     @Test
1419     @IR(failOn = {ALLOC})
1420     public long test43(boolean deopt, Method m) {
1421         MyValue1[] vals = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 2, MyValue1.DEFAULT);
1422         vals[0] = test42VT1;
1423         vals[1] = test42VT2;
1424 
1425         if (deopt) {
1426             // uncommon trap
1427             TestFramework.deoptimize(m);
1428             Asserts.assertEQ(vals[0].hash(), test42VT1.hash());
1429             Asserts.assertEQ(vals[1].hash(), test42VT2.hash());
1430         }
1431 
1432         return vals[0].hash();
1433     }
1434 
1435     @Run(test = "test43")
1436     public void test43_verifier(RunInfo info) {
1437         test43(!info.isWarmUp(), info.getTest());
1438     }
1439 
1440     // Tests writing an array element with a (statically known) incompatible type
1441     private static final MethodHandle setArrayElementIncompatible = InstructionHelper.buildMethodHandle(MethodHandles.lookup(),
1442         "setArrayElementIncompatible",
1443         MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class, MyValue2.class),
1444         CODE -> {
1445             CODE.
1446             aload(1).
1447             iload(2).
1448             aload(3).
1449             aastore().
1450             return_();
1451         });
1452 
1453     @Test
1454     public void test44(MyValue1[] va, int index, MyValue2 v) throws Throwable {
1455         setArrayElementIncompatible.invoke(this, va, index, v);
1456     }
1457 
1458     @Run(test = "test44")
1459     @Warmup(10000)
1460     public void test44_verifier() throws Throwable {
1461         int index = Math.abs(rI) % 3;
1462         try {
1463             test44(testValue1Array, index, testValue2);
1464             throw new RuntimeException("No ArrayStoreException thrown");
1465         } catch (ArrayStoreException e) {
1466             // Expected
1467         }
1468         Asserts.assertEQ(testValue1Array[index].hash(), hash());
1469     }
1470 
1471     // Tests writing an array element with a (statically known) incompatible type
1472     @ForceInline
1473     public void test45_inline(Object[] oa, Object o, int index) {
1474         oa[index] = o;
1475     }
1476 
1477     @Test
1478     public void test45(MyValue1[] va, int index, MyValue2 v) throws Throwable {
1479         test45_inline(va, v, index);
1480     }
1481 
1482     @Run(test = "test45")
1483     public void test45_verifier() throws Throwable {
1484         int index = Math.abs(rI) % 3;
1485         try {
1486             test45(testValue1Array, index, testValue2);
1487             throw new RuntimeException("No ArrayStoreException thrown");
1488         } catch (ArrayStoreException e) {
1489             // Expected
1490         }
1491         Asserts.assertEQ(testValue1Array[index].hash(), hash());
1492     }
1493 
1494     // instanceof tests with inline types
1495     @Test
1496     @IR(failOn = {ALLOC_G})
1497     public boolean test46(MyValue1 vt) {
1498         Object obj = vt;
1499         return obj instanceof MyValue1;
1500     }
1501 
1502     @Run(test = "test46")
1503     public void test46_verifier() {
1504         MyValue1 vt = testValue1;
1505         boolean result = test46(vt);
1506         Asserts.assertTrue(result);
1507     }
1508 
1509     @Test
1510     @IR(failOn = {ALLOC_G})
1511     public boolean test47(MyValue1 vt) {
1512         Object obj = vt;
1513         return obj instanceof MyValue2;
1514     }
1515 
1516     @Run(test = "test47")
1517     public void test47_verifier() {
1518         MyValue1 vt = testValue1;
1519         boolean result = test47(vt);
1520         Asserts.assertFalse(result);
1521     }
1522 
1523     @Test
1524     @IR(failOn = {ALLOC_G})
1525     public boolean test48(Object obj) {
1526         return obj instanceof MyValue1;
1527     }
1528 
1529     @Run(test = "test48")
1530     public void test48_verifier() {
1531         MyValue1 vt = testValue1;
1532         boolean result = test48(vt);
1533         Asserts.assertTrue(result);
1534     }
1535 
1536     @Test
1537     @IR(failOn = {ALLOC_G})
1538     public boolean test49(Object obj) {
1539         return obj instanceof MyValue2;
1540     }
1541 
1542     @Run(test = "test49")
1543     public void test49_verifier() {
1544         MyValue1 vt = testValue1;
1545         boolean result = test49(vt);
1546         Asserts.assertFalse(result);
1547     }
1548 
1549     @Test
1550     @IR(failOn = {ALLOC_G})
1551     public boolean test50(Object obj) {
1552         return obj instanceof MyValue1;
1553     }
1554 
1555     @Run(test = "test50")
1556     public void test50_verifier() {
1557         Asserts.assertFalse(test49(new NonValueClass(42)));
1558     }
1559 
1560     // Inline type with some non-flattened fields
1561     @LooselyConsistentValue
1562     static value class Test51Value {
1563         Object objectField1;
1564         Object objectField2;
1565         Object objectField3;
1566         Object objectField4;
1567         Object objectField5;
1568         Object objectField6;
1569 
1570         @Strict
1571         @NullRestricted
1572         MyValue1 valueField1;
1573         @Strict
1574         @NullRestricted
1575         MyValue1 valueField2;
1576         MyValue1 valueField3;
1577         @Strict
1578         @NullRestricted
1579         MyValue1 valueField4;
1580         MyValue1 valueField5;
1581 
1582         public Test51Value() {
1583             objectField1 = null;
1584             objectField2 = null;
1585             objectField3 = null;
1586             objectField4 = null;
1587             objectField5 = null;
1588             objectField6 = null;
1589             valueField1 = testValue1;
1590             valueField2 = testValue1;
1591             valueField3 = testValue1;
1592             valueField4 = MyValue1.createDefaultDontInline();
1593             valueField5 = MyValue1.createDefaultDontInline();
1594         }
1595 
1596         public Test51Value(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6,
1597                            MyValue1 vt1, MyValue1 vt2, MyValue1 vt3, MyValue1 vt4, MyValue1 vt5) {
1598             objectField1 = o1;
1599             objectField2 = o2;
1600             objectField3 = o3;
1601             objectField4 = o4;
1602             objectField5 = o5;
1603             objectField6 = o6;
1604             valueField1 = vt1;
1605             valueField2 = vt2;
1606             valueField3 = vt3;
1607             valueField4 = vt4;
1608             valueField5 = vt5;
1609         }
1610 
1611         @ForceInline
1612         public long test(Test51Value holder, MyValue1 vt1, Object vt2) {
1613             holder = new Test51Value(vt1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6,
1614                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1615             holder = new Test51Value(holder.objectField1, (MyValue1)vt2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6,
1616                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1617             holder = new Test51Value(holder.objectField1, holder.objectField2, testValue1, holder.objectField4, holder.objectField5, holder.objectField6,
1618                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1619             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, MyValue1.createWithFieldsDontInline(rI, rL), holder.objectField5, holder.objectField6,
1620                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1621             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.valueField1, holder.objectField6,
1622                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1623             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.valueField3,
1624                                      holder.valueField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1625             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6,
1626                                      (MyValue1)holder.objectField1, holder.valueField2, holder.valueField3, holder.valueField4, holder.valueField5);
1627             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6,
1628                                      holder.valueField1, (MyValue1)vt2, holder.valueField3, holder.valueField4, holder.valueField5);
1629             holder = new Test51Value(holder.objectField1, holder.objectField2, holder.objectField3, holder.objectField4, holder.objectField5, holder.objectField6,
1630                                      holder.valueField1, holder.valueField2, (MyValue1)vt2, holder.valueField4, holder.valueField5);
1631 
1632             return ((MyValue1)holder.objectField1).hash() +
1633                    ((MyValue1)holder.objectField2).hash() +
1634                    ((MyValue1)holder.objectField3).hash() +
1635                    ((MyValue1)holder.objectField4).hash() +
1636                    ((MyValue1)holder.objectField5).hash() +
1637                    ((MyValue1)holder.objectField6).hash() +
1638                    holder.valueField1.hash() +
1639                    holder.valueField2.hash() +
1640                    holder.valueField3.hash() +
1641                    holder.valueField4.hashPrimitive();
1642         }
1643     }
1644 
1645     // Pass arguments via fields to avoid exzessive spilling leading to compilation bailouts
1646     @Strict
1647     @NullRestricted
1648     static Test51Value test51_arg1 = new Test51Value();
1649     @Strict
1650     @NullRestricted
1651     static MyValue1 test51_arg2 = MyValue1.DEFAULT;
1652     static Object test51_arg3;
1653 
1654     // Same as test2 but with field holder being an inline type
1655     @Test
1656     public long test51() {
1657         return test51_arg1.test(test51_arg1, test51_arg2, test51_arg3);
1658     }
1659 
1660     @Run(test = "test51")
1661     public void test51_verifier() {
1662         MyValue1 vt = testValue1;
1663         MyValue1 def = MyValue1.createDefaultDontInline();
1664         Test51Value holder = new Test51Value();
1665         Asserts.assertEQ(testValue1.hash(), vt.hash());
1666         Asserts.assertEQ(holder.valueField1.hash(), vt.hash());
1667         test51_arg1 = holder;
1668         test51_arg2 = vt;
1669         test51_arg3 = vt;
1670         long result = test51();
1671         Asserts.assertEQ(result, 9*vt.hash() + def.hashPrimitive());
1672     }
1673 
1674     // Access non-flattened, uninitialized inline type field with inline type holder
1675     @Test
1676     @IR(failOn = {ALLOC})
1677     public void test52(Test51Value holder) {
1678         if ((Object)holder.valueField5 != null) {
1679             throw new RuntimeException("Should be null");
1680         }
1681     }
1682 
1683     @Run(test = "test52")
1684     public void test52_verifier() {
1685         Test51Value vt = new Test51Value(null, null, null, null, null, null,
1686                                          MyValue1.createDefaultInline(), MyValue1.createDefaultInline(), null, MyValue1.createDefaultInline(), null);
1687         test52(vt);
1688     }
1689 
1690     // Merging inline types of different types
1691     @Test
1692     public Object test53(Object o, boolean b) {
1693         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1694         return b ? vt : o;
1695     }
1696 
1697     @Run(test = "test53")
1698     public void test53_verifier() {
1699         test53(new Object(), false);
1700         MyValue1 result = (MyValue1)test53(new Object(), true);
1701         Asserts.assertEQ(result.hash(), hash());
1702     }
1703 
1704     @Test
1705     public Object test54(boolean b) {
1706         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1707         return b ? vt : testValue2;
1708     }
1709 
1710     @Run(test = "test54")
1711     public void test54_verifier() {
1712         MyValue1 result1 = (MyValue1)test54(true);
1713         Asserts.assertEQ(result1.hash(), hash());
1714         MyValue2 result2 = (MyValue2)test54(false);
1715         Asserts.assertEQ(result2.hash(), testValue2.hash());
1716     }
1717 
1718     @Test
1719     public Object test55(boolean b) {
1720         MyValue1 vt1 = MyValue1.createWithFieldsInline(rI, rL);
1721         MyValue2 vt2 = MyValue2.createWithFieldsInline(rI, rD);
1722         return b ? vt1 : vt2;
1723     }
1724 
1725     @Run(test = "test55")
1726     public void test55_verifier() {
1727         MyValue1 result1 = (MyValue1)test55(true);
1728         Asserts.assertEQ(result1.hash(), hash());
1729         MyValue2 result2 = (MyValue2)test55(false);
1730         Asserts.assertEQ(result2.hash(), testValue2.hash());
1731     }
1732 
1733     // Test synchronization on inline types
1734     @Test
1735     public void test56(Object vt) {
1736         synchronized (vt) {
1737             throw new RuntimeException("test56 failed: synchronization on inline type should not succeed");
1738         }
1739     }
1740 
1741     @Run(test = "test56")
1742     public void test56_verifier() {
1743         try {
1744             test56(testValue1);
1745             throw new RuntimeException("test56 failed: no exception thrown");
1746         } catch (IdentityException ex) {
1747             // Expected
1748         }
1749     }
1750 
1751     @ForceInline
1752     public void test57_inline(Object vt) {
1753         synchronized (vt) {
1754             throw new RuntimeException("test57 failed: synchronization on inline type should not succeed");
1755         }
1756     }
1757 
1758     @Test
1759     @IR(failOn = {ALLOC_G})
1760     public void test57(MyValue1 vt) {
1761         test57_inline(vt);
1762     }
1763 
1764     @Run(test = "test57")
1765     public void test57_verifier() {
1766         try {
1767             test57(testValue1);
1768             throw new RuntimeException("test57 failed: no exception thrown");
1769         } catch (IdentityException ex) {
1770             // Expected
1771         }
1772     }
1773 
1774     @ForceInline
1775     public void test58_inline(Object vt) {
1776         synchronized (vt) {
1777             throw new RuntimeException("test58 failed: synchronization on inline type should not succeed");
1778         }
1779     }
1780 
1781     @Test
1782     @IR(failOn = {ALLOC})
1783     public void test58() {
1784         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1785         test58_inline(vt);
1786     }
1787 
1788     @Run(test = "test58")
1789     public void test58_verifier() {
1790         try {
1791             test58();
1792             throw new RuntimeException("test58 failed: no exception thrown");
1793         } catch (IdentityException ex) {
1794             // Expected
1795         }
1796     }
1797 
1798     @Test
1799     public void test59(Object o, boolean b) {
1800         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1801         Object sync = b ? vt : o;
1802         synchronized (sync) {
1803             if (b) {
1804                 throw new RuntimeException("test59 failed: synchronization on inline type should not succeed");
1805             }
1806         }
1807     }
1808 
1809     @Run(test = "test59")
1810     public void test59_verifier() {
1811         test59(new Object(), false);
1812         try {
1813             test59(new Object(), true);
1814             throw new RuntimeException("test59 failed: no exception thrown");
1815         } catch (IdentityException ex) {
1816             // Expected
1817         }
1818     }
1819 
1820     @Test
1821     public void test60(boolean b) {
1822         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
1823         Object sync = b ? vt : testValue2;
1824         synchronized (sync) {
1825             throw new RuntimeException("test60 failed: synchronization on inline type should not succeed");
1826         }
1827     }
1828 
1829     @Run(test = "test60")
1830     public void test60_verifier() {
1831         try {
1832             test60(false);
1833             throw new RuntimeException("test60 failed: no exception thrown");
1834         } catch (IdentityException ex) {
1835             // Expected
1836         }
1837         try {
1838             test60(true);
1839             throw new RuntimeException("test60 failed: no exception thrown");
1840         } catch (IdentityException ex) {
1841             // Expected
1842         }
1843     }
1844 
1845     // Test catching the IdentityException in compiled code
1846     @Test
1847     public void test61(Object vt) {
1848         boolean thrown = false;
1849         try {
1850             synchronized (vt) {
1851                 throw new RuntimeException("test61 failed: no exception thrown");
1852             }
1853         } catch (IdentityException ex) {
1854             thrown = true;
1855         }
1856         if (!thrown) {
1857             throw new RuntimeException("test61 failed: no exception thrown");
1858         }
1859     }
1860 
1861     @Run(test = "test61")
1862     public void test61_verifier() {
1863         test61(testValue1);
1864     }
1865 
1866     @Test
1867     public void test62(Object o) {
1868         try {
1869             synchronized (o) { }
1870         } catch (IdentityException ex) {
1871             // Expected
1872             return;
1873         }
1874         throw new RuntimeException("test62 failed: no exception thrown");
1875     }
1876 
1877     @Run(test = "test62")
1878     public void test62_verifier() {
1879         test62(testValue1);
1880     }
1881 
1882     // Test synchronization without any instructions in the synchronized block
1883     @Test
1884     public void test63(Object o) {
1885         synchronized (o) { }
1886     }
1887 
1888     @Run(test = "test63")
1889     public void test63_verifier() {
1890         try {
1891             test63(testValue1);
1892         } catch (IdentityException ex) {
1893             // Expected
1894             return;
1895         }
1896         throw new RuntimeException("test63 failed: no exception thrown");
1897     }
1898 
1899     // type system test with interface and inline type
1900     @ForceInline
1901     public MyInterface test64Interface_helper(MyValue1 vt) {
1902         return vt;
1903     }
1904 
1905     @Test
1906     public MyInterface test64Interface(MyValue1 vt) {
1907         return test64Interface_helper(vt);
1908     }
1909 
1910     @Run(test = "test64Interface")
1911     public void test64Interface_verifier() {
1912         test64Interface(testValue1);
1913     }
1914 
1915     // type system test with abstract and inline type
1916     @ForceInline
1917     public MyAbstract test64Abstract_helper(MyValue1 vt) {
1918         return vt;
1919     }
1920 
1921     @Test
1922     public MyAbstract test64Abstract(MyValue1 vt) {
1923         return test64Abstract_helper(vt);
1924     }
1925 
1926     @Run(test = "test64Abstract")
1927     public void test64Abstract_verifier() {
1928         test64Abstract(testValue1);
1929     }
1930 
1931     // Array store tests
1932     @Test
1933     public void test65(Object[] array, MyValue1 vt) {
1934         array[0] = vt;
1935     }
1936 
1937     @Run(test = "test65")
1938     public void test65_verifier() {
1939         Object[] array = new Object[1];
1940         test65(array, testValue1);
1941         Asserts.assertEQ(((MyValue1)array[0]).hash(), testValue1.hash());
1942     }
1943 
1944     @Test
1945     public void test66(Object[] array, MyValue1 vt) {
1946         array[0] = vt;
1947     }
1948 
1949     @Run(test = "test66")
1950     public void test66_verifier() {
1951         MyValue1[] array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT);
1952         test66(array, testValue1);
1953         Asserts.assertEQ(array[0].hash(), testValue1.hash());
1954     }
1955 
1956     @Test
1957     public void test67(Object[] array, Object vt) {
1958         array[0] = vt;
1959     }
1960 
1961     @Run(test = "test67")
1962     public void test67_verifier() {
1963         MyValue1[] array = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT);
1964         test67(array, testValue1);
1965         Asserts.assertEQ(array[0].hash(), testValue1.hash());
1966     }
1967 
1968     @Test
1969     public void test68(Object[] array, NonValueClass o) {
1970         array[0] = o;
1971     }
1972 
1973     @Run(test = "test68")
1974     public void test68_verifier() {
1975         NonValueClass[] array = new NonValueClass[1];
1976         NonValueClass obj = new NonValueClass(1);
1977         test68(array, obj);
1978         Asserts.assertEQ(array[0], obj);
1979     }
1980 
1981     // Test convertion between an inline type and java.lang.Object without an allocation
1982     @ForceInline
1983     public Object test69_sum(Object a, Object b) {
1984         int sum = ((MyValue1)a).x + ((MyValue1)b).x;
1985         return MyValue1.setX(((MyValue1)a), sum);
1986     }
1987 
1988     @Test
1989     @IR(failOn = {ALLOC_G, STORE})
1990     public int test69(MyValue1[] array) {
1991         MyValue1 result = MyValue1.createDefaultInline();
1992         for (int i = 0; i < array.length; ++i) {
1993             result = (MyValue1)test69_sum(result, array[i]);
1994         }
1995         return result.x;
1996     }
1997 
1998     @Run(test = "test69")
1999     public void test69_verifier() {
2000         int result = test69(testValue1Array);
2001         Asserts.assertEQ(result, rI * testValue1Array.length);
2002     }
2003 
2004     // Same as test69 but with an Interface
2005     @ForceInline
2006     public MyInterface test70Interface_sum(MyInterface a, MyInterface b) {
2007         int sum = ((MyValue1)a).x + ((MyValue1)b).x;
2008         return MyValue1.setX(((MyValue1)a), sum);
2009     }
2010 
2011     @Test
2012     @IR(failOn = {ALLOC_G, STORE})
2013     public int test70Interface(MyValue1[] array) {
2014         MyValue1 result = MyValue1.createDefaultInline();
2015         for (int i = 0; i < array.length; ++i) {
2016             result = (MyValue1)test70Interface_sum(result, array[i]);
2017         }
2018         return result.x;
2019     }
2020 
2021     @Run(test = "test70Interface")
2022     public void test70Interface_verifier() {
2023         int result = test70Interface(testValue1Array);
2024         Asserts.assertEQ(result, rI * testValue1Array.length);
2025     }
2026 
2027     // Same as test69 but with an Abstract
2028     @ForceInline
2029     public MyAbstract test70Abstract_sum(MyAbstract a, MyAbstract b) {
2030         int sum = ((MyValue1)a).x + ((MyValue1)b).x;
2031         return MyValue1.setX(((MyValue1)a), sum);
2032     }
2033 
2034     @Test
2035     @IR(failOn = {ALLOC_G, STORE})
2036     public int test70Abstract(MyValue1[] array) {
2037         MyValue1 result = MyValue1.createDefaultInline();
2038         for (int i = 0; i < array.length; ++i) {
2039             result = (MyValue1)test70Abstract_sum(result, array[i]);
2040         }
2041         return result.x;
2042     }
2043 
2044     @Run(test = "test70Abstract")
2045     public void test70Abstract_verifier() {
2046         int result = test70Abstract(testValue1Array);
2047         Asserts.assertEQ(result, rI * testValue1Array.length);
2048     }
2049 
2050     // Test that allocated inline type is not used in non-dominated path
2051     public MyValue1 test71_inline(Object obj) {
2052         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
2053         try {
2054             vt = (MyValue1)Objects.requireNonNull(obj);
2055             throw new RuntimeException("NullPointerException expected");
2056         } catch (NullPointerException e) {
2057             // Expected
2058         }
2059         return vt;
2060     }
2061 
2062     @Test
2063     @IR(failOn = {ALLOC})
2064     public MyValue1 test71() {
2065         return test71_inline(null);
2066     }
2067 
2068     @Run(test = "test71")
2069     public void test71_verifier() {
2070         MyValue1 vt = test71();
2071         Asserts.assertEquals(vt.hash(), hash());
2072     }
2073 
2074     // Test calling a method on an uninitialized inline type
2075     @LooselyConsistentValue
2076     value class Test72Value {
2077         int x = 0;
2078 
2079         public int get() {
2080             return x;
2081         }
2082     }
2083 
2084     // Make sure Test72Value is loaded but not initialized
2085     public void unused(Test72Value vt) { }
2086 
2087     @Test
2088     @IR(failOn = {ALLOC_G})
2089     public int test72() {
2090         Test72Value vt = new Test72Value();
2091         return vt.get();
2092     }
2093 
2094     @Run(test = "test72")
2095     @Warmup(0)
2096     public void test72_verifier() {
2097         int result = test72();
2098         Asserts.assertEquals(result, 0);
2099     }
2100 
2101     // Tests for loading/storing unkown values
2102     @Test
2103     public Object test73(Object[] va) {
2104         return va[0];
2105     }
2106 
2107     @Run(test = "test73")
2108     public void test73_verifier() {
2109         MyValue1 vt = (MyValue1)test73(testValue1Array);
2110         Asserts.assertEquals(testValue1Array[0].hash(), vt.hash());
2111     }
2112 
2113     @Test
2114     public void test74(Object[] va, Object vt) {
2115         va[0] = vt;
2116     }
2117 
2118     @Run(test = "test74")
2119     public void test74_verifier() {
2120         MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT);
2121         test74(va, testValue1);
2122         Asserts.assertEquals(va[0].hash(), testValue1.hash());
2123     }
2124 
2125     // Verify that mixing instances and arrays with the clone api
2126     // doesn't break anything
2127     @Test
2128     @IR(failOn = {ALLOC_G})
2129     public Object test75(Object o) {
2130         MyValue1[] va = (MyValue1[])ValueClass.newNullRestrictedNonAtomicArray(MyValue1.class, 1, MyValue1.DEFAULT);
2131         Object[] next = va;
2132         Object[] arr = va;
2133         for (int i = 0; i < 10; i++) {
2134             arr = next;
2135             next = new NonValueClass[1];
2136         }
2137         return arr[0];
2138     }
2139 
2140     @Run(test = "test75")
2141     public void test75_verifier() {
2142         test75(42);
2143     }
2144 
2145     // Casting an NonValueClass to a inline type should throw a ClassCastException
2146     @ForceInline
2147     public MyValue1 test77_helper(Object o) {
2148         return (MyValue1)o;
2149     }
2150 
2151     @Test
2152     @IR(failOn = {ALLOC_G})
2153     public MyValue1 test77(NonValueClass obj) throws Throwable {
2154         return test77_helper(obj);
2155     }
2156 
2157     @Run(test = "test77")
2158     public void test77_verifier() throws Throwable {
2159         try {
2160             test77(new NonValueClass(42));
2161             throw new RuntimeException("ClassCastException expected");
2162         } catch (ClassCastException e) {
2163             // Expected
2164         } catch (Exception e) {
2165             throw new RuntimeException("test77 failed: unexpected exception", e);
2166         }
2167     }
2168 
2169     // Casting a null NonValueClass to a nullable inline type should not throw
2170     @ForceInline
2171     public MyValue1 test78_helper(Object o) {
2172         return (MyValue1)o;
2173     }
2174 
2175     @Test
2176     @IR(failOn = {ALLOC_G})
2177     public MyValue1 test78(NonValueClass obj) throws Throwable {
2178         return test78_helper(obj);
2179     }
2180 
2181     @Run(test = "test78")
2182     public void test78_verifier() throws Throwable {
2183         try {
2184             test78(null); // Should not throw
2185         } catch (Exception e) {
2186             throw new RuntimeException("test78 failed: unexpected exception", e);
2187         }
2188     }
2189 
2190     // Casting an NonValueClass to a nullable inline type should throw a ClassCastException
2191     @ForceInline
2192     public MyValue1 test79_helper(Object o) {
2193         return (MyValue1)o;
2194     }
2195 
2196     @Test
2197     @IR(failOn = {ALLOC_G})
2198     public MyValue1 test79(NonValueClass obj) throws Throwable {
2199         return test79_helper(obj);
2200     }
2201 
2202     @Run(test = "test79")
2203     public void test79_verifier() throws Throwable {
2204         try {
2205             test79(new NonValueClass(42));
2206             throw new RuntimeException("ClassCastException expected");
2207         } catch (ClassCastException e) {
2208             // Expected
2209         } catch (Exception e) {
2210             throw new RuntimeException("test79 failed: unexpected exception", e);
2211         }
2212     }
2213 
2214     // Test flattened field with non-flattenend (but flattenable) inline type field
2215     @LooselyConsistentValue
2216     static value class Small {
2217         int i;
2218         @Strict
2219         @NullRestricted
2220         Big big; // Too big to be flattened
2221 
2222         private Small() {
2223             i = rI;
2224             big = new Big();
2225         }
2226 
2227         private Small(int i, Big big) {
2228             this.i = i;
2229             this.big = big;
2230         }
2231     }
2232 
2233     @LooselyConsistentValue
2234     static value class Big {
2235         long l0,l1,l2,l3,l4,l5,l6,l7,l8,l9;
2236         long l10,l11,l12,l13,l14,l15,l16,l17,l18,l19;
2237         long l20,l21,l22,l23,l24,l25,l26,l27,l28,l29;
2238 
2239         private Big() {
2240             l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = rL;
2241             l10 = l11 = l12 = l13 = l14 = l15 = l16 = l17 = l18 = l19 = rL+1;
2242             l20 = l21 = l22 = l23 = l24 = l25 = l26 = l27 = l28 = l29 = rL+2;
2243         }
2244 
2245         private Big(long l) {
2246             l0 = l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = l10 =
2247             l11 = l12 = l13 = l14 = l15 = l16 = l17 = l18 = l19 = l20 =
2248             l21 = l22 = l23 = l24 = l25 = l26 = l27 = l28 = l29 = 0;
2249         }
2250     }
2251 
2252     @Strict
2253     @NullRestricted
2254     Small small = new Small();
2255     @Strict
2256     @NullRestricted
2257     Small smallDefault = new Small(0, new Big(0));
2258     @Strict
2259     @NullRestricted
2260     Big big = new Big();
2261     @Strict
2262     @NullRestricted
2263     Big bigDefault = new Big(0);
2264 
2265     @Test
2266     public long test80() {
2267         return small.i + small.big.l0 + smallDefault.i + smallDefault.big.l29 + big.l0 + bigDefault.l29;
2268     }
2269 
2270     @Run(test = "test80")
2271     public void test80_verifier() throws Throwable {
2272         long result = test80();
2273         Asserts.assertEQ(result, rI + 2*rL);
2274     }
2275 
2276     // Test scalarization with exceptional control flow
2277     public int test81Callee(MyValue1 vt)  {
2278         return vt.x;
2279     }
2280 
2281     @Test
2282     @IR(failOn = {ALLOC_G, LOAD, STORE})
2283     public int test81()  {
2284         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
2285         int result = 0;
2286         for (int i = 0; i < 10; i++) {
2287             try {
2288                 result += test81Callee(vt);
2289             } catch (NullPointerException npe) {
2290                 result += rI;
2291             }
2292         }
2293         return result;
2294     }
2295 
2296     @Run(test = "test81")
2297     public void test81_verifier() {
2298         int result = test81();
2299         Asserts.assertEQ(result, 10*rI);
2300     }
2301 
2302     // Test check for null free array when storing to inline tpye array
2303     @Test
2304     public void test82(Object[] dst, Object v) {
2305         dst[0] = v;
2306     }
2307 
2308     @Run(test = "test82")
2309     public void test82_verifier(RunInfo info) {
2310         MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT);
2311         test82(dst, testValue2);
2312         if (!info.isWarmUp()) {
2313             try {
2314                 test82(dst, null);
2315                 throw new RuntimeException("No ArrayStoreException thrown");
2316             } catch (NullPointerException e) {
2317                 // Expected
2318             }
2319         }
2320     }
2321 
2322     @Test
2323     @IR(failOn = {ALLOC_G})
2324     public void test83(Object[] dst, Object v, boolean flag) {
2325         if (dst == null) { // null check
2326         }
2327         if (flag) {
2328             if (dst.getClass() == MyValue1[].class) { // trigger split if
2329             }
2330         } else {
2331             dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT); // constant null free property
2332         }
2333         dst[0] = v;
2334     }
2335 
2336     @Run(test = "test83")
2337     @Warmup(10000)
2338     public void test83_verifier(RunInfo info) {
2339         MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT);
2340         test83(dst, testValue2, false);
2341         test83(dst, testValue2, true);
2342         if (!info.isWarmUp()) {
2343             try {
2344                 test83(dst, null, true);
2345                 throw new RuntimeException("No ArrayStoreException thrown");
2346             } catch (NullPointerException e) {
2347                 // Expected
2348             }
2349         }
2350     }
2351 
2352     private void rerun_and_recompile_for(Method m, int num, Runnable test) {
2353         for (int i = 1; i < num; i++) {
2354             test.run();
2355 
2356             if (!TestFramework.isCompiled(m)) {
2357                 TestFramework.compile(m, CompLevel.C2);
2358             }
2359         }
2360     }
2361 
2362     // Tests for the Loop Unswitching optimization
2363     // Should make 2 copies of the loop, one for non flattened arrays, one for other cases.
2364     @Test
2365     @IR(applyIf = {"UseArrayFlattening", "true"},
2366         counts = {COUNTEDLOOP_MAIN, "= 2"})
2367     @IR(applyIf = {"UseArrayFlattening", "false"},
2368         counts = {COUNTEDLOOP_MAIN, "= 1"})
2369     public void test84(Object[] src, Object[] dst) {
2370         for (int i = 0; i < src.length; i++) {
2371             dst[i] = src[i];
2372         }
2373     }
2374 
2375     @Run(test = "test84")
2376     @Warmup(0)
2377     public void test84_verifier(RunInfo info) {
2378         MyValue2[] src = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2379         Arrays.fill(src, testValue2);
2380         MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2381         rerun_and_recompile_for(info.getTest(), 10,
2382                                 () ->  { test84(src, dst);
2383                                          Asserts.assertTrue(Arrays.equals(src, dst)); });
2384     }
2385 
2386     @Test
2387     @IR(applyIf = {"UseArrayFlattening", "true"},
2388         counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 1"})
2389     public void test85(Object[] src, Object[] dst) {
2390         for (int i = 0; i < src.length; i++) {
2391             dst[i] = src[i];
2392         }
2393     }
2394 
2395     @Run(test = "test85")
2396     @Warmup(0)
2397     public void test85_verifier(RunInfo info) {
2398         Object[] src = new Object[100];
2399         Arrays.fill(src, new Object());
2400         src[0] = null;
2401         Object[] dst = new Object[100];
2402         rerun_and_recompile_for(info.getTest(), 10,
2403                                 () -> { test85(src, dst);
2404                                         Asserts.assertTrue(Arrays.equals(src, dst)); });
2405     }
2406 
2407     @Test
2408     @IR(applyIf = {"UseArrayFlattening", "true"},
2409         counts = {COUNTEDLOOP, "= 2"})
2410     public void test86(Object[] src, Object[] dst) {
2411         for (int i = 0; i < src.length; i++) {
2412             dst[i] = src[i];
2413         }
2414     }
2415 
2416     @Run(test = "test86")
2417     @Warmup(0)
2418     public void test86_verifier(RunInfo info) {
2419         MyValue2[] src = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2420         Arrays.fill(src, testValue2);
2421         Object[] dst = new Object[100];
2422         rerun_and_recompile_for(info.getTest(), 10,
2423                                 () -> { test86(src, dst);
2424                                         Asserts.assertTrue(Arrays.equals(src, dst)); });
2425     }
2426 
2427     @Test
2428     @IR(applyIf = {"UseArrayFlattening", "true"},
2429         counts = {COUNTEDLOOP_MAIN, "= 2"})
2430     @IR(applyIf = {"UseArrayFlattening", "false"},
2431         counts = {COUNTEDLOOP_MAIN, "= 1"})
2432     public void test87(Object[] src, Object[] dst) {
2433         for (int i = 0; i < src.length; i++) {
2434             dst[i] = src[i];
2435         }
2436     }
2437 
2438     @Run(test = "test87")
2439     @Warmup(0)
2440     public void test87_verifier(RunInfo info) {
2441         Object[] src = new Object[100];
2442         Arrays.fill(src, testValue2);
2443         MyValue2[] dst = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2444 
2445         rerun_and_recompile_for(info.getTest(), 10,
2446                                 () -> { test87(src, dst);
2447                                         Asserts.assertTrue(Arrays.equals(src, dst)); });
2448     }
2449 
2450     @Test
2451     @IR(applyIf = {"UseArrayFlattening", "true"},
2452         counts = {COUNTEDLOOP_MAIN, "= 2"})
2453     @IR(applyIf = {"UseArrayFlattening", "false"},
2454         counts = {COUNTEDLOOP_MAIN, "= 0"})
2455     public void test88(Object[] src1, Object[] dst1, Object[] src2, Object[] dst2) {
2456         for (int i = 0; i < src1.length; i++) {
2457             dst1[i] = src1[i];
2458             dst2[i] = src2[i];
2459         }
2460     }
2461 
2462     @Run(test = "test88")
2463     @Warmup(0)
2464     public void test88_verifier(RunInfo info) {
2465         MyValue2[] src1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2466         Arrays.fill(src1, testValue2);
2467         MyValue2[] dst1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
2468         Object[] src2 = new Object[100];
2469         Arrays.fill(src2, new Object());
2470         Object[] dst2 = new Object[100];
2471 
2472         rerun_and_recompile_for(info.getTest(), 10,
2473                                 () -> { test88(src1, dst1, src2, dst2);
2474                                         Asserts.assertTrue(Arrays.equals(src1, dst1));
2475                                         Asserts.assertTrue(Arrays.equals(src2, dst2)); });
2476     }
2477 
2478     @Test
2479     public boolean test89(Object obj) {
2480         return obj.getClass() == NonValueClass.class;
2481     }
2482 
2483     @Run(test = "test89")
2484     public void test89_verifier() {
2485         Asserts.assertTrue(test89(new NonValueClass(42)));
2486         Asserts.assertFalse(test89(new Object()));
2487     }
2488 
2489     @Test
2490     public NonValueClass test90(Object obj) {
2491         return (NonValueClass)obj;
2492     }
2493 
2494     @Run(test = "test90")
2495     public void test90_verifier() {
2496         test90(new NonValueClass(42));
2497         try {
2498             test90(new Object());
2499             throw new RuntimeException("ClassCastException expected");
2500         } catch (ClassCastException e) {
2501             // Expected
2502         }
2503     }
2504 
2505     @Test
2506     public boolean test91(Object obj) {
2507         return obj.getClass() == MyValue2[].class;
2508     }
2509 
2510     @Run(test = "test91")
2511     public void test91_verifier() {
2512         Asserts.assertFalse(test91((MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 1, MyValue2.DEFAULT)));
2513         Asserts.assertTrue(test91(new MyValue2[1]));
2514         Asserts.assertFalse(test91(new Object()));
2515     }
2516 
2517     @LooselyConsistentValue
2518     static value class Test92Value {
2519         int field;
2520 
2521         public Test92Value() {
2522             field = 0x42;
2523         }
2524     }
2525 
2526     @Test
2527     // TODO 8355382 The optimization only applies to null-free, flat arrays
2528     @IR(applyIfAnd = {"UseArrayFlattening", "true", "UseNullableValueFlattening", "false"},
2529         counts = {CLASS_CHECK_TRAP, "= 2"},
2530         failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR})
2531     public Object test92(Object[] array) {
2532         // Dummy loops to ensure we run enough passes of split if
2533         for (int i = 0; i < 2; i++) {
2534             for (int j = 0; j < 2; j++) {
2535                 for (int k = 0; k < 2; k++) {
2536                 }
2537             }
2538         }
2539         return (NonValueClass)array[0];
2540     }
2541 
2542     @Run(test = "test92")
2543     @Warmup(10000)
2544     public void test92_verifier() {
2545         Object[] array = new Object[1];
2546         Object obj = new NonValueClass(rI);
2547         array[0] = obj;
2548         Object result = test92(array);
2549         Asserts.assertEquals(result, obj);
2550     }
2551 
2552     // If the class check succeeds, the flattened array check that
2553     // precedes will never succeed and the flat array branch should
2554     // trigger an uncommon trap.
2555     @Test
2556     public Object test93(Object[] array) {
2557         for (int i = 0; i < 2; i++) {
2558             for (int j = 0; j < 2; j++) {
2559             }
2560         }
2561 
2562         return (NonValueClass)array[0];
2563     }
2564 
2565     @Run(test = "test93")
2566     @Warmup(10000)
2567     public void test93_verifier(RunInfo info) {
2568         if (info.isWarmUp()) {
2569             Object[] array = new Object[1];
2570             array[0] = new NonValueClass(42);
2571             Object result = test93(array);
2572             Asserts.assertEquals(((NonValueClass)result).x, 42);
2573         } else {
2574             Object[] array = (Test92Value[])ValueClass.newNullRestrictedNonAtomicArray(Test92Value.class, 1, new Test92Value());
2575             Method m = info.getTest();
2576             int extra = 3;
2577             for (int j = 0; j < extra; j++) {
2578                 for (int i = 0; i < 10; i++) {
2579                     try {
2580                         test93(array);
2581                     } catch (ClassCastException cce) {
2582                     }
2583                 }
2584                 boolean compiled = TestFramework.isCompiled(m);
2585                 boolean compilationSkipped = info.isCompilationSkipped();
2586                 Asserts.assertTrue(compilationSkipped || compiled || (j != extra-1));
2587                 if (!compilationSkipped && !compiled) {
2588                     TestFramework.compile(m, CompLevel.ANY);
2589                 }
2590             }
2591         }
2592     }
2593 
2594     @Test
2595     // TODO 8355382 The optimization only applies to null-free, flat arrays
2596     @IR(applyIfAnd = {"UseArrayFlattening", "true", "UseNullableValueFlattening", "false"},
2597         counts = {CLASS_CHECK_TRAP, "= 2", LOOP, "= 1"},
2598         failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR})
2599     public int test94(Object[] array) {
2600         int res = 0;
2601         for (int i = 1; i < 4; i *= 2) {
2602             Object v = array[i];
2603             res += ((NonValueClass)v).x;
2604         }
2605         return res;
2606     }
2607 
2608     @Run(test = "test94")
2609     @Warmup(10000)
2610     public void test94_verifier() {
2611         Object[] array = new Object[4];
2612         Object obj = new NonValueClass(rI);
2613         array[0] = obj;
2614         array[1] = obj;
2615         array[2] = obj;
2616         array[3] = obj;
2617         int result = test94(array);
2618         Asserts.assertEquals(result, rI * 2);
2619     }
2620 
2621     @Test
2622     public boolean test95(Object o1, Object o2) {
2623         return o1 == o2;
2624     }
2625 
2626     @Run(test = "test95")
2627     @Warmup(10000)
2628     public void test95_verifier() {
2629         Object o1 = new Object();
2630         Object o2 = new Object();
2631         Asserts.assertTrue(test95(o1, o1));
2632         Asserts.assertTrue(test95(null, null));
2633         Asserts.assertFalse(test95(o1, null));
2634         Asserts.assertFalse(test95(o1, o2));
2635     }
2636 
2637     @Test
2638     public boolean test96(Object o1, Object o2) {
2639         return o1 == o2;
2640     }
2641 
2642     @Run(test = "test96")
2643     @Warmup(10000)
2644     public void test96_verifier(RunInfo info) {
2645         Object o1 = new Object();
2646         Object o2 = new Object();
2647         Asserts.assertTrue(test96(o1, o1));
2648         Asserts.assertFalse(test96(o1, o2));
2649         if (!info.isWarmUp()) {
2650             Asserts.assertTrue(test96(null, null));
2651             Asserts.assertFalse(test96(o1, null));
2652         }
2653     }
2654 
2655     // Abstract class tests
2656 
2657     @DontInline
2658     public MyAbstract test97_dontinline1(MyAbstract o) {
2659         return o;
2660     }
2661 
2662     @DontInline
2663     public MyValue1 test97_dontinline2(MyAbstract o) {
2664         return (MyValue1)o;
2665     }
2666 
2667     @ForceInline
2668     public MyAbstract test97_inline1(MyAbstract o) {
2669         return o;
2670     }
2671 
2672     @ForceInline
2673     public MyValue1 test97_inline2(MyAbstract o) {
2674         return (MyValue1)o;
2675     }
2676 
2677     @Test
2678     public MyValue1 test97() {
2679         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
2680         vt = (MyValue1)test97_dontinline1(vt);
2681         vt =           test97_dontinline2(vt);
2682         vt = (MyValue1)test97_inline1(vt);
2683         vt =           test97_inline2(vt);
2684         return vt;
2685     }
2686 
2687     @Run(test = "test97")
2688     public void test97_verifier() {
2689         Asserts.assertEQ(test97().hash(), hash());
2690     }
2691 
2692     // Test storing/loading inline types to/from abstract and inline type fields
2693     MyAbstract abstractField1 = null;
2694     MyAbstract abstractField2 = null;
2695     MyAbstract abstractField3 = null;
2696     MyAbstract abstractField4 = null;
2697     MyAbstract abstractField5 = null;
2698     MyAbstract abstractField6 = null;
2699 
2700     @DontInline
2701     public MyAbstract readValueField5AsAbstract() {
2702         return (MyAbstract)valueField5;
2703     }
2704 
2705     @DontInline
2706     public MyAbstract readStaticValueField4AsAbstract() {
2707         return (MyAbstract)staticValueField4;
2708     }
2709 
2710     @Test
2711     public long test98(MyValue1 vt1, MyAbstract vt2) {
2712         abstractField1 = vt1;
2713         abstractField2 = (MyValue1)vt2;
2714         abstractField3 = MyValue1.createWithFieldsInline(rI, rL);
2715         abstractField4 = MyValue1.createWithFieldsDontInline(rI, rL);
2716         abstractField5 = valueField1;
2717         abstractField6 = valueField3;
2718         valueField1 = (MyValue1)abstractField1;
2719         valueField2 = (MyValue1)vt2;
2720         valueField3 = (MyValue1)vt2;
2721         staticValueField1 = (MyValue1)abstractField1;
2722         staticValueField2 = (MyValue1)vt1;
2723         // Don't inline these methods because reading NULL will trigger a deoptimization
2724         if (readValueField5AsAbstract() != null || readStaticValueField4AsAbstract() != null) {
2725             throw new RuntimeException("Should be null");
2726         }
2727         return ((MyValue1)abstractField1).hash() + ((MyValue1)abstractField2).hash() +
2728                ((MyValue1)abstractField3).hash() + ((MyValue1)abstractField4).hash() +
2729                ((MyValue1)abstractField5).hash() + ((MyValue1)abstractField6).hash() +
2730                 valueField1.hash() + valueField2.hash() + valueField3.hash() + valueField4.hashPrimitive() +
2731                 staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
2732     }
2733 
2734     @Run(test = "test98")
2735     public void test98_verifier() {
2736         MyValue1 vt = testValue1;
2737         MyValue1 def = MyValue1.createDefaultDontInline();
2738         long result = test98(vt, vt);
2739         Asserts.assertEQ(result, 11*vt.hash() + 2*def.hashPrimitive());
2740     }
2741 
2742     value class MyObject2 extends MyAbstract {
2743         public int x;
2744 
2745         public MyObject2(int x) {
2746             this.x = x;
2747         }
2748 
2749         @ForceInline
2750         public long hash() {
2751             return x;
2752         }
2753     }
2754 
2755     // Test merging inline types and abstract classes
2756     @Test
2757     public MyAbstract test99(int state) {
2758         MyAbstract res = null;
2759         if (state == 0) {
2760             res = new MyObject2(rI);
2761         } else if (state == 1) {
2762             res = MyValue1.createWithFieldsInline(rI, rL);
2763         } else if (state == 2) {
2764             res = MyValue1.createWithFieldsDontInline(rI, rL);
2765         } else if (state == 3) {
2766             res = (MyValue1)objectField1;
2767         } else if (state == 4) {
2768             res = valueField1;
2769         } else if (state == 5) {
2770             res = null;
2771         }
2772         return res;
2773     }
2774 
2775     @Run(test = "test99")
2776     public void test99_verifier() {
2777         objectField1 = valueField1;
2778         MyAbstract result = null;
2779         result = test99(0);
2780         Asserts.assertEQ(((MyObject2)result).x, rI);
2781         result = test99(1);
2782         Asserts.assertEQ(((MyValue1)result).hash(), hash());
2783         result = test99(2);
2784         Asserts.assertEQ(((MyValue1)result).hash(), hash());
2785         result = test99(3);
2786         Asserts.assertEQ(((MyValue1)result).hash(), hash());
2787         result = test99(4);
2788         Asserts.assertEQ(((MyValue1)result).hash(), hash());
2789         result = test99(5);
2790         Asserts.assertEQ(result, null);
2791     }
2792 
2793     // Test merging inline types and abstract classes in loops
2794     @Test
2795     public MyAbstract test100(int iters) {
2796         MyAbstract res = new MyObject2(rI);
2797         for (int i = 0; i < iters; ++i) {
2798             if (res instanceof MyObject2) {
2799                 res = MyValue1.createWithFieldsInline(rI, rL);
2800             } else {
2801                 res = MyValue1.createWithFieldsInline(((MyValue1)res).x + 1, rL);
2802             }
2803         }
2804         return res;
2805     }
2806 
2807     @Run(test = "test100")
2808     public void test100_verifier() {
2809         MyObject2 result1 = (MyObject2)test100(0);
2810         Asserts.assertEQ(result1.x, rI);
2811         int iters = (Math.abs(rI) % 10) + 1;
2812         MyValue1 result2 = (MyValue1)test100(iters);
2813         MyValue1 vt = MyValue1.createWithFieldsInline(rI + iters - 1, rL);
2814         Asserts.assertEQ(result2.hash(), vt.hash());
2815     }
2816 
2817     // Test inline types in abstract class variables that are live at safepoint
2818     @Test
2819     @IR(failOn = {ALLOC, STORE, LOOP})
2820     public long test101(MyValue1 arg, boolean deopt, Method m) {
2821         MyAbstract vt1 = MyValue1.createWithFieldsInline(rI, rL);
2822         MyAbstract vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
2823         MyAbstract vt3 = arg;
2824         MyAbstract vt4 = valueField1;
2825         if (deopt) {
2826             // uncommon trap
2827             TestFramework.deoptimize(m);
2828         }
2829         return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
2830                ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
2831     }
2832 
2833     @Run(test = "test101")
2834     public void test101_verifier(RunInfo info) {
2835         long result = test101(valueField1, !info.isWarmUp(), info.getTest());
2836         Asserts.assertEQ(result, 4*hash());
2837     }
2838 
2839     // Test comparing inline types with abstract classes
2840     @Test
2841     public boolean test102(Object arg) {
2842         MyAbstract vt = MyValue1.createWithFieldsInline(rI, rL);
2843         if (vt == arg || vt == (MyAbstract)valueField1 || vt == abstractField1 || vt == null ||
2844             arg == vt || (MyAbstract)valueField1 == vt || abstractField1 == vt || null == vt) {
2845             return true;
2846         }
2847         return false;
2848     }
2849 
2850     @Run(test = "test102")
2851     public void test102_verifier() {
2852         boolean result = test102(null);
2853         Asserts.assertFalse(result);
2854     }
2855 
2856     // An abstract class with a non-static field can never be implemented by an inline type
2857     abstract class NoValueImplementors1 {
2858         int field = 42;
2859     }
2860 
2861     class MyObject3 extends NoValueImplementors1 {
2862 
2863     }
2864 
2865     class MyObject4 extends NoValueImplementors1 {
2866 
2867     }
2868 
2869     // Loading from an abstract class array does not require a flatness check if the abstract class has a non-static field
2870     @Test
2871     @IR(failOn = {ALLOC_G, MEMBAR, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
2872     public NoValueImplementors1 test103(NoValueImplementors1[] array, int i) {
2873         return array[i];
2874     }
2875 
2876     @Run(test = "test103")
2877     public void test103_verifier() {
2878         NoValueImplementors1[] array1 = new NoValueImplementors1[3];
2879         MyObject3[] array2 = new MyObject3[3];
2880         MyObject4[] array3 = new MyObject4[3];
2881         NoValueImplementors1 result = test103(array1, 0);
2882         Asserts.assertEquals(result, array1[0]);
2883 
2884         result = test103(array2, 1);
2885         Asserts.assertEquals(result, array1[1]);
2886 
2887         result = test103(array3, 2);
2888         Asserts.assertEquals(result, array1[2]);
2889     }
2890 
2891     // Storing to an abstract class array does not require a flatness/null check if the abstract class has a non-static field
2892     @Test
2893     @IR(failOn = {ALLOC_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
2894     public NoValueImplementors1 test104(NoValueImplementors1[] array, NoValueImplementors1 v, MyObject3 o, int i) {
2895         array[0] = v;
2896         array[1] = array[0];
2897         array[2] = o;
2898         return array[i];
2899     }
2900 
2901     @Run(test = "test104")
2902     public void test104_verifier() {
2903         MyObject4 v = new MyObject4();
2904         MyObject3 o = new MyObject3();
2905         NoValueImplementors1[] array1 = new NoValueImplementors1[3];
2906         MyObject3[] array2 = new MyObject3[3];
2907         MyObject4[] array3 = new MyObject4[3];
2908         NoValueImplementors1 result = test104(array1, v, o, 0);
2909         Asserts.assertEquals(array1[0], v);
2910         Asserts.assertEquals(array1[1], v);
2911         Asserts.assertEquals(array1[2], o);
2912         Asserts.assertEquals(result, v);
2913 
2914         result = test104(array2, o, o, 1);
2915         Asserts.assertEquals(array2[0], o);
2916         Asserts.assertEquals(array2[1], o);
2917         Asserts.assertEquals(array2[2], o);
2918         Asserts.assertEquals(result, o);
2919 
2920         result = test104(array3, v, null, 1);
2921         Asserts.assertEquals(array3[0], v);
2922         Asserts.assertEquals(array3[1], v);
2923         Asserts.assertEquals(array3[2], null);
2924         Asserts.assertEquals(result, v);
2925     }
2926 
2927     // An abstract class with a single, non-inline implementor
2928     abstract class NoValueImplementors2 {
2929 
2930     }
2931 
2932     class MyObject5 extends NoValueImplementors2 {
2933 
2934     }
2935 
2936     // Loading from an abstract class array does not require a flatness check if the abstract class has no inline implementor
2937     @Test
2938     @IR(failOn = {ALLOC_G, MEMBAR, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
2939     public NoValueImplementors2 test105(NoValueImplementors2[] array, int i) {
2940         return array[i];
2941     }
2942 
2943     @Run(test = "test105")
2944     public void test105_verifier() {
2945         NoValueImplementors2[] array1 = new NoValueImplementors2[3];
2946         MyObject5[] array2 = new MyObject5[3];
2947         NoValueImplementors2 result = test105(array1, 0);
2948         Asserts.assertEquals(result, array1[0]);
2949 
2950         result = test105(array2, 1);
2951         Asserts.assertEquals(result, array1[1]);
2952     }
2953 
2954     // Storing to an abstract class array does not require a flatness/null check if the abstract class has no inline implementor
2955     @Test
2956     @IR(failOn = {ALLOC_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
2957     public NoValueImplementors2 test106(NoValueImplementors2[] array, NoValueImplementors2 v, MyObject5 o, int i) {
2958         array[0] = v;
2959         array[1] = array[0];
2960         array[2] = o;
2961         return array[i];
2962     }
2963 
2964     @Run(test = "test106")
2965     public void test106_verifier() {
2966         MyObject5 v = new MyObject5();
2967         NoValueImplementors2[] array1 = new NoValueImplementors2[3];
2968         MyObject5[] array2 = new MyObject5[3];
2969         NoValueImplementors2 result = test106(array1, v, null, 0);
2970         Asserts.assertEquals(array1[0], v);
2971         Asserts.assertEquals(array1[1], v);
2972         Asserts.assertEquals(array1[2], null);
2973         Asserts.assertEquals(result, v);
2974 
2975         result = test106(array2, v, v, 1);
2976         Asserts.assertEquals(array2[0], v);
2977         Asserts.assertEquals(array2[1], v);
2978         Asserts.assertEquals(array2[2], v);
2979         Asserts.assertEquals(result, v);
2980     }
2981 
2982     // More tests for the Loop Unswitching optimization (similar to test84 and following)
2983     Object oFld1, oFld2;
2984 
2985     @Test
2986     @IR(applyIf = {"UseArrayFlattening", "true"},
2987         failOn = {STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
2988         counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 2"},
2989          // Match on CCP since we are removing one of the unswitched loop versions later due to being empty
2990         phase = {CompilePhase.CCP1})
2991     public void test107(Object[] src1, Object[] src2) {
2992         for (int i = 0; i < src1.length; i++) {
2993             oFld1 = src1[i];
2994             oFld2 = src2[i];
2995         }
2996     }
2997 
2998     @Run(test = "test107")
2999     @Warmup(0)
3000     public void test107_verifier(RunInfo info) {
3001         MyValue2[] src1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
3002         Arrays.fill(src1, testValue2);
3003         Object[] src2 = new Object[100];
3004         Object obj = new Object();
3005         Arrays.fill(src2, obj);
3006         rerun_and_recompile_for(info.getTest(), 10,
3007                                 () -> { test107(src1, src2);
3008                                         Asserts.assertEquals(oFld1, testValue2);
3009                                         Asserts.assertEquals(oFld2, obj);
3010                                         test107(src2, src1);
3011                                         Asserts.assertEquals(oFld1, obj);
3012                                         Asserts.assertEquals(oFld2, testValue2);  });
3013     }
3014 
3015     @Test
3016     @IR(applyIf = {"UseArrayFlattening", "true"},
3017         failOn = {LOAD_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
3018         counts = {COUNTEDLOOP, "= 4", STORE_UNKNOWN_INLINE, "= 9"})
3019     public void test108(Object[] dst1, Object[] dst2, Object o1, Object o2) {
3020         for (int i = 0; i < dst1.length; i++) {
3021             dst1[i] = o1;
3022             dst2[i] = o2;
3023         }
3024     }
3025 
3026     @Run(test = "test108")
3027     @Warmup(0)
3028     public void test108_verifier(RunInfo info) {
3029         MyValue2[] dst1 = (MyValue2[])ValueClass.newNullRestrictedNonAtomicArray(MyValue2.class, 100, MyValue2.DEFAULT);
3030         Object[] dst2 = new Object[100];
3031         Object o1 = new Object();
3032         rerun_and_recompile_for(info.getTest(), 10,
3033                                 () -> { test108(dst1, dst2, testValue2, o1);
3034                                         for (int i = 0; i < dst1.length; i++) {
3035                                             Asserts.assertEquals(dst1[i], testValue2);
3036                                             Asserts.assertEquals(dst2[i], o1);
3037                                         }
3038                                         test108(dst2, dst1, o1, testValue2);
3039                                         for (int i = 0; i < dst1.length; i++) {
3040                                             Asserts.assertEquals(dst1[i], testValue2);
3041                                             Asserts.assertEquals(dst2[i], o1);
3042                                         } });
3043     }
3044 
3045     // Escape analysis tests
3046 
3047     static interface WrapperInterface {
3048         long value();
3049 
3050         final static WrapperInterface ZERO = new LongWrapper(0);
3051 
3052         @ForceInline
3053         static WrapperInterface wrap(long val) {
3054             return (val == 0L) ? ZERO : new LongWrapper(val);
3055         }
3056     }
3057 
3058     @ForceCompileClassInitializer
3059     @LooselyConsistentValue
3060     static value class LongWrapper implements WrapperInterface {
3061         @Strict
3062         @NullRestricted
3063         final static LongWrapper ZERO = new LongWrapper(0);
3064         private long val;
3065 
3066         @ForceInline
3067         LongWrapper(long val) {
3068             this.val = val;
3069         }
3070 
3071         @ForceInline
3072         static LongWrapper wrap(long val) {
3073             return (val == 0L) ? ZERO : new LongWrapper(val);
3074         }
3075 
3076         @ForceInline
3077         public long value() {
3078             return val;
3079         }
3080     }
3081 
3082     static class InterfaceBox {
3083         WrapperInterface content;
3084 
3085         @ForceInline
3086         InterfaceBox(WrapperInterface content) {
3087             this.content = content;
3088         }
3089 
3090         @ForceInline
3091         static InterfaceBox box_sharp(long val) {
3092             return new InterfaceBox(LongWrapper.wrap(val));
3093         }
3094 
3095         @ForceInline
3096         static InterfaceBox box(long val) {
3097             return new InterfaceBox(WrapperInterface.wrap(val));
3098         }
3099     }
3100 
3101     static class ObjectBox {
3102         Object content;
3103 
3104         @ForceInline
3105         ObjectBox(Object content) {
3106             this.content = content;
3107         }
3108 
3109         @ForceInline
3110         static ObjectBox box_sharp(long val) {
3111             return new ObjectBox(LongWrapper.wrap(val));
3112         }
3113 
3114         @ForceInline
3115         static ObjectBox box(long val) {
3116             return new ObjectBox(WrapperInterface.wrap(val));
3117         }
3118     }
3119 
3120     static class RefBox {
3121         LongWrapper content;
3122 
3123         @ForceInline
3124         RefBox(LongWrapper content) {
3125             this.content = content;
3126         }
3127 
3128         @ForceInline
3129         static RefBox box_sharp(long val) {
3130             return new RefBox(LongWrapper.wrap(val));
3131         }
3132 
3133         @ForceInline
3134         static RefBox box(long val) {
3135             return new RefBox((LongWrapper)WrapperInterface.wrap(val));
3136         }
3137     }
3138 
3139     static class InlineBox {
3140         @Strict
3141         @NullRestricted
3142         LongWrapper content;
3143 
3144         @ForceInline
3145         InlineBox(long val) {
3146             this.content = LongWrapper.wrap(val);
3147         }
3148 
3149         @ForceInline
3150         static InlineBox box(long val) {
3151             return new InlineBox(val);
3152         }
3153     }
3154 
3155     static class GenericBox<T> {
3156         T content;
3157 
3158         @ForceInline
3159         static GenericBox<LongWrapper> box_sharp(long val) {
3160             GenericBox<LongWrapper> res = new GenericBox<>();
3161             res.content = LongWrapper.wrap(val);
3162             return res;
3163         }
3164 
3165         @ForceInline
3166         static GenericBox<WrapperInterface> box(long val) {
3167             GenericBox<WrapperInterface> res = new GenericBox<>();
3168             res.content = WrapperInterface.wrap(val);
3169             return res;
3170         }
3171     }
3172 
3173     long[] lArr = {0L, rL, 0L, rL, 0L, rL, 0L, rL, 0L, rL};
3174 
3175     // Test removal of allocations when inline type instance is wrapped into box object
3176     @Test
3177     @IR(failOn = {ALLOC_G, MEMBAR},
3178         counts = {PREDICATE_TRAP, "= 1"})
3179     public long test109() {
3180         long res = 0;
3181         for (int i = 0; i < lArr.length; i++) {
3182             res += InterfaceBox.box(lArr[i]).content.value();
3183         }
3184         return res;
3185     }
3186 
3187     @Run(test = "test109")
3188     @Warmup(10000) // Make sure interface calls are inlined
3189     public void test109_verifier() {
3190         long res = test109();
3191         Asserts.assertEquals(res, 5*rL);
3192     }
3193 
3194     @Test
3195     @IR(failOn = {ALLOC_G, MEMBAR},
3196         counts = {PREDICATE_TRAP, "= 1"})
3197     @IR(failOn = {ALLOC_G, MEMBAR})
3198     public long test109_sharp() {
3199         long res = 0;
3200         for (int i = 0; i < lArr.length; i++) {
3201             res += InterfaceBox.box_sharp(lArr[i]).content.value();
3202         }
3203         return res;
3204     }
3205 
3206     @Run(test = "test109_sharp")
3207     @Warmup(10000) // Make sure interface calls are inlined
3208     public void test109_sharp_verifier() {
3209         long res = test109_sharp();
3210         Asserts.assertEquals(res, 5*rL);
3211     }
3212 
3213     // Same as test109 but with ObjectBox
3214     @Test
3215     @IR(failOn = {ALLOC_G, MEMBAR},
3216         counts = {PREDICATE_TRAP, "= 1"})
3217     public long test110() {
3218         long res = 0;
3219         for (int i = 0; i < lArr.length; i++) {
3220             res += ((WrapperInterface)ObjectBox.box(lArr[i]).content).value();
3221         }
3222         return res;
3223     }
3224 
3225     @Run(test = "test110")
3226     @Warmup(10000) // Make sure interface calls are inlined
3227     public void test110_verifier() {
3228         long res = test110();
3229         Asserts.assertEquals(res, 5*rL);
3230     }
3231 
3232     @Test
3233     @IR(failOn = {ALLOC_G, MEMBAR},
3234         counts = {PREDICATE_TRAP, "= 1"})
3235     @IR(failOn = {ALLOC_G, MEMBAR})
3236     public long test110_sharp() {
3237         long res = 0;
3238         for (int i = 0; i < lArr.length; i++) {
3239             res += ((WrapperInterface)ObjectBox.box_sharp(lArr[i]).content).value();
3240         }
3241         return res;
3242     }
3243 
3244     @Run(test = "test110_sharp")
3245     @Warmup(10000) // Make sure interface calls are inlined
3246     public void test110_sharp_verifier() {
3247         long res = test110_sharp();
3248         Asserts.assertEquals(res, 5*rL);
3249     }
3250 
3251     // Same as test109 but with RefBox
3252     @Test
3253     @IR(failOn = {ALLOC_G, MEMBAR},
3254         counts = {PREDICATE_TRAP, "= 1"})
3255     public long test111() {
3256         long res = 0;
3257         for (int i = 0; i < lArr.length; i++) {
3258             res += RefBox.box(lArr[i]).content.value();
3259         }
3260         return res;
3261     }
3262 
3263     @Run(test = "test111")
3264     public void test111_verifier() {
3265         long res = test111();
3266         Asserts.assertEquals(res, 5*rL);
3267     }
3268 
3269     @Test
3270     @IR(failOn = {ALLOC_G, MEMBAR},
3271         counts = {PREDICATE_TRAP, "= 1"})
3272     public long test111_sharp() {
3273         long res = 0;
3274         for (int i = 0; i < lArr.length; i++) {
3275             res += RefBox.box_sharp(lArr[i]).content.value();
3276         }
3277         return res;
3278     }
3279 
3280     @Run(test = "test111_sharp")
3281     public void test111_sharp_verifier() {
3282         long res = test111_sharp();
3283         Asserts.assertEquals(res, 5*rL);
3284     }
3285 
3286     // Same as test109 but with InlineBox
3287     @Test
3288     @IR(failOn = {ALLOC_G, MEMBAR},
3289         counts = {PREDICATE_TRAP, "= 1"})
3290     public long test112() {
3291         long res = 0;
3292         for (int i = 0; i < lArr.length; i++) {
3293             res += InlineBox.box(lArr[i]).content.value();
3294         }
3295         return res;
3296     }
3297 
3298     @Run(test = "test112")
3299     public void test112_verifier() {
3300         long res = test112();
3301         Asserts.assertEquals(res, 5*rL);
3302     }
3303 
3304     // Same as test109 but with GenericBox
3305     @Test
3306     @IR(failOn = {ALLOC_G, MEMBAR},
3307         counts = {PREDICATE_TRAP, "= 1"})
3308     public long test113() {
3309         long res = 0;
3310         for (int i = 0; i < lArr.length; i++) {
3311             res += GenericBox.box(lArr[i]).content.value();
3312         }
3313         return res;
3314     }
3315 
3316     @Run(test = "test113")
3317     @Warmup(10000) // Make sure interface calls are inlined
3318     public void test113_verifier() {
3319         long res = test113();
3320         Asserts.assertEquals(res, 5*rL);
3321     }
3322 
3323     @Test
3324     @IR(failOn = {ALLOC_G, MEMBAR},
3325         counts = {PREDICATE_TRAP, "= 1"})
3326     public long test113_sharp() {
3327         long res = 0;
3328         for (int i = 0; i < lArr.length; i++) {
3329             res += GenericBox.box_sharp(lArr[i]).content.value();
3330         }
3331         return res;
3332     }
3333 
3334     @Run(test = "test113_sharp")
3335     @Warmup(10000) // Make sure interface calls are inlined
3336     public void test113_sharp_verifier() {
3337         long res = test113_sharp();
3338         Asserts.assertEquals(res, 5*rL);
3339     }
3340 
3341     static interface WrapperInterface2 {
3342         public long value();
3343 
3344         static final InlineWrapper ZERO = new InlineWrapper(0);
3345 
3346         @ForceInline
3347         public static WrapperInterface2 wrap(long val) {
3348             return (val == 0) ? ZERO.content : new LongWrapper2(val);
3349         }
3350 
3351         @ForceInline
3352         public static WrapperInterface2 wrap_dynamic(long val) {
3353             return (val == 0) ? new LongWrapper2(0) : new LongWrapper2(val);
3354         }
3355     }
3356 
3357     @LooselyConsistentValue
3358     static value class LongWrapper2 implements WrapperInterface2 {
3359         private long val;
3360 
3361         @ForceInline
3362         public LongWrapper2(long val) {
3363             this.val = val;
3364         }
3365 
3366         @ForceInline
3367         public long value() {
3368             return val;
3369         }
3370     }
3371 
3372     @LooselyConsistentValue
3373     static value class InlineWrapper {
3374         WrapperInterface2 content;
3375 
3376         @ForceInline
3377         public InlineWrapper(long val) {
3378             content = new LongWrapper2(val);
3379         }
3380     }
3381 
3382     static class InterfaceBox2 {
3383         WrapperInterface2 content;
3384 
3385         @ForceInline
3386         public InterfaceBox2(long val, boolean def) {
3387             this.content = def ? WrapperInterface2.wrap_dynamic(val) : WrapperInterface2.wrap(val);
3388         }
3389 
3390         @ForceInline
3391         static InterfaceBox2 box(long val) {
3392             return new InterfaceBox2(val, false);
3393         }
3394 
3395         @ForceInline
3396         static InterfaceBox2 box_dynamic(long val) {
3397             return new InterfaceBox2(val, true);
3398         }
3399     }
3400 
3401     // Same as tests above but with ZERO hidden in field of another inline type
3402     @Test
3403     @IR(failOn = {ALLOC_G, MEMBAR},
3404         counts = {PREDICATE_TRAP, "= 1"})
3405     public long test114() {
3406         long res = 0;
3407         for (int i = 0; i < lArr.length; i++) {
3408             res += InterfaceBox2.box(lArr[i]).content.value();
3409         }
3410         return res;
3411     }
3412 
3413     @Run(test = "test114")
3414     @Warmup(10000)
3415     public void test114_verifier() {
3416         long res = test114();
3417         Asserts.assertEquals(res, 5*rL);
3418     }
3419 
3420     // Same as test114 but with dynamic instead of constant ZERO field
3421     @Test
3422     @IR(failOn = {ALLOC_G, MEMBAR},
3423         counts = {PREDICATE_TRAP, "= 1"})
3424     public long test115() {
3425         long res = 0;
3426         for (int i = 0; i < lArr.length; i++) {
3427             res += InterfaceBox2.box_dynamic(lArr[i]).content.value();
3428         }
3429         return res;
3430     }
3431 
3432     @Run(test = "test115")
3433     @Warmup(10000)
3434     public void test115_verifier() {
3435         long res = test115();
3436         Asserts.assertEquals(res, 5*rL);
3437     }
3438 
3439     @Strict
3440     @NullRestricted
3441     static MyValueEmpty fEmpty1 = new MyValueEmpty();
3442     static MyValueEmpty fEmpty2 = new MyValueEmpty();
3443     @Strict
3444     @NullRestricted
3445            MyValueEmpty fEmpty3 = new MyValueEmpty();
3446            MyValueEmpty fEmpty4 = new MyValueEmpty();
3447 
3448     // Test fields loads/stores with empty inline types
3449     @Test
3450     public void test116() {
3451         fEmpty1 = fEmpty4;
3452         fEmpty2 = fEmpty1;
3453         fEmpty3 = fEmpty2;
3454         fEmpty4 = fEmpty3;
3455     }
3456 
3457     @Run(test = "test116")
3458     public void test116_verifier() {
3459         test116();
3460         Asserts.assertEquals(fEmpty1, fEmpty2);
3461         Asserts.assertEquals(fEmpty2, fEmpty3);
3462         Asserts.assertEquals(fEmpty3, fEmpty4);
3463     }
3464 
3465     // Test array loads/stores with empty inline types
3466     @Test
3467     public MyValueEmpty test117(MyValueEmpty[] arr1, MyValueEmpty[] arr2) {
3468         arr1[0] = arr2[0];
3469         arr2[0] = new MyValueEmpty();
3470         return arr1[0];
3471     }
3472 
3473     @Run(test = "test117")
3474     public void test117_verifier() {
3475         MyValueEmpty[] arr1 = new MyValueEmpty[] { new MyValueEmpty() };
3476         MyValueEmpty res = test117(arr1, arr1);
3477         Asserts.assertEquals(res, new MyValueEmpty());
3478         Asserts.assertEquals(arr1[0], new MyValueEmpty());
3479     }
3480 
3481     // Test acmp with empty inline types
3482     @Test
3483     public boolean test118(MyValueEmpty v1, MyValueEmpty v2, Object o1) {
3484         return (v1 == v2) && (v2 == o1);
3485     }
3486 
3487     @Run(test = "test118")
3488     public void test118_verifier() {
3489         boolean res = test118(new MyValueEmpty(), new MyValueEmpty(), new MyValueEmpty());
3490         Asserts.assertTrue(res);
3491     }
3492 
3493     @LooselyConsistentValue
3494     static value class EmptyContainer {
3495         @Strict
3496         @NullRestricted
3497         private MyValueEmpty empty = new MyValueEmpty();
3498     }
3499 
3500     @LooselyConsistentValue
3501     static value class MixedContainer {
3502         public int val = 0;
3503         @Strict
3504         @NullRestricted
3505         private EmptyContainer empty = new EmptyContainer();
3506     }
3507 
3508     @Strict
3509     @NullRestricted
3510     static final MyValueEmpty empty = new MyValueEmpty();
3511 
3512     @Strict
3513     @NullRestricted
3514     static final EmptyContainer emptyC = new EmptyContainer();
3515 
3516     @Strict
3517     @NullRestricted
3518     static final MixedContainer mixedContainer = new MixedContainer();
3519 
3520     // Test re-allocation of empty inline type array during deoptimization
3521     @Test
3522     public void test119(boolean deopt, Method m) {
3523         MyValueEmpty[]   array1 = new MyValueEmpty[] { empty };
3524         EmptyContainer[] array2 = (EmptyContainer[])ValueClass.newNullRestrictedNonAtomicArray(EmptyContainer.class, 1, emptyC);
3525         array2[0] = emptyC;
3526         MixedContainer[] array3 = (MixedContainer[])ValueClass.newNullRestrictedNonAtomicArray(MixedContainer.class, 1, mixedContainer);
3527         array3[0] = mixedContainer;
3528         if (deopt) {
3529             // uncommon trap
3530             TestFramework.deoptimize(m);
3531         }
3532         Asserts.assertEquals(array1[0], empty);
3533         Asserts.assertEquals(array2[0], emptyC);
3534         Asserts.assertEquals(array3[0], mixedContainer);
3535     }
3536 
3537     @Run(test = "test119")
3538     public void test119_verifier(RunInfo info) {
3539         test119(!info.isWarmUp(), info.getTest());
3540     }
3541 
3542     // Test optimization of empty inline type field stores
3543     @Test
3544     @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
3545     public void test120() {
3546         fEmpty1 = empty;
3547         fEmpty3 = empty;
3548         // fEmpty2 and fEmpty4 could be null, store can't be removed
3549     }
3550 
3551     @Run(test = "test120")
3552     public void test120_verifier() {
3553         test120();
3554         Asserts.assertEquals(fEmpty1, empty);
3555     }
3556 
3557     // Test removal of empty inline type field loads
3558     @Test
3559     @IR(failOn = {LOAD, STORE, FIELD_ACCESS, NULL_CHECK_TRAP, TRAP})
3560     public boolean test121() {
3561         return fEmpty1.equals(fEmpty3);
3562         // fEmpty2 and fEmpty4 could be null, load can't be removed
3563     }
3564 
3565     @Run(test = "test121")
3566     public void test121_verifier() {
3567         boolean res = test121();
3568         Asserts.assertTrue(res);
3569     }
3570 
3571     // Verify that empty inline type field loads check for null holder
3572     @Test
3573     @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
3574         failOn = {ALLOC_G})
3575     public MyValueEmpty test122(TestLWorld t) {
3576         return t.fEmpty3;
3577     }
3578 
3579     @Run(test = "test122")
3580     public void test122_verifier() {
3581         MyValueEmpty res = test122(this);
3582         Asserts.assertEquals(res, new MyValueEmpty());
3583         try {
3584             test122(null);
3585             throw new RuntimeException("No NPE thrown");
3586         } catch (NullPointerException e) {
3587             // Expected
3588         }
3589     }
3590 
3591     // Verify that empty inline type field stores check for null holder
3592     @Test
3593     @IR(failOn = {ALLOC_G})
3594     public void test123(TestLWorld t) {
3595         t.fEmpty3 = new MyValueEmpty();
3596     }
3597 
3598     @Run(test = "test123")
3599     public void test123_verifier() {
3600         test123(this);
3601         Asserts.assertEquals(fEmpty3, new MyValueEmpty());
3602         try {
3603             test123(null);
3604             throw new RuntimeException("No NPE thrown");
3605         } catch (NullPointerException e) {
3606             // Expected
3607         }
3608     }
3609 
3610     // acmp doesn't need substitutability test when one input is known
3611     // not to be a value type
3612     @Test
3613     @IR(failOn = SUBSTITUTABILITY_TEST)
3614     public boolean test124(NonValueClass o1, Object o2) {
3615         return o1 == o2;
3616     }
3617 
3618     @Run(test = "test124")
3619     public void test124_verifier() {
3620         NonValueClass obj = new NonValueClass(rI);
3621         test124(obj, obj);
3622         test124(obj, testValue1);
3623     }
3624 
3625     // acmp doesn't need substitutability test when one input is null
3626     @Test
3627     @IR(failOn = {SUBSTITUTABILITY_TEST})
3628     public boolean test125(Object o1) {
3629         Object o2 = null;
3630         return o1 == o2;
3631     }
3632 
3633     @Run(test = "test125")
3634     public void test125_verifier() {
3635         test125(testValue1);
3636         test125(null);
3637     }
3638 
3639     // Test inline type that can only be scalarized after loop opts
3640     @Test
3641     @IR(failOn = {ALLOC_G, LOAD, STORE})
3642     public long test126(boolean trap) {
3643         MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3644         MyValue2 val = null;
3645 
3646         for (int i = 0; i < 4; i++) {
3647             if ((i % 2) == 0) {
3648                 val = nonNull;
3649             }
3650         }
3651         // 'val' is always non-null here but that's only known after loop opts
3652         if (trap) {
3653             // Uncommon trap with an inline input that can only be scalarized after loop opts
3654             return val.hash();
3655         }
3656         return 0;
3657     }
3658 
3659     @Run(test = "test126")
3660     @Warmup(10000)
3661     public void test126_verifier(RunInfo info) {
3662         long res = test126(false);
3663         Asserts.assertEquals(res, 0L);
3664         if (!info.isWarmUp()) {
3665             res = test126(true);
3666             Asserts.assertEquals(res, testValue2.hash());
3667         }
3668     }
3669 
3670     // Same as test126 but with interface type
3671     @Test
3672     @IR(failOn = {ALLOC_G, LOAD, STORE})
3673     public long test127(boolean trap) {
3674         MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3675         MyInterface val = null;
3676 
3677         for (int i = 0; i < 4; i++) {
3678             if ((i % 2) == 0) {
3679                 val = nonNull;
3680             }
3681         }
3682         // 'val' is always non-null here but that's only known after loop opts
3683         if (trap) {
3684             // Uncommon trap with an inline input that can only be scalarized after loop opts
3685             return val.hash();
3686         }
3687         return 0;
3688     }
3689 
3690     @Run(test = "test127")
3691     @Warmup(10000)
3692     public void test127_verifier(RunInfo info) {
3693         long res = test127(false);
3694         Asserts.assertEquals(res, 0L);
3695         if (!info.isWarmUp()) {
3696             res = test127(true);
3697             Asserts.assertEquals(res, testValue2.hash());
3698         }
3699     }
3700 
3701     // Test inline type that can only be scalarized after CCP
3702     @Test
3703     @IR(failOn = {ALLOC_G, LOAD, STORE})
3704     public long test128(boolean trap) {
3705         MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3706         MyValue2 val = null;
3707 
3708         int limit = 2;
3709         for (; limit < 4; limit *= 2);
3710         for (int i = 2; i < limit; i++) {
3711             val = nonNull;
3712         }
3713         // 'val' is always non-null here but that's only known after CCP
3714         if (trap) {
3715             // Uncommon trap with an inline input that can only be scalarized after CCP
3716             return val.hash();
3717         }
3718         return 0;
3719     }
3720 
3721     @Run(test = "test128")
3722     @Warmup(10000)
3723     public void test128_verifier(RunInfo info) {
3724         long res = test128(false);
3725         Asserts.assertEquals(res, 0L);
3726         if (!info.isWarmUp()) {
3727             res = test128(true);
3728             Asserts.assertEquals(res, testValue2.hash());
3729         }
3730     }
3731 
3732     // Same as test128 but with interface type
3733     @Test
3734     @IR(failOn = {ALLOC_G, LOAD, STORE})
3735     public long test129(boolean trap) {
3736         MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3737         MyInterface val = null;
3738 
3739         int limit = 2;
3740         for (; limit < 4; limit *= 2);
3741         for (int i = 0; i < limit; i++) {
3742             val = nonNull;
3743         }
3744         // 'val' is always non-null here but that's only known after CCP
3745         if (trap) {
3746             // Uncommon trap with an inline input that can only be scalarized after CCP
3747             return val.hash();
3748         }
3749         return 0;
3750     }
3751 
3752     @Run(test = "test129")
3753     @Warmup(10000)
3754     public void test129_verifier(RunInfo info) {
3755         long res = test129(false);
3756         Asserts.assertEquals(res, 0L);
3757         if (!info.isWarmUp()) {
3758             res = test129(true);
3759             Asserts.assertEquals(res, testValue2.hash());
3760         }
3761     }
3762 
3763     // Lock on inline type (known after inlining)
3764     @ForceInline
3765     public Object test130_inlinee() {
3766         return MyValue1.createWithFieldsInline(rI, rL);
3767     }
3768 
3769     @Test
3770     @IR(failOn = {LOAD},
3771         // LockNode keeps MyValue1 allocation alive up until macro expansion which in turn keeps MyValue2
3772         // alloc alive. Although the MyValue1 allocation is removed (unused), MyValue2 is expanded first
3773         // and therefore stays.
3774         counts = {ALLOC, "<= 1", STORE, "<= 1"})
3775     public void test130() {
3776         Object obj = test130_inlinee();
3777         synchronized (obj) {
3778             throw new RuntimeException("test130 failed: synchronization on inline type should not succeed");
3779         }
3780     }
3781 
3782     @Run(test = "test130")
3783     public void test130_verifier() {
3784         try {
3785             test130();
3786             throw new RuntimeException("test130 failed: no exception thrown");
3787         } catch (IdentityException ex) {
3788             // Expected
3789         }
3790     }
3791 
3792     // Same as test130 but with field load instead of allocation
3793     @ForceInline
3794     public Object test131_inlinee() {
3795         return testValue1;
3796     }
3797 
3798     @Test
3799     @IR(failOn = {ALLOC_G})
3800     public void test131() {
3801         Object obj = test131_inlinee();
3802         synchronized (obj) {
3803             throw new RuntimeException("test131 failed: synchronization on inline type should not succeed");
3804         }
3805     }
3806 
3807     @Run(test = "test131")
3808     public void test131_verifier() {
3809         try {
3810             test131();
3811             throw new RuntimeException("test131 failed: no exception thrown");
3812         } catch (IdentityException ex) {
3813             // Expected
3814         }
3815     }
3816 
3817     // Test locking on object that is known to be an inline type only after CCP
3818     @Test
3819     @IR(failOn = {ALLOC, LOAD, STORE})
3820     public void test132() {
3821         MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
3822         Object obj = new NonValueClass(42);
3823 
3824         int limit = 2;
3825         for (; limit < 4; limit *= 2);
3826         for (int i = 2; i < limit; i++) {
3827             obj = vt;
3828         }
3829         synchronized (obj) {
3830             throw new RuntimeException("test132 failed: synchronization on inline type should not succeed");
3831         }
3832     }
3833 
3834     @Run(test = "test132")
3835     @Warmup(10000)
3836     public void test132_verifier() {
3837         try {
3838             test132();
3839             throw new RuntimeException("test132 failed: no exception thrown");
3840         } catch (IdentityException ex) {
3841             // Expected
3842         }
3843     }
3844 
3845     // Test conditional locking on inline type and non-escaping object
3846     @Test
3847     public void test133(boolean b) {
3848         Object obj = b ? new NonValueClass(rI) : MyValue2.createWithFieldsInline(rI, rD);
3849         synchronized (obj) {
3850             if (!b) {
3851                 throw new RuntimeException("test133 failed: synchronization on inline type should not succeed");
3852             }
3853         }
3854     }
3855 
3856     @Run(test = "test133")
3857     public void test133_verifier() {
3858         test133(true);
3859         try {
3860             test133(false);
3861             throw new RuntimeException("test133 failed: no exception thrown");
3862         } catch (IdentityException ex) {
3863             // Expected
3864         }
3865     }
3866 
3867     // Variant with non-scalarized inline type
3868     @Test
3869     @IR(failOn = {ALLOC_G})
3870     public void test134(boolean b) {
3871         Object obj = null;
3872         if (b) {
3873             obj = MyValue2.createWithFieldsInline(rI, rD);
3874         }
3875         synchronized (obj) {
3876 
3877         }
3878     }
3879 
3880     @Run(test = "test134")
3881     public void test134_verifier() {
3882         try {
3883             test134(true);
3884             throw new RuntimeException("test134 failed: no exception thrown");
3885         } catch (IdentityException ex) {
3886             // Expected
3887         }
3888     }
3889 
3890     // Test that acmp of the same inline object is removed
3891     @Test
3892     @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
3893     public boolean test135() {
3894         MyValue1 val = MyValue1.createWithFieldsInline(rI, rL);
3895         return val == val;
3896     }
3897 
3898     @Run(test = "test135")
3899     public void test135_verifier() {
3900         Asserts.assertTrue(test135());
3901     }
3902 
3903     // Same as test135 but with null
3904     @Test
3905     @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
3906     public boolean test136(boolean b) {
3907         MyValue1 val = MyValue1.createWithFieldsInline(rI, rL);
3908         if (b) {
3909             val = null;
3910         }
3911         return val == val;
3912     }
3913 
3914     @Run(test = "test136")
3915     public void test136_verifier() {
3916         Asserts.assertTrue(test136(false));
3917         Asserts.assertTrue(test136(true));
3918     }
3919 
3920     // Test that acmp of different inline objects with same content is removed
3921     @Test
3922     // TODO 8228361
3923     // @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
3924     public boolean test137(int i) {
3925         MyValue2 val1 = MyValue2.createWithFieldsInline(i, rD);
3926         MyValue2 val2 = MyValue2.createWithFieldsInline(i, rD);
3927         return val1 == val2;
3928     }
3929 
3930     @Run(test = "test137")
3931     public void test137_verifier() {
3932         Asserts.assertTrue(test137(rI));
3933     }
3934 
3935     // Same as test137 but with null
3936     @Test
3937     // TODO 8228361
3938     // @IR(failOn = {ALLOC_G, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
3939     public boolean test138(int i, boolean b) {
3940         MyValue2 val1 = MyValue2.createWithFieldsInline(i, rD);
3941         MyValue2 val2 = MyValue2.createWithFieldsInline(i, rD);
3942         if (b) {
3943             val1 = null;
3944             val2 = null;
3945         }
3946         return val1 == val2;
3947     }
3948 
3949     @Run(test = "test138")
3950     public void test138_verifier() {
3951         Asserts.assertTrue(test138(rI, false));
3952         Asserts.assertTrue(test138(rI, true));
3953     }
3954 
3955     @LooselyConsistentValue
3956     static value class Test139Value {
3957         Object obj = null;
3958         @Strict
3959         @NullRestricted
3960         MyValueEmpty empty = new MyValueEmpty();
3961     }
3962 
3963     @LooselyConsistentValue
3964     static value class Test139Wrapper {
3965         @Strict
3966         @NullRestricted
3967         Test139Value value = new Test139Value();
3968     }
3969 
3970     @Test
3971     @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
3972         failOn = {ALLOC_G})
3973     @IR(failOn = {LOAD, STORE, TRAP})
3974     public MyValueEmpty test139() {
3975         Test139Wrapper w = new Test139Wrapper();
3976         return w.value.empty;
3977     }
3978 
3979     @Run(test = "test139")
3980     public void test139_verifier() {
3981         MyValueEmpty empty = test139();
3982         Asserts.assertEquals(empty, new MyValueEmpty());
3983     }
3984 
3985     // Test calling a method on a loaded but not linked inline type
3986     @LooselyConsistentValue
3987     value class Test140Value {
3988         int x = 0;
3989 
3990         public int get() {
3991             return x;
3992         }
3993     }
3994 
3995     @Test
3996     @IR(failOn = {ALLOC_G})
3997     public int test140() {
3998         Test140Value vt = new Test140Value();
3999         return vt.get();
4000     }
4001 
4002     @Run(test = "test140")
4003     @Warmup(0)
4004     public void test140_verifier() {
4005         int result = test140();
4006         Asserts.assertEquals(result, 0);
4007     }
4008 
4009     // Test calling a method on a linked but not initialized inline type
4010     @LooselyConsistentValue
4011     value class Test141Value {
4012         int x = 0;
4013 
4014         public int get() {
4015             return x;
4016         }
4017     }
4018 
4019     @Test
4020     @IR(failOn = {ALLOC_G})
4021     public int test141() {
4022         Test141Value vt = new Test141Value();
4023         return vt.get();
4024     }
4025 
4026     @Run(test = "test141")
4027     @Warmup(0)
4028     public void test141_verifier() {
4029         int result = test141();
4030         Asserts.assertEquals(result, 0);
4031     }
4032 
4033     // Test that virtual calls on inline type receivers are properly inlined
4034     @Test
4035     @IR(failOn = {ALLOC_G, LOAD, STORE})
4036     public long test142() {
4037         MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
4038         MyInterface val = null;
4039 
4040         for (int i = 0; i < 4; i++) {
4041             if ((i % 2) == 0) {
4042                 val = nonNull;
4043             }
4044         }
4045         return val.hash();
4046     }
4047 
4048     @Run(test = "test142")
4049     public void test142_verifier() {
4050         long res = test142();
4051         Asserts.assertEquals(res, testValue2.hash());
4052     }
4053 
4054     // Test merging of buffered inline types
4055     @Test
4056     public Object test144(int i) {
4057         if (i == 0) {
4058             return MyValue1.createDefaultInline();
4059         } else if (i == 1) {
4060             return testValue1;
4061         } else {
4062             return MyValue1.createDefaultInline();
4063         }
4064     }
4065 
4066     @Run(test = "test144")
4067     public void test144_verifier() {
4068         Asserts.assertEquals(test144(0), MyValue1.createDefaultInline());
4069         Asserts.assertEquals(test144(1), testValue1);
4070         Asserts.assertEquals(test144(2), MyValue1.createDefaultInline());
4071     }
4072 
4073     // Tests writing an array element with a (statically known) incompatible type
4074     private static final MethodHandle setArrayElementIncompatibleRef = InstructionHelper.buildMethodHandle(MethodHandles.lookup(),
4075         "setArrayElementIncompatibleRef",
4076         MethodType.methodType(void.class, TestLWorld.class, MyValue1[].class, int.class, MyValue2.class),
4077         CODE -> {
4078             CODE.
4079             aload(1).
4080             iload(2).
4081             aload(3).
4082             aastore().
4083             return_();
4084         });
4085 
4086     // Test inline type connected to result node
4087     @Test
4088     @IR(failOn = {ALLOC_G})
4089     public MyValue1 test146(Object obj) {
4090         return (MyValue1)obj;
4091     }
4092 
4093     @Run(test = "test146")
4094     @Warmup(10000)
4095     public void test146_verifier() {
4096         Asserts.assertEQ(test146(testValue1), testValue1);
4097     }
4098 
4099     @ForceInline
4100     public Object test148_helper(Object obj) {
4101         return (MyValue1)obj;
4102     }
4103 
4104     // Same as test146 but with helper method
4105     @Test
4106     public Object test148(Object obj) {
4107         return test148_helper(obj);
4108     }
4109 
4110     @Run(test = "test148")
4111     @Warmup(10000)
4112     public void test148_verifier() {
4113         Asserts.assertEQ(test148(testValue1), testValue1);
4114     }
4115 
4116     @ForceInline
4117     public Object test149_helper(Object obj) {
4118         return (MyValue1)obj;
4119     }
4120 
4121     // Same as test147 but with helper method
4122     @Test
4123     public Object test149(Object obj) {
4124         return test149_helper(obj);
4125     }
4126 
4127     @Run(test = "test149")
4128     @Warmup(10000)
4129     public void test149_verifier() {
4130         Asserts.assertEQ(test149(testValue1), testValue1);
4131         Asserts.assertEQ(test149(null), null);
4132     }
4133 
4134     // Test post-parse call devirtualization with inline type receiver
4135     @Test
4136     @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
4137         failOn = {ALLOC})
4138     @IR(failOn = {compiler.lib.ir_framework.IRNode.DYNAMIC_CALL_OF_METHOD, "MyValue2::hash"},
4139         counts = {compiler.lib.ir_framework.IRNode.STATIC_CALL_OF_METHOD, "MyValue2::hash", "= 1"})
4140     public long test150() {
4141         MyValue2 val = MyValue2.createWithFieldsInline(rI, rD);
4142         MyInterface receiver = MyValue1.createWithFieldsInline(rI, rL);
4143 
4144         for (int i = 0; i < 4; i++) {
4145             if ((i % 2) == 0) {
4146                 receiver = val;
4147             }
4148         }
4149         // Trigger post parse call devirtualization (strength-reducing
4150         // virtual calls to direct calls).
4151         return receiver.hash();
4152     }
4153 
4154     @Run(test = "test150")
4155     public void test150_verifier() {
4156         Asserts.assertEquals(test150(), testValue2.hash());
4157     }
4158 
4159 // TODO 8336003 This triggers #  assert(false) failed: Should have been buffered
4160 /*
4161     // Same as test150 but with val not being allocated in the scope of the method
4162     @Test
4163     @IR(failOn = {compiler.lib.ir_framework.IRNode.DYNAMIC_CALL_OF_METHOD, "MyValue2::hash"},
4164         counts = {compiler.lib.ir_framework.IRNode.STATIC_CALL_OF_METHOD, "MyValue2::hash", "= 1"})
4165     public long test151(MyValue2 val) {
4166         MyAbstract receiver = MyValue1.createWithFieldsInline(rI, rL);
4167 
4168         for (int i = 0; i < 100; i++) {
4169             if ((i % 2) == 0) {
4170                 receiver = val;
4171             }
4172         }
4173         // Trigger post parse call devirtualization (strength-reducing
4174         // virtual calls to direct calls).
4175         return receiver.hash();
4176     }
4177 
4178     @Run(test = "test151")
4179     @Warmup(0) // Make sure there is no receiver type profile
4180     public void test151_verifier() {
4181         Asserts.assertEquals(test151(testValue2), testValue2.hash());
4182     }
4183 */
4184 
4185     static interface MyInterface2 {
4186         public int val();
4187     }
4188 
4189     static abstract value class MyAbstract2 implements MyInterface2 {
4190 
4191     }
4192 
4193     static class MyClass152 extends MyAbstract2 {
4194         private int val;
4195 
4196         @ForceInline
4197         public MyClass152(int val) {
4198             this.val = val;
4199         }
4200 
4201         @Override
4202         public int val() {
4203             return val;
4204         }
4205     }
4206 
4207     @LooselyConsistentValue
4208     static value class MyValue152 extends MyAbstract2 {
4209         private int unused = 0; // Make sure sub-offset of val is field non-zero
4210         private int val;
4211 
4212         @ForceInline
4213         public MyValue152(int val) {
4214             this.val = val;
4215         }
4216 
4217         @Override
4218         public int val() {
4219             return val;
4220         }
4221     }
4222 
4223     @LooselyConsistentValue
4224     static value class MyWrapper152 {
4225         private int unused = 0; // Make sure sub-offset of val field is non-zero
4226         @Strict
4227         @NullRestricted
4228         MyValue152 val;
4229 
4230         @ForceInline
4231         public MyWrapper152(MyInterface2 val) {
4232             this.val = (MyValue152)val;
4233         }
4234     }
4235 
4236     // Test that checkcast with speculative type does not break scalarization in return
4237     @Test
4238     public MyWrapper152 test152(MyInterface2 val) {
4239         return new MyWrapper152(val);
4240     }
4241 
4242     @Run(test = "test152")
4243     @Warmup(10000) // Make sure profile information is available at cast
4244     public void test152_verifier() {
4245         MyClass152 unused = new MyClass152(rI);
4246         MyValue152 val = new MyValue152(rI);
4247         Asserts.assertEquals(test152(val).val, val);
4248     }
4249 
4250     @DontInline
4251     static void test153_helper(MyWrapper152 arg) {
4252 
4253     }
4254 
4255     // Test that checkcast with speculative type does not prevent scalarization in args
4256     @Test
4257     public void test153(MyInterface2 val) {
4258         test153_helper(new MyWrapper152(val));
4259     }
4260 
4261     @Run(test = "test153")
4262     @Warmup(10000) // Make sure profile information is available at cast
4263     public void test153_verifier() {
4264         MyClass152 unused = new MyClass152(rI);
4265         MyValue152 val = new MyValue152(rI);
4266         test153(val);
4267     }
4268 
4269     // Test that checkcast with speculative type enables scalarization
4270     @Test
4271     @IR(failOn = {ALLOC_G, STORE})
4272     public int test154(Method m, MyInterface2 val, boolean b1, boolean b2) {
4273         MyInterface2 obj = new MyValue152(rI);
4274         if (b1) {
4275             // Speculative cast to MyValue152 enables scalarization
4276             obj = (MyAbstract2)val;
4277         }
4278         if (b2) {
4279             // Uncommon trap
4280             TestFramework.deoptimize(m);
4281             return obj.val();
4282         }
4283         return -1;
4284     }
4285 
4286     @Run(test = "test154")
4287     @Warmup(10000) // Make sure profile information is available at cast
4288     public void test154_verifier(RunInfo info) {
4289         MyClass152 unused = new MyClass152(rI);
4290         MyValue152 val = new MyValue152(rI);
4291         Asserts.assertEquals(test154(info.getTest(), val, false, false), -1);
4292         Asserts.assertEquals(test154(info.getTest(), val, true, false), -1);
4293         if (!info.isWarmUp()) {
4294             Asserts.assertEquals(test154(info.getTest(), val, false, true), rI);
4295         }
4296     }
4297 
4298     // Same as test154 but with null val
4299     @Test
4300     @IR(failOn = {ALLOC_G, STORE})
4301     public int test155(Method m, MyInterface2 val, boolean b1, boolean b2) {
4302         MyInterface2 obj = new MyValue152(rI);
4303         if (b1) {
4304             // Speculative cast to MyValue152 enables scalarization
4305             obj = (MyAbstract2)val;
4306         }
4307         if (b2) {
4308             // Uncommon trap
4309             TestFramework.deoptimize(m);
4310             return obj.val();
4311         }
4312         return -1;
4313     }
4314 
4315     @Run(test = "test155")
4316     @Warmup(10000) // Make sure profile information is available at cast
4317     public void test155_verifier(RunInfo info) {
4318         MyClass152 unused = new MyClass152(rI);
4319         MyValue152 val = new MyValue152(rI);
4320         Asserts.assertEquals(test155(info.getTest(), val, false, false), -1);
4321         Asserts.assertEquals(test155(info.getTest(), val, true, false), -1);
4322         Asserts.assertEquals(test155(info.getTest(), null, true, false), -1);
4323         if (!info.isWarmUp()) {
4324             Asserts.assertEquals(test155(info.getTest(), val, false, true), rI);
4325         }
4326     }
4327 
4328     @Strict
4329     @NullRestricted
4330     final static MyValue1 test157Cache = MyValue1.createWithFieldsInline(rI, 0);
4331 
4332     // Test merging buffered inline type from field load with non-buffered inline type
4333     @Test
4334     public MyValue1 test157(long val) {
4335         return (val == 0L) ? test157Cache : MyValue1.createWithFieldsInline(rI, val);
4336     }
4337 
4338     @Run(test = "test157")
4339     public void test157_verifier() {
4340         Asserts.assertEquals(test157(0), test157Cache);
4341         Asserts.assertEquals(test157(rL).hash(), testValue1.hash());
4342     }
4343 
4344     @Strict
4345     @NullRestricted
4346     static MyValue1 test158Cache = MyValue1.createWithFieldsInline(rI, 0);
4347 
4348     // Same as test157 but with non-final field load
4349     @Test
4350     public MyValue1 test158(long val) {
4351         return (val == 0L) ? test158Cache : MyValue1.createWithFieldsInline(rI, val);
4352     }
4353 
4354     @Run(test = "test158")
4355     public void test158_verifier() {
4356         Asserts.assertEquals(test158(0), test158Cache);
4357         Asserts.assertEquals(test158(rL).hash(), testValue1.hash());
4358     }
4359 
4360     // Verify that cast that with incompatible types is properly handled
4361     @Test
4362     public void test160(NonValueClass arg) {
4363         Object tmp = arg;
4364         MyValue1 res = (MyValue1)tmp;
4365     }
4366 
4367     @Run(test = "test160")
4368     @Warmup(10000)
4369     public void test160_verifier(RunInfo info) {
4370         try {
4371             test160(new NonValueClass(42));
4372             throw new RuntimeException("No CCE thrown");
4373         } catch (ClassCastException e) {
4374             // Expected
4375         }
4376         test160(null);
4377     }
4378 
4379     abstract value static class AbstractValueClassSingleSubclass {
4380     }
4381 
4382     value static class UniqueValueSubClass extends AbstractValueClassSingleSubclass {
4383         int x = 34;
4384     }
4385 
4386     static AbstractValueClassSingleSubclass abstractValueClassSingleSubclass = new UniqueValueSubClass();
4387 
4388     @Test
4389     public void testUniqueConcreteValueSubKlass(boolean flag) {
4390         // C2 should recognize that even though we do not know the exact layout of the underlying inline type of the
4391         // abstract field abstractValueClassSingleSubclass (i.e. cannot scalarize), we only have a unique concrete sub
4392         // class from which we know at compile time whether it can be scalarized or not. This unique sub class
4393         // optimization was missing, resulting in a missing InlineTypeNode assertion failure.
4394         doNothing(abstractValueClassSingleSubclass, flag ? 23 : 34);
4395     }
4396 
4397     void doNothing(Object a, int i) {}
4398 
4399     @Run(test = "testUniqueConcreteValueSubKlass")
4400     public void testUniqueConcreteValueSubKlass_verifier() {
4401         testUniqueConcreteValueSubKlass(true);
4402     }
4403 
4404     static value class MyValueContainer {
4405         private final Object value;
4406 
4407         private MyValueContainer(Object value) {
4408             this.value = value;
4409         }
4410     }
4411 
4412     static value class MyValue161 {
4413         int x = 0;
4414     }
4415 
4416     // Test merging value classes with Object fields
4417     @Test
4418     public MyValueContainer test161(boolean b) {
4419         MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : null;
4420         // Cast to verify that merged values are of correct type
4421         Object obj = b ? (MyValue161)res.value : null;
4422         return res;
4423     }
4424 
4425     @Run(test = "test161")
4426     public void test161_verifier() {
4427         Asserts.assertEquals(test161(true), new MyValueContainer(new MyValue161()));
4428         Asserts.assertEquals(test161(false), null);
4429     }
4430 
4431     @Test
4432     public MyValueContainer test162(boolean b) {
4433         MyValueContainer res = b ? null : new MyValueContainer(new MyValue161());
4434         // Cast to verify that merged values are of correct type
4435         Object obj = b ? null : (MyValue161)res.value;
4436         return res;
4437     }
4438 
4439     @Run(test = "test162")
4440     public void test162_verifier() {
4441         Asserts.assertEquals(test162(true), null);
4442         Asserts.assertEquals(test162(false), new MyValueContainer(new MyValue161()));
4443     }
4444 
4445     @Test
4446     public MyValueContainer test163(boolean b) {
4447         MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : new MyValueContainer(null);
4448         // Cast to verify that merged values are of correct type
4449         Object obj = b ? (MyValue161)res.value : (MyValue161)res.value;
4450         return res;
4451     }
4452 
4453     @Run(test = "test163")
4454     public void test163_verifier() {
4455         Asserts.assertEquals(test163(true), new MyValueContainer(new MyValue161()));
4456         Asserts.assertEquals(test163(false), new MyValueContainer(null));
4457     }
4458 
4459     @Test
4460     public MyValueContainer test164(boolean b) {
4461         MyValueContainer res = b ? new MyValueContainer(null) : new MyValueContainer(new MyValue161());
4462         // Cast to verify that merged values are of correct type
4463         Object obj = b ? (MyValue161)res.value : (MyValue161)res.value;
4464         return res;
4465     }
4466 
4467     @Run(test = "test164")
4468     public void test164_verifier() {
4469         Asserts.assertEquals(test164(true), new MyValueContainer(null));
4470         Asserts.assertEquals(test164(false), new MyValueContainer(new MyValue161()));
4471     }
4472 
4473     @Test
4474     public MyValueContainer test165(boolean b) {
4475         MyValueContainer res = b ? new MyValueContainer(new MyValue161()) : new MyValueContainer(42);
4476         // Cast to verify that merged values are of correct type
4477         Object obj = b ? (MyValue161)res.value : (Integer)res.value;
4478         return res;
4479     }
4480 
4481     @Run(test = "test165")
4482     public void test165_verifier() {
4483         Asserts.assertEquals(test165(true), new MyValueContainer(new MyValue161()));
4484         Asserts.assertEquals(test165(false), new MyValueContainer(42));
4485     }
4486 
4487     @Test
4488     public MyValueContainer test166(boolean b) {
4489         MyValueContainer res = b ? new MyValueContainer(42) : new MyValueContainer(new MyValue161());
4490         // Cast to verify that merged values are of correct type
4491         Object obj = b ? (Integer)res.value : (MyValue161)res.value;
4492         return res;
4493     }
4494 
4495     @Run(test = "test166")
4496     public void test166_verifier() {
4497         Asserts.assertEquals(test166(true), new MyValueContainer(42));
4498         Asserts.assertEquals(test166(false), new MyValueContainer(new MyValue161()));
4499     }
4500 
4501     // Verify that monitor information in JVMState is correct at method exit
4502     @Test
4503     public synchronized Object test167() {
4504         return MyValue1.createWithFieldsInline(rI, rL); // Might trigger buffering which requires JVMState
4505     }
4506 
4507     @Run(test = "test167")
4508     public void test167_verifier() {
4509         Asserts.assertEquals(((MyValue1)test167()).hash(), hash());
4510     }
4511 
4512     @LooselyConsistentValue
4513     static value class ValueClassWithInt {
4514         int i;
4515 
4516         ValueClassWithInt(int i) {
4517             this.i = i;
4518         }
4519     }
4520 
4521     @LooselyConsistentValue
4522     static value class ValueClassWithDouble {
4523         double d;
4524 
4525         ValueClassWithDouble(double d) {
4526             this.d = d;
4527         }
4528     }
4529 
4530     @LooselyConsistentValue
4531     static abstract value class AbstractValueClassWithByte {
4532         byte b;
4533 
4534         AbstractValueClassWithByte(byte b) {
4535             this.b = b;
4536         }
4537     }
4538 
4539     @LooselyConsistentValue
4540     static value class SubValueClassWithInt extends AbstractValueClassWithByte {
4541         int i;
4542 
4543         SubValueClassWithInt(int i) {
4544             this.i = i;
4545             super((byte)(i + 1));
4546         }
4547     }
4548 
4549     @LooselyConsistentValue
4550     static value class SubValueClassWithDouble extends AbstractValueClassWithByte {
4551         double d;
4552 
4553         SubValueClassWithDouble(double d) {
4554             this.d = d;
4555             super((byte)(d + 1));
4556         }
4557     }
4558 
4559     // TODO 8350865 We need more copies of these tests for all ValueClass array factories
4560     static final ValueClassWithInt[] VALUE_CLASS_WITH_INT_ARRAY = (ValueClassWithInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueClassWithInt.class, 2, new ValueClassWithInt(0));
4561     static final ValueClassWithDouble[] VALUE_CLASS_WITH_DOUBLE_ARRAY = (ValueClassWithDouble[]) ValueClass.newNullRestrictedNonAtomicArray(ValueClassWithDouble.class, 2, new ValueClassWithDouble(0));
4562     static final SubValueClassWithInt[] SUB_VALUE_CLASS_WITH_INT_ARRAY = (SubValueClassWithInt[]) ValueClass.newNullRestrictedNonAtomicArray(SubValueClassWithInt.class, 2, new SubValueClassWithInt(0));
4563     static final SubValueClassWithDouble[] SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY = (SubValueClassWithDouble[]) ValueClass.newNullRestrictedNonAtomicArray(SubValueClassWithDouble.class, 2, new SubValueClassWithDouble(0));
4564 
4565 // TODO: Can only be enabled once JDK-8343835 is fixed. Otherwise, we hit the mismatched stores assert.
4566 //    static {
4567 //        VALUE_CLASS_WITH_INT_ARRAY[0] = new ValueClassWithInt(5);
4568 //        VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new ValueClassWithDouble(6);
4569 //        SUB_VALUE_CLASS_WITH_INT_ARRAY[0] = new SubValueClassWithInt(7);
4570 //        SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new SubValueClassWithDouble(8);
4571 //    }
4572 
4573     @Test
4574     static void testFlatArrayInexactObjectStore(Object o, boolean flag) {
4575         Object[] oArr;
4576         if (flag) {
4577             oArr = VALUE_CLASS_WITH_INT_ARRAY; // VALUE_CLASS_WITH_INT_ARRAY is statically known to be flat.
4578         } else {
4579             oArr = VALUE_CLASS_WITH_DOUBLE_ARRAY; // VALUE_CLASS_WITH_DOUBLE_ARRAY is statically known to be flat.
4580         }
4581         // The type of 'oArr' is inexact here because we merge two arrays. Since both arrays are flat, 'oArr' is also flat:
4582         //     Type: flat:narrowoop: java/lang/Object:NotNull * (flat in array)[int:2]
4583         // Since the type is inexact, we do not know the exact flat array layout statically and thus need to fall back
4584         // to call "store_unknown_inline_Type()" at runtime where we know the flat array layout
4585         oArr[0] = o;
4586     }
4587 
4588     @Test
4589     static Object testFlatArrayInexactObjectLoad(boolean flag) {
4590         Object[] oArr;
4591         if (flag) {
4592             oArr = VALUE_CLASS_WITH_INT_ARRAY; // VALUE_CLASS_WITH_INT_ARRAY is statically known to be flat.
4593         } else {
4594             oArr = VALUE_CLASS_WITH_DOUBLE_ARRAY; // VALUE_CLASS_WITH_DOUBLE_ARRAY is statically known to be flat.
4595         }
4596         // The type of 'oArr' is inexact here because we merge two arrays. Since both arrays are flat, 'oArr' is also flat:
4597         //     Type: flat:narrowoop: java/lang/Object:NotNull * (flat in array)[int:2]
4598         // Since the type is inexact, we do not know the exact flat array layout statically and thus need to fall back
4599         // to call "load_unknown_inline_Type()" at runtime where we know the flat array layout
4600         return oArr[0];
4601     }
4602 
4603     @Test
4604     static void testFlatArrayInexactAbstractValueClassStore(AbstractValueClassWithByte abstractValueClassWithByte,
4605                                                             boolean flag) {
4606         AbstractValueClassWithByte[] avArr;
4607         if (flag) {
4608             avArr = SUB_VALUE_CLASS_WITH_INT_ARRAY;
4609         } else {
4610             avArr = SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY;
4611         }
4612         // Same as testFlatArrayInexactObjectStore() but the inexact type is with an abstract value class:
4613         //    flat:narrowoop: compiler/valhalla/inlinetypes/TestLWorld$AbstractValueClassWithByte:NotNull * (flat in array)[int:2]
4614         avArr[0] = abstractValueClassWithByte;
4615     }
4616 
4617     @Test
4618     static AbstractValueClassWithByte testFlatArrayInexactAbstractValueClassLoad(boolean flag) {
4619         AbstractValueClassWithByte[] avArr;
4620         if (flag) {
4621             avArr = SUB_VALUE_CLASS_WITH_INT_ARRAY;
4622         } else {
4623             avArr = SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY;
4624         }
4625         // Same as testFlatArrayInexactObjectLoad() but the inexact type is with an abstract value class:
4626         //    flat:narrowoop: compiler/valhalla/inlinetypes/TestLWorld$AbstractValueClassWithByte:NotNull * (flat in array)[int:2]
4627         return avArr[0];
4628     }
4629 
4630     @Run(test = {"testFlatArrayInexactObjectStore",
4631                  "testFlatArrayInexactObjectLoad",
4632                  "testFlatArrayInexactAbstractValueClassStore",
4633                  "testFlatArrayInexactAbstractValueClassLoad"})
4634     static void runFlatArrayInexactLoadAndStore() {
4635         // TODO: Remove these again once JDK-8343835 is fixed and uncomment static initializer above
4636         VALUE_CLASS_WITH_INT_ARRAY[0] = new ValueClassWithInt(5);
4637         VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new ValueClassWithDouble(6);
4638         SUB_VALUE_CLASS_WITH_INT_ARRAY[0] = new SubValueClassWithInt(7);
4639         SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0] = new SubValueClassWithDouble(8);
4640 
4641         boolean flag = true;
4642         ValueClassWithInt valueClassWithInt = new ValueClassWithInt(15);
4643         ValueClassWithDouble valueClassWithDouble = new ValueClassWithDouble(16);
4644 
4645         testFlatArrayInexactObjectStore(valueClassWithInt, true);
4646         Asserts.assertEQ(valueClassWithInt, VALUE_CLASS_WITH_INT_ARRAY[0]);
4647         testFlatArrayInexactObjectStore(valueClassWithDouble, false);
4648         Asserts.assertEQ(valueClassWithDouble, VALUE_CLASS_WITH_DOUBLE_ARRAY[0]);
4649 
4650         Asserts.assertEQ(valueClassWithInt, testFlatArrayInexactObjectLoad(true));
4651         Asserts.assertEQ(valueClassWithDouble, testFlatArrayInexactObjectLoad(false));
4652 
4653         SubValueClassWithInt subValueClassWithInt = new SubValueClassWithInt(17);
4654         SubValueClassWithDouble subValueClassWithDouble = new SubValueClassWithDouble(18);
4655 
4656         testFlatArrayInexactAbstractValueClassStore(subValueClassWithInt, true);
4657         Asserts.assertEQ(subValueClassWithInt, SUB_VALUE_CLASS_WITH_INT_ARRAY[0]);
4658         testFlatArrayInexactAbstractValueClassStore(subValueClassWithDouble, false);
4659         Asserts.assertEQ(subValueClassWithDouble, SUB_VALUE_CLASS_WITH_DOUBLE_ARRAY[0]);
4660 
4661         Asserts.assertEQ(subValueClassWithInt, testFlatArrayInexactAbstractValueClassLoad(true));
4662         Asserts.assertEQ(subValueClassWithDouble, testFlatArrayInexactAbstractValueClassLoad(false));
4663     }
4664 }