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=Oops32 26 * @requires vm.bits == 32 27 * @requires vm.flagless 28 * @library /test/lib 29 * @modules java.base/jdk.internal.vm.annotation 30 * @enablePreview 31 * @compile FieldLayoutAnalyzer.java FieldAlignmentTest.java 32 * @run main/othervm FieldAlignmentTest 0 33 */ 34 35 /* 36 * @test id=CompressedOops 37 * @requires vm.bits == 64 38 * @requires vm.flagless 39 * @library /test/lib 40 * @modules java.base/jdk.internal.vm.annotation 41 * @enablePreview 42 * @compile FieldLayoutAnalyzer.java FieldAlignmentTest.java 43 * @run main/othervm FieldAlignmentTest 1 44 */ 45 46 /* 47 * @test id=NoCompressedOops 48 * @requires vm.bits == 64 49 * @requires vm.flagless 50 * @library /test/lib 51 * @modules java.base/jdk.internal.vm.annotation 52 * @enablePreview 53 * @compile FieldLayoutAnalyzer.java FieldAlignmentTest.java 54 * @run main/othervm FieldAlignmentTest 2 55 */ 56 57 import java.util.ArrayList; 58 import java.util.Collections; 59 import java.util.List; 60 61 import jdk.internal.vm.annotation.LooselyConsistentValue; 62 import jdk.internal.vm.annotation.NullRestricted; 63 import jdk.internal.vm.annotation.Strict; 64 65 66 import jdk.test.lib.Asserts; 67 import jdk.test.lib.ByteCodeLoader; 68 import jdk.test.lib.helpers.ClassFileInstaller; 69 import jdk.test.lib.compiler.InMemoryJavaCompiler; 70 import jdk.test.lib.process.OutputAnalyzer; 71 import jdk.test.lib.process.ProcessTools; 72 73 public class FieldAlignmentTest { 74 public static class ZeroByte { } 75 public static class OneByte { byte b; } 76 public static class TwoByte { byte b0; byte b1; } 77 public static class ThreeByte { byte b0; byte b1; byte b2; } 78 public static class FourByte { byte b0; byte b1; byte b2; byte b3; } 79 public static class FiveByte { byte b0; byte b1; byte b2; byte b3; byte b4; } 80 public static class SixByte { byte b0; byte b1; byte b2; byte b3; byte b4; byte b5; } 81 public static class SevenByte { byte b0; byte b1; byte b2; byte b3; byte b4; byte b5; byte b6; } 82 public static final String[] superNames = { ZeroByte.class.getCanonicalName(), 83 OneByte.class.getCanonicalName(), 84 TwoByte.class.getCanonicalName(), 85 ThreeByte.class.getCanonicalName(), 86 FourByte.class.getCanonicalName(), 87 FiveByte.class.getCanonicalName(), 88 SixByte.class.getCanonicalName(), 89 SevenByte.class.getCanonicalName() }; 90 public static final String[] valueNames = { ValueOneByte.class.getCanonicalName(), 91 ValueOneChar.class.getCanonicalName(), 92 ValueOneShort.class.getCanonicalName(), 93 ValueOneInt.class.getCanonicalName(), 94 ValueOneLong.class.getCanonicalName(), 95 ValueOneFloat.class.getCanonicalName(), 96 ValueOneDouble.class.getCanonicalName(), 97 ValueByteLong.class.getCanonicalName(), 98 ValueByteInt.class.getCanonicalName() }; 99 100 List<String> testNames = new ArrayList<String>(); 101 102 @LooselyConsistentValue static value class ValueOneByte { byte val = 0; } 103 @LooselyConsistentValue static value class ValueOneChar { char val = 0; } 104 @LooselyConsistentValue static value class ValueOneShort { short val = 0; } 105 @LooselyConsistentValue static value class ValueOneInt { int val = 0; } 106 @LooselyConsistentValue static value class ValueOneLong { long val = 0; } 107 @LooselyConsistentValue static value class ValueOneFloat { float val = 0f; } 108 @LooselyConsistentValue static value class ValueOneDouble { double val = 0d; } 109 110 @LooselyConsistentValue static value class ValueByteLong { byte b = 0; long l = 0; } 111 @LooselyConsistentValue static value class ValueByteInt { byte b = 0; int i = 0; } 112 113 void generateTests() throws Exception { 114 for (String vName : valueNames) { 115 for (String sName : superNames) { 116 String vNameShort = vName.substring(vName.lastIndexOf('.') + 1); 117 String sNameShort = sName.substring(sName.lastIndexOf('.') + 1); 118 String className = "Test" + vNameShort + "With" + sNameShort; 119 String sourceCode = "import jdk.internal.vm.annotation.NullRestricted;" + 120 "import jdk.internal.vm.annotation.Strict;" + 121 "public class " + className + " extends " + sName + " { " + 122 " @Strict" + 123 " @NullRestricted" + 124 " " + vName + " v1 = new " + vName + "();" + 125 "}"; 126 String java_version = System.getProperty("java.specification.version"); 127 byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode, 128 "-source", java_version, "--enable-preview", 129 "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED"); 130 jdk.test.lib.helpers.ClassFileInstaller.writeClassToDisk(className, byteCode); 131 testNames.add(className); 132 } 133 } 134 } 135 136 void generateTestRunner() throws Exception { 137 String className = "TestRunner"; 138 StringBuilder sb = new StringBuilder(); 139 sb.append("public class ").append(className).append(" {"); 140 sb.append(" public void main(String[] args) {"); 141 for (String name : testNames) { 142 sb.append(" ").append(name).append(" var").append(name).append(" = new ").append(name).append("();"); 143 } 144 sb.append(" }"); 145 sb.append("}"); 146 String java_version = System.getProperty("java.specification.version"); 147 byte[] byteCode = InMemoryJavaCompiler.compile(className, sb.toString(), 148 "-source", java_version, "--enable-preview", 149 "-cp", "."); 150 jdk.test.lib.helpers.ClassFileInstaller.writeClassToDisk(className, byteCode); 151 } 152 153 static ProcessBuilder exec(String compressedOopsArg, String... args) throws Exception { 154 List<String> argsList = new ArrayList<>(); 155 Collections.addAll(argsList, "--enable-preview"); 156 Collections.addAll(argsList, "-XX:+UnlockDiagnosticVMOptions"); 157 Collections.addAll(argsList, "-XX:+PrintFieldLayout"); 158 Collections.addAll(argsList, "-Xshare:off"); 159 if (compressedOopsArg != null) { 160 Collections.addAll(argsList, compressedOopsArg); 161 } 162 Collections.addAll(argsList, "-Xmx256m"); 163 Collections.addAll(argsList, "-cp", System.getProperty("java.class.path") + System.getProperty("path.separator") +"."); 164 Collections.addAll(argsList, args); 165 return ProcessTools.createTestJavaProcessBuilder(argsList); 166 } 167 168 public static void main(String[] args) throws Exception { 169 String compressedOopsArg; 170 171 switch(args[0]) { 172 case "0": compressedOopsArg = null; 173 break; 174 case "1": compressedOopsArg = "-XX:+UseCompressedOops"; 175 break; 176 case "2": compressedOopsArg = "-XX:-UseCompressedOops"; 177 break; 178 default: throw new RuntimeException("Unrecognized configuration"); 179 } 180 181 // Generate test classes 182 FieldAlignmentTest fat = new FieldAlignmentTest(); 183 fat.generateTests(); 184 fat.generateTestRunner(); 185 186 // Execute the test runner in charge of loading all test classes 187 ProcessBuilder pb = exec(compressedOopsArg, "TestRunner"); 188 OutputAnalyzer out = new OutputAnalyzer(pb.start()); 189 190 if (out.getExitValue() != 0) { 191 out.outputTo(System.out); 192 } 193 Asserts.assertEquals(out.getExitValue(), 0, "Something went wrong while running the tests"); 194 195 // Analyze the test runner output 196 FieldLayoutAnalyzer.LogOutput lo = new FieldLayoutAnalyzer.LogOutput(out.asLines()); 197 198 FieldLayoutAnalyzer fla = FieldLayoutAnalyzer.createFieldLayoutAnalyzer(lo); 199 try { 200 fla.check(); 201 } catch (Throwable t) { 202 out.outputTo(System.out); 203 throw t; 204 } 205 } 206 }