8381968: Extend cds/appcds/aotCode/AOTCodeFlags.java to run test with different flags in assembly and prod run

Reviewed-by: kvn, adinn
This commit is contained in:
Ashutosh Mehra 2026-04-15 14:30:30 +00:00
parent a06f3cd469
commit 974596775b
6 changed files with 310 additions and 79 deletions

View File

@ -587,7 +587,8 @@ hotspot_metaspace = \
tier1_runtime_appcds = \
runtime/cds/appcds/aotCache/HelloAOTCache.java \
runtime/cds/appcds/aotCode \
runtime/cds/appcds/HelloTest.java
runtime/cds/appcds/HelloTest.java \
-runtime/cds/appcds/aotCode/AOTCodeFlags.java
tier1_runtime_appcds_exclude = \
runtime/cds/appcds/ \

View File

@ -31,13 +31,9 @@
* @comment The test verifies AOT checks during VM startup and not code generation.
* No need to run it with -Xcomp.
* @library /test/lib /test/setup_aot
* @build AOTCodeCPUFeatureIncompatibilityTest JavacBenchApp
* @build AOTCodeCPUFeatureIncompatibilityTest HelloWorld
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloWorld
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI AOTCodeCPUFeatureIncompatibilityTest
*/
@ -98,9 +94,7 @@ public class AOTCodeCPUFeatureIncompatibilityTest {
}
@Override
public String[] appCommandLine(RunMode runMode) {
return new String[] {
"JavacBenchApp", "10"
};
return new String[] { "HelloWorld" };
}
}.runAOTWorkflow("--two-step-training");
}

View File

@ -33,12 +33,8 @@
* No need to run it with -Xcomp. It takes a lot of time to complete all
* subtests with this flag.
* @library /test/lib /test/setup_aot
* @build AOTCodeCompressedOopsTest JavacBenchApp
* @run driver/timeout=480 jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @build AOTCodeCompressedOopsTest HelloWorld
* @run driver/timeout=480 jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloWorld
* @run driver/timeout=480 AOTCodeCompressedOopsTest
*/
@ -149,9 +145,7 @@ public class AOTCodeCompressedOopsTest {
@Override
public String[] appCommandLine(RunMode runMode) {
return new String[] {
"JavacBenchApp", "10"
};
return new String[] { "HelloWorld" };
}
@Override

View File

@ -109,39 +109,44 @@ public class AOTCodeFlags {
private static String gcName = null;
public static void main(String... args) throws Exception {
Tester t = new Tester(args.length == 0 ? null : args[0]);
// Run only 2 modes (0 - no AOT code, 1 - AOT adapters) until JDK-8357398 is fixed
for (int mode = 0; mode < 4; mode++) {
t.setTestMode(mode);
t.run(new String[] {"AOT", "--two-step-training"});
// mode bits 0 and 1 encode AOTAdapterCaching and AOTStubCaching settings
// aMode is used for assembly run, pMode for production run
for (int aMode = 0; aMode < 4; aMode++) {
for (int pMode = 0; pMode < 4; pMode++) {
t.setTestMode(aMode, pMode);
t.run(new String[] {"AOT", "--two-step-training"});
}
}
}
static class Tester extends CDSAppTester {
private int testMode;
private int aMode, pMode;
private String gcName;
public Tester(String name) {
super("AOTCodeFlags");
testMode = 0;
aMode = 0;
pMode = 0;
gcName = name;
}
boolean isAdapterCachingOn() {
return (testMode & 0x1) != 0;
boolean isAdapterCachingOn(int mode) {
return (mode & 0x1) != 0;
}
boolean isStubCachingOn() {
return (testMode & 0x2) != 0;
boolean isStubCachingOn(int mode) {
return (mode & 0x2) != 0;
}
public void setTestMode(int mode) {
testMode = mode;
public void setTestMode(int aMode, int pMode) {
this.aMode = aMode;
this.pMode = pMode;
}
public List<String> getVMArgsForTestMode() {
public List<String> getVMArgsForTestMode(int mode) {
List<String> list = new ArrayList<String>();
list.add("-XX:+UnlockDiagnosticVMOptions");
list.add(isAdapterCachingOn() ? "-XX:+AOTAdapterCaching" : "-XX:-AOTAdapterCaching");
list.add(isStubCachingOn() ? "-XX:+AOTStubCaching" : "-XX:-AOTStubCaching");
list.add(isAdapterCachingOn(mode) ? "-XX:+AOTAdapterCaching" : "-XX:-AOTAdapterCaching");
list.add(isStubCachingOn(mode) ? "-XX:+AOTStubCaching" : "-XX:-AOTStubCaching");
return list;
}
@ -170,79 +175,91 @@ public class AOTCodeFlags {
@Override
public String[] vmArgs(RunMode runMode) {
List<String> args = getGCArgs();
args.addAll(List.of("-Xlog:aot+codecache+init=debug",
"-Xlog:aot+codecache+exit=debug",
"-Xlog:aot+codecache+stubs=debug"));
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION: {
List<String> args = getVMArgsForTestMode();
args.addAll(List.of("-Xlog:aot+codecache+init=debug",
"-Xlog:aot+codecache+exit=debug"));
args.addAll(getGCArgs());
return args.toArray(new String[0]);
}
args.addAll(getVMArgsForTestMode(aMode));
break;
case RunMode.PRODUCTION:
args.addAll(getVMArgsForTestMode(pMode));
break;
default:
break;
}
List<String> args = getGCArgs();
return args.toArray(new String[args.size()]);
}
@Override
public String[] appCommandLine(RunMode runMode) {
return new String[] {
"JavacBenchApp", "10"
};
return new String[] { "JavacBenchApp", "10" };
}
@Override
public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {
if (!isAdapterCachingOn() && !isStubCachingOn()) { // this is equivalent to completely disable AOT code cache
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION:
if (runMode == RunMode.ASSEMBLY) {
if (!isAdapterCachingOn(aMode) && !isStubCachingOn(aMode)) { // this is equivalent to completely disable AOT code cache
out.shouldNotMatch("Adapters:\\s+total");
out.shouldNotMatch("Shared Blobs:\\s+total");
out.shouldNotMatch("C1 Blobs:\\s+total");
out.shouldNotMatch("C2 Blobs:\\s+total");
break;
}
} else {
if (isAdapterCachingOn()) {
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION:
// AOTAdapterCaching is on, non-zero adapters should be stored/loaded
out.shouldMatch("Adapters:\\s+total=[1-9][0-9]+");
break;
}
} else {
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION:
// AOTAdapterCaching is off, no adapters should be stored/loaded
if (isAdapterCachingOn(aMode)) {
// AOTAdapterCaching is on, non-zero adapters should be stored
out.shouldMatch("Adapters:\\s+total=[1-9][0-9]+");
} else {
// AOTAdapterCaching is off, no adapters should be stored
out.shouldMatch("Adapters:\\s+total=0");
break;
}
}
if (isStubCachingOn()) {
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION:
// AOTStubCaching is on, non-zero stubs should be stored/loaded
if (isStubCachingOn(aMode)) {
// AOTStubCaching is on, non-zero stubs should be stored
out.shouldMatch("Shared Blobs:\\s+total=[1-9][0-9]+");
out.shouldMatch("C1 Blobs:\\s+total=[1-9][0-9]+");
// we do not currently load or store C2 stubs
// because we are seeing weird memory errors
// when loading them -- see JDK-8357593
out.shouldMatch("C2 Blobs:\\s+total=0");
break;
}
} else {
switch (runMode) {
case RunMode.ASSEMBLY:
case RunMode.PRODUCTION:
// AOTStubCaching is off, no stubs should be stored/loaded
} else {
// AOTStubCaching is off, no stubs should be stored
out.shouldMatch("Shared Blobs:\\s+total=0");
out.shouldMatch("C1 Blobs:\\s+total=0");
out.shouldMatch("C2 Blobs:\\s+total=0");
break;
}
}
} else if (runMode == RunMode.PRODUCTION) {
// Irrespective of assembly run mode, if both adapter and stub caching is disabled
// in production run, then it is equivalent to completely disabling AOT code cache
if (!isAdapterCachingOn(pMode) && !isStubCachingOn(pMode)) {
out.shouldNotMatch("Adapters:\\s+total");
out.shouldNotMatch("Shared Blobs:\\s+total");
out.shouldNotMatch("C1 Blobs:\\s+total");
out.shouldNotMatch("C2 Blobs:\\s+total");
} else {
// If AOT code cache is effectively disabled in the assembly run, then production run
// would emit empty code cache message.
if (!isAdapterCachingOn(aMode) && !isStubCachingOn(aMode)) {
if (isAdapterCachingOn(pMode) || isStubCachingOn(pMode)) {
out.shouldMatch("AOT Code Cache is empty");
}
} else {
if (isAdapterCachingOn(aMode)) {
if (isAdapterCachingOn(pMode)) {
out.shouldMatch("Read blob.*kind=Adapter.*");
} else {
out.shouldNotMatch("Read blob.*kind=Adapter.*");
}
}
if (isStubCachingOn(aMode)) {
if (isStubCachingOn(pMode)) {
out.shouldMatch("Read blob.*kind=SharedBlob.*");
out.shouldMatch("Read blob.*kind=C1Blob.*");
} else {
out.shouldNotMatch("Read blob.*kind=SharedBlob.*");
out.shouldNotMatch("Read blob.*kind=C1Blob.*");
}
}
}
}
}

View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test id=g1
* @requires vm.gc.G1
* @summary Sanity test of AOTCodeCache
* @requires vm.cds.supports.aot.code.caching
* @requires vm.compiler1.enabled & vm.compiler2.enabled
* @comment Both C1 and C2 JIT compilers are required because the test verifies
* compiler's runtime blobs generation.
* @requires vm.opt.VerifyOops == null | vm.opt.VerifyOops == false
* @comment VerifyOops flag switch off AOT code generation. Skip it.
* @library /test/lib /test/setup_aot
* @build AOTCodeTest JavacBenchApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver/timeout=1500 AOTCodeTest G1
*/
/**
* @test id=parallel
* @requires vm.gc.Parallel
* @summary Sanity test of AOTCodeCache
* @requires vm.cds.supports.aot.code.caching
* @requires vm.compiler1.enabled & vm.compiler2.enabled
* @comment Both C1 and C2 JIT compilers are required because the test verifies
* compiler's runtime blobs generation.
* @requires vm.opt.VerifyOops == null | vm.opt.VerifyOops == false
* @comment VerifyOops flag switch off AOT code generation. Skip it.
* @library /test/lib /test/setup_aot
* @build AOTCodeTest JavacBenchApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver/timeout=1500 AOTCodeTest Parallel
*/
/**
* @test id=serial
* @requires vm.gc.Serial
* @summary Sanity test of AOTCodeCache
* @requires vm.cds.supports.aot.code.caching
* @requires vm.compiler1.enabled & vm.compiler2.enabled
* @comment Both C1 and C2 JIT compilers are required because the test verifies
* compiler's runtime blobs generation.
* @requires vm.opt.VerifyOops == null | vm.opt.VerifyOops == false
* @comment VerifyOops flag switch off AOT code generation. Skip it.
* @library /test/lib /test/setup_aot
* @build AOTCodeTest JavacBenchApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver/timeout=1500 AOTCodeTest Serial
*/
/**
* @test id=shenandoah
* @requires vm.gc.Shenandoah
* @summary Sanity test of AOTCodeCache
* @requires vm.cds.supports.aot.code.caching
* @requires vm.compiler1.enabled & vm.compiler2.enabled
* @comment Both C1 and C2 JIT compilers are required because the test verifies
* compiler's runtime blobs generation.
* @requires vm.opt.VerifyOops == null | vm.opt.VerifyOops == false
* @comment VerifyOops flag switch off AOT code generation. Skip it.
* @library /test/lib /test/setup_aot
* @build AOTCodeTest JavacBenchApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver/timeout=1500 AOTCodeTest Shenandoah
*/
/**
* @test id=Z
* @requires vm.gc.Z
* @summary Sanity test of AOTCodeCache
* @requires vm.cds.supports.aot.code.caching
* @requires vm.compiler1.enabled & vm.compiler2.enabled
* @comment Both C1 and C2 JIT compilers are required because the test verifies
* compiler's runtime blobs generation.
* @requires vm.opt.VerifyOops == null | vm.opt.VerifyOops == false
* @comment VerifyOops flag switch off AOT code generation. Skip it.
* @library /test/lib /test/setup_aot
* @build AOTCodeTest JavacBenchApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
* JavacBenchApp
* JavacBenchApp$ClassFile
* JavacBenchApp$FileManager
* JavacBenchApp$SourceFile
* @run driver/timeout=1500 AOTCodeTest Z
*/
import java.util.ArrayList;
import java.util.List;
import jdk.test.lib.cds.CDSAppTester;
import jdk.test.lib.process.OutputAnalyzer;
public class AOTCodeTest {
private static String gcName = null;
public static void main(String... args) throws Exception {
if (args.length == 0) {
throw new RuntimeException("Expected GC name");
}
Tester t = new Tester(args[0]);
t.run(new String[] {"AOT", "--two-step-training"});
}
static class Tester extends CDSAppTester {
private String gcName;
public Tester(String name) {
super("AOTCodeTest");
gcName = name;
}
public List<String> getGCArgs() {
List<String> args = new ArrayList<String>();
args.add("-Xmx100M");
switch (gcName) {
case "G1":
case "Parallel":
case "Serial":
case "Shenandoah":
case "Z":
args.add("-XX:+Use" + gcName + "GC");
return args;
default:
throw new RuntimeException("Unexpected GC name " + gcName);
}
}
@Override
public String classpath(RunMode runMode) {
return "app.jar";
}
@Override
public String[] vmArgs(RunMode runMode) {
List<String> args = getGCArgs();
// Add flags for logs
args.addAll(List.of("-Xlog:aot+codecache+init=debug",
"-Xlog:aot+codecache+exit=debug",
"-Xlog:aot+codecache+stubs=debug"));
// Add diagnostic flags
args.addAll(List.of("-XX:+UnlockDiagnosticVMOptions",
"-XX:+AbortVMOnAOTCodeFailure"));
return args.toArray(new String[args.size()]);
}
@Override
public String[] appCommandLine(RunMode runMode) {
return new String[] { "JavacBenchApp", "10" };
}
@Override
public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {
if (runMode == RunMode.ASSEMBLY) {
out.shouldMatch("aot,codecache,exit.*\\s+AOT code cache size: [1-9]\\d+ bytes");
} else if (runMode == RunMode.PRODUCTION) {
out.shouldMatch("aot,codecache,init.*\\s+Loaded [1-9]\\d+ AOT code entries from AOT Code Cache");
out.shouldMatch("aot,codecache,stubs.*\\s+Read blob.*kind=Adapter.*");
out.shouldMatch("aot,codecache,stubs.*\\s+Read blob.*kind=SharedBlob.*");
out.shouldMatch("aot,codecache,stubs.*\\s+Read blob.*kind=C1Blob.*");
}
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
public class HelloWorld {
public static void main(String args[]) {
System.out.println("HelloWorld");
}
}