1 # Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 2 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 # 4 # This code is free software; you can redistribute it and/or modify it 5 # under the terms of the GNU General Public License version 2 only, as 6 # published by the Free Software Foundation. 7 # 8 # This code is distributed in the hope that it will be useful, but WITHOUT 9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 # version 2 for more details (a copy is included in the LICENSE file that 12 # accompanied this code). 13 # 14 # You should have received a copy of the GNU General Public License version 15 # 2 along with this work; if not, write to the Free Software Foundation, 16 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 # 18 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 # or visit www.oracle.com if you need additional information or have any 20 # questions. 21 22 #====================================================================== 23 # Regression test to run javac with premain prototype, to test the CDS and AOT changes. 24 # 25 # QUICK START: 26 # bash javac-test.sh -n $JAVA 27 # 28 # This shows you all the 5 steps for using the premain prototype: 29 # 30 # (STEP 1 of 5) Dump javac.classlist (skipped) 31 # (STEP 2 of 5) Create Static javac-static.jsa (skipped) 32 # (STEP 3 of 4) Run with javac-static.jsa and dump profile in javac-dynamic.jsa (With Training Data Replay) (skipped) 33 # (STEP 4 of 4) Run with javac-dynamic.jsa and generate AOT code (skipped) 34 # (STEP 5 of 5) Final production run: with javac-dynamic.jsa and load AOT code (skipped) 35 # 36 # bash javac-test.sh $JAVA 37 # This runs all the above 5 steps 38 #====================================================================== 39 40 # Usage: bash javac-test.sh $OPTS $JAVA 41 # bash javac-test.sh $OPTS $JAVA $JVMARGS 42 # 43 # $JAVA must be from inside your JDK build dir. E.g., /your/build/dir/images/jdk/bin/java 44 # 45 # $OPTS is optional. Examples: 46 # 47 # - Don't run any tests, just print the command-lines 48 # bash cds-test.sh -n $JAVA 49 # 50 # - Just run test #4 51 # bash cds-test.sh -r 4 $JAVA 52 # 53 # - Run test 5, enable the JIT compile log, and loop for 10000 iterations. Also pass -Xmx16g to the JVM. 54 # bash cds-test.sh -r 5 -lcomp -l 10000 $JAVA -Xmx16g 55 # 56 # See the "while" loop below for all available options 57 58 MYDIR=$(cd $(dirname $0); pwd) 59 echo script is installed at $MYDIR 60 61 LIMIT= 62 QUIET= 63 LOOPS=100 64 EXTRA_ARGS= 65 EXIT_WHEN_FAIL=0 66 67 while true; do 68 if [[ $1 = "-lcomp" ]]; then 69 # Log compiler 70 EXTRA_ARGS="$EXTRA_ARGS -XX:+PrintCompilation" 71 shift 72 elif [[ $1 = "-lsc" ]]; then 73 # Log shared code 74 EXTRA_ARGS="$EXTRA_ARGS -Xlog:scc -Xlog:scc,nmethod" 75 shift 76 elif [[ $1 = "-r" ]]; then 77 # Limit the run to a single test case 78 LIMIT=$2 79 shift 80 shift 81 elif [[ $1 = "-l" ]]; then 82 # Number of loops for JavacBench 83 LOOPS=$2 84 shift 85 shift 86 elif [[ $1 = "-n" ]]; then 87 # Don't run any test cases, just print their help message and command line 88 LIMIT=0 89 shift 90 elif [[ $1 = "-f" ]]; then 91 # Exit the script with exit code 1 as soon as a test fails 92 EXIT_WHEN_FAIL=1 93 shift 94 elif [[ $1 = "-q" ]]; then 95 # Don't print the help messages and command line of test cases that are skipped 96 QUIET=1 97 shift 98 elif [[ $1 = "-all" ]]; then 99 # Run all test cases (that are not included in the 5 steps)" 100 # If this flag is NOT specified, only the tests with STEP in their description will be executed. 101 DOALL=1 102 shift 103 else 104 break 105 fi 106 done 107 108 JVM=$1 109 110 echo JVM=$JVM 111 112 JSA_SUFFIX=-$JVM 113 114 # Ioi-specific 115 if test "$TESTBED" != ""; then 116 IOI_PREFIX=$(cd $TESTBED/../..; pwd) 117 fi 118 119 if test "$JVM" = "p"; then 120 # Ioi-specific 121 PRODUCT_BLD=${IOI_PREFIX} 122 IOI_TEST_VM=${IOI_PREFIX}-product/images/jdk 123 elif test "$JVM" = "d"; then 124 PRODUCT_BLD=${IOI_PREFIX} 125 IOI_TEST_VM=${IOI_PREFIX}-debug/images/jdk 126 elif test "$JVM" = "fd"; then 127 PRODUCT_BLD=${IOI_PREFIX} 128 IOI_TEST_VM=${IOI_PREFIX}-fastdebug/images/jdk 129 elif [[ ${JVM}XX =~ /images/jdk/bin/javaXX ]]; then 130 PRODUCT_BLD=$(cd $(dirname $JVM)/../../..; pwd); 131 JSA_SUFFIX= 132 else 133 echo "Please specify the location of the JVM (must be in your /build/dir/images/jdk/bin)" 134 exit 1 135 fi 136 137 JVM_AND_ARGS=$@ 138 TEST_NUM=0 139 140 function test-info () { 141 if test "$DOALL" != "1"; then 142 if [[ "$@" =~ STEP ]] ; then 143 true 144 else 145 return 1 146 fi 147 fi 148 149 TEST_NUM=$(expr $TEST_NUM + 1) 150 declare -gA infos 151 declare -gA cmds 152 cmds[$TEST_NUM]=$CMD 153 infos[$TEST_NUM]=$* 154 local SKIPPED="" 155 if test "$LIMIT" != "" && test "$LIMIT" != "$TEST_NUM"; then 156 SKIPPED=" (skipped)" 157 fi 158 if test "$QUIET" = ""; then 159 echo ====================================================================== 160 echo "Test $TEST_NUM $*$SKIPPED" 161 echo $CMD 162 fi 163 if test "$SKIPPED" != ""; then 164 return 1 165 else 166 return 0 167 fi 168 } 169 170 function record_success () { 171 somepassed=1 172 declare -gA status 173 status[$TEST_NUM]=OK 174 echo "RESULT: $TEST_NUM = OK" 175 } 176 177 function record_failure () { 178 somefailed=1 179 declare -gA status 180 status[$TEST_NUM]=FAILED 181 echo "RESULT: $TEST_NUM = FAILED" 182 if test "$EXIT_WHEN_FAIL" = "1"; then 183 touch fail-stop.txt 184 exit 1 185 fi 186 } 187 188 cd $MYDIR 189 190 if test ! -f JavacBench.jar; then 191 cat > JavacBench.java <<EOF 192 //this file is auto-generated. Do not add to source control and do not edit. 193 //import org.openjdk.jmh.annotations.*; 194 195 import javax.tools.*; 196 import java.io.*; 197 import java.net.URI; 198 import java.util.*; 199 200 //@State(Scope.Benchmark) 201 public class JavacBench { 202 static class ClassFile extends SimpleJavaFileObject { 203 private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 204 protected ClassFile(String name) { 205 super(URI.create("memo:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); 206 } 207 @Override 208 public ByteArrayOutputStream openOutputStream() { return this.baos; } 209 byte[] toByteArray() { return baos.toByteArray(); } 210 } 211 static class FileManager extends ForwardingJavaFileManager<JavaFileManager> { 212 private Map<String, ClassFile> classesMap = new HashMap<String, ClassFile>(); 213 protected FileManager(JavaFileManager fileManager) { 214 super(fileManager); 215 } 216 @Override 217 public ClassFile getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject source) { 218 ClassFile classFile = new ClassFile(name); 219 classesMap.put(name, classFile); 220 return classFile; 221 } 222 public Map<String, byte[]> getByteCode() { 223 Map<String, byte[]> result = new HashMap<>(); 224 for (Map.Entry<String, ClassFile> entry : classesMap.entrySet()) { 225 result.put(entry.getKey(), entry.getValue().toByteArray()); 226 } 227 return result; 228 } 229 } 230 static class SourceFile extends SimpleJavaFileObject { 231 private CharSequence sourceCode; 232 public SourceFile(String name, CharSequence sourceCode) { 233 super(URI.create("memo:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); 234 this.sourceCode = sourceCode; 235 } 236 @Override 237 public CharSequence getCharContent(boolean ignore) { 238 return this.sourceCode; 239 } 240 } 241 242 public Object compile(int count) { 243 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 244 DiagnosticCollector<JavaFileObject> ds = new DiagnosticCollector<>(); 245 Collection<SourceFile> sourceFiles = sources10k.subList(0, count); 246 247 try (FileManager fileManager = new FileManager(compiler.getStandardFileManager(ds, null, null))) { 248 JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, sourceFiles); 249 if (task.call()) { 250 return fileManager.getByteCode(); 251 } else { 252 for (Diagnostic<? extends JavaFileObject> d : ds.getDiagnostics()) { 253 System.out.format("Line: %d, %s in %s", d.getLineNumber(), d.getMessage(null), d.getSource().getName()); 254 } 255 throw new InternalError("compilation failure"); 256 } 257 } catch (IOException e) { 258 throw new InternalError(e); 259 } 260 } 261 262 List<SourceFile> sources10k; 263 264 List<SourceFile> generate(int count) { 265 ArrayList<SourceFile> sources = new ArrayList<>(count); 266 for (int i = 0; i < count; i++) { 267 sources.add(new SourceFile("HelloWorld" + i, 268 "public class HelloWorld" + i + " {" + 269 " public static void main(String[] args) {" + 270 " System.out.println(\"Hellow World!\");" + 271 " }" + 272 "}")); 273 } 274 return sources; 275 } 276 //@Setup 277 public void setup() { 278 sources10k = generate(10_000); 279 } 280 281 public static void main(String args[]) throws Throwable { 282 JavacBench bench = new JavacBench(); 283 bench.setup(); 284 285 if (args.length >= 0) { 286 int count = Integer.parseInt(args[0]); 287 if (count > 0) { 288 bench.compile(count); 289 } 290 } 291 } 292 } 293 EOF 294 (set -x 295 rm -rf tmpclasses 296 mkdir -p tmpclasses 297 ${PRODUCT_BLD}/images/jdk/bin/javac -d tmpclasses JavacBench.java || exit 1 298 ${PRODUCT_BLD}/images/jdk/bin/jar cf JavacBench.jar -C tmpclasses . || exit 1 299 rm -rf tmpclasses 300 ) || exit 1 301 fi 302 303 #---------------------------------------------------------------------- 304 CMD="$JVM_AND_ARGS \ 305 -cp JavacBench.jar -XX:DumpLoadedClassList=javac.classlist \ 306 -Xlog:class+load=debug:file=javac.class+load.log \ 307 JavacBench 1000" 308 test-info "(STEP 1 of 5) Dump javac.classlist" && 309 if $CMD; then 310 ls -l javac.classlist 311 wc -l javac.classlist 312 record_success 313 # remove old log 314 rm -f javac.class+load.log.* 315 else 316 record_failure 317 fi 318 319 JSA=javac-static${JSA_SUFFIX}.jsa 320 321 #---------------------------------------------------------------------- 322 CMD="$JVM_AND_ARGS \ 323 -Xshare:dump -XX:SharedArchiveFile=$JSA \ 324 -XX:SharedClassListFile=javac.classlist \ 325 -XX:+AOTClassLinking \ 326 -cp JavacBench.jar \ 327 -Xlog:cds=debug,cds+class=debug,cds+resolve=debug:file=javac.staticdump.log::filesize=0" 328 test-info "(STEP 2 of 5) Create Static $JSA" && 329 if $CMD; then 330 ls -l $JSA 331 record_success 332 rm -f javac.staticdump.log.* 333 else 334 record_failure 335 fi 336 337 #---------------------------------------------------------------------- 338 CMD="$JVM_AND_ARGS $EXTRA_ARGS \ 339 -XX:SharedArchiveFile=$JSA \ 340 -cp JavacBench.jar JavacBench $LOOPS" 341 test-info "Run with $JSA" && 342 if $CMD; then 343 record_success 344 else 345 record_failure 346 fi 347 348 #---------------------------------------------------------------------- 349 CMD="$JVM_AND_ARGS $EXTRA_ARGS \ 350 -cp JavacBench.jar JavacBench $LOOPS" 351 test-info "Run with default archive" && 352 if $CMD; then 353 record_success 354 else 355 record_failure 356 fi 357 358 #---------------------------------------------------------------------- 359 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xshare:off -Xlog:cds=debug \ 360 -cp JavacBench.jar JavacBench $LOOPS" 361 test-info "Run without CDS" && 362 if $CMD; then 363 record_success 364 else 365 record_failure 366 fi 367 368 TESTS="1 2" 369 370 for i in $TESTS; do 371 if test $i = 2; then 372 REPLAY=" (With Training Data Replay)" 373 X1="-XX:+RecordTraining" 374 X2="-XX:+ReplayTraining" 375 STEP3="(STEP 3 of 5) " 376 STEP4="(STEP 4 of 5) " 377 STEP5="(STEP 5 of 5) " 378 fi 379 380 DYNJSA=javac-dynamic1${JSA_SUFFIX}-$i.jsa 381 382 #---------------------------------------------------------------------- 383 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xlog:cds=debug \ 384 -cp JavacBench.jar -XX:ArchiveClassesAtExit=$DYNJSA $X1 JavacBench $LOOPS" 385 test-info "Dump CDS dynamic archive$REPLAY" && 386 if $CMD; then 387 record_success 388 else 389 record_failure 390 fi 391 392 393 #---------------------------------------------------------------------- 394 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xlog:cds \ 395 -cp JavacBench.jar -XX:SharedArchiveFile=$DYNJSA $X2 JavacBench $LOOPS" 396 test-info "Use CDS dynamic archive$REPLAY" && 397 if $CMD; then 398 record_success 399 else 400 record_failure 401 fi 402 403 JSA2=javac-dynamic2${JSA_SUFFIX}-$i.jsa 404 if test "$JSA2" = "javac-dynamic2-2.jsa"; then 405 JSA2=javac-dynamic.jsa 406 fi 407 408 #---------------------------------------------------------------------- 409 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xlog:cds=debug,cds+class=debug:file=javac.dynamicdump.log::filesize=0 \ 410 -XX:SharedArchiveFile=$JSA -XX:ArchiveClassesAtExit=$JSA2 $X1 \ 411 -cp JavacBench.jar JavacBench $LOOPS" 412 test-info "${STEP3}Run with $JSA and dump profile in $JSA2${REPLAY}" && 413 if $CMD; then 414 record_success 415 else 416 record_failure 417 fi 418 419 #---------------------------------------------------------------------- 420 CMD="$JVM_AND_ARGS $EXTRA_ARGS \ 421 -XX:SharedArchiveFile=$JSA2 $X2 \ 422 -cp JavacBench.jar JavacBench $LOOPS" 423 test-info "Run with $JSA2 $REPLAY" && 424 if $CMD; then 425 record_success 426 else 427 record_failure 428 fi 429 430 #---------------------------------------------------------------------- 431 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xlog:scc*=warning:file=javac.scc-store.log::filesize=0 \ 432 -XX:SharedArchiveFile=$JSA2 $X2 -XX:+StoreCachedCode -XX:CachedCodeFile=${JSA2}-sc -XX:CachedCodeMaxSize=100M \ 433 -cp JavacBench.jar JavacBench $LOOPS" 434 test-info "${STEP4}Run with $JSA2 and generate AOT code" && 435 if $CMD; then 436 record_success 437 else 438 record_failure 439 fi 440 441 #---------------------------------------------------------------------- 442 CMD="$JVM_AND_ARGS $EXTRA_ARGS -Xlog:scc*=warning:file=javac.scc-load.log::filesize=0 \ 443 -XX:SharedArchiveFile=$JSA2 $X2 -XX:+LoadCachedCode -XX:CachedCodeFile=${JSA2}-sc \ 444 -cp JavacBench.jar JavacBench $LOOPS" 445 test-info "${STEP5}Final production run: with $JSA2 and load AOT code" && 446 if $CMD; then 447 record_success 448 else 449 record_failure 450 fi 451 done 452 453 echo ===SUMMARY=== 454 for (( i=1; i<=$TEST_NUM; i++ )) ; do 455 if test "${status[$i]}" != ""; then 456 echo ...................... 457 echo $i ${infos[$i]} = ${status[$i]} 458 echo " $(echo ${cmds[$i]})" 459 fi 460 done 461 462 if test "$somefailed" = "1"; then 463 echo "" 464 echo '***********************SOME TESTS FAILED ********************************************' 465 echo "" 466 for (( i=1; i<=$TEST_NUM; i++ )) ; do 467 if test "${status[$i]}" = "FAILED"; then 468 echo $i ${infos[$i]} = ${status[$i]} 469 fi 470 done 471 echo "" 472 elif test "$somepassed" = "1"; then 473 echo "" 474 echo '*** all passed *****' 475 echo "" 476 fi