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 /**
  25  * @test
  26  * @library /test/lib
  27  * @summary Test the handling of fields of unloaded value classes.
  28  * @compile -XDallowWithFieldOperator hack/GetUnresolvedValueFieldWrongSignature.java
  29  * @compile -XDallowWithFieldOperator TestUnloadedValueTypeField.java
  30  * @run main/othervm -XX:+EnableValhalla -Xcomp
  31  *        -XX:CompileCommand=compileonly,TestUnloadedValueTypeField::test1
  32  *        -XX:CompileCommand=compileonly,TestUnloadedValueTypeField::test2
  33  *        -XX:CompileCommand=compileonly,GetUnresolvedValueFieldWrongSignature::test3
  34  *        -XX:CompileCommand=compileonly,TestUnloadedValueTypeField::test4
  35  *        -XX:CompileCommand=compileonly,TestUnloadedValueTypeField::test5
  36  *      TestUnloadedValueTypeField
  37  */
  38 
  39 import jdk.test.lib.Asserts;
  40 
  41 public class TestUnloadedValueTypeField {
  42     static public void main(String[] args) {
  43         test1_verifier();
  44         test2_verifier();
  45         test3_verifier();
  46         test4_verifier();
  47         test5_verifier();
  48     }
  49 
  50     // Test case 1:
  51     // The value type field class has been loaded, but the holder class has not been loaded.
  52     //
  53     //     aload_0
  54     //     getfield  MyValue1Holder.v:QMyValue1;
  55     //               ^ not loaded      ^ already loaded
  56     //
  57     // MyValue1 has already been loaded, because it's in the ValueType attribute of
  58     // TestUnloadedValueTypeField, due to TestUnloadedValueTypeField.test1_precondition().
  59     static value final class MyValue1 {
  60         final int foo = 0;
  61 
  62         static MyValue1 make() {
  63             return __WithField(MyValue1.default.foo, 1234);
  64         }
  65     }
  66 
  67     static class MyValue1Holder {
  68         MyValue1 v;
  69 
  70         public MyValue1Holder() {
  71             v = MyValue1.make();
  72         }
  73     }
  74 
  75     static MyValue1 test1_precondition() {
  76         return MyValue1.make();
  77     }
  78 
  79     static int test1(MyValue1Holder holder) {
  80         if (holder != null) {
  81             return holder.v.foo + 1;
  82         } else {
  83             return 0;
  84         }
  85     }
  86 
  87     static void test1_verifier() {
  88         for (int i=0; i<10000; i++) {
  89             // Make sure test1() is compiled for the first iteration of this loop,
  90             // while MyValue1Holder is yet to be loaded.
  91             test1(null);
  92             MyValue1Holder holder = new MyValue1Holder();
  93             Asserts.assertEQ(test1(holder), 1235);
  94         }
  95     }
  96 
  97     // Test case 2:
  98     // Both the value type field class, and the holder class have not been loaded.
  99     //
 100     //     aload_0
 101     //     getfield  MyValueHolder2.v:QMyValue2;
 102     //               ^ not loaded     ^ not loaded
 103     //
 104     // MyValue2 has already been loaded, because it is not explicitly referenced by
 105     // TestUnloadedValueTypeField.
 106     static value final class MyValue2 {
 107         final int foo = 0;
 108 
 109         static MyValue2 make(int n) {
 110             return __WithField(MyValue2.default.foo, n);
 111         }
 112     }
 113 
 114     static class MyValue2Holder {
 115         MyValue2 v;
 116 
 117         public MyValue2Holder() {
 118             v = MyValue2.make(1234);
 119         }
 120     }
 121 
 122 
 123     static int test2(MyValue2Holder holder) {
 124         if (holder != null) {
 125             return holder.v.foo + 2;
 126         } else {
 127             return 0;
 128         }
 129     }
 130 
 131     static void test2_verifier() {
 132         for (int i=0; i<10000; i++) {
 133             // Make sure test2() is compiled for the first iteration of this loop,
 134             // while MyValue2Holder2 and MyValue2  is yet to be loaded.
 135             test2(null);
 136             MyValue2Holder holder2 = new MyValue2Holder();
 137             Asserts.assertEQ(test2(holder2), 1236);
 138         }
 139     }
 140 
 141     // Test case 3: same as test1, except we are using an incorrect signature to
 142     // refer to the value class.
 143     // The value type field class has been loaded, but the holder class has not been loaded.
 144     //
 145     // GetUnresolvedValueFieldWrongSignature::test3() {
 146     //     aload_0
 147     //     getfield  MyValueHolder3.v:LMyValue3;
 148     //               ^ not loaded    ^ already loaded (but should have been "Q")
 149     //     ...
 150     // }
 151     //
 152     // MyValue3 has already been loaded, because it's in the ValueType attribute of
 153     // TestUnloadedValueTypeField, due to TestUnloadedValueTypeField.test3_precondition().
 154     static value final class MyValue3 {
 155         final int foo = 0;
 156 
 157         static MyValue3 make() {
 158             return __WithField(MyValue3.default.foo, 1234);
 159         }
 160     }
 161 
 162     static class MyValue3Holder {
 163         MyValue3 v;
 164 
 165         public MyValue3Holder() {
 166             v = MyValue3.make();
 167         }
 168     }
 169 
 170     static MyValue3 test3_precondition() {
 171         return MyValue3.make();
 172     }
 173 
 174     static int test3(MyValue3Holder holder) {
 175         return GetUnresolvedValueFieldWrongSignature.test3(holder);
 176     }
 177 
 178     static void test3_verifier() {
 179         for (int i=0; i<10000; i++) {
 180             // Make sure test3() is compiled for the first iteration of this loop,
 181             // while MyValue3Holder is yet to be loaded.
 182             test3(null);
 183             MyValue3Holder holder = new MyValue3Holder();
 184             try {
 185                 test3(holder);
 186                 Asserts.fail("Should have thrown NoSuchFieldError");
 187             } catch (NoSuchFieldError e) {
 188                 // OK
 189             }
 190         }
 191     }
 192 
 193     // Test case 4:
 194     // Same as case 1, except we use putfield instead of getfield.
 195     static value final class MyValue4 {
 196         final int foo = 0;
 197 
 198         static MyValue4 make(int n) {
 199             return __WithField(MyValue4.default.foo, n);
 200         }
 201     }
 202 
 203     static class MyValue4Holder {
 204         MyValue4 v;
 205 
 206         public MyValue4Holder() {
 207             v = MyValue4.make(0);
 208         }
 209     }
 210 
 211     static MyValue4 test4_precondition() {
 212         return MyValue4.make(0);
 213     }
 214 
 215     static void test4(MyValue4Holder holder, MyValue4 v) {
 216         if (holder != null) {
 217             holder.v = v;
 218         }
 219     }
 220 
 221     static void test4_verifier() {
 222         MyValue4 v = MyValue4.make(5678);
 223         for (int i=0; i<10000; i++) {
 224             // Make sure test4() is compiled for the first iteration of this loop,
 225             // while MyValue4Holder is yet to be loaded.
 226             test4(null, v);
 227             MyValue4Holder holder = new MyValue4Holder();
 228             test4(holder, v);
 229             Asserts.assertEQ(holder.v.foo, 5678);
 230         }
 231     }
 232 
 233     // Test case 5:
 234     // Same as case 2, except we use putfield instead of getfield.
 235     static value final class MyValue5 {
 236         final int foo = 0;
 237 
 238         static MyValue5 make(int n) {
 239             return __WithField(MyValue5.default.foo, n);
 240         }
 241     }
 242 
 243     static class MyValue5Holder {
 244         MyValue5 v;
 245 
 246         public MyValue5Holder() {
 247             v = MyValue5.make(0);
 248         }
 249         public Object make(int n) {
 250             return MyValue5.make(n);
 251         }
 252     }
 253 
 254     static void test5(MyValue5Holder holder, Object o) {
 255         if (holder != null) {
 256             MyValue5 v = (MyValue5)o;
 257             holder.v = v;
 258         }
 259     }
 260 
 261     static void test5_verifier() {
 262         for (int i=0; i<10000; i++) {
 263             // Make sure test5() is compiled for the first iteration of this loop,
 264             // while both MyValue5Holder and MyValye5 are yet to be loaded.
 265             test5(null, null);
 266             MyValue5Holder holder = new MyValue5Holder();
 267             Object v = holder.make(5679);
 268             test5(holder, v);
 269             Asserts.assertEQ(holder.v.foo, 5679);
 270         }
 271     }
 272 }