diff --git a/make/Main.gmk b/make/Main.gmk index 4690139e6adff..f2f1bce0e1062 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -753,6 +753,17 @@ $(eval $(call SetupTarget, test-image-lib, \ DEPS := build-test-lib, \ )) +$(eval $(call SetupTarget, build-test-setup-aot, \ + MAKEFILE := test/BuildTestSetupAOT, \ + DEPS := interim-langtools exploded-image, \ +)) + +$(eval $(call SetupTarget, test-image-setup-aot, \ + MAKEFILE := test/BuildTestSetupAOT, \ + TARGET := images, \ + DEPS := build-test-setup-aot, \ +)) + ifeq ($(BUILD_FAILURE_HANDLER), true) # Builds the failure handler jtreg extension $(eval $(call SetupTarget, build-test-failure-handler, \ @@ -1281,7 +1292,8 @@ all-docs-bundles: docs-jdk-bundles docs-javase-bundles docs-reference-bundles # This target builds the test image test-image: prepare-test-image test-image-jdk-jtreg-native \ test-image-demos-jdk test-image-libtest-jtreg-native \ - test-image-lib test-image-lib-native + test-image-lib test-image-lib-native \ + test-image-setup-aot ifneq ($(JVM_TEST_IMAGE_TARGETS), ) # If JVM_TEST_IMAGE_TARGETS is externally defined, use it instead of the diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 3e20de3f82ed0..616341a89019e 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -703,6 +703,9 @@ define SetJtregValue endif endef +################################################################################ +# Helper function for creating a customized AOT cache for running tests +################################################################################ # Parameter 1 is the name of the rule. # @@ -713,48 +716,47 @@ endef # $1_AOT_TARGETS List of all targets that the test rule will need to depend on # $1_AOT_JDK_CACHE The AOT cache file to be used to run the test with # -SetupAot = $(NamedParamsMacroTemplate) -define SetupAotBody - $1_AOT_JDK_CONF := $$($1_TEST_SUPPORT_DIR)/aot/jdk.aotconf +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_JAVA_TOOL_OPTS := $$(addprefix -J, $$($1_VM_OPTIONS)) + $1_AOT_JDK_LOG := $$($1_TEST_SUPPORT_DIR)/aot/TestSetupAOT.log + + # We execute the training run with $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.class + # 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. + # The "java" launcher will have an implicit classpath of ".", so it can pick up the TestSetupAOT + # class from the JVM's current directory. + # + # The TestSetupAOT class (or any other classes that are loaded from ".") will be excluded + # from the the AOT cache as "." is an unsupported location. As a result, the AOT cache will contain + # only classes from the JDK. $$($1_AOT_JDK_CACHE): $$(JDK_IMAGE_DIR)/release $$(call MakeDir, $$($1_TEST_SUPPORT_DIR)/aot) - $(foreach jtool, javac javap jlink jar, \ - $(info AOT: Create cache configuration for $(jtool)) \ - $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot.$(jtool), ( \ - $$(FIXPATH) $(JDK_UNDER_TEST)/bin/$(jtool) $$($1_JAVA_TOOL_OPTS) \ - -J-XX:AOTMode=record -J-XX:AOTConfiguration=$$($1_AOT_JDK_CONF).$(jtool) --help \ - )) - ) - - $$(info AOT: Copy $(JDK_UNDER_TEST)/lib/classlist to $$($1_AOT_JDK_CONF).jdk ) + $$(call LogWarn, AOT: Create cache configuration) \ $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ - $$(FIXPATH) $(CP) $(JDK_UNDER_TEST)/lib/classlist $$($1_AOT_JDK_CONF).jdk \ + $(CD) $(TEST_IMAGE_DIR)/setup_aot; \ + $$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \ + -Xlog: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) \ )) - $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).* > $$($1_AOT_JDK_CONF).temp - $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).temp | $(GREP) -v '#' | $(GREP) -v '@' | $(SORT) | \ - $(SED) -e 's/id:.*//g' | uniq \ - > $$($1_AOT_JDK_CONF) - $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).temp | $(GREP) '@cp' | $(SORT) \ - >> $$($1_AOT_JDK_CONF) - - $$(info AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS)) + $$(call LogWarn, AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS)) $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ - $$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \ - $$($1_VM_OPTIONS) -Xlog:cds,cds+class=debug:file=$$($1_AOT_JDK_CACHE).log \ - -XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \ + $$(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 \ + -XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \ )) $1_AOT_TARGETS += $$($1_AOT_JDK_CACHE) endef - SetupRunJtregTest = $(NamedParamsMacroTemplate) define SetupRunJtregTestBody $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1 @@ -946,11 +948,10 @@ define SetupRunJtregTestBody endif ifeq ($$(JTREG_AOT_JDK), true) - $$(info Add AOT target for $1) - $$(eval $$(call SetupAot, $1, VM_OPTIONS := $$(JTREG_ALL_OPTIONS) )) + $$(call LogWarn, Add AOT target for $1) + $$(eval $$(call SetupAOT, $1, VM_OPTIONS := $$(JTREG_ALL_OPTIONS) )) - $$(info AOT_TARGETS=$$($1_AOT_TARGETS)) - $$(info AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE)) + $$(call LogWarn, AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE)) $1_JTREG_BASIC_OPTIONS += -vmoption:-XX:AOTCache="$$($1_AOT_JDK_CACHE)" endif diff --git a/make/test/BuildTestSetupAOT.gmk b/make/test/BuildTestSetupAOT.gmk new file mode 100644 index 0000000000000..46b18005366dc --- /dev/null +++ b/make/test/BuildTestSetupAOT.gmk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2025, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +include MakeFileStart.gmk + +################################################################################ +# This file builds the TestSetupAOT.class, which is used by SetupAOT +# in ../RunTests.gmk +################################################################################ + +include CopyFiles.gmk +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 + +$(eval $(call SetupJavaCompilation, BUILD_SETUP_AOT, \ + TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ + SRC := $(SETUP_AOT_BASEDIR), \ + BIN := $(SETUP_AOT_SUPPORT)/classes, \ +)) + +TARGETS += $(BUILD_SETUP_AOT) + +################################################################################ +# Targets for building test-image. +################################################################################ + +# 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, \ +)) + +IMAGES_TARGETS += $(COPY_SETUP_AOT) + +images: $(IMAGES_TARGETS) + +.PHONY: images + +################################################################################ + +include MakeFileEnd.gmk diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 1b4b6ffb22c7a..9a5ac12b475da 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -443,10 +443,9 @@ void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, v error_index = 0; } - jio_fprintf(defaultStream::error_stream(), - "An error has occurred while processing class list file %s %zu:%d.\n", - _classlist_file, lineno(), (error_index + 1)); - jio_vfprintf(defaultStream::error_stream(), msg, ap); + st->print("An error has occurred while processing class list file %s %zu:%d.\n", + _classlist_file, lineno(), (error_index + 1)); + st->vprint(msg, ap); if (_line_len <= 0) { st->print("\n"); diff --git a/test/setup_aot/TestSetupAOT.java b/test/setup_aot/TestSetupAOT.java new file mode 100644 index 0000000000000..1cae8bae2461f --- /dev/null +++ b/test/setup_aot/TestSetupAOT.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +import java.util.spi.ToolProvider; + +// This program is executed by make/RunTests.gmk to support running HotSpot tests +// in the "AOT mode", for example: +// +// make test JTREG=AOT_JDK=true TEST=open/test/hotspot/jtreg/runtime/invokedynamic +// +// All JDK classes touched by this program will be stored into a customized AOT cache. +// This is a larger set of classes than those stored in the JDK's default CDS archive. +// This customized cache can also have additional optimizations that are not +// enabled in the default CDS archive. For example, AOT-linked classes and lambda +// expressions. In the future, it can also contain AOT profiles and AOT compiled methods. +// +// We can use this customized AOT cache to run various HotSpot tests to improve +// coverage on AOT. +// +// Note that make/RunTests.gmk loads this class using an implicit classpath of ".", so +// this class will be excluded from the customized AOT cache. As a result, +// the customized AOT cache contains *only* classes from the JDK itself. + +public class TestSetupAOT { + 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"); + } + } +}