From 974596775b2b1fe048ec7de0e35dc6f8283d844a Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Wed, 15 Apr 2026 14:30:30 +0000 Subject: [PATCH] 8381968: Extend cds/appcds/aotCode/AOTCodeFlags.java to run test with different flags in assembly and prod run Reviewed-by: kvn, adinn --- test/hotspot/jtreg/TEST.groups | 3 +- .../AOTCodeCPUFeatureIncompatibilityTest.java | 12 +- .../aotCode/AOTCodeCompressedOopsTest.java | 12 +- .../cds/appcds/aotCode/AOTCodeFlags.java | 137 ++++++------ .../cds/appcds/aotCode/AOTCodeTest.java | 196 ++++++++++++++++++ test/setup_aot/HelloWorld.java | 29 +++ 6 files changed, 310 insertions(+), 79 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeTest.java create mode 100644 test/setup_aot/HelloWorld.java diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 6e9421e5c09..6623676d2ba 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -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/ \ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCPUFeatureIncompatibilityTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCPUFeatureIncompatibilityTest.java index e9e610330ad..aa7becdb6f8 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCPUFeatureIncompatibilityTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCPUFeatureIncompatibilityTest.java @@ -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"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java index 3b9458c14da..0fe11235749 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java @@ -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 diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java index d3c6a23efa0..01b64a7fff0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java @@ -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 getVMArgsForTestMode() { + public List getVMArgsForTestMode(int mode) { List list = new ArrayList(); 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 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 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 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.*"); + } + } } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeTest.java new file mode 100644 index 00000000000..2afcd802fc5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeTest.java @@ -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 getGCArgs() { + List args = new ArrayList(); + 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 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.*"); + } + } + } +} diff --git a/test/setup_aot/HelloWorld.java b/test/setup_aot/HelloWorld.java new file mode 100644 index 00000000000..e243dfb4e8e --- /dev/null +++ b/test/setup_aot/HelloWorld.java @@ -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"); + } +}