From 38499b3fbfcd22252ddf860d42b9eb0bf6f77235 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 18 Mar 2025 00:49:36 +0000 Subject: [PATCH] 8352084: Add more test code in TestSetupAOT.java Reviewed-by: erikj, kvn, lmesnik --- make/RunTests.gmk | 25 +-- make/test/BuildTestSetupAOT.gmk | 6 +- .../cds/appcds/applications/JavacBench.java | 6 +- .../JavacBenchApp.java | 0 test/setup_aot/TestSetupAOT.java | 173 +++++++++++++++++- 5 files changed, 184 insertions(+), 26 deletions(-) rename test/{hotspot/jtreg/runtime/cds/appcds/applications => setup_aot}/JavacBenchApp.java (100%) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 37193fb8171..4f81c096a33 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -732,14 +732,16 @@ endef # SetupAOT = $(NamedParamsMacroTemplate) define SetupAOTBody - $1_AOT_JDK_CONF := $$($1_TEST_SUPPORT_DIR)/aot/jdk.aotconf - $1_AOT_JDK_CACHE := $$($1_TEST_SUPPORT_DIR)/aot/jdk.aotcache - $1_AOT_JDK_LOG := $$($1_TEST_SUPPORT_DIR)/aot/TestSetupAOT.log + $1_AOT_JDK_OUTPUT_DIR := $$($1_TEST_SUPPORT_DIR)/aot + $1_AOT_JDK_CONF := $$($1_AOT_JDK_OUTPUT_DIR)/jdk.aotconf + $1_AOT_JDK_CACHE := $$($1_AOT_JDK_OUTPUT_DIR)/jdk.aotcache + $1_AOT_JDK_LOG := $$($1_AOT_JDK_OUTPUT_DIR)/TestSetupAOT.log - # We execute the training run with $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.class + # We execute the training run with the TestSetupAOT class from $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar # to touch a fair number of classes inside the JDK. Note that we can't specify a classpath, # or else the AOT cache cannot be used with jtreg test cases that use a different value - # for their classpaths. Instead, we run in the $(TEST_IMAGE_DIR)/setup_aot/ directory. + # for their classpaths. Instead, we cd in the $$($1_AOT_JDK_OUTPUT_DIR) directory, + # extract the TestSetupAOT.jar there, and run in that directory without specifying a classpath. # The "java" launcher will have an implicit classpath of ".", so it can pick up the TestSetupAOT # class from the JVM's current directory. # @@ -748,19 +750,20 @@ define SetupAOTBody # only classes from the JDK. $$($1_AOT_JDK_CACHE): $$(JDK_IMAGE_DIR)/release - $$(call MakeDir, $$($1_TEST_SUPPORT_DIR)/aot) + $$(call MakeDir, $$($1_AOT_JDK_OUTPUT_DIR)) $$(call LogWarn, AOT: Create cache configuration) \ - $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ - $(CD) $(TEST_IMAGE_DIR)/setup_aot; \ + $$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \ + cd $$($1_AOT_JDK_OUTPUT_DIR); \ + $(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \ $$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \ - -Xlog:cds,cds+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error \ + -Xlog:class+load,cds,cds+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error \ -XX:AOTMode=record -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) \ - TestSetupAOT > $$($1_AOT_JDK_LOG) \ + TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \ )) $$(call LogWarn, AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS)) - $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ + $$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \ $$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \ $$($1_VM_OPTIONS) -Xlog:cds,cds+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error \ -XX:ExtraSharedClassListFile=$(JDK_UNDER_TEST)/lib/classlist \ diff --git a/make/test/BuildTestSetupAOT.gmk b/make/test/BuildTestSetupAOT.gmk index 46b18005366..0b6376c0d89 100644 --- a/make/test/BuildTestSetupAOT.gmk +++ b/make/test/BuildTestSetupAOT.gmk @@ -37,12 +37,13 @@ include JavaCompilation.gmk SETUP_AOT_BASEDIR := $(TOPDIR)/test/setup_aot SETUP_AOT_SUPPORT := $(SUPPORT_OUTPUTDIR)/test/setup_aot -SETUP_AOT_CLASS := $(SETUP_AOT_SUPPORT)/classes/TestSetupAOT.class +SETUP_AOT_JAR := $(SETUP_AOT_SUPPORT)/TestSetupAOT.jar $(eval $(call SetupJavaCompilation, BUILD_SETUP_AOT, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ SRC := $(SETUP_AOT_BASEDIR), \ BIN := $(SETUP_AOT_SUPPORT)/classes, \ + JAR := $(SETUP_AOT_JAR), \ )) TARGETS += $(BUILD_SETUP_AOT) @@ -53,9 +54,8 @@ TARGETS += $(BUILD_SETUP_AOT) # Copy to hotspot jtreg test image $(eval $(call SetupCopyFiles, COPY_SETUP_AOT, \ - SRC := $(SETUP_AOT_SUPPORT)/classes, \ DEST := $(TEST_IMAGE_DIR)/setup_aot, \ - FILES := TestSetupAOT.class, \ + FILES := $(SETUP_AOT_JAR), \ )) IMAGES_TARGETS += $(COPY_SETUP_AOT) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBench.java b/test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBench.java index 332f2fc909e..3034a7e92ae 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBench.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBench.java @@ -26,7 +26,7 @@ * @test id=static * @summary Run JavacBenchApp with the classic static archive workflow * @requires vm.cds - * @library /test/lib + * @library /test/lib /test/setup_aot * @run driver JavacBench STATIC */ @@ -34,7 +34,7 @@ * @test id=dynamic * @summary Run JavacBenchApp with the classic dynamic archive workflow * @requires vm.cds - * @library /test/lib + * @library /test/lib /test/setup_aot * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. JavacBench DYNAMIC @@ -45,7 +45,7 @@ * @requires vm.cds.supports.aot.class.linking * @summary Run JavacBenchApp with AOT cache (JEP 483) * @requires vm.cds - * @library /test/lib + * @library /test/lib /test/setup_aot * @run driver JavacBench AOT */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBenchApp.java b/test/setup_aot/JavacBenchApp.java similarity index 100% rename from test/hotspot/jtreg/runtime/cds/appcds/applications/JavacBenchApp.java rename to test/setup_aot/JavacBenchApp.java diff --git a/test/setup_aot/TestSetupAOT.java b/test/setup_aot/TestSetupAOT.java index 1cae8bae246..89a6dd30c72 100644 --- a/test/setup_aot/TestSetupAOT.java +++ b/test/setup_aot/TestSetupAOT.java @@ -23,7 +23,15 @@ * questions. */ +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.spi.ToolProvider; +import java.util.stream.Stream; +import static java.util.stream.Collectors.*; // This program is executed by make/RunTests.gmk to support running HotSpot tests // in the "AOT mode", for example: @@ -44,16 +52,163 @@ import java.util.spi.ToolProvider; // the customized AOT cache contains *only* classes from the JDK itself. public class TestSetupAOT { + private static final Logger LOGGER = Logger.getLogger("Hello"); + public static void main(String[] args) throws Throwable { - String[] tools = { - "javac", "javap", "jlink", "jar", - }; - // TODO: we should do more substantial work than just running with "--help". - // E.g., use javac to compile a program. - for (String tool : tools) { - ToolProvider t = ToolProvider.findFirst(tool) - .orElseThrow(() -> new RuntimeException(tool + " not found")); - t.run(System.out, System.out, "--help"); + runJDKTools(args); + invokedynamicTests(args); + LOGGER.log(Level.FINE, "Done"); + } + + static void runJDKTools(String[] args) throws Throwable { + String tmpDir = args[0]; + System.out.println("Working Directory = " + System.getProperty("user.dir")); + System.out.println("Temp output dir = " + tmpDir); + + // ------------------------------ + // javac + + execTool("javac", "--help"); + + JavacBenchApp.main(new String[] {"5"}); + + // ------------------------------ + // javap + + execTool("javap", "--help"); + execTool("javap", "-c", "-private", "-v", "-verify", + "java.lang.System", + "java/util/stream/IntStream", + "jdk.internal.module.ModuleBootstrap"); + + // ------------------------------ + // jlink + + String jlinkOutput = tmpDir + File.separator + "jlinkOutput"; + + execTool("jlink", "--help"); + execTool("jlink", "--list-plugins"); + + deleteAll(jlinkOutput); + execTool("jlink", "--add-modules", "java.base", "--strip-debug", "--output", jlinkOutput); + deleteAll(jlinkOutput); + + // ------------------------------ + // jar + + String jarOutput = tmpDir + File.separator + "tmp.jar"; + + execTool("jar", "--help"); + + deleteAll(jarOutput); + execTool("jar", "cvf", jarOutput, "TestSetupAOT.class"); + execTool("jar", "uvf", jarOutput, "TestSetupAOT.class"); + execTool("jar", "tvf", jarOutput); + execTool("jar", "--describe-module", "--file=" + jarOutput); + deleteAll(jarOutput); + + // ------------------------------ + // jdeps + + execTool("jdeps", "--help"); + execTool("jdeps", "-v", "TestSetupAOT.class"); + } + + static void deleteAll(String f) { + deleteAll(new File(f)); + } + + static void deleteAll(File f) { + File[] files = f.listFiles(); + if (files != null) { + for (File file : files) { + deleteAll(file); + } } + System.out.println("Deleting: " + f); + f.delete(); + } + + static void execTool(String tool, String... args) throws Throwable { + System.out.println("== Running tool ======================================================"); + System.out.print(tool); + for (String s : args) { + System.out.print(" " + s); + } + System.out.println(); + System.out.println("======================================================================"); + + ToolProvider t = ToolProvider.findFirst(tool) + .orElseThrow(() -> new RuntimeException(tool + " not found")); + t.run(System.out, System.out, args); + } + + + // Run some operations with java.util.stream, lambda expressions and string concatenation. This + // will lead to AOT resolution of invokedynamic call sites. + static void invokedynamicTests(String args[]) { + List strings = Arrays.asList("Hello", "World!"); + + String helloWorld = strings.parallelStream() + .filter(s -> s.contains("o")) + .map(s -> s.toLowerCase(Locale.ROOT)) + .collect(joining(",")); + + Stream.of(helloWorld.split("([,x-z]{1,3})([\\s]*)")) + .map(String::toString) + .forEach(System.out::println); + + // Common concatenation patterns + int i = args.length * 12357; // Seed with this so javac will not perform constant folding. + String s = String.valueOf(i); + + String SS = s + s; + String CS = "string" + s; + String SC = s + "string"; + String SCS = s + "string" + s; + String CSS = "string" + s + s; + String CSC = "string" + s + "string"; + String SSC = s + s + "string"; + String CSCS = "string" + s + "string" + s; + String SCSC = s + "string" + s + "string"; + String CSCSC = "string" + s + "string" + s + "string"; + String SCSCS = s + "string" + s + "string" + s; + String SSCSS = s + s + "string" + s + s; + String S5 = s + s + s + s + s; + String S6 = s + s + s + s + s + s; + String S7 = s + s + s + s + s + s + s; + String S8 = s + s + s + s + s + s + s + s; + String S9 = s + s + s + s + s + s + s + s + s; + String S10 = s + s + s + s + s + s + s + s + s + s; + + String CI = "string" + i; + String IC = i + "string"; + String SI = s + i; + String IS = i + s; + String CIS = "string" + i + s; + String CSCI = "string" + s + "string" + i; + String CIC = "string" + i + "string"; + String CICI = "string" + i + "string" + i; + + float f = 0.1f; + String CF = "string" + f; + String CFS = "string" + f + s; + String CSCF = "string" + s + "string" + f; + + char c = 'a'; + String CC = "string" + c; + String CCS = "string" + c + s; + String CSCC = "string" + s + "string" + c; + + long l = i + 12345678; + String CJ = "string" + l; + String JC = l + "string"; + String CJC = "string" + l + "string"; + String CJCJ = "string" + l + "string" + l; + String CJCJC = "string" + l + "string" + l + "string"; + double d = i / 2.0; + String CD = "string" + d; + String CDS = "string" + d + s; + String CSCD = "string" + s + "string" + d; } }