1 /*
  2  * Copyright (c) 2018, 2024, 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 runtime.valhalla.inlinetypes;
 25 
 26 import jdk.internal.vm.annotation.ImplicitlyConstructible;
 27 import jdk.internal.vm.annotation.LooselyConsistentValue;
 28 import jdk.internal.vm.annotation.NullRestricted;
 29 import jdk.test.lib.Asserts;
 30 
 31 /*
 32  * @test QuickeningTest
 33  * @summary Test quickening of getfield and putfield applied to inline fields
 34  * @library /test/lib
 35  * @modules java.base/jdk.internal.vm.annotation
 36  * @enablePreview
 37  * @compile QuickeningTest.java
 38  * @run main/othervm runtime.valhalla.inlinetypes.QuickeningTest
 39  */
 40 
 41 public class QuickeningTest {
 42 
 43     @ImplicitlyConstructible
 44     @LooselyConsistentValue
 45     static value class Point {
 46         final int x;
 47         final int y;
 48 
 49         public Point(int x, int y) {
 50             this.x = x;
 51             this.y = y;
 52         }
 53     }
 54 
 55     @ImplicitlyConstructible
 56     @LooselyConsistentValue
 57     static value class JumboInline {
 58         final long l0;
 59         final long l1;
 60         final long l2;
 61         final long l3;
 62         final long l4;
 63         final long l5;
 64         final long l6;
 65         final long l7;
 66         final long l8;
 67         final long l9;
 68         final long l10;
 69         final long l11;
 70         final long l12;
 71         final long l13;
 72         final long l14;
 73         final long l15;
 74         final long l16;
 75         final long l17;
 76         final long l18;
 77         final long l19;
 78 
 79         public JumboInline(long l0Val, long l1Val) {
 80             l0 = l0Val;
 81             l1 = l1Val;
 82             l2 = l0Val+1;
 83             l3 = l1Val+2;
 84             l4 = l0Val+3;
 85             l5 = l1Val+4;
 86             l6 = l0Val+5;
 87             l7 = l1Val+6;
 88             l8 = l0Val+7;
 89             l9 = l1Val+8;
 90             l10 = l0Val+9;
 91             l11 = l1Val+10;
 92             l12 = l0Val+11;
 93             l13 = l1Val+12;
 94             l14 = l0Val+13;
 95             l15 = l1Val+14;
 96             l16 = l0Val+15;
 97             l17 = l1Val+16;
 98             l18 = l0Val+17;
 99             l19 = l1Val+18;
100         }
101     }
102 
103     static class Parent {
104     Point nfp;       /* Not flattenable inline field */
105     @NullRestricted
106     Point fp;         /* Flattenable and flattened inline field */
107     @NullRestricted
108     JumboInline fj;    /* Flattenable not flattened inline field */
109 
110         public void setNfp(Point p) { nfp = p; }
111         public void setFp(Point p) { fp = p; }
112         public void setFj(JumboInline j) { fj = j; }
113     }
114 
115     static class Child extends Parent {
116         // This class inherited fields from the Parent class
117         Point nfp2;      /* Not flattenable inline field */
118         @NullRestricted
119         Point fp2;        /* Flattenable and flattened inline field */
120         @NullRestricted
121         JumboInline fj2;   /* Flattenable not flattened inline field */
122 
123         public void setNfp2(Point p) { nfp2 = p; }
124         public void setFp2(Point p)  { fp2 = p; }
125         public void setFj2(JumboInline j) { fj2 = j; }
126     }
127 
128     @ImplicitlyConstructible
129     @LooselyConsistentValue
130     static value class Value {
131         final Point nfp;       /* Not flattenable inline field */
132         @NullRestricted
133         final Point fp;         /* Flattenable and flattened inline field */
134         @NullRestricted
135         final JumboInline fj;    /* Flattenable not flattened inline field */
136 
137         private Value() {
138             nfp = null;
139             fp = new Point(0, 0);
140             fj = new JumboInline(0, 0);
141         }
142     }
143 
144     static void testUninitializedFields() {
145         Parent p = new Parent();
146         Asserts.assertEquals(p.nfp, null, "invalid uninitialized not flattenable");
147         Asserts.assertEquals(p.fp.x, 0, "invalid value for uninitialized flattened field");
148         Asserts.assertEquals(p.fp.y, 0, "invalid value for uninitialized flattened field");
149         Asserts.assertEquals(p.fj.l0, 0L, "invalid value for uninitialized flattened field");
150         Asserts.assertEquals(p.fj.l1, 0L, "invalid value for uninitialized flattened field");
151 
152         Child c = new Child();
153         Asserts.assertEquals(c.nfp, null, "invalid uninitialized not flattenable field");
154         Asserts.assertEquals(c.fp.x, 0, "invalid value for uninitialized flattened field");
155         Asserts.assertEquals(c.fp.y, 0, "invalid value for uninitialized flattened field");
156         Asserts.assertEquals(c.fj.l0, 0L, "invalid value for uninitialized flattened field");
157         Asserts.assertEquals(c.fj.l1, 0L, "invalid value for uninitialized flattened field");
158         Asserts.assertEquals(c.nfp2, null, "invalid uninitialized not flattenable");
159         Asserts.assertEquals(c.fp2.x, 0, "invalid value for uninitialized flattened field");
160         Asserts.assertEquals(c.fp2.y, 0, "invalid value for uninitialized flattened field");
161         Asserts.assertEquals(c.fj2.l0, 0L, "invalid value for uninitialized not flattened field");
162         Asserts.assertEquals(c.fj2.l1, 0L, "invalid value for uninitialized not flattened field");
163 
164         Value v = new Value();
165         Asserts.assertEquals(v.nfp, null, "invalid uninitialized not flattenable");
166         Asserts.assertEquals(v.fp.x, 0, "invalid value for uninitialized flattened field");
167         Asserts.assertEquals(v.fp.y, 0, "invalid value for uninitialized flattened field");
168         Asserts.assertEquals(v.fj.l0, 0L, "invalid value for uninitialized not flattened field");
169         Asserts.assertEquals(v.fj.l1, 0L, "invalid value for uninitialized not flattened field");
170     }
171 
172     static void testPutfieldAndGetField() {
173         Point p1 = new Point(16, 47);
174         Point p2 = new Point(32, 64);
175 
176         JumboInline j1 = new JumboInline(4, 5);
177         JumboInline j2 = new JumboInline(7, 9);
178 
179         Parent p = new Parent();
180         // executing each setter twice to test quickened bytecodes
181         p.setNfp(p1);
182         p.setNfp(p2);
183         p.setFp(p2);
184         p.setFp(p1);
185         p.setFj(j1);
186         p.setFj(j2);
187 
188         Asserts.assertTrue(p.nfp.equals(p2), "invalid updated not flattenable field");
189         Asserts.assertEquals(p.fp.x, 16, "invalid value for updated flattened field");
190         Asserts.assertEquals(p.fp.y, 47, "invalid value for updated flattened field");
191         Asserts.assertTrue(p.fj.equals(j2), "invalid value for updated not flattened field");
192 
193         Child c = new Child();
194         c.setNfp(p1);
195         c.setNfp(p2);
196         c.setFp(p2);
197         c.setFp(p1);
198         c.setFj(j1);
199         c.setFj(j2);
200         c.setNfp2(p2);
201         c.setNfp2(p1);
202         c.setFp2(p1);
203         c.setFp2(p2);
204         c.setFj2(j2);
205         c.setFj2(j1);
206 
207         Asserts.assertTrue(c.nfp.equals(p2), "invalid updated not flattenable field");
208         Asserts.assertEquals(c.fp.x, 16, "invalid value for updated flattened field");
209         Asserts.assertEquals(c.fp.y, 47, "invalid value for updated flattened field");
210         Asserts.assertTrue(c.fj.equals(j2), "invalid value for updated not flattened field");
211 
212         Asserts.assertTrue(c.nfp2.equals(p1), "invalid updated not flattenable field");
213         Asserts.assertEquals(c.fp2.x, 32, "invalid value for updated flattened field");
214         Asserts.assertEquals(c.fp2.y, 64, "invalid value for updated flattened field");
215         Asserts.assertTrue(c.fj2.equals(j1), "invalid value for updated not flattened field");
216     }
217 
218     public static void main(String[] args) {
219         testUninitializedFields();
220         testUninitializedFields(); // run twice to test quickened bytecodes
221         testPutfieldAndGetField();
222     }
223 }