1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package compiler.valhalla.valuetypes;
  25 import jdk.test.lib.Asserts;
  26 
  27 /**
  28  * @test
  29  * @library /testlibrary /test/lib /compiler/whitebox /
  30  * @summary Test the handling of fields of unloaded value classes.
  31  * @compile -XDallowWithFieldOperator hack/GetUnresolvedValueFieldWrongSignature.java
  32  * @compile -XDallowWithFieldOperator TestUnloadedValueTypeField.java
  33  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  34  * @run main/othervm/timeout=120 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  35  *                               -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+EnableValhalla
  36  *                               compiler.valhalla.valuetypes.ValueTypeTest
  37  *                               compiler.valhalla.valuetypes.TestUnloadedValueTypeField
  38  */
  39 
  40 public class TestUnloadedValueTypeField extends compiler.valhalla.valuetypes.ValueTypeTest {
  41     public static void main(String[] args) throws Throwable {
  42         TestUnloadedValueTypeField test = new TestUnloadedValueTypeField();
  43         test.run(args);
  44     }
  45 
  46     static final String[][] scenarios = {
  47         {},
  48         {"-XX:ValueFieldMaxFlatSize=0"}
  49     };
  50 
  51     @Override
  52     public int getNumScenarios() {
  53         return scenarios.length;
  54     }
  55 
  56     @Override
  57     public String[] getVMParameters(int scenario) {
  58         return scenarios[scenario];
  59     }
  60 
  61     // Test case 1:
  62     // The value type field class has been loaded, but the holder class has not been loaded.
  63     //
  64     //     aload_0
  65     //     getfield  MyValue1Holder.v:QMyValue1;
  66     //               ^ not loaded      ^ already loaded
  67     //
  68     // MyValue1 has already been loaded, because it's in the ValueType attribute of
  69     // TestUnloadedValueTypeField, due to TestUnloadedValueTypeField.test1_precondition().
  70     static value final class MyValue1 {
  71         final int foo = 0;
  72 
  73         static MyValue1 make() {
  74             return __WithField(MyValue1.default.foo, 1234);
  75         }
  76     }
  77 
  78     static class MyValue1Holder {
  79         MyValue1 v;
  80 
  81         public MyValue1Holder() {
  82             v = MyValue1.make();
  83         }
  84     }
  85 
  86     static MyValue1 test1_precondition() {
  87         return MyValue1.make();
  88     }
  89 
  90     @Test
  91     public int test1(MyValue1Holder holder) {
  92         if (holder != null) {
  93             return holder.v.foo + 1;
  94         } else {
  95             return 0;
  96         }
  97     }
  98 
  99     public void test1_verifier(boolean warmup) {
 100         if (warmup) {
 101             test1(null);
 102         } else {
 103             MyValue1Holder holder = new MyValue1Holder();
 104             Asserts.assertEQ(test1(holder), 1235);
 105         }
 106     }
 107 
 108     // Test case 2:
 109     // Both the value type field class, and the holder class have not been loaded.
 110     //
 111     //     aload_0
 112     //     getfield  MyValueHolder2.v:QMyValue2;
 113     //               ^ not loaded     ^ not loaded
 114     //
 115     // MyValue2 has not been loaded, because it is not explicitly referenced by
 116     // TestUnloadedValueTypeField.
 117     static value final class MyValue2 {
 118         final int foo = 0;
 119 
 120         static MyValue2 make(int n) {
 121             return __WithField(MyValue2.default.foo, n);
 122         }
 123     }
 124 
 125     static class MyValue2Holder {
 126         MyValue2 v;
 127 
 128         public MyValue2Holder() {
 129             v = MyValue2.make(1234);
 130         }
 131     }
 132 
 133 
 134     @Test
 135     public int test2(MyValue2Holder holder) {
 136         if (holder != null) {
 137             return holder.v.foo + 2;
 138         } else {
 139             return 0;
 140         }
 141     }
 142 
 143     public void test2_verifier(boolean warmup) {
 144         if (warmup) {
 145             test2(null);
 146         } else {
 147             MyValue2Holder holder2 = new MyValue2Holder();
 148             Asserts.assertEQ(test2(holder2), 1236);
 149         }
 150     }
 151 
 152     // Test case 3: same as test1, except we are using an incorrect signature to
 153     // refer to the value class.
 154     // The value type field class has been loaded, but the holder class has not been loaded.
 155     //
 156     // GetUnresolvedValueFieldWrongSignature::test3() {
 157     //     aload_0
 158     //     getfield  MyValueHolder3.v:LMyValue3;
 159     //               ^ not loaded    ^ already loaded (but should have been "Q")
 160     //     ...
 161     // }
 162     //
 163     // MyValue3 has already been loaded, because it's in the ValueType attribute of
 164     // TestUnloadedValueTypeField, due to TestUnloadedValueTypeField.test3_precondition().
 165     static value final class MyValue3 {
 166         final int foo = 0;
 167 
 168         static MyValue3 make() {
 169             return __WithField(MyValue3.default.foo, 1234);
 170         }
 171     }
 172 
 173     static class MyValue3Holder {
 174         MyValue3 v;
 175 
 176         public MyValue3Holder() {
 177             v = MyValue3.make();
 178         }
 179     }
 180 
 181     static MyValue3 test3_precondition() {
 182         return MyValue3.make();
 183     }
 184 
 185     @Test
 186     public int test3(MyValue3Holder holder) {
 187         return GetUnresolvedValueFieldWrongSignature.test3(holder);
 188     }
 189 
 190     public void test3_verifier(boolean warmup) {
 191         if (warmup) {
 192             test3(null);
 193         } else {
 194             MyValue3Holder holder = new MyValue3Holder();
 195             try {
 196                 test3(holder);
 197                 Asserts.fail("Should have thrown NoSuchFieldError");
 198             } catch (NoSuchFieldError e) {
 199                 // OK
 200             }
 201         }
 202     }
 203 
 204     // Test case 4:
 205     // Same as case 1, except we use putfield instead of getfield.
 206     static value final class MyValue4 {
 207         final int foo = 0;
 208 
 209         static MyValue4 make(int n) {
 210             return __WithField(MyValue4.default.foo, n);
 211         }
 212     }
 213 
 214     static class MyValue4Holder {
 215         MyValue4 v;
 216 
 217         public MyValue4Holder() {
 218             v = MyValue4.make(0);
 219         }
 220     }
 221 
 222     static MyValue4 test4_precondition() {
 223         return MyValue4.make(0);
 224     }
 225 
 226     @Test
 227     public void test4(MyValue4Holder holder, MyValue4 v) {
 228         if (holder != null) {
 229             holder.v = v;
 230         }
 231     }
 232 
 233     public void test4_verifier(boolean warmup) {
 234         MyValue4 v = MyValue4.make(5678);
 235         if (warmup) {
 236             test4(null, v);
 237         } else {
 238             MyValue4Holder holder = new MyValue4Holder();
 239             test4(holder, v);
 240             Asserts.assertEQ(holder.v.foo, 5678);
 241         }
 242     }
 243 
 244     // Test case 5:
 245     // Same as case 2, except we use putfield instead of getfield.
 246     static value final class MyValue5 {
 247         final int foo = 0;
 248 
 249         static MyValue5 make(int n) {
 250             return __WithField(MyValue5.default.foo, n);
 251         }
 252     }
 253 
 254     static class MyValue5Holder {
 255         MyValue5 v;
 256 
 257         public MyValue5Holder() {
 258             v = MyValue5.make(0);
 259         }
 260         public Object make(int n) {
 261             return MyValue5.make(n);
 262         }
 263     }
 264 
 265     @Test
 266     public void test5(MyValue5Holder holder, Object o) {
 267         if (holder != null) {
 268             MyValue5 v = (MyValue5)o;
 269             holder.v = v;
 270         }
 271     }
 272 
 273     public void test5_verifier(boolean warmup) {
 274         if (warmup) {
 275             test5(null, null);
 276         } else {
 277             MyValue5Holder holder = new MyValue5Holder();
 278             Object v = holder.make(5679);
 279             test5(holder, v);
 280             Asserts.assertEQ(holder.v.foo, 5679);
 281         }
 282     }
 283 
 284 
 285     // Test case 11: (same as test1, except we use getstatic instead of getfield)
 286     // The value type field class has been loaded, but the holder class has not been loaded.
 287     //
 288     //     getstatic  MyValue11Holder.v:QMyValue1;
 289     //                ^ not loaded       ^ already loaded
 290     //
 291     // MyValue11 has already been loaded, because it's in the ValueType attribute of
 292     // TestUnloadedValueTypeField, due to TestUnloadedValueTypeField.test1_precondition().
 293     static value final class MyValue11 {
 294         final int foo = 0;
 295 
 296         static MyValue11 make() {
 297             return __WithField(MyValue11.default.foo, 1234);
 298         }
 299     }
 300 
 301     static class MyValue11Holder {
 302         static MyValue11 v = MyValue11.make();
 303     }
 304 
 305     static MyValue11 test11_precondition() {
 306         return MyValue11.make();
 307     }
 308 
 309     @Test
 310     public int test11(int n) {
 311         if (n == 0) {
 312             return 0;
 313         } else {
 314             return MyValue11Holder.v.foo + n;
 315         }
 316     }
 317 
 318     public void test11_verifier(boolean warmup) {
 319         if (warmup) {
 320             test11(0);
 321         } else {
 322             Asserts.assertEQ(test11(2), 1236);
 323         }
 324     }
 325 
 326 
 327     // Test case 12:  (same as test2, except we use getstatic instead of getfield)
 328     // Both the value type field class, and the holder class have not been loaded.
 329     //
 330     //     getstatic  MyValueHolder12.v:QMyValue12;
 331     //                ^ not loaded       ^ not loaded
 332     //
 333     // MyValue12 has not been loaded, because it is not explicitly referenced by
 334     // TestUnloadedValueTypeField.
 335     static value final class MyValue12 {
 336         final int foo = 0;
 337 
 338         static MyValue12 make(int n) {
 339             return __WithField(MyValue12.default.foo, n);
 340         }
 341     }
 342 
 343     static class MyValue12Holder {
 344         static MyValue12 v = MyValue12.make(12);
 345     }
 346 
 347     @Test
 348     public int test12(int n) {
 349         if (n == 0) {
 350             return 0;
 351         } else {
 352             return MyValue12Holder.v.foo + n;
 353         }
 354     }
 355 
 356     public void test12_verifier(boolean warmup) {
 357         if (warmup) {
 358             test12(0);
 359         } else {
 360           Asserts.assertEQ(test12(1), 13);
 361         }
 362     }
 363 }