1 /*
  2  * Copyright (c) 2024, 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   /*
 25  * @test id=32bits
 26  * @requires vm.bits == 32 & vm.flagless
 27  * @library /test/lib
 28  * @modules java.base/jdk.internal.vm.annotation
 29  * @enablePreview
 30  * @compile FieldLayoutAnalyzer.java ValueFieldInheritanceTest.java
 31  * @run main/othervm -Xint ValueFieldInheritanceTest 0
 32  */
 33 
 34 /*
 35  * @test id=64bitsCompressedOops
 36  * @requires vm.bits == 64 & vm.flagless
 37  * @library /test/lib
 38  * @modules java.base/jdk.internal.vm.annotation
 39  * @enablePreview
 40  * @compile FieldLayoutAnalyzer.java ValueFieldInheritanceTest.java
 41  * @run main/othervm -Xint ValueFieldInheritanceTest 1
 42  */
 43 
 44 /*
 45  * @test id=64bitsNoCompressedOops
 46  * @requires vm.bits == 64 & vm.flagless
 47  * @library /test/lib
 48  * @modules java.base/jdk.internal.vm.annotation
 49  * @enablePreview
 50  * @compile FieldLayoutAnalyzer.java ValueFieldInheritanceTest.java
 51  * @run main/othervm -Xint ValueFieldInheritanceTest 2
 52  */
 53 
 54 /*
 55  * @test id=64bitsNoCompressedOopsNoCompressKlassPointers
 56  * @requires vm.bits == 64 & vm.flagless
 57  * @library /test/lib
 58  * @modules java.base/jdk.internal.vm.annotation
 59  * @enablePreview
 60  * @compile FieldLayoutAnalyzer.java ValueFieldInheritanceTest.java
 61  * @run main/othervm -Xint ValueFieldInheritanceTest 3
 62  */
 63 
 64 import java.util.ArrayList;
 65 import java.util.Collections;
 66 import java.util.List;
 67 
 68 import org.w3c.dom.views.AbstractView;
 69 
 70 import jdk.internal.vm.annotation.ImplicitlyConstructible;
 71 import jdk.internal.vm.annotation.LooselyConsistentValue;
 72 import jdk.internal.vm.annotation.NullRestricted;
 73 
 74 import java.lang.reflect.Method;
 75 import java.lang.reflect.Modifier;
 76 import jdk.test.lib.Asserts;
 77 import jdk.test.lib.process.OutputAnalyzer;
 78 import jdk.test.lib.process.ProcessTools;
 79 
 80 
 81 public class ValueFieldInheritanceTest {
 82 
 83   static abstract value class AbstractNoField { };
 84 
 85   static abstract value class AbstractOneField { byte b = 0; }
 86 
 87   static abstract value class SubAbstractOne extends AbstractNoField { }
 88 
 89   static abstract value class SubAbstractTwo extends AbstractOneField { }
 90 
 91   static abstract value class SubAbstractThree extends AbstractNoField  { int i = 0; }
 92 
 93   static abstract value class SubAbstractFour extends AbstractOneField { int i = 0; }
 94 
 95   static class Identity0 extends AbstractNoField { }
 96 
 97   static class Identity1 extends AbstractNoField { short s; }
 98 
 99   static class Identity2 extends SubAbstractOne { }
100 
101   static class Identity3 extends SubAbstractOne { char c; }
102 
103   static class Identity4 extends SubAbstractTwo { }
104 
105   static class Identity5 extends SubAbstractTwo { int i; }
106 
107   static class Identity6 extends SubAbstractThree { }
108 
109   static class Identity7 extends SubAbstractThree { int i; }
110 
111   static class Identity8 extends SubAbstractFour { }
112 
113   static class Identity9 extends SubAbstractFour { int i; }
114 
115   static class ConcreteValue0 extends AbstractNoField { }
116 
117   static class ConcreteValue1 extends AbstractNoField { short s; }
118 
119   static class ConcreteValue2 extends SubAbstractOne { }
120 
121   static class ConcreteValue3 extends SubAbstractOne { char c; }
122 
123   static class ConcreteValue4 extends SubAbstractTwo { }
124 
125   static class ConcreteValue5 extends SubAbstractTwo { int i; }
126 
127   static class ConcreteValue6 extends SubAbstractThree { }
128 
129   static class ConcreteValue7 extends SubAbstractThree { int i; }
130 
131   static class ConcreteValue8 extends SubAbstractFour { }
132 
133   static class ConcreteValue9 extends SubAbstractFour { int i; }
134 
135   static public void test_0() {
136     var i0 = new Identity0();
137     var i1 = new Identity1();
138     var i2 = new Identity2();
139     var i3 = new Identity3();
140     var i4 = new Identity4();
141     var i5 = new Identity5();
142     var i6 = new Identity6();
143     var i7 = new Identity7();
144     var i8 = new Identity8();
145     var i9 = new Identity9();
146     var c0 = new ConcreteValue0();
147     var c1 = new ConcreteValue1();
148     var c2 = new ConcreteValue2();
149     var c3 = new ConcreteValue3();
150     var c4 = new ConcreteValue4();
151     var c5 = new ConcreteValue5();
152     var c6 = new ConcreteValue6();
153     var c7 = new ConcreteValue7();
154     var c8 = new ConcreteValue8();
155     var c9 = new ConcreteValue9();
156   }
157 
158   static class TestRunner {
159     public static void main(String[] args) throws Exception {
160       Class testClass = Class.forName("ValueFieldInheritanceTest");
161       Asserts.assertNotNull(testClass);
162       Method[] testMethods = testClass.getMethods();
163       for (Method test : testMethods) {
164         if (test.getName().startsWith("test_")) {
165           Asserts.assertTrue(Modifier.isStatic(test.getModifiers()));
166           Asserts.assertTrue(test.getReturnType().equals(Void.TYPE));
167           System.out.println("Running " + test.getName());
168           test.invoke(null);
169         }
170       }
171     }
172   }
173 
174   static ProcessBuilder exec(String compressedOopsArg, String compressedKlassPointersArg, String... args) throws Exception {
175     List<String> argsList = new ArrayList<>();
176     Collections.addAll(argsList, "--enable-preview");
177     Collections.addAll(argsList, "-XX:+UnlockDiagnosticVMOptions");
178     Collections.addAll(argsList, "-XX:+PrintFieldLayout");
179     Collections.addAll(argsList, "-Xshare:off");
180     if (compressedOopsArg != null) {
181       Collections.addAll(argsList, compressedOopsArg);
182     }
183     if (compressedKlassPointersArg != null) {
184       Collections.addAll(argsList, compressedKlassPointersArg);
185     }
186     Collections.addAll(argsList, "-Xmx256m");
187     Collections.addAll(argsList, "-cp", System.getProperty("java.class.path") + ":.");
188     Collections.addAll(argsList, args);
189     return ProcessTools.createTestJavaProcessBuilder(argsList);
190   }
191 
192   public static void main(String[] args) throws Exception {
193     String compressedOopsArg;
194     String compressedKlassPointersArg;
195 
196     switch(args[0]) {
197       case "0": compressedOopsArg = null;
198                 compressedKlassPointersArg = null;
199                 break;
200       case "1": compressedOopsArg = "-XX:+UseCompressedOops";
201                 compressedKlassPointersArg =  "-XX:+UseCompressedClassPointers";
202                 break;
203       case "2": compressedOopsArg = "-XX:-UseCompressedOops";
204                 compressedKlassPointersArg = "-XX:+UseCompressedClassPointers";
205                 break;
206       case "3": compressedOopsArg = "-XX:-UseCompressedOops";
207                 compressedKlassPointersArg = "-XX:-UseCompressedClassPointers";
208                 break;
209       default: throw new RuntimeException("Unrecognized configuration");
210     }
211 
212     // Generate test classes
213     // NullMarkersTest fat = new NullMarkersTest();
214 
215     // Execute the test runner in charge of loading all test classes
216     ProcessBuilder pb = exec(compressedOopsArg, compressedKlassPointersArg, "ValueFieldInheritanceTest$TestRunner");
217     OutputAnalyzer out = new OutputAnalyzer(pb.start());
218 
219     if (out.getExitValue() != 0) {
220       out.outputTo(System.out);
221     }
222     Asserts.assertEquals(out.getExitValue(), 0, "Something went wrong while running the tests");
223 
224     // Get and parse the test output
225     System.out.print(out.getOutput());
226     FieldLayoutAnalyzer.LogOutput lo = new FieldLayoutAnalyzer.LogOutput(out.asLines());
227     FieldLayoutAnalyzer fla =  FieldLayoutAnalyzer.createFieldLayoutAnalyzer(lo);
228 
229     // Running tests verification method (check that tests produced the right configuration)
230     Class testClass = ValueFieldInheritanceTest.class;
231       Method[] testMethods = testClass.getMethods();
232       for (Method test : testMethods) {
233         if (test.getName().startsWith("check_")) {
234           Asserts.assertTrue(Modifier.isStatic(test.getModifiers()));
235           Asserts.assertTrue(test.getReturnType().equals(Void.TYPE));
236           test.invoke(null, fla);
237         }
238       }
239 
240     // Verify that all layouts are correct
241     fla.check();
242   }
243 
244 }