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=NullMarker32 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 NullMarkersTest.java 31 * @run main/othervm NullMarkersTest 0 32 */ 33 34 /* 35 * @test id=NullMarker64CompressedOops 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 NullMarkersTest.java 41 * @run main/othervm NullMarkersTest 1 42 */ 43 44 /* 45 * @test id=NullMarker64NoCompressedOops 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 NullMarkersTest.java 51 * @run main/othervm NullMarkersTest 2 52 */ 53 54 /* 55 * @test id=NullMarker64NoCompressedOopsNoCompressedKlassPointers 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 NullMarkersTest.java 61 * @run main/othervm NullMarkersTest 3 62 */ 63 64 import java.util.ArrayList; 65 import java.util.Collections; 66 import java.util.List; 67 68 import jdk.internal.vm.annotation.ImplicitlyConstructible; 69 import jdk.internal.vm.annotation.LooselyConsistentValue; 70 import jdk.internal.vm.annotation.NullRestricted; 71 72 import java.lang.reflect.Method; 73 import java.lang.reflect.Modifier; 74 import jdk.test.lib.Asserts; 75 import jdk.test.lib.process.OutputAnalyzer; 76 import jdk.test.lib.process.ProcessTools; 77 78 public class NullMarkersTest { 79 80 81 static class TestRunner { 82 public static void main(String[] args) throws Exception { 83 Class testClass = Class.forName("NullMarkersTest"); 84 Asserts.assertNotNull(testClass); 85 Method[] testMethods = testClass.getMethods(); 86 for (Method test : testMethods) { 87 if (test.getName().startsWith("test_")) { 88 Asserts.assertTrue(Modifier.isStatic(test.getModifiers())); 89 Asserts.assertTrue(test.getReturnType().equals(Void.TYPE)); 90 System.out.println("Running " + test.getName()); 91 test.invoke(null); 92 } 93 } 94 } 95 } 96 97 static value class Value0 { 98 int i = 0; 99 } 100 101 static class Container0 { 102 Value0 val; 103 } 104 105 // Simple test with a single nullable flattenable field 106 static public void test_0() { 107 Container0 c = new Container0(); 108 } 109 110 static public void check_0(FieldLayoutAnalyzer fla) { 111 FieldLayoutAnalyzer.ClassLayout cl = fla.getClassLayoutFromName("NullMarkersTest$Container0"); 112 FieldLayoutAnalyzer.FieldBlock f = cl.getFieldFromName("val", false); 113 Asserts.assertTrue(f.isFlat()); 114 Asserts.assertTrue(f.hasNullMarker()); 115 } 116 117 @ImplicitlyConstructible 118 static value class Value1 { 119 short s = 0; 120 } 121 122 static class Container1 { 123 Value1 val0; 124 Value1 val1; 125 @NullRestricted 126 Value1 val2 = new Value1(); 127 } 128 129 static public void test_1() { 130 Container1 c = new Container1(); 131 } 132 133 static public void check_1(FieldLayoutAnalyzer fla) { 134 FieldLayoutAnalyzer.ClassLayout cl = fla.getClassLayoutFromName("NullMarkersTest$Container1"); 135 FieldLayoutAnalyzer.FieldBlock f0 = cl.getFieldFromName("val0", false); 136 Asserts.assertTrue(f0.isFlat()); 137 Asserts.assertTrue(f0.hasNullMarker()); 138 FieldLayoutAnalyzer.FieldBlock f1 = cl.getFieldFromName("val1", false); 139 Asserts.assertTrue(f1.isFlat()); 140 Asserts.assertTrue(f1.hasNullMarker()); 141 FieldLayoutAnalyzer.FieldBlock f2 = cl.getFieldFromName("val2", false); 142 Asserts.assertTrue(f2.isFlat()); 143 Asserts.assertFalse(f2.hasNullMarker()); 144 } 145 146 static value class Value2 { 147 long l = 0; 148 } 149 150 static class Container2a { 151 Value2 vala; 152 } 153 154 static class Container2b extends Container2a { 155 Value2 valb; 156 } 157 158 static public void test_2() { 159 Container2b c = new Container2b(); 160 } 161 162 static public void check_2(FieldLayoutAnalyzer fla) { 163 FieldLayoutAnalyzer.ClassLayout cla = fla.getClassLayoutFromName("NullMarkersTest$Container2a"); 164 FieldLayoutAnalyzer.FieldBlock fa = cla.getFieldFromName("vala", false); 165 Asserts.assertTrue(fa.isFlat()); 166 Asserts.assertTrue(fa.hasNullMarker()); 167 FieldLayoutAnalyzer.ClassLayout clb = fla.getClassLayoutFromName("NullMarkersTest$Container2b"); 168 FieldLayoutAnalyzer.FieldBlock fb = clb.getFieldFromName("valb", false); 169 Asserts.assertTrue(fb.isFlat()); 170 Asserts.assertTrue(fb.hasNullMarker()); 171 } 172 173 @ImplicitlyConstructible 174 static value class Value3 { 175 double d = 0.0d; 176 } 177 178 static class Container3a { 179 @NullRestricted 180 Value3 val0; 181 Value3 val1; 182 } 183 184 static class Container3b extends Container3a { 185 Value3 val2; 186 @NullRestricted 187 Value3 val3; 188 } 189 190 static class Container3c extends Container3b { 191 Value3 val4; 192 Value3 val5; 193 } 194 195 static public void test_3() { 196 Container3c c = new Container3c(); 197 } 198 199 static public void check_3(FieldLayoutAnalyzer fla) { 200 FieldLayoutAnalyzer.ClassLayout cla = fla.getClassLayoutFromName("NullMarkersTest$Container3a"); 201 FieldLayoutAnalyzer.FieldBlock f0 = cla.getFieldFromName("val0", false); 202 Asserts.assertTrue(f0.isFlat()); 203 Asserts.assertFalse(f0.hasNullMarker()); 204 FieldLayoutAnalyzer.FieldBlock f1 = cla.getFieldFromName("val1", false); 205 Asserts.assertTrue(f1.isFlat()); 206 Asserts.assertTrue(f1.hasNullMarker()); 207 FieldLayoutAnalyzer.ClassLayout clb = fla.getClassLayoutFromName("NullMarkersTest$Container3b"); 208 FieldLayoutAnalyzer.FieldBlock f2 = clb.getFieldFromName("val2", false); 209 Asserts.assertTrue(f2.isFlat()); 210 Asserts.assertTrue(f2.hasNullMarker()); 211 FieldLayoutAnalyzer.FieldBlock f3 = clb.getFieldFromName("val3", false); 212 Asserts.assertTrue(f3.isFlat()); 213 Asserts.assertFalse(f3.hasNullMarker()); 214 FieldLayoutAnalyzer.ClassLayout clc = fla.getClassLayoutFromName("NullMarkersTest$Container3c"); 215 FieldLayoutAnalyzer.FieldBlock f4 = clc.getFieldFromName("val4", false); 216 Asserts.assertTrue(f4.isFlat()); 217 Asserts.assertTrue(f4.hasNullMarker()); 218 FieldLayoutAnalyzer.FieldBlock f5 = clc.getFieldFromName("val5", false); 219 Asserts.assertTrue(f5.isFlat()); 220 Asserts.assertTrue(f5.hasNullMarker()); 221 } 222 223 @ImplicitlyConstructible 224 @LooselyConsistentValue 225 static value class Value4 { 226 int i = 0; 227 byte b = 0; 228 } 229 230 static class Container4 { 231 Value4 val0; 232 Value4 val1; 233 } 234 235 static public void test_4() { 236 Container4 c = new Container4(); 237 } 238 239 static void check_4(FieldLayoutAnalyzer fla) { 240 FieldLayoutAnalyzer.ClassLayout cl = fla.getClassLayoutFromName("NullMarkersTest$Container4"); 241 FieldLayoutAnalyzer.FieldBlock f0 = cl.getFieldFromName("val0", false); 242 Asserts.assertTrue(f0.isFlat()); 243 Asserts.assertTrue(f0.hasNullMarker()); 244 FieldLayoutAnalyzer.FieldBlock f1 = cl.getFieldFromName("val1", false); 245 Asserts.assertTrue(f1.isFlat()); 246 Asserts.assertTrue(f1.hasNullMarker()); 247 } 248 249 @ImplicitlyConstructible 250 @LooselyConsistentValue 251 static value class Value5a { 252 short s = 0; 253 byte b = 0; 254 } 255 256 @ImplicitlyConstructible 257 @LooselyConsistentValue 258 static value class Value5b { 259 @NullRestricted 260 Value5a val0 = new Value5a(); 261 @NullRestricted 262 Value5a val1 = new Value5a(); 263 } 264 265 static class Container5 { 266 Value5a vala; 267 Value5b valb0; 268 Value5b valb1; 269 } 270 271 static public void test_5() { 272 Container5 c = new Container5(); 273 } 274 275 static void check_5(FieldLayoutAnalyzer fla) { 276 FieldLayoutAnalyzer.ClassLayout cl = fla.getClassLayoutFromName("NullMarkersTest$Container5"); 277 FieldLayoutAnalyzer.FieldBlock fa = cl.getFieldFromName("vala", false); 278 Asserts.assertTrue(fa.isFlat()); 279 Asserts.assertTrue(fa.hasNullMarker()); 280 FieldLayoutAnalyzer.FieldBlock fb0 = cl.getFieldFromName("valb0", false); 281 Asserts.assertTrue(fb0.isFlat()); 282 Asserts.assertTrue(fb0.hasNullMarker()); 283 FieldLayoutAnalyzer.FieldBlock fb1 = cl.getFieldFromName("valb1", false); 284 Asserts.assertTrue(fb1.isFlat()); 285 Asserts.assertTrue(fb1.hasNullMarker()); 286 } 287 288 static ProcessBuilder exec(String compressedOopsArg, String compressedKlassPointersArg, String... args) throws Exception { 289 List<String> argsList = new ArrayList<>(); 290 Collections.addAll(argsList, "--enable-preview"); 291 Collections.addAll(argsList, "-Xint"); 292 Collections.addAll(argsList, "-XX:+UnlockDiagnosticVMOptions"); 293 Collections.addAll(argsList, "-XX:+PrintFieldLayout"); 294 Collections.addAll(argsList, "-Xshare:off"); 295 if (compressedOopsArg != null) { 296 Collections.addAll(argsList, compressedOopsArg); 297 } 298 if (compressedKlassPointersArg != null) { 299 Collections.addAll(argsList, compressedKlassPointersArg); 300 } 301 Collections.addAll(argsList, "-Xmx256m"); 302 Collections.addAll(argsList, "-XX:+EnableNullableFieldFlattening"); 303 Collections.addAll(argsList, "-cp", System.getProperty("java.class.path") + ":."); 304 Collections.addAll(argsList, args); 305 return ProcessTools.createTestJavaProcessBuilder(argsList); 306 } 307 308 public static void main(String[] args) throws Exception { 309 String compressedOopsArg; 310 String compressedKlassPointersArg; 311 312 switch(args[0]) { 313 case "0": compressedOopsArg = null; 314 compressedKlassPointersArg = null; 315 break; 316 case "1": compressedOopsArg = "-XX:+UseCompressedOops"; 317 compressedKlassPointersArg = "-XX:+UseCompressedClassPointers"; 318 break; 319 case "2": compressedOopsArg = "-XX:-UseCompressedOops"; 320 compressedKlassPointersArg = "-XX:+UseCompressedClassPointers"; 321 break; 322 case "3": compressedOopsArg = "-XX:-UseCompressedOops"; 323 compressedKlassPointersArg = "-XX:-UseCompressedClassPointers"; 324 break; 325 default: throw new RuntimeException("Unrecognized configuration"); 326 } 327 328 // Generate test classes 329 NullMarkersTest fat = new NullMarkersTest(); 330 331 // Execute the test runner in charge of loading all test classes 332 ProcessBuilder pb = exec(compressedOopsArg, compressedKlassPointersArg, "NullMarkersTest$TestRunner"); 333 OutputAnalyzer out = new OutputAnalyzer(pb.start()); 334 335 if (out.getExitValue() != 0) { 336 out.outputTo(System.out); 337 } 338 Asserts.assertEquals(out.getExitValue(), 0, "Something went wrong while running the tests"); 339 340 // Get and parse the test output 341 System.out.print(out.getOutput()); 342 FieldLayoutAnalyzer.LogOutput lo = new FieldLayoutAnalyzer.LogOutput(out.asLines()); 343 FieldLayoutAnalyzer fla = FieldLayoutAnalyzer.createFieldLayoutAnalyzer(lo); 344 345 // Running tests verification method (check that tests produced the right configuration) 346 Class testClass = NullMarkersTest.class; 347 Method[] testMethods = testClass.getMethods(); 348 for (Method test : testMethods) { 349 if (test.getName().startsWith("check_")) { 350 Asserts.assertTrue(Modifier.isStatic(test.getModifiers())); 351 Asserts.assertTrue(test.getReturnType().equals(Void.TYPE)); 352 test.invoke(null, fla); 353 } 354 } 355 356 // Verify that all layouts are correct 357 fla.check(); 358 } 359 }