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