diff --git a/.github/workflows/build-alpine-linux.yml b/.github/workflows/build-alpine-linux.yml index ac5870ca675..0d366a4bdd0 100644 --- a/.github/workflows/build-alpine-linux.yml +++ b/.github/workflows/build-alpine-linux.yml @@ -51,6 +51,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-linux: @@ -104,9 +108,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml index 3f4ba67f996..5aadaab05c9 100644 --- a/.github/workflows/build-cross-compile.yml +++ b/.github/workflows/build-cross-compile.yml @@ -40,6 +40,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-cross-compile: @@ -189,4 +193,4 @@ jobs: with: make-target: 'hotspot ${{ inputs.make-arguments }}' platform: linux-${{ matrix.target-cpu }} - if: steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true' + if: ((steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true') && inputs.dry-run == false) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 9c991eed419..f398625cb2c 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -61,6 +61,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false bundle-suffix: required: false type: string @@ -139,6 +143,7 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles @@ -147,3 +152,4 @@ jobs: debug-suffix: "${{ matrix.debug-level == 'debug' && '-debug' || '' }}" bundle-suffix: ${{ inputs.bundle-suffix }} static-suffix: ${{ inputs.static-suffix }} + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 90bb6af044f..0a12df668e5 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -54,6 +54,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false jobs: build-macos: @@ -118,9 +122,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 9bb43a8b83c..a3091b94cef 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -54,6 +54,10 @@ on: make-arguments: required: false type: string + dry-run: + required: false + type: boolean + default: false env: # These are needed to make the MSYS2 bash work properly @@ -139,6 +143,7 @@ jobs: # Set PATH to "", so just GITHUB_PATH is included PATH: '' shell: env /usr/bin/bash --login -eo pipefail {0} + if: ${{ inputs.dry-run == false }} - name: 'Build' id: build @@ -147,9 +152,11 @@ jobs: make-target: '${{ inputs.make-target }} ${{ inputs.make-arguments }}' platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} - name: 'Upload bundles' uses: ./.github/actions/upload-bundles with: platform: ${{ inputs.platform }} debug-suffix: '${{ matrix.suffix }}' + if: ${{ inputs.dry-run == false }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8c058440ad7..0d8663fab1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,9 +28,7 @@ name: 'OpenJDK GHA Sanity Checks' on: push: branches-ignore: - - master - pr/* - - jdk* workflow_dispatch: inputs: platforms: @@ -43,6 +41,9 @@ on: make-arguments: description: 'Additional make arguments' required: false + dry-run: + description: 'Dry run: skip actual builds and tests' + required: false concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -70,6 +71,7 @@ jobs: windows-x64: ${{ steps.include.outputs.windows-x64 }} windows-aarch64: ${{ steps.include.outputs.windows-aarch64 }} docs: ${{ steps.include.outputs.docs }} + dry-run: ${{ steps.include.outputs.dry-run }} steps: - name: 'Checkout the scripts' @@ -143,6 +145,35 @@ jobs: echo 'false' } + function check_dry_run() { + if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then + # Take the user-specified one. + echo '${{ github.event.inputs.dry-run }}' + return + elif [[ $GITHUB_EVENT_NAME == push ]]; then + # Cut out the real branch name + BRANCH=${GITHUB_REF##*/} + + # Dry run rebuilds the caches in current branch, so they can be reused + # for any child PR branches. Because of this, we want to trigger this + # workflow in master branch, so that actual PR branches can use the cache. + # This workflow would trigger every time contributors sync their master + # branches in their personal forks. + if [[ $BRANCH == "master" ]]; then + echo 'true' + return + fi + + # ...same for stabilization branches + if [[ $BRANCH =~ "jdk(.*)" ]]; then + echo 'true' + return + fi + fi + + echo 'false' + } + echo "linux-x64=$(check_platform linux-x64 linux x64)" >> $GITHUB_OUTPUT echo "linux-x64-variants=$(check_platform linux-x64-variants variants)" >> $GITHUB_OUTPUT echo "linux-cross-compile=$(check_platform linux-cross-compile cross-compile)" >> $GITHUB_OUTPUT @@ -152,6 +183,7 @@ jobs: echo "windows-x64=$(check_platform windows-x64 windows x64)" >> $GITHUB_OUTPUT echo "windows-aarch64=$(check_platform windows-aarch64 windows aarch64)" >> $GITHUB_OUTPUT echo "docs=$(check_platform docs)" >> $GITHUB_OUTPUT + echo "dry-run=$(check_dry_run)" >> $GITHUB_OUTPUT ### ### Build jobs @@ -166,6 +198,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64 == 'true' build-linux-x64-hs-nopch: @@ -180,6 +213,7 @@ jobs: extra-conf-options: '--disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-zero: @@ -194,6 +228,7 @@ jobs: extra-conf-options: '--with-jvm-variants=zero --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-minimal: @@ -208,6 +243,7 @@ jobs: extra-conf-options: '--with-jvm-variants=minimal --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-hs-optimized: @@ -223,6 +259,7 @@ jobs: extra-conf-options: '--with-debug-level=optimized --disable-precompiled-headers' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64-variants == 'true' build-linux-x64-static: @@ -238,6 +275,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} static-suffix: "-static" if: needs.prepare.outputs.linux-x64 == 'true' @@ -254,6 +292,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} # Upload static libs bundles separately to avoid interference with normal linux-x64 bundle. # This bundle is not used by testing jobs, but downstreams use it to check that # dependent projects, e.g. libgraal, builds fine. @@ -268,6 +307,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-cross-compile == 'true' build-alpine-linux-x64: @@ -278,6 +318,7 @@ jobs: platform: alpine-linux-x64 configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.alpine-linux-x64 == 'true' build-macos-x64: @@ -290,6 +331,7 @@ jobs: xcode-toolset-version: '14.3.1' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.macos-x64 == 'true' build-macos-aarch64: @@ -302,6 +344,7 @@ jobs: xcode-toolset-version: '15.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.macos-aarch64 == 'true' build-windows-x64: @@ -314,6 +357,7 @@ jobs: msvc-toolset-architecture: 'x86.x64' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.windows-x64 == 'true' build-windows-aarch64: @@ -328,6 +372,7 @@ jobs: extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.windows-aarch64 == 'true' build-docs: @@ -344,6 +389,7 @@ jobs: gcc-major-version: '10' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.docs == 'true' ### @@ -353,17 +399,20 @@ jobs: test-linux-x64: name: linux-x64 needs: + - prepare - build-linux-x64 uses: ./.github/workflows/test.yml with: platform: linux-x64 bootjdk-platform: linux-x64 runs-on: ubuntu-22.04 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} debug-suffix: -debug test-linux-x64-static: name: linux-x64-static needs: + - prepare - build-linux-x64 - build-linux-x64-static uses: ./.github/workflows/test.yml @@ -371,27 +420,32 @@ jobs: platform: linux-x64 bootjdk-platform: linux-x64 runs-on: ubuntu-22.04 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} static-suffix: "-static" test-macos-aarch64: name: macos-aarch64 needs: + - prepare - build-macos-aarch64 uses: ./.github/workflows/test.yml with: platform: macos-aarch64 bootjdk-platform: macos-aarch64 runs-on: macos-14 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} xcode-toolset-version: '15.4' debug-suffix: -debug test-windows-x64: name: windows-x64 needs: + - prepare - build-windows-x64 uses: ./.github/workflows/test.yml with: platform: windows-x64 bootjdk-platform: windows-x64 runs-on: windows-2025 + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} debug-suffix: -debug diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 665ae224372..f2c8916a369 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,10 @@ on: xcode-toolset-version: required: false type: string + dry-run: + required: false + type: boolean + default: false debug-suffix: required: false type: string @@ -147,6 +151,7 @@ jobs: platform: ${{ inputs.platform }} debug-suffix: ${{ matrix.debug-suffix }} static-suffix: ${{ inputs.static-suffix }} + if: ${{ inputs.dry-run == false }} - name: 'Install dependencies' run: | @@ -199,6 +204,7 @@ jobs: && bash ./.github/scripts/gen-test-summary.sh "$GITHUB_STEP_SUMMARY" "$GITHUB_OUTPUT" env: PATH: ${{ steps.path.outputs.value }} + if: ${{ inputs.dry-run == false }} # This is a separate step, since if the markdown from a step gets bigger than # 1024 kB it is skipped, but then the short summary above is still generated diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 3ec32971ed8..2667524df88 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -99,13 +99,16 @@ endif ################################################################################ # Setup the main compilation + +COMPILATION_OUTPUTDIR := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules) + $(eval $(call SetupJavaCompilation, $(MODULE), \ SMALL_JAVA := false, \ MODULE := $(MODULE), \ SRC := $(wildcard $(MODULE_SRC_DIRS)), \ INCLUDES := $(JDK_USER_DEFINED_FILTER), \ FAIL_NO_SRC := $(FAIL_NO_SRC), \ - BIN := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules), \ + BIN := $(COMPILATION_OUTPUTDIR), \ HEADERS := $(SUPPORT_OUTPUTDIR)/headers, \ CREATE_API_DIGEST := true, \ CLEAN := $(CLEAN), \ @@ -137,6 +140,15 @@ ifneq ($(COMPILER), bootjdk) MODULE_VALUECLASS_SRC_DIRS := $(call FindModuleValueClassSrcDirs, $(MODULE)) MODULE_VALUECLASS_SOURCEPATH := $(call GetModuleValueClassSrcPath) + # Temporarily compile valueclasses into a separate directory with the form: + # // + # and then copy the class files into: + # //META-INF/preview/ + # We cannot compile directly into the desired directory because it's the + # compiler which creates the original '//...' hierarchy. + VALUECLASS_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/$(VALUECLASSES_STR) + PREVIEW_OUTPUTDIR := $(COMPILATION_OUTPUTDIR)/$(MODULE)/META-INF/preview + ifneq ($(MODULE_VALUECLASS_SRC_DIRS),) $(eval $(call SetupJavaCompilation, $(MODULE)-$(VALUECLASSES_STR), \ SMALL_JAVA := false, \ @@ -144,7 +156,7 @@ ifneq ($(COMPILER), bootjdk) SRC := $(wildcard $(MODULE_VALUECLASS_SRC_DIRS)), \ INCLUDES := $(JDK_USER_DEFINED_FILTER), \ FAIL_NO_SRC := $(FAIL_NO_SRC), \ - BIN := $(SUPPORT_OUTPUTDIR)/$(VALUECLASSES_STR)/, \ + BIN := $(VALUECLASS_OUTPUTDIR)/, \ JAR := $(JDK_OUTPUTDIR)/lib/$(VALUECLASSES_STR)/$(MODULE)-$(VALUECLASSES_STR).jar, \ HEADERS := $(SUPPORT_OUTPUTDIR)/headers, \ DISABLED_WARNINGS := $(DISABLED_WARNINGS_java) preview, \ @@ -162,6 +174,14 @@ ifneq ($(COMPILER), bootjdk) TARGETS += $($(MODULE)-$(VALUECLASSES_STR)) + # Restructure the class file hierarchy from //... to /META-INF/preview//... + $(PREVIEW_OUTPUTDIR)/_copy_valueclasses.marker: $($(MODULE)-$(VALUECLASSES_STR)) + $(call MakeTargetDir) + $(CP) -R $(VALUECLASS_OUTPUTDIR)/$(MODULE)/. $(@D)/ + $(TOUCH) $@ + + TARGETS += $(PREVIEW_OUTPUTDIR)/_copy_valueclasses.marker + $(eval $(call SetupCopyFiles, $(MODULE)-copy-valueclass-jar, \ FILES := $(JDK_OUTPUTDIR)/lib/$(VALUECLASSES_STR)/$(MODULE)-$(VALUECLASSES_STR).jar, \ DEST := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/$(VALUECLASSES_STR), \ diff --git a/make/Main.gmk b/make/Main.gmk index d0568509a4e..d9433e722f0 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -1014,7 +1014,7 @@ else else ifeq ($(EXTERNAL_BUILDJDK), false) # When not cross compiling, the BUILD_JDK is the interim jdk image, and # the javac launcher is needed. - jdk.compiler-gendata: jdk.compiler-launchers + jdk.compiler-gendata: jdk.compiler-launchers java.base-launchers jdk.javadoc-gendata: jdk.compiler-launchers endif diff --git a/make/ToolsJdk.gmk b/make/ToolsJdk.gmk index f301ddb53d1..a7a2289f78a 100644 --- a/make/ToolsJdk.gmk +++ b/make/ToolsJdk.gmk @@ -78,6 +78,9 @@ TOOL_GENERATECACERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_class TOOL_GENERATEEXTRAPROPERTIES = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ build.tools.generateextraproperties.GenerateExtraProperties +TOOL_GENERATECASEFOLDING = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ + build.tools.generatecharacter.CaseFolding + TOOL_MAKEZIPREPRODUCIBLE = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ build.tools.makezipreproducible.MakeZipReproducible diff --git a/make/data/asan/asan_default_options.c b/make/data/asan/asan_default_options.c index 9e0887c5f67..70821045176 100644 --- a/make/data/asan/asan_default_options.c +++ b/make/data/asan/asan_default_options.c @@ -67,6 +67,8 @@ ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* CDECL __asan_default_opt #endif "print_suppressions=0," "handle_segv=0," + // A lot of libjsig related tests fail because of the link order check; so better avoid it + "verify_asan_link_order=0," // See https://github.com/google/sanitizers/issues/1322. Hopefully this is resolved // at some point and we can remove this option. "intercept_tls_get_addr=0"; diff --git a/make/data/ubsan/ubsan_default_options.c b/make/data/ubsan/ubsan_default_options.c index 05e4722e45a..5615436e39f 100644 --- a/make/data/ubsan/ubsan_default_options.c +++ b/make/data/ubsan/ubsan_default_options.c @@ -62,5 +62,8 @@ // thread so it is easier to track down. You can override these options by setting the environment // variable UBSAN_OPTIONS. ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __ubsan_default_options() { - return "halt_on_error=1,print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER); + return "halt_on_error=1," + "handle_segv=0," + "handle_sigbus=0," + "print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER); } diff --git a/make/devkit/createWindowsDevkit.sh b/make/devkit/createWindowsDevkit.sh index 757fb157ad4..7c55605c776 100644 --- a/make/devkit/createWindowsDevkit.sh +++ b/make/devkit/createWindowsDevkit.sh @@ -64,6 +64,30 @@ IS_WSL=`echo $UNAME_RELEASE | grep Microsoft` IS_MSYS=`echo $UNAME_OS | grep -i Msys` MSYS2_ARG_CONV_EXCL="*" # make "cmd.exe /c" work for msys2 CMD_EXE="cmd.exe /c" + +# Detect host architecture to determine devkit platform support +# Note: The devkit always includes x86, x64, and aarch64 libraries and tools +# The difference is in toolchain capabilities: +# - On x64|AMD64 hosts: aarch64 tools are cross-compilation tools (Hostx64/arm64) +# - On aarch64|ARMv8 hosts: aarch64 tools are native tools (Hostarm64/arm64) +HOST_ARCH=`echo $PROCESSOR_IDENTIFIER` +case $HOST_ARCH in + AMD64) + echo "Running on x64 host - generating devkit with native x86/x64 tools and cross-compiled aarch64 tools." + echo "For native aarch64 compilation tools, run this script on a Windows/aarch64 machine." + SUPPORTED_PLATFORMS="x86, x64 (native) and aarch64 (cross-compiled)" + ;; + ARMv8) + echo "Running on aarch64 host - generating devkit with native tools for all platforms (x86, x64, aarch64)." + SUPPORTED_PLATFORMS="x86, x64, and aarch64 (all native)" + ;; + *) + echo "Unknown host architecture: $HOST_ARCH" + echo "Proceeding with devkit generation - toolchain capabilities may vary." + SUPPORTED_PLATFORMS="x86, x64, and aarch64" + ;; +esac + if test "x$IS_CYGWIN" != "x"; then BUILD_ENV="cygwin" elif test "x$IS_MSYS" != "x"; then @@ -139,6 +163,7 @@ DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit" DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" echo "Creating devkit in $DEVKIT_ROOT" +echo "Platform support: $SUPPORTED_PLATFORMS" MSVCR_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}.dll VCRUNTIME_1_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}_1.dll @@ -156,7 +181,11 @@ REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION" echo "Copying VC..." rm -rf $DEVKIT_ROOT/VC mkdir -p $DEVKIT_ROOT/VC/bin -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ +if [ -d "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostarm64/arm64" ]; then + cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostarm64/arm64" $DEVKIT_ROOT/VC/bin/ +else + cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ +fi cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/ cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/ mkdir -p $DEVKIT_ROOT/VC/lib diff --git a/make/jdk/src/classes/build/tools/generatecharacter/CaseFolding.java b/make/jdk/src/classes/build/tools/generatecharacter/CaseFolding.java new file mode 100644 index 00000000000..9abc2059b6a --- /dev/null +++ b/make/jdk/src/classes/build/tools/generatecharacter/CaseFolding.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package build.tools.generatecharacter; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class CaseFolding { + + public static void main(String[] args) throws Throwable { + if (args.length != 3) { + System.err.println("Usage: java CaseFolding TemplateFile CaseFolding.txt CaseFolding.java"); + System.exit(1); + } + var templateFile = Paths.get(args[0]); + var caseFoldingTxt = Paths.get(args[1]); + var genSrcFile = Paths.get(args[2]); + var supportedTypes = "^.*; [CTS]; .*$"; + var caseFoldingEntries = Files.lines(caseFoldingTxt) + .filter(line -> !line.startsWith("#") && line.matches(supportedTypes)) + .map(line -> { + String[] cols = line.split("; "); + return new String[] {cols[0], cols[1], cols[2]}; + }) + .filter(cols -> { + // the folding case doesn't map back to the original char. + var cp1 = Integer.parseInt(cols[0], 16); + var cp2 = Integer.parseInt(cols[2], 16); + return Character.toUpperCase(cp2) != cp1 && Character.toLowerCase(cp2) != cp1; + }) + .map(cols -> String.format(" entry(0x%s, 0x%s)", cols[0], cols[2])) + .collect(Collectors.joining(",\n", "", "")); + + // hack, hack, hack! the logic does not pick 0131. just add manually to support 'I's. + // 0049; T; 0131; # LATIN CAPITAL LETTER I + final String T_0x0131_0x49 = String.format(" entry(0x%04x, 0x%04x),\n", 0x0131, 0x49); + + // Generate .java file + Files.write( + genSrcFile, + Files.lines(templateFile) + .map(line -> line.contains("%%%Entries") ? T_0x0131_0x49 + caseFoldingEntries : line) + .collect(Collectors.toList()), + StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } +} diff --git a/make/langtools/tools/propertiesparser/gen/ClassGenerator.java b/make/langtools/tools/propertiesparser/gen/ClassGenerator.java index e869d60bbc5..247537b4676 100644 --- a/make/langtools/tools/propertiesparser/gen/ClassGenerator.java +++ b/make/langtools/tools/propertiesparser/gen/ClassGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -47,6 +47,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; @@ -93,7 +94,9 @@ enum StubKind { FACTORY_FIELD_LINT("factory.decl.field.lint"), WILDCARDS_EXTENDS("wildcards.extends"), SUPPRESS_WARNINGS("suppress.warnings"), - LINT_CATEGORY("lint.category"); + LINT_CATEGORY("lint.category"), + DIAGNOSTIC_FLAGS_EMPTY("diagnostic.flags.empty"), + DIAGNOSTIC_FLAGS_NON_EMPTY("diagnostic.flags.non-empty"); /** stub key (as it appears in the property file) */ String key; @@ -259,17 +262,30 @@ List generateFactoryMethodsAndFields(FactoryKind k, String key, Message .map(MessageLine::lintCategory) .findFirst().orElse(null); //System.out.println("category for " + key + " = " + lintCategory); + String diagnosticFlags = lines.stream() + .filter(MessageLine::isDiagnosticFlags) + .map(MessageLine::diagnosticFlags) + .flatMap(Stream::of) + .map(s -> s.replace('-', '_')) + .map(s -> s.toUpperCase(Locale.ROOT)) + .collect(Collectors.joining(", ")); String factoryName = factoryName(key); if (msgInfo.getTypes().isEmpty()) { //generate field String factoryField; if (lintCategory == null) { factoryField = StubKind.FACTORY_FIELD.format(k.keyClazz, factoryName, + diagnosticFlags.isEmpty() ? + StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() : + StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags), "\"" + keyParts[0] + "\"", "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"", javadoc); } else { factoryField = StubKind.FACTORY_FIELD_LINT.format(k.keyClazz, factoryName, + diagnosticFlags.isEmpty() ? + StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() : + StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags), StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""), "\"" + keyParts[0] + "\"", "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"", @@ -287,11 +303,17 @@ List generateFactoryMethodsAndFields(FactoryKind k, String key, Message String methodBody; if (lintCategory == null) { methodBody = StubKind.FACTORY_METHOD_BODY.format(k.keyClazz, + diagnosticFlags.isEmpty() ? + StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() : + StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags), "\"" + keyParts[0] + "\"", "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"", argNames.stream().collect(Collectors.joining(", "))); } else { methodBody = StubKind.FACTORY_METHOD_BODY_LINT.format(k.keyClazz, + diagnosticFlags.isEmpty() ? + StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() : + StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags), StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""), "\"" + keyParts[0] + "\"", "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"", diff --git a/make/langtools/tools/propertiesparser/parser/Message.java b/make/langtools/tools/propertiesparser/parser/Message.java index 3c1191084ec..fb0809fb1bd 100644 --- a/make/langtools/tools/propertiesparser/parser/Message.java +++ b/make/langtools/tools/propertiesparser/parser/Message.java @@ -32,7 +32,8 @@ * A message within the message file. * A message is a series of lines containing a "name=value" property, * optionally preceded by a comment describing the use of placeholders - * such as {0}, {1}, etc within the property value. + * such as {0}, {1}, etc within the property value, a lint category, + * and/or a list of diagnostic flags. */ public final class Message { final MessageLine firstLine; @@ -49,7 +50,7 @@ public final class Message { public MessageInfo getMessageInfo() { if (messageInfo == null) { MessageLine l = firstLine.prev; - if (l != null && l.isLint()) { + while (l != null && (l.isLint() || l.isDiagnosticFlags())) { l = l.prev; } if (l != null && l.isInfo()) @@ -74,7 +75,7 @@ public List getLines(boolean includeAllPrecedingComments) { while (l.text.isEmpty()) l = l.next; } else { - if (l.prev != null && (l.prev.isInfo() || l.prev.isLint())) + while (l.prev != null && (l.prev.isInfo() || l.prev.isLint() || l.prev.isDiagnosticFlags())) l = l.prev; } diff --git a/make/langtools/tools/propertiesparser/parser/MessageLine.java b/make/langtools/tools/propertiesparser/parser/MessageLine.java index c73021e0827..f1a29c20255 100644 --- a/make/langtools/tools/propertiesparser/parser/MessageLine.java +++ b/make/langtools/tools/propertiesparser/parser/MessageLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -25,6 +25,7 @@ package propertiesparser.parser; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,6 +40,7 @@ public class MessageLine { static final Pattern infoPattern = Pattern.compile(String.format("# ([0-9]+: %s, )*[0-9]+: %s", typePattern.pattern(), typePattern.pattern())); static final Pattern lintPattern = Pattern.compile("# lint: ([a-z\\-]+)"); + static final Pattern diagnosticFlagsPattern = Pattern.compile("# flags: ([a-z\\-]+(, ([a-z\\-]+))*)"); public String text; MessageLine prev; @@ -69,6 +71,19 @@ public String lintCategory() { } } + public boolean isDiagnosticFlags() { + return diagnosticFlagsPattern.matcher(text).matches(); + } + + public String[] diagnosticFlags() { + Matcher matcher = diagnosticFlagsPattern.matcher(text); + if (matcher.matches()) { + return matcher.group(1).split(", ", -1); + } else { + return null; + } + } + boolean hasContinuation() { return (next != null) && text.endsWith("\\"); } diff --git a/make/langtools/tools/propertiesparser/resources/templates.properties b/make/langtools/tools/propertiesparser/resources/templates.properties index 991739aa403..81a9be2552c 100644 --- a/make/langtools/tools/propertiesparser/resources/templates.properties +++ b/make/langtools/tools/propertiesparser/resources/templates.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -27,6 +27,7 @@ toplevel.decl=\ package {0};\n\ \n\ {1}\n\ + import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;\n\ import com.sun.tools.javac.util.JCDiagnostic.Error;\n\ import com.sun.tools.javac.util.JCDiagnostic.Warning;\n\ import com.sun.tools.javac.util.JCDiagnostic.LintWarning;\n\ @@ -34,6 +35,10 @@ toplevel.decl=\ import com.sun.tools.javac.util.JCDiagnostic.Fragment;\n\ import com.sun.tools.javac.code.Lint.LintCategory;\n\ \n\ + import java.util.EnumSet;\n\ + \n\ + import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;\n\ + \n\ public class {2} '{'\n\ {3}\n\ '}'\n @@ -58,22 +63,22 @@ factory.decl.method.arg=\ arg{0} factory.decl.method.body=\ - return new {0}({1}, {2}, {3}); + return new {0}({1}, {2}, {3}, {4}); factory.decl.method.body.lint=\ - return new {0}({1}, {2}, {3}, {4}); + return new {0}({1}, {2}, {3}, {4}, {5}); factory.decl.field=\ /**\n\ ' '* {4}\n\ ' '*/\n\ - public static final {0} {1} = new {0}({2}, {3}); + public static final {0} {1} = new {0}({2}, {3}, {4}); factory.decl.field.lint=\ /**\n\ ' '* {5}\n\ ' '*/\n\ - public static final {0} {1} = new {0}({2}, {3}, {4}); + public static final {0} {1} = new {0}({2}, {3}, {4}, {5}); wildcards.extends=\ {0} @@ -84,3 +89,9 @@ suppress.warnings=\ lint.category=\ LintCategory.get({0}).get() +diagnostic.flags.empty=\ + EnumSet.noneOf(DiagnosticFlag.class) + +diagnostic.flags.non-empty=\ + EnumSet.of({0}) + diff --git a/make/modules/java.base/gensrc/GensrcRegex.gmk b/make/modules/java.base/gensrc/GensrcRegex.gmk index c46a029e2c2..a30f22b34d4 100644 --- a/make/modules/java.base/gensrc/GensrcRegex.gmk +++ b/make/modules/java.base/gensrc/GensrcRegex.gmk @@ -50,5 +50,22 @@ TARGETS += $(GENSRC_INDICCONJUNCTBREAK) ################################################################################ +GENSRC_CASEFOLDING := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/util/regex/CaseFolding.java + +CASEFOLDINGTEMP := $(MODULE_SRC)/share/classes/jdk/internal/util/regex/CaseFolding.java.template +CASEFOLDINGTXT := $(MODULE_SRC)/share/data/unicodedata/CaseFolding.txt + +$(GENSRC_CASEFOLDING): $(BUILD_TOOLS_JDK) $(CASEFOLDINGTEMP) $(CASEFOLDINGTXT) + $(call LogInfo, Generating $@) + $(call MakeTargetDir) + $(TOOL_GENERATECASEFOLDING) \ + $(CASEFOLDINGTEMP) \ + $(CASEFOLDINGTXT) \ + $(GENSRC_CASEFOLDING) + +TARGETS += $(GENSRC_CASEFOLDING) + +################################################################################ + endif # include guard include MakeIncludeEnd.gmk diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 44737179792..6c415ea10cb 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -92,10 +92,12 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ --add-exports java.base/jdk.internal.classfile.impl=ALL-UNNAMED \ --add-exports java.base/jdk.internal.event=ALL-UNNAMED \ --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.jimage=ALL-UNNAMED \ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED \ --add-exports java.base/jdk.internal.util=ALL-UNNAMED \ --add-exports java.base/jdk.internal.value=ALL-UNNAMED \ --add-exports java.base/jdk.internal.vm=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED \ --add-exports java.base/sun.invoke.util=ALL-UNNAMED \ --add-exports java.base/sun.security.util=ALL-UNNAMED \ --add-exports java.base/sun.security.util.math=ALL-UNNAMED \ diff --git a/src/demo/share/java2d/J2DBench/Makefile b/src/demo/share/java2d/J2DBench/Makefile index d9dd6258329..f8949845b4f 100644 --- a/src/demo/share/java2d/J2DBench/Makefile +++ b/src/demo/share/java2d/J2DBench/Makefile @@ -31,10 +31,10 @@ ifndef SOURCE -export SOURCE := 7 +export SOURCE := 8 endif ifndef TARGET -export TARGET := 7 +export TARGET := 8 endif ifndef JAVAC export JAVAC := javac diff --git a/src/demo/share/java2d/J2DBench/build.xml b/src/demo/share/java2d/J2DBench/build.xml index 2942e5fa260..d48b446d0f3 100644 --- a/src/demo/share/java2d/J2DBench/build.xml +++ b/src/demo/share/java2d/J2DBench/build.xml @@ -39,12 +39,12 @@ - + - + @@ -54,11 +54,6 @@ - - - - - @@ -70,7 +65,7 @@ - + store_parameter(rscratch1, 1); ce->store_parameter(_bci, 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::counter_overflow_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_counter_overflow_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ b(_continuation); @@ -65,7 +65,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ far_call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -78,13 +78,13 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { } else { __ mov(rscratch1, _index->as_jint()); } - C1StubId stub_id; + StubId stub_id; if (_throw_index_out_of_bounds_exception) { - stub_id = C1StubId::throw_index_exception_id; + stub_id = StubId::c1_throw_index_exception_id; } else { assert(_array != LIR_Opr::nullOpr(), "sanity"); __ mov(rscratch2, _array->as_pointer_register()); - stub_id = C1StubId::throw_range_check_failed_id; + stub_id = StubId::c1_throw_range_check_failed_id; } __ lea(lr, RuntimeAddress(Runtime1::entry_for(stub_id))); __ blr(lr); @@ -99,7 +99,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ far_call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -111,7 +111,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_throw_div0_exception_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); #ifdef ASSERT @@ -134,7 +134,7 @@ void LoadFlattenedArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_array->as_register(), 1); ce->store_parameter(_index->as_register(), 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::load_flat_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_load_flat_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); if (_result->as_register() != r0) { @@ -161,7 +161,7 @@ void StoreFlattenedArrayStub::emit_code(LIR_Assembler* ce) { ce->store_parameter(_array->as_register(), 2); ce->store_parameter(_index->as_register(), 1); ce->store_parameter(_value->as_register(), 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::store_flat_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_store_flat_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ b(_continuation); @@ -180,7 +180,7 @@ void SubstitutabilityCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_left->as_register(), 1); ce->store_parameter(_right->as_register(), 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::substitutability_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_substitutability_check_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ b(_continuation); @@ -189,14 +189,14 @@ void SubstitutabilityCheckStub::emit_code(LIR_Assembler* ce) { // Implementation of NewInstanceStub -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -230,7 +230,7 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_length->as_register() == r19, "length must in r19,"); assert(_klass_reg->as_register() == r3, "klass_reg must in r3"); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_type_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_type_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == r0, "result must in r0"); @@ -257,9 +257,9 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { assert(_klass_reg->as_register() == r3, "klass_reg must in r3"); if (_is_null_free) { - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_null_free_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_null_free_array_id))); } else { - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_object_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_object_array_id))); } ce->add_call_info_here(_info); @@ -283,11 +283,11 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) { ce->store_parameter(_obj_reg->as_register(), 1); ce->store_parameter(_lock_reg->as_register(), 0); - C1StubId enter_id; + StubId enter_id; if (ce->compilation()->has_fpu_code()) { - enter_id = C1StubId::monitorenter_id; + enter_id = StubId::c1_monitorenter_id; } else { - enter_id = C1StubId::monitorenter_nofpu_id; + enter_id = StubId::c1_monitorenter_nofpu_id; } __ far_call(RuntimeAddress(Runtime1::entry_for(enter_id))); ce->add_call_info_here(_info); @@ -304,11 +304,11 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { } ce->store_parameter(_lock_reg->as_register(), 0); // note: non-blocking leaf routine => no call info needed - C1StubId exit_id; + StubId exit_id; if (ce->compilation()->has_fpu_code()) { - exit_id = C1StubId::monitorexit_id; + exit_id = StubId::c1_monitorexit_id; } else { - exit_id = C1StubId::monitorexit_nofpu_id; + exit_id = StubId::c1_monitorexit_nofpu_id; } __ adr(lr, _continuation); __ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id))); @@ -336,7 +336,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_trap_request, 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::deoptimize_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_deoptimize_id))); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); } @@ -346,9 +346,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { address a; if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is probably wrong to do it here. - a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); } ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 5f4c727da04..9c7cac917b2 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -322,19 +322,19 @@ void LIR_Assembler::deoptimize_trap(CodeEmitInfo *info) { switch (patching_id(info)) { case PatchingStub::access_field_id: - target = Runtime1::entry_for(C1StubId::access_field_patching_id); + target = Runtime1::entry_for(StubId::c1_access_field_patching_id); reloc_type = relocInfo::section_word_type; break; case PatchingStub::load_klass_id: - target = Runtime1::entry_for(C1StubId::load_klass_patching_id); + target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; case PatchingStub::load_mirror_id: - target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); + target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; case PatchingStub::load_appendix_id: - target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); + target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); @@ -376,7 +376,7 @@ int LIR_Assembler::emit_exception_handler() { __ verify_not_null_oop(r0); // search an exception handler (r0: exception oop, r3: throwing pc) - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::handle_exception_from_callee_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_handle_exception_from_callee_id))); __ should_not_reach_here(); guarantee(code_offset() - offset <= exception_handler_size(), "overflow"); __ end_a_stub(); @@ -433,7 +433,7 @@ int LIR_Assembler::emit_unwind_handler() { // remove the activation and dispatch to the unwind handler __ block_comment("remove_frame and dispatch to the unwind handler"); __ remove_frame(initial_frame_size_in_bytes(), needs_stack_repair()); - __ far_jump(RuntimeAddress(Runtime1::entry_for(C1StubId::unwind_exception_id))); + __ far_jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_unwind_exception_id))); // Emit the slow path assembly if (stub != nullptr) { @@ -924,19 +924,19 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) { switch (patching_id(info)) { case PatchingStub::access_field_id: - target = Runtime1::entry_for(C1StubId::access_field_patching_id); + target = Runtime1::entry_for(StubId::c1_access_field_patching_id); reloc_type = relocInfo::section_word_type; break; case PatchingStub::load_klass_id: - target = Runtime1::entry_for(C1StubId::load_klass_patching_id); + target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; case PatchingStub::load_mirror_id: - target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); + target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; case PatchingStub::load_appendix_id: - target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); + target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); @@ -1424,7 +1424,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ br(Assembler::EQ, *success_target); __ stp(klass_RInfo, k_RInfo, Address(__ pre(sp, -2 * wordSize))); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ ldr(klass_RInfo, Address(__ post(sp, 2 * wordSize))); // result is a boolean __ cbzw(klass_RInfo, *failure_target); @@ -1435,7 +1435,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, nullptr); // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ stp(klass_RInfo, k_RInfo, Address(__ pre(sp, -2 * wordSize))); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ ldp(k_RInfo, klass_RInfo, Address(__ post(sp, 2 * wordSize))); // result is a boolean __ cbz(k_RInfo, *failure_target); @@ -1513,7 +1513,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, nullptr); // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ stp(klass_RInfo, k_RInfo, Address(__ pre(sp, -2 * wordSize))); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ ldp(k_RInfo, klass_RInfo, Address(__ post(sp, 2 * wordSize))); // result is a boolean __ cbzw(k_RInfo, *failure_target); @@ -2205,7 +2205,7 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit // exception object is not added to oop map by LinearScan // (LinearScan assumes that no oops are in fixed registers) info->add_register_oop(exceptionOop); - C1StubId unwind_id; + StubId unwind_id; // get current pc information // pc is only needed if the method has an exception handler, the unwind code does not need it. @@ -2224,9 +2224,9 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit __ verify_not_null_oop(r0); // search an exception handler (r0: exception oop, r3: throwing pc) if (compilation()->has_fpu_code()) { - unwind_id = C1StubId::handle_exception_id; + unwind_id = StubId::c1_handle_exception_id; } else { - unwind_id = C1StubId::handle_exception_nofpu_id; + unwind_id = StubId::c1_handle_exception_nofpu_id; } __ far_call(RuntimeAddress(Runtime1::entry_for(unwind_id))); @@ -2523,7 +2523,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, nullptr); __ PUSH(src, dst); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ POP(src, dst); __ cbnz(src, cont); diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp index c9db4f04eea..6e50b977642 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp @@ -333,7 +333,7 @@ void LIRGenerator::do_MonitorEnter(MonitorEnter* x) { CodeStub* throw_ie_stub = x->maybe_inlinetype() ? - new SimpleExceptionStub(C1StubId::throw_identity_exception_id, obj.result(), state_for(x)) : + new SimpleExceptionStub(StubId::c1_throw_identity_exception_id, obj.result(), state_for(x)) : nullptr; // this CodeEmitInfo must not have the xhandlers because here the @@ -1265,7 +1265,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); LIR_Opr reg = result_register_for(x->type()); - __ call_runtime(Runtime1::entry_for(C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for(StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); @@ -1296,14 +1296,14 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { CodeStub* stub; if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); stub = new DeoptimizeStub(info_for_exception, Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, obj.result(), info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, obj.result(), info_for_exception); } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; @@ -1341,7 +1341,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { // Intrinsic for Class::isInstance address LIRGenerator::isInstance_entry() { - return Runtime1::entry_for(C1StubId::is_instance_of_id); + return Runtime1::entry_for(StubId::c1_is_instance_of_id); } void LIRGenerator::do_If(If* x) { diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index 82cd489d8f6..4975485db06 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -282,7 +282,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == r0, "must be"); - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); @@ -323,7 +323,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == r0, "must be"); - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); @@ -397,9 +397,9 @@ int C1_MacroAssembler::scalarized_entry(const CompiledEntrySignature* ces, int f // FIXME -- call runtime only if we cannot in-line allocate all the incoming inline type args. mov(r19, (intptr_t) ces->method()); if (is_inline_ro_entry) { - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::buffer_inline_args_no_receiver_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_buffer_inline_args_no_receiver_id))); } else { - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::buffer_inline_args_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_buffer_inline_args_id))); } int rt_call_offset = offset(); diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 460342b3812..260cf5fc5da 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -99,10 +99,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre if (frame_size() == no_frame_size) { leave(); far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - } else if (_stub_id == (int)C1StubId::forward_exception_id) { + } else if (_stub_id == (int)StubId::c1_forward_exception_id) { should_not_reach_here(); } else { - far_jump(RuntimeAddress(Runtime1::entry_for(C1StubId::forward_exception_id))); + far_jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_forward_exception_id))); } bind(L); } @@ -350,8 +350,8 @@ void Runtime1::initialize_pd() { // return: offset in 64-bit words. uint Runtime1::runtime_blob_current_thread_offset(frame f) { CodeBlob* cb = f.cb(); - assert(cb == Runtime1::blob_for(C1StubId::monitorenter_id) || - cb == Runtime1::blob_for(C1StubId::monitorenter_nofpu_id), "must be"); + assert(cb == Runtime1::blob_for(StubId::c1_monitorenter_id) || + cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id), "must be"); assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame"); int offset = cpu_reg_save_offsets[rthread->encoding()]; return offset / 2; // SP offsets are in halfwords @@ -377,7 +377,7 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler *sasm) { __ block_comment("generate_handle_exception"); // incoming parameters @@ -389,7 +389,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) OopMapSet* oop_maps = new OopMapSet(); OopMap* oop_map = nullptr; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: // We're handling an exception in the context of a compiled frame. // The registers have been saved in the standard places. Perform // an exception lookup in the caller and dispatch to the handler @@ -409,12 +409,12 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ str(zr, Address(rthread, JavaThread::vm_result_oop_offset())); __ str(zr, Address(rthread, JavaThread::vm_result_metadata_offset())); break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { // At this point all registers except exception oop (r0) and // exception pc (lr) are dead. const int frame_size = 2 /*fp, return address*/; @@ -472,13 +472,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ str(r0, Address(rfp, 1*BytesPerWord)); switch (id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); + restore_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: break; default: ShouldNotReachHere(); } @@ -630,7 +630,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { const Register exception_oop = r0; const Register exception_pc = r3; @@ -647,7 +647,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { OopMap* oop_map = nullptr; switch (id) { { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); __ leave(); @@ -655,31 +655,31 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { Register klass = r3; // Incoming Register obj = r0; // Result - if (id == C1StubId::new_instance_id) { + if (id == StubId::c1_new_instance_id) { __ set_info("new_instance", dont_gc_arguments); - } else if (id == C1StubId::fast_new_instance_id) { + } else if (id == StubId::c1_fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { - assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId"); + assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId"); __ set_info("fast new_instance init check", dont_gc_arguments); } @@ -699,7 +699,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: { Register bci = r0, method = r1; __ enter(); @@ -717,17 +717,17 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: - case C1StubId::new_null_free_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: + case StubId::c1_new_null_free_array_id: { Register length = r19; // Incoming Register klass = r3; // Incoming Register obj = r0; // Result - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); - } else if (id == C1StubId::new_object_array_id) { + } else if (id == StubId::c1_new_object_array_id) { __ set_info("new_object_array", dont_gc_arguments); } else { __ set_info("new_null_free_array", dont_gc_arguments); @@ -741,19 +741,19 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ ldrw(t0, Address(klass, Klass::layout_helper_offset())); __ asrw(t0, t0, Klass::_lh_array_tag_shift); switch (id) { - case C1StubId::new_type_array_id: + case StubId::c1_new_type_array_id: __ cmpw(t0, Klass::_lh_array_tag_type_value); __ br(Assembler::EQ, ok); __ stop("assert(is a type array klass)"); break; - case C1StubId::new_object_array_id: + case StubId::c1_new_object_array_id: __ cmpw(t0, Klass::_lh_array_tag_ref_value); // new "[Ljava/lang/Object;" __ br(Assembler::EQ, ok); __ cmpw(t0, Klass::_lh_array_tag_flat_value); // new "[LVT;" __ br(Assembler::EQ, ok); __ stop("assert(is an object or inline type array klass)"); break; - case C1StubId::new_null_free_array_id: + case StubId::c1_new_null_free_array_id: __ cmpw(t0, Klass::_lh_array_tag_flat_value); // the array can be a flat array. __ br(Assembler::EQ, ok); __ cmpw(t0, Klass::_lh_array_tag_ref_value); // the array cannot be a flat array (due to the InlineArrayElementMaxFlatSize, etc.) @@ -770,12 +770,12 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ enter(); OopMap* map = save_live_registers(sasm); int call_offset; - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); - } else if (id == C1StubId::new_object_array_id) { + } else if (id == StubId::c1_new_object_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); } else { - assert(id == C1StubId::new_null_free_array_id, "must be"); + assert(id == StubId::c1_new_null_free_array_id, "must be"); call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length); } @@ -791,7 +791,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { StubFrame f(sasm, "new_multi_array", dont_gc_arguments); // r0,: klass // r19,: rank @@ -811,15 +811,15 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::buffer_inline_args_id: - case C1StubId::buffer_inline_args_no_receiver_id: + case StubId::c1_buffer_inline_args_id: + case StubId::c1_buffer_inline_args_no_receiver_id: { - const char* name = (id == C1StubId::buffer_inline_args_id) ? + const char* name = (id == StubId::c1_buffer_inline_args_id) ? "buffer_inline_args" : "buffer_inline_args_no_receiver"; StubFrame f(sasm, name, dont_gc_arguments); OopMap* map = save_live_registers(sasm); Register method = r19; // Incoming - address entry = (id == C1StubId::buffer_inline_args_id) ? + address entry = (id == StubId::c1_buffer_inline_args_id) ? CAST_FROM_FN_PTR(address, buffer_inline_args) : CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver); // This is called from a C1 method's scalarized entry point @@ -837,7 +837,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::load_flat_array_id: + case StubId::c1_load_flat_array_id: { StubFrame f(sasm, "load_flat_array", dont_gc_arguments); OopMap* map = save_live_registers(sasm); @@ -861,7 +861,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::store_flat_array_id: + case StubId::c1_store_flat_array_id: { StubFrame f(sasm, "store_flat_array", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 4); @@ -879,7 +879,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::substitutability_check_id: + case StubId::c1_substitutability_check_id: { StubFrame f(sasm, "substitutability_check", dont_gc_arguments); OopMap* map = save_live_registers(sasm); @@ -898,7 +898,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -930,31 +930,31 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; - case C1StubId::throw_illegal_monitor_state_exception_id: + case StubId::c1_throw_illegal_monitor_state_exception_id: { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false); } break; - case C1StubId::throw_identity_exception_id: + case StubId::c1_throw_identity_exception_id: { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true); } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // Typical calling sequence: // __ push(klass_RInfo); // object klass or other subclass @@ -1003,10 +1003,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorenter_nofpu_id: + case StubId::c1_monitorenter_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_id: { StubFrame f(sasm, "monitorenter", dont_gc_arguments, requires_pop_epilogue_return); OopMap* map = save_live_registers(sasm, save_fpu_registers); @@ -1024,7 +1024,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::is_instance_of_id: + case StubId::c1_is_instance_of_id: { // Mirror: c_rarg0 // Object: c_rarg1 @@ -1073,10 +1073,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: + case StubId::c1_monitorexit_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_id: { StubFrame f(sasm, "monitorexit", dont_gc_arguments); OopMap* map = save_live_registers(sasm, save_fpu_registers); @@ -1096,7 +1096,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { StubFrame f(sasm, "deoptimize", dont_gc_arguments, does_not_return); OopMap* oop_map = save_live_registers(sasm); @@ -1113,13 +1113,13 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { StubFrame f(sasm, "range_check_failed", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { __ set_info("unwind_exception", dont_gc_arguments); // note: no stubframe since we are about to leave the current // activation and we are calling a leaf VM function only. @@ -1127,54 +1127,54 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { StubFrame f(sasm, "access_field_patching", dont_gc_arguments, does_not_return); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { StubFrame f(sasm, "load_klass_patching", dont_gc_arguments, does_not_return); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments, does_not_return); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments, does_not_return); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { StubFrame f(sasm, "handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments, does_not_return); // tos + 0: link // + 1: return address @@ -1182,7 +1182,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments, does_not_return); @@ -1200,7 +1200,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::dtrace_object_alloc_id: + case StubId::c1_dtrace_object_alloc_id: { // c_rarg0: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); save_live_registers(sasm); diff --git a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp index e82162df4ab..2d751709b6b 100644 --- a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp @@ -67,6 +67,12 @@ inline frame FreezeBase::sender(const frame& f) { int slot = 0; CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap(sender_pc, slot); + + // Repair the sender sp if the frame has been extended + if (sender_cb->is_nmethod()) { + sender_sp = f.repair_sender_sp(sender_sp, link_addr); + } + return sender_cb != nullptr ? frame(sender_sp, sender_sp, *link_addr, sender_pc, sender_cb, slot == -1 ? nullptr : sender_cb->oop_map_for_slot(slot, sender_pc), @@ -75,7 +81,7 @@ inline frame FreezeBase::sender(const frame& f) { } template -frame FreezeBase::new_heap_frame(frame& f, frame& caller) { +frame FreezeBase::new_heap_frame(frame& f, frame& caller, int size_adjust) { assert(FKind::is_instance(f), ""); assert(!caller.is_interpreted_frame() || caller.unextended_sp() == (intptr_t*)caller.at(frame::interpreter_frame_last_sp_offset), ""); @@ -106,8 +112,8 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) { fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset); int fsize = FKind::size(f); - sp = caller.unextended_sp() - fsize; - if (caller.is_interpreted_frame()) { + sp = caller.unextended_sp() - fsize - size_adjust; + if (caller.is_interpreted_frame() && size_adjust == 0) { // If the caller is interpreted, our stackargs are not supposed to overlap with it // so we make more room by moving sp down by argsize int argsize = FKind::stack_argsize(f); @@ -180,11 +186,12 @@ inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) { : (intptr_t)hf.fp(); } -inline void FreezeBase::patch_pd(frame& hf, const frame& caller) { +inline void FreezeBase::patch_pd(frame& hf, const frame& caller, bool is_bottom_frame) { if (caller.is_interpreted_frame()) { assert(!caller.is_empty(), ""); patch_callee_link_relative(caller, caller.fp()); - } else { + } else if (is_bottom_frame && caller.pc() != nullptr) { + assert(caller.is_compiled_frame(), ""); // If we're the bottom-most frame frozen in this freeze, the caller might have stayed frozen in the chunk, // and its oop-containing fp fixed. We've now just overwritten it, so we must patch it back to its value // as read from the chunk. @@ -215,7 +222,7 @@ inline frame ThawBase::new_entry_frame() { return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state } -template frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) { +template frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom, int size_adjust) { assert(FKind::is_instance(hf), ""); // The values in the returned frame object will be written into the callee's stack in patch. @@ -243,24 +250,23 @@ template frame ThawBase::new_stack_frame(const frame& hf, frame& return f; } else { int fsize = FKind::size(hf); - intptr_t* frame_sp = caller.unextended_sp() - fsize; + intptr_t* frame_sp = caller.unextended_sp() - fsize - size_adjust; if (bottom || caller.is_interpreted_frame()) { - int argsize = FKind::stack_argsize(hf); - - fsize += argsize; - frame_sp -= argsize; - caller.set_sp(caller.sp() - argsize); - assert(caller.sp() == frame_sp + (fsize-argsize), ""); - + if (size_adjust == 0) { + int argsize = FKind::stack_argsize(hf); + frame_sp -= argsize; + } frame_sp = align(hf, frame_sp, caller, bottom); } + caller.set_sp(frame_sp + fsize); + assert(is_aligned(frame_sp, frame::frame_alignment), ""); assert(hf.cb() != nullptr, ""); assert(hf.oop_map() != nullptr, ""); intptr_t* fp; if (PreserveFramePointer) { // we need to recreate a "real" frame pointer, pointing into the stack - fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset; + fp = frame_sp + fsize - frame::sender_sp_offset; } else { fp = FKind::stub || FKind::native ? frame_sp + fsize - frame::sender_sp_offset // fp always points to the address below the pushed return pc. We need correct address. @@ -275,16 +281,16 @@ inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& cal if (((intptr_t)frame_sp & 0xf) != 0) { assert(caller.is_interpreted_frame() || (bottom && hf.compiled_frame_stack_argsize() % 2 != 0), ""); frame_sp--; - caller.set_sp(caller.sp() - 1); } assert(is_aligned(frame_sp, frame::frame_alignment), ""); #endif - return frame_sp; } inline void ThawBase::patch_pd(frame& f, const frame& caller) { - patch_callee_link(caller, caller.fp()); + if (caller.is_interpreted_frame() || PreserveFramePointer) { + patch_callee_link(caller, caller.fp()); + } } inline void ThawBase::patch_pd(frame& f, intptr_t* caller_sp) { diff --git a/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp index e39580369db..c74e1d5d7ab 100644 --- a/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp @@ -141,8 +141,8 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return pauth_strip_pointer(*pc_addr); } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { - address* pc_addr = &(((address*) f.sp())[-1]); +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { + address* pc_addr = &(((address*) (callee_augmented ? f.unextended_sp() : f.sp()))[-1]); *pc_addr = pauth_sign_return_address(pc); } diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index 5f68206c814..ad4a4f65185 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -444,8 +444,8 @@ JavaThread** frame::saved_thread_address(const frame& f) { JavaThread** thread_addr; #ifdef COMPILER1 - if (cb == Runtime1::blob_for(C1StubId::monitorenter_id) || - cb == Runtime1::blob_for(C1StubId::monitorenter_nofpu_id)) { + if (cb == Runtime1::blob_for(StubId::c1_monitorenter_id) || + cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id)) { thread_addr = (JavaThread**)(f.sp() + Runtime1::runtime_blob_current_thread_offset(f)); } else #endif @@ -670,6 +670,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } else { ret_pc_loc = real_fp() - return_addr_offset; fp_loc = real_fp() - sender_sp_offset; + if (cb()->is_nmethod() && cb()->as_nmethod_or_null()->needs_stack_repair()) { + values.describe(frame_no, fp_loc - 1, err_msg("fsize for #%d", frame_no), 1); + } } address ret_pc = *(address*)ret_pc_loc; values.describe(frame_no, ret_pc_loc, @@ -841,6 +844,28 @@ intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) return sender_sp; } +intptr_t* frame::repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr) { + assert(nm != nullptr && nm->needs_stack_repair(), ""); + // The stack increment resides just below the saved FP on the stack and + // records the total frame size excluding the two words for saving FP and LR. + intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1); + int real_frame_size = (*real_frame_size_addr / wordSize) + 2; + assert(real_frame_size >= nm->frame_size() && real_frame_size <= 1000000, "invalid frame size"); + return sp + real_frame_size; +} + +bool frame::was_augmented_on_entry(int& real_size) const { + assert(is_compiled_frame(), ""); + if (_cb->as_nmethod_or_null()->needs_stack_repair()) { + intptr_t* real_frame_size_addr = unextended_sp() + _cb->frame_size() - sender_sp_offset - 1; + log_trace(continuations)("real_frame_size is addr is " INTPTR_FORMAT, p2i(real_frame_size_addr)); + real_size = (*real_frame_size_addr / wordSize) + 2; + return real_size != _cb->frame_size(); + } + real_size = _cb->frame_size(); + return false; +} + void JavaFrameAnchor::make_walkable() { // last frame set? if (last_Java_sp() == nullptr) return; diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.hpp index f8f2aaca45b..64dc087c1c6 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.hpp @@ -152,8 +152,13 @@ return (intptr_t*) addr_at(offset); } + public: // Support for scalarized inline type calling convention intptr_t* repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) const; + static intptr_t* repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr); + bool was_augmented_on_entry(int& real_size) const; + + private: #ifdef ASSERT // Used in frame::sender_for_{interpreter,compiled}_frame diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index 0d7cc9a8aaa..8c48a890df7 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -489,7 +489,7 @@ inline frame frame::sender_for_compiled_frame(RegisterMap* map) const { nmethod* nm = _cb->as_nmethod_or_null(); if (nm != nullptr && nm->is_compiled_by_c1() && nm->method()->has_scalarized_args() && pc() < nm->verified_inline_entry_point()) { - // TODO 8284443 Can't we do that by not passing 'dont_gc_arguments' in case 'C1StubId::buffer_inline_args_id' in 'Runtime1::generate_code_for'? + // TODO 8284443 Can't we do that by not passing 'dont_gc_arguments' in case 'StubId::c1_buffer_inline_args_id' in 'Runtime1::generate_code_for'? // The VEP and VIEP(RO) of C1-compiled methods call buffer_inline_args_xxx // before doing any argument shuffling, so we need to scan the oops // as the caller passes them. diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 1a0c3d1f262..66ba5987aca 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -120,7 +120,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \ "The instruction to use to implement " \ "java.lang.Thread.onSpinWait()." \ - "Options: none, nop, isb, yield.") \ + "Options: none, nop, isb, yield, sb.") \ product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \ "The number of OnSpinWaitInst instructions to generate." \ "It cannot be used with OnSpinWaitInst=none.") \ diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index f46964bc447..ff965d2193b 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -225,12 +225,16 @@ void InterpreterMacroAssembler::allocate_instance(Register klass, Register new_o void InterpreterMacroAssembler::read_flat_field(Register entry, Register field_index, Register field_offset, Register temp, Register obj) { - Label alloc_failed, done; + Label failed_alloc, slow_path, done; const Register src = field_offset; const Register alloc_temp = r10; const Register dst_temp = field_index; const Register layout_info = temp; - assert_different_registers(obj, entry, field_index, field_offset, temp, alloc_temp); + assert_different_registers(obj, entry, field_index, field_offset, temp, alloc_temp, rscratch1); + + load_unsigned_byte(temp, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset()))); + // If the field is nullable, jump to slow path + tbz(temp, ResolvedFieldEntry::is_null_free_inline_type_shift, slow_path); // Grab the inline field klass ldr(rscratch1, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset()))); @@ -241,7 +245,7 @@ void InterpreterMacroAssembler::read_flat_field(Register entry, // allocate buffer push(obj); // save holder - allocate_instance(field_klass, obj, alloc_temp, rscratch2, false, alloc_failed); + allocate_instance(field_klass, obj, alloc_temp, rscratch2, false, failed_alloc); // Have an oop instance buffer, copy into it payload_address(obj, dst_temp, field_klass); // danger, uses rscratch1 @@ -253,8 +257,9 @@ void InterpreterMacroAssembler::read_flat_field(Register entry, pop(obj); b(done); - bind(alloc_failed); + bind(failed_alloc); pop(obj); + bind(slow_path); call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field), obj, entry); @@ -262,6 +267,35 @@ void InterpreterMacroAssembler::read_flat_field(Register entry, membar(Assembler::StoreStore); } +void InterpreterMacroAssembler::write_flat_field(Register entry, Register field_offset, + Register tmp1, Register tmp2, + Register obj) { + assert_different_registers(entry, field_offset, tmp1, tmp2, obj); + Label slow_path, done; + + load_unsigned_byte(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset()))); + test_field_is_not_null_free_inline_type(tmp1, noreg /* temp */, slow_path); + + null_check(r0); // FIXME JDK-8341120 + + add(obj, obj, field_offset); + + load_klass(tmp1, r0); + payload_address(r0, r0, tmp1); + + Register layout_info = field_offset; + load_unsigned_short(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset()))); + ldr(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset()))); + inline_layout_info(tmp2, tmp1, layout_info); + + flat_field_copy(IN_HEAP, r0, obj, layout_info); + b(done); + + bind(slow_path); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, r0, entry); + bind(done); +} + // Load object from cpool->resolved_references(index) void InterpreterMacroAssembler::load_resolved_reference_at_index( Register result, Register index, Register tmp) { diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index 2382a58ade3..05d5e516dc6 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -156,7 +156,11 @@ class InterpreterMacroAssembler: public MacroAssembler { // - assumes holder_klass and valueKlass field klass have both been resolved void read_flat_field(Register entry, Register field_index, Register field_offset, - Register temp, Register obj = r0); + Register temp, Register obj); + + void write_flat_field(Register entry, Register field_offset, + Register tmp1, Register tmp2, + Register obj); // Allocate value buffer in "obj" and read in flat element at the given index // NOTES: diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 78db7d06813..21d2f0361ff 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -6136,7 +6136,8 @@ void MacroAssembler::remove_frame(int initial_framesize, bool needs_stack_repair int sp_inc_offset = initial_framesize - 3 * wordSize; // Immediately below saved LR and FP - ldp(rscratch1, rfp, Address(sp, sp_inc_offset)); + ldr(rscratch1, Address(sp, sp_inc_offset)); + ldr(rfp, Address(sp, sp_inc_offset + wordSize)); add(sp, sp, rscratch1); ldr(lr, Address(sp, wordSize)); add(sp, sp, 2 * wordSize); @@ -7594,6 +7595,7 @@ void MacroAssembler::verify_cross_modify_fence_not_required() { #endif void MacroAssembler::spin_wait() { + block_comment("spin_wait {"); for (int i = 0; i < VM_Version::spin_wait_desc().inst_count(); ++i) { switch (VM_Version::spin_wait_desc().inst()) { case SpinWait::NOP: @@ -7605,10 +7607,14 @@ void MacroAssembler::spin_wait() { case SpinWait::YIELD: yield(); break; + case SpinWait::SB: + sb(); + break; default: ShouldNotReachHere(); } } + block_comment("}"); } // Stack frame creation/removal diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp index d4bc983511f..1a3a0300e95 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp @@ -543,7 +543,7 @@ void MacroAssembler::generate__ieee754_rem_pio2(address npio2_hw, // } // // /* compute n */ -// z = scalbnA(z,q0); /* actual value of z */ +// z = scalbn(z,q0); /* actual value of z */ // z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ // n = (int) z; // z -= (double)n; @@ -576,7 +576,7 @@ void MacroAssembler::generate__ieee754_rem_pio2(address npio2_hw, // } // if(ih==2) { // z = one - z; -// if(carry!=0) z -= scalbnA(one,q0); +// if(carry!=0) z -= scalbn(one,q0); // } // } // @@ -602,7 +602,7 @@ void MacroAssembler::generate__ieee754_rem_pio2(address npio2_hw, // jz -= 1; q0 -= 24; // while(iq[jz]==0) { jz--; q0-=24;} // } else { /* break z into 24-bit if necessary */ -// z = scalbnA(z,-q0); +// z = scalbn(z,-q0); // if(z>=two24B) { // fw = (double)((int)(twon24*z)); // iq[jz] = (int)(z-two24B*fw); @@ -612,7 +612,7 @@ void MacroAssembler::generate__ieee754_rem_pio2(address npio2_hw, // } // // /* convert integer "bit" chunk to floating-point value */ -// fw = scalbnA(one,q0); +// fw = scalbn(one,q0); // for(i=jz;i>=0;i--) { // q[i] = fw*(double)iq[i]; fw*=twon24; // } @@ -925,7 +925,7 @@ void MacroAssembler::generate__kernel_rem_pio2(address two_over_pi, address pio2 fmovd(v25, 1.0); fsubd(v18, v25, v18); // z = one - z; cbzw(rscratch2, IH_HANDLED); - fsubd(v18, v18, v30); // z -= scalbnA(one,q0); + fsubd(v18, v18, v30); // z -= scalbn(one,q0); } } bind(IH_HANDLED); @@ -1026,7 +1026,7 @@ void MacroAssembler::generate__kernel_rem_pio2(address two_over_pi, address pio2 bind(Z_ZERO_CHECK_DONE); // convert integer "bit" chunk to floating-point value // v17 = twon24 - // update v30, which was scalbnA(1.0, ); + // update v30, which was scalbn(1.0, ); addw(tmp2, rscratch1, 1023); // biased exponent lsl(tmp2, tmp2, 52); // put at correct position mov(i, jz); diff --git a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp index 3fcb0e70b57..d45f9865bd2 100644 --- a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp @@ -61,8 +61,8 @@ class SimpleRuntimeFrame { //------------------------------generate_uncommon_trap_blob-------------------- UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, BlobId::c2_uncommon_trap_id); if (blob != nullptr) { return blob->as_uncommon_trap_blob(); } @@ -254,7 +254,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); - AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name); + AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, BlobId::c2_uncommon_trap_id); return ut_blob; } @@ -291,8 +291,8 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)BlobId::c2_exception_id, name); if (blob != nullptr) { return blob->as_exception_blob(); } @@ -398,7 +398,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // Set exception blob ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); - AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name); + AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, BlobId::c2_exception_id); return ex_blob; } #endif // COMPILER2 diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 7f34a560b1a..e8b765ddbf8 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -2480,8 +2480,8 @@ void SharedRuntime::generate_deopt_blob() { pad += 512; // Increase the buffer size when compiling for JVMCI } #endif - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, BlobId::shared_deopt_id); if (blob != nullptr) { _deopt_blob = blob->as_deoptimization_blob(); return; @@ -2851,7 +2851,7 @@ void SharedRuntime::generate_deopt_blob() { } #endif - AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name); + AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, BlobId::shared_deopt_id); } // Number of stack slots between incoming argument block and the start of @@ -2877,12 +2877,12 @@ VMReg SharedRuntime::thread_register() { // Generate a special Compile2Runtime blob that saves all registers, // and setup oopmap. // -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(is_polling_page_id(id), "expected a polling page stub id"); // Allocate space for the code. Setup code generation tools. const char* name = SharedRuntime::stub_name(id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_safepoint_blob(); } @@ -2896,8 +2896,8 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal address start = __ pc(); address call_pc = nullptr; int frame_size_in_words; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); - RegisterSaver reg_save(id == SharedStubId::polling_page_vectors_safepoint_handler_id /* save_vectors */); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); + RegisterSaver reg_save(id == StubId::shared_polling_page_vectors_safepoint_handler_id /* save_vectors */); // When the signal occurred, the LR was either signed and stored on the stack (in which // case it will be restored from the stack before being used) or unsigned and not stored @@ -3000,7 +3000,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // Fill-out other meta info SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); - AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return sp_blob; } @@ -3012,12 +3012,12 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // but since this is generic code we don't know what they are and the caller // must do any gc of the args. // -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert (StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_resolve_id(id), "expected a resolve stub id"); const char* name = SharedRuntime::stub_name(id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_runtime_stub(); } @@ -3098,7 +3098,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // frame_size_words or bytes?? RuntimeStub* rs_blob = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); - AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return rs_blob; } @@ -3258,7 +3258,7 @@ BufferedInlineTypeBlob* SharedRuntime::generate_buffered_inline_type_adapter(con // otherwise assume that stack unwinding will be initiated, so // caller saved registers were assumed volatile in the compiler. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); @@ -3282,7 +3282,7 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru const char* timer_msg = "SharedRuntime generate_throw_exception"; TraceTime timer(timer_msg, TRACETIME_LOG(Info, startuptime)); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_runtime_stub(); } @@ -3347,7 +3347,7 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru frame_complete, (framesize >> (LogBytesPerWord - LogBytesPerInt)), oop_maps, false); - AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return stub; } @@ -3378,7 +3378,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { int insts_size = 1024; int locs_size = 64; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_write_checkpoint_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_write_checkpoint_id); CodeBuffer code(name, insts_size, locs_size); OopMapSet* oop_maps = new OopMapSet(); MacroAssembler* masm = new MacroAssembler(&code); @@ -3417,7 +3417,7 @@ RuntimeStub* SharedRuntime::generate_jfr_return_lease() { int insts_size = 1024; int locs_size = 64; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_return_lease_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_return_lease_id); CodeBuffer code(name, insts_size, locs_size); OopMapSet* oop_maps = new OopMapSet(); MacroAssembler* masm = new MacroAssembler(&code); diff --git a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp index 28ffeafda48..08850f05f53 100644 --- a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp @@ -31,7 +31,8 @@ class SpinWait { NONE = -1, NOP, ISB, - YIELD + YIELD, + SB }; private: diff --git a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp index 8a221f13772..5776a8a75b5 100644 --- a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp @@ -35,8 +35,30 @@ template inline bool StackChunkFrameStream::is_in_frame(void* p0) const { assert(!is_done(), ""); intptr_t* p = (intptr_t*)p0; - int argsize = is_compiled() ? (_cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0; - int frame_size = _cb->frame_size() + argsize; + int frame_size = _cb->frame_size(); + if (is_compiled()) { + nmethod* nm = _cb->as_nmethod_or_null(); + if (nm->needs_stack_repair() && nm->is_compiled_by_c2()) { + frame f = to_frame(); + bool augmented = f.was_augmented_on_entry(frame_size); + if (!augmented) { + // Fix: C2 caller, so frame was not extended and thus the + // size read from the frame does not include the arguments. + // Ideally we have to count the arg size for the scalarized + // convention. For now we include the size of the caller frame + // which would at least be equal to that. + RegisterMap map(nullptr, + RegisterMap::UpdateMap::skip, + RegisterMap::ProcessFrames::skip, + RegisterMap::WalkContinuation::skip); + frame caller = to_frame().sender(&map); + assert(caller.is_compiled_frame() && caller.cb()->as_nmethod()->is_compiled_by_c2(), "needs stack repair but was not extended with c1/interpreter caller"); + frame_size += (caller.real_fp() - caller.sp()); + } + } else { + frame_size += _cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size >> LogBytesPerWord; + } + } return p == sp() - frame::sender_sp_offset || ((p - unextended_sp()) >= 0 && (p - unextended_sp()) < frame_size); } #endif @@ -46,7 +68,13 @@ inline frame StackChunkFrameStream::to_frame() const { if (is_done()) { return frame(_sp, _sp, nullptr, nullptr, nullptr, nullptr, true); } else { - return frame(sp(), unextended_sp(), fp(), pc(), cb(), _oopmap, true); + frame f = frame(sp(), unextended_sp(), fp(), pc(), cb(), _oopmap, true); + // If caller tries to get the sender of this frame and PreserveFramePointer + // is set, fp() will be used which contains the old value at the time of + // freeze (fp is reconstructed again during thaw). Setting sp as trusted + // causes the sender code to use _unextended_sp instead (see sender_for_compiled_frame()). + f.set_sp_is_trusted(); + return f; } } @@ -54,7 +82,7 @@ template inline address StackChunkFrameStream::get_pc() const { assert(!is_done(), ""); // Just strip it for frames on the heap. - return pauth_strip_pointer(*(address*)(_sp - 1)); + return pauth_strip_pointer(*(address*)((_callee_augmented ? _unextended_sp : _sp) - 1)); } template diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 3e5408cb318..8ae6bc5758f 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -202,7 +202,7 @@ class StubGenerator: public StubCodeGenerator { (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, "adjust this code"); - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -438,7 +438,7 @@ class StubGenerator: public StubCodeGenerator { // r0: exception oop address generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -494,7 +494,7 @@ class StubGenerator: public StubCodeGenerator { // so it just needs to be generated code with no x86 prolog address generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -584,7 +584,7 @@ class StubGenerator: public StubCodeGenerator { // [tos + 4]: saved r0 // [tos + 5]: saved rscratch1 address generate_verify_oop() { - StubGenStubId stub_id = StubGenStubId::verify_oop_id; + StubId stub_id = StubId::stubgen_verify_oop_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -633,7 +633,7 @@ class StubGenerator: public StubCodeGenerator { } // Generate indices for iota vector. - address generate_iota_indices(StubGenStubId stub_id) { + address generate_iota_indices(StubId stub_id) { __ align(CodeEntryAlignment); StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -678,7 +678,7 @@ class StubGenerator: public StubCodeGenerator { Register base = r10, cnt = r11; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::zero_blocks_id; + StubId stub_id = StubId::stubgen_zero_blocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -818,32 +818,32 @@ class StubGenerator: public StubCodeGenerator { // // s and d are adjusted to point to the remaining words to copy // - void generate_copy_longs(StubGenStubId stub_id, DecoratorSet decorators, Label &start, Register s, Register d, Register count) { + void generate_copy_longs(StubId stub_id, DecoratorSet decorators, Label &start, Register s, Register d, Register count) { BasicType type; copy_direction direction; switch (stub_id) { - case copy_byte_f_id: + case StubId::stubgen_copy_byte_f_id: direction = copy_forwards; type = T_BYTE; break; - case copy_byte_b_id: + case StubId::stubgen_copy_byte_b_id: direction = copy_backwards; type = T_BYTE; break; - case copy_oop_f_id: + case StubId::stubgen_copy_oop_f_id: direction = copy_forwards; type = T_OBJECT; break; - case copy_oop_b_id: + case StubId::stubgen_copy_oop_b_id: direction = copy_backwards; type = T_OBJECT; break; - case copy_oop_uninit_f_id: + case StubId::stubgen_copy_oop_uninit_f_id: direction = copy_forwards; type = T_OBJECT; break; - case copy_oop_uninit_b_id: + case StubId::stubgen_copy_oop_uninit_b_id: direction = copy_backwards; type = T_OBJECT; break; @@ -1542,7 +1542,7 @@ class StubGenerator: public StubCodeGenerator { // can be used by the corresponding conjoint copy // method // - address generate_disjoint_copy(StubGenStubId stub_id, address *entry) { + address generate_disjoint_copy(StubId stub_id, address *entry) { Register s = c_rarg0, d = c_rarg1, count = c_rarg2; RegSet saved_reg = RegSet::of(s, d, count); int size; @@ -1550,72 +1550,72 @@ class StubGenerator: public StubCodeGenerator { bool is_oop; bool dest_uninitialized; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: size = sizeof(jbyte); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jbyte_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id: size = sizeof(jbyte); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: size = sizeof(jshort); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jshort_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id: size = sizeof(jshort); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: size = sizeof(jint); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jint_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jint_disjoint_arraycopy_id: size = sizeof(jint); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: // since this is always aligned we can (should!) use the same - // stub as for case arrayof_jlong_disjoint_arraycopy + // stub as for case StubId::stubgen_arrayof_jlong_disjoint_arraycopy ShouldNotReachHere(); break; - case arrayof_jlong_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id: size = sizeof(jlong); aligned = true; is_oop = false; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case arrayof_oop_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = true; break; - case arrayof_oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; @@ -1698,7 +1698,7 @@ class StubGenerator: public StubCodeGenerator { // entry is set to the no-overlap entry point so it can be used by // some other conjoint copy method // - address generate_conjoint_copy(StubGenStubId stub_id, address nooverlap_target, address *entry) { + address generate_conjoint_copy(StubId stub_id, address nooverlap_target, address *entry) { Register s = c_rarg0, d = c_rarg1, count = c_rarg2; RegSet saved_regs = RegSet::of(s, d, count); int size; @@ -1706,72 +1706,72 @@ class StubGenerator: public StubCodeGenerator { bool is_oop; bool dest_uninitialized; switch (stub_id) { - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: size = sizeof(jbyte); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jbyte_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_arraycopy_id: size = sizeof(jbyte); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: size = sizeof(jshort); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jshort_arraycopy_id: + case StubId::stubgen_arrayof_jshort_arraycopy_id: size = sizeof(jshort); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: size = sizeof(jint); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jint_arraycopy_id: + case StubId::stubgen_arrayof_jint_arraycopy_id: size = sizeof(jint); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: // since this is always aligned we can (should!) use the same - // stub as for case arrayof_jlong_disjoint_arraycopy + // stub as for case StubId::stubgen_arrayof_jlong_disjoint_arraycopy ShouldNotReachHere(); break; - case arrayof_jlong_arraycopy_id: + case StubId::stubgen_arrayof_jlong_arraycopy_id: size = sizeof(jlong); aligned = true; is_oop = false; dest_uninitialized = false; break; - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case arrayof_oop_arraycopy_id: + case StubId::stubgen_arrayof_oop_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = true; break; - case arrayof_oop_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; @@ -1866,13 +1866,13 @@ class StubGenerator: public StubCodeGenerator { // r0 == 0 - success // r0 == -1^K - failure, where K is partial transfer count // - address generate_checkcast_copy(StubGenStubId stub_id, address *entry) { + address generate_checkcast_copy(StubId stub_id, address *entry) { bool dest_uninitialized; switch (stub_id) { - case checkcast_arraycopy_id: + case StubId::stubgen_checkcast_arraycopy_id: dest_uninitialized = false; break; - case checkcast_arraycopy_uninit_id: + case StubId::stubgen_checkcast_arraycopy_uninit_id: dest_uninitialized = true; break; default: @@ -2087,7 +2087,7 @@ class StubGenerator: public StubCodeGenerator { address short_copy_entry, address int_copy_entry, address long_copy_entry) { - StubGenStubId stub_id = StubGenStubId::unsafe_arraycopy_id; + StubId stub_id = StubId::stubgen_unsafe_arraycopy_id; Label L_long_aligned, L_int_aligned, L_short_aligned; Register s = c_rarg0, d = c_rarg1, count = c_rarg2; @@ -2140,7 +2140,7 @@ class StubGenerator: public StubCodeGenerator { address generate_generic_copy(address byte_copy_entry, address short_copy_entry, address int_copy_entry, address oop_copy_entry, address long_copy_entry, address checkcast_copy_entry) { - StubGenStubId stub_id = StubGenStubId::generic_arraycopy_id; + StubId stub_id = StubId::stubgen_generic_arraycopy_id; Label L_failed, L_objArray; Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; @@ -2417,32 +2417,32 @@ class StubGenerator: public StubCodeGenerator { // value: c_rarg1 // count: c_rarg2 treated as signed // - address generate_fill(StubGenStubId stub_id) { + address generate_fill(StubId stub_id) { BasicType t; bool aligned; switch (stub_id) { - case jbyte_fill_id: + case StubId::stubgen_jbyte_fill_id: t = T_BYTE; aligned = false; break; - case jshort_fill_id: + case StubId::stubgen_jshort_fill_id: t = T_SHORT; aligned = false; break; - case jint_fill_id: + case StubId::stubgen_jint_fill_id: t = T_INT; aligned = false; break; - case arrayof_jbyte_fill_id: + case StubId::stubgen_arrayof_jbyte_fill_id: t = T_BYTE; aligned = true; break; - case arrayof_jshort_fill_id: + case StubId::stubgen_arrayof_jshort_fill_id: t = T_SHORT; aligned = true; break; - case arrayof_jint_fill_id: + case StubId::stubgen_arrayof_jint_fill_id: t = T_INT; aligned = true; break; @@ -2612,7 +2612,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_unsafe_setmemory() { __ align(CodeEntryAlignment); - StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id); + StubCodeMark mark(this, StubId::stubgen_unsafe_setmemory_id); address start = __ pc(); Register dest = c_rarg0, count = c_rarg1, value = c_rarg2; @@ -2710,7 +2710,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2727,7 +2727,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_sync_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_sync_id; StubCodeMark mark(this, stub_id); // pre wbsync is a no-op @@ -2757,44 +2757,44 @@ class StubGenerator: public StubCodeGenerator { address ucm_common_error_exit = generate_unsafecopy_common_error_exit(); UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit); - generate_copy_longs(StubGenStubId::copy_byte_f_id, IN_HEAP | IS_ARRAY, copy_f, r0, r1, r15); - generate_copy_longs(StubGenStubId::copy_byte_b_id, IN_HEAP | IS_ARRAY, copy_b, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_byte_f_id, IN_HEAP | IS_ARRAY, copy_f, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_byte_b_id, IN_HEAP | IS_ARRAY, copy_b, r0, r1, r15); - generate_copy_longs(StubGenStubId::copy_oop_f_id, IN_HEAP | IS_ARRAY, copy_obj_f, r0, r1, r15); - generate_copy_longs(StubGenStubId::copy_oop_b_id, IN_HEAP | IS_ARRAY, copy_obj_b, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_oop_f_id, IN_HEAP | IS_ARRAY, copy_obj_f, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_oop_b_id, IN_HEAP | IS_ARRAY, copy_obj_b, r0, r1, r15); - generate_copy_longs(StubGenStubId::copy_oop_uninit_f_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_f, r0, r1, r15); - generate_copy_longs(StubGenStubId::copy_oop_uninit_b_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_b, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_oop_uninit_f_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_f, r0, r1, r15); + generate_copy_longs(StubId::stubgen_copy_oop_uninit_b_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_b, r0, r1, r15); StubRoutines::aarch64::_zero_blocks = generate_zero_blocks(); //*** jbyte // Always need aligned and unaligned versions - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jbyte_disjoint_arraycopy_id, &entry); - StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubGenStubId::jbyte_arraycopy_id, entry, &entry_jbyte_arraycopy); - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jbyte_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jbyte_arraycopy_id, entry, nullptr); + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id, &entry); + StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_jbyte_arraycopy_id, entry, &entry_jbyte_arraycopy); + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id, entry, nullptr); //*** jshort // Always need aligned and unaligned versions - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jshort_disjoint_arraycopy_id, &entry); - StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubGenStubId::jshort_arraycopy_id, entry, &entry_jshort_arraycopy); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jshort_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jshort_arraycopy_id, entry, nullptr); + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jshort_disjoint_arraycopy_id, &entry); + StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_jshort_arraycopy_id, entry, &entry_jshort_arraycopy); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jshort_arraycopy_id, entry, nullptr); //*** jint // Aligned versions - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jint_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jint_arraycopy_id, entry, &entry_jint_arraycopy); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jint_arraycopy_id, entry, &entry_jint_arraycopy); // In 64 bit we need both aligned and unaligned versions of jint arraycopy. // entry_jint_arraycopy always points to the unaligned version - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jint_disjoint_arraycopy_id, &entry); - StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubGenStubId::jint_arraycopy_id, entry, &entry_jint_arraycopy); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jint_disjoint_arraycopy_id, &entry); + StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_jint_arraycopy_id, entry, &entry_jint_arraycopy); //*** jlong // It is always aligned - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jlong_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jlong_arraycopy_id, entry, &entry_jlong_arraycopy); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jlong_arraycopy_id, entry, &entry_jlong_arraycopy); StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy; StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy; @@ -2805,14 +2805,14 @@ class StubGenerator: public StubCodeGenerator { bool aligned = !UseCompressedOops; StubRoutines::_arrayof_oop_disjoint_arraycopy - = generate_disjoint_copy(StubGenStubId::arrayof_oop_disjoint_arraycopy_id, &entry); + = generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id, &entry); StubRoutines::_arrayof_oop_arraycopy - = generate_conjoint_copy(StubGenStubId::arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy); + = generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy); // Aligned versions without pre-barriers StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit - = generate_disjoint_copy(StubGenStubId::arrayof_oop_disjoint_arraycopy_uninit_id, &entry); + = generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id, &entry); StubRoutines::_arrayof_oop_arraycopy_uninit - = generate_conjoint_copy(StubGenStubId::arrayof_oop_arraycopy_uninit_id, entry, nullptr); + = generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, entry, nullptr); } StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; @@ -2820,8 +2820,8 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit; StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit; - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_id, &entry_checkcast_arraycopy); - StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_uninit_id, nullptr); + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id, nullptr); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(entry_jbyte_arraycopy, entry_jshort_arraycopy, @@ -2835,12 +2835,12 @@ class StubGenerator: public StubCodeGenerator { entry_jlong_arraycopy, entry_checkcast_arraycopy); - StubRoutines::_jbyte_fill = generate_fill(StubGenStubId::jbyte_fill_id); - StubRoutines::_jshort_fill = generate_fill(StubGenStubId::jshort_fill_id); - StubRoutines::_jint_fill = generate_fill(StubGenStubId::jint_fill_id); - StubRoutines::_arrayof_jbyte_fill = generate_fill(StubGenStubId::arrayof_jbyte_fill_id); - StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); - StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); + StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id); + StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id); + StubRoutines::_jint_fill = generate_fill(StubId::stubgen_jint_fill_id); + StubRoutines::_arrayof_jbyte_fill = generate_fill(StubId::stubgen_arrayof_jbyte_fill_id); + StubRoutines::_arrayof_jshort_fill = generate_fill(StubId::stubgen_arrayof_jshort_fill_id); + StubRoutines::_arrayof_jint_fill = generate_fill(StubId::stubgen_arrayof_jint_fill_id); } void generate_math_stubs() { Unimplemented(); } @@ -2854,7 +2854,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_aescrypt_encryptBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); const Register from = c_rarg0; // source array address @@ -2888,7 +2888,7 @@ class StubGenerator: public StubCodeGenerator { address generate_aescrypt_decryptBlock() { assert(UseAES, "need AES cryptographic extension support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); Label L_doLast; @@ -2927,7 +2927,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cipherBlockChaining_encryptAESCrypt() { assert(UseAES, "need AES cryptographic extension support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_encryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); Label L_loadkeys_44, L_loadkeys_52, L_aes_loop, L_rounds_44, L_rounds_52; @@ -3032,7 +3032,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cipherBlockChaining_decryptAESCrypt() { assert(UseAES, "need AES cryptographic extension support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); Label L_loadkeys_44, L_loadkeys_52, L_aes_loop, L_rounds_44, L_rounds_52; @@ -3219,7 +3219,7 @@ class StubGenerator: public StubCodeGenerator { // Wide bulk encryption of whole blocks. __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::counterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_counterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); const address start = __ pc(); __ enter(); @@ -3429,7 +3429,7 @@ class StubGenerator: public StubCodeGenerator { __ emit_int64(0x87); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::galoisCounterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_galoisCounterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -3639,13 +3639,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg2 - int offset // c_rarg3 - int limit // - address generate_md5_implCompress(StubGenStubId stub_id) { + address generate_md5_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case md5_implCompress_id: + case StubId::stubgen_md5_implCompress_id: multi_block = false; break; - case md5_implCompressMB_id: + case StubId::stubgen_md5_implCompressMB_id: multi_block = true; break; default: @@ -3792,13 +3792,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg2 - int offset // c_rarg3 - int limit // - address generate_sha1_implCompress(StubGenStubId stub_id) { + address generate_sha1_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha1_implCompress_id: + case StubId::stubgen_sha1_implCompress_id: multi_block = false; break; - case sha1_implCompressMB_id: + case StubId::stubgen_sha1_implCompressMB_id: multi_block = true; break; default: @@ -3897,13 +3897,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg2 - int offset // c_rarg3 - int limit // - address generate_sha256_implCompress(StubGenStubId stub_id) { + address generate_sha256_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha256_implCompress_id: + case StubId::stubgen_sha256_implCompress_id: multi_block = false; break; - case sha256_implCompressMB_id: + case StubId::stubgen_sha256_implCompressMB_id: multi_block = true; break; default: @@ -4053,13 +4053,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg2 - int offset // c_rarg3 - int limit // - address generate_sha512_implCompress(StubGenStubId stub_id) { + address generate_sha512_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha512_implCompress_id: + case StubId::stubgen_sha512_implCompress_id: multi_block = false; break; - case sha512_implCompressMB_id: + case StubId::stubgen_sha512_implCompressMB_id: multi_block = true; break; default: @@ -4303,13 +4303,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg3 - int offset // c_rarg4 - int limit // - address generate_sha3_implCompress(StubGenStubId stub_id) { + address generate_sha3_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha3_implCompress_id: + case StubId::stubgen_sha3_implCompress_id: multi_block = false; break; - case sha3_implCompressMB_id: + case StubId::stubgen_sha3_implCompressMB_id: multi_block = true; break; default: @@ -4589,7 +4589,7 @@ class StubGenerator: public StubCodeGenerator { __ emit_int64(0x0E0D0C0F0A09080BUL); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::chacha20Block_id; + StubId stub_id = StubId::stubgen_chacha20Block_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5225,7 +5225,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberNtt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberNtt_id; + StubId stub_id = StubId::stubgen_kyberNtt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5463,7 +5463,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberInverseNtt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberInverseNtt_id; + StubId stub_id = StubId::stubgen_kyberInverseNtt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5750,7 +5750,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberNttMult() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberNttMult_id; + StubId stub_id = StubId::stubgen_kyberNttMult_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5867,7 +5867,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberAddPoly_2() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberAddPoly_2_id; + StubId stub_id = StubId::stubgen_kyberAddPoly_2_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5952,7 +5952,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberAddPoly_3() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberAddPoly_3_id; + StubId stub_id = StubId::stubgen_kyberAddPoly_3_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6060,7 +6060,7 @@ class StubGenerator: public StubCodeGenerator { __ emit_int64(0x0f000f000f000f00); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyber12To16_id; + StubId stub_id = StubId::stubgen_kyber12To16_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6263,7 +6263,7 @@ class StubGenerator: public StubCodeGenerator { address generate_kyberBarrettReduce() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::kyberBarrettReduce_id; + StubId stub_id = StubId::stubgen_kyberBarrettReduce_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6510,7 +6510,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dilithiumAlmostNtt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::dilithiumAlmostNtt_id; + StubId stub_id = StubId::stubgen_dilithiumAlmostNtt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6717,7 +6717,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dilithiumAlmostInverseNtt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::dilithiumAlmostInverseNtt_id; + StubId stub_id = StubId::stubgen_dilithiumAlmostInverseNtt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6830,7 +6830,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dilithiumNttMult() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::dilithiumNttMult_id; + StubId stub_id = StubId::stubgen_dilithiumNttMult_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6894,7 +6894,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dilithiumMontMulByConstant() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::dilithiumMontMulByConstant_id; + StubId stub_id = StubId::stubgen_dilithiumMontMulByConstant_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6958,7 +6958,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dilithiumDecomposePoly() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::dilithiumDecomposePoly_id; + StubId stub_id = StubId::stubgen_dilithiumDecomposePoly_id; StubCodeMark mark(this, stub_id); address start = __ pc(); Label L_loop; @@ -7227,13 +7227,13 @@ class StubGenerator: public StubCodeGenerator { // c_rarg3 - int offset // c_rarg4 - int limit // - address generate_sha3_implCompress_gpr(StubGenStubId stub_id) { + address generate_sha3_implCompress_gpr(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha3_implCompress_id: + case StubId::stubgen_sha3_implCompress_id: multi_block = false; break; - case sha3_implCompressMB_id: + case StubId::stubgen_sha3_implCompressMB_id: multi_block = true; break; default: @@ -7478,7 +7478,7 @@ class StubGenerator: public StubCodeGenerator { assert(UseCRC32Intrinsics, "what are we doing here?"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7520,7 +7520,7 @@ class StubGenerator: public StubCodeGenerator { assert(UseCRC32CIntrinsics, "what are we doing here?"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32C_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32C_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7559,7 +7559,7 @@ class StubGenerator: public StubCodeGenerator { */ address generate_updateBytesAdler32() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesAdler32_id; + StubId stub_id = StubId::stubgen_updateBytesAdler32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7781,7 +7781,7 @@ class StubGenerator: public StubCodeGenerator { */ address generate_multiplyToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::multiplyToLen_id; + StubId stub_id = StubId::stubgen_multiplyToLen_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7814,7 +7814,7 @@ class StubGenerator: public StubCodeGenerator { // faster than multiply_to_len on some CPUs and slower on others, but // multiply_to_len shows a bit better overall results __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::squareToLen_id; + StubId stub_id = StubId::stubgen_squareToLen_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7848,7 +7848,7 @@ class StubGenerator: public StubCodeGenerator { address generate_mulAdd() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::mulAdd_id; + StubId stub_id = StubId::stubgen_mulAdd_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -7879,7 +7879,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_bigIntegerRightShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerRightShiftWorker_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -8002,7 +8002,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_bigIntegerLeftShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerLeftShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerLeftShiftWorker_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -8111,7 +8111,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::count_positives_id; + StubId stub_id = StubId::stubgen_count_positives_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -8373,7 +8373,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::large_array_equals_id; + StubId stub_id = StubId::stubgen_large_array_equals_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -8499,25 +8499,25 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id; + StubId stub_id; switch (eltype) { case T_BOOLEAN: - stub_id = StubGenStubId::large_arrays_hashcode_boolean_id; + stub_id = StubId::stubgen_large_arrays_hashcode_boolean_id; break; case T_BYTE: - stub_id = StubGenStubId::large_arrays_hashcode_byte_id; + stub_id = StubId::stubgen_large_arrays_hashcode_byte_id; break; case T_CHAR: - stub_id = StubGenStubId::large_arrays_hashcode_char_id; + stub_id = StubId::stubgen_large_arrays_hashcode_char_id; break; case T_SHORT: - stub_id = StubGenStubId::large_arrays_hashcode_short_id; + stub_id = StubId::stubgen_large_arrays_hashcode_short_id; break; case T_INT: - stub_id = StubGenStubId::large_arrays_hashcode_int_id; + stub_id = StubId::stubgen_large_arrays_hashcode_int_id; break; default: - stub_id = StubGenStubId::NO_STUBID; + stub_id = StubId::NO_STUBID; ShouldNotReachHere(); }; @@ -8760,7 +8760,7 @@ class StubGenerator: public StubCodeGenerator { address generate_dsin_dcos(bool isCos) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = (isCos ? StubGenStubId::dcos_id : StubGenStubId::dsin_id); + StubId stub_id = (isCos ? StubId::stubgen_dcos_id : StubId::stubgen_dsin_id); StubCodeMark mark(this, stub_id); address start = __ pc(); __ generate_dsin_dcos(isCos, (address)StubRoutines::aarch64::_npio2_hw, @@ -8812,7 +8812,7 @@ class StubGenerator: public StubCodeGenerator { // r11 = tmp2 address generate_compare_long_string_different_encoding(bool isLU) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = (isLU ? StubGenStubId::compare_long_string_LU_id : StubGenStubId::compare_long_string_UL_id); + StubId stub_id = (isLU ? StubId::stubgen_compare_long_string_LU_id : StubId::stubgen_compare_long_string_UL_id); StubCodeMark mark(this, stub_id); address entry = __ pc(); Label SMALL_LOOP, TAIL, TAIL_LOAD_16, LOAD_LAST, DIFF1, DIFF2, @@ -8922,7 +8922,7 @@ class StubGenerator: public StubCodeGenerator { // v1 = temporary float register address generate_float16ToFloat() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::hf2f_id; + StubId stub_id = StubId::stubgen_hf2f_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); BLOCK_COMMENT("Entry:"); @@ -8936,7 +8936,7 @@ class StubGenerator: public StubCodeGenerator { // v1 = temporary float register address generate_floatToFloat16() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::f2hf_id; + StubId stub_id = StubId::stubgen_f2hf_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); BLOCK_COMMENT("Entry:"); @@ -8947,7 +8947,7 @@ class StubGenerator: public StubCodeGenerator { address generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); Label deoptimize_label; @@ -9013,7 +9013,7 @@ class StubGenerator: public StubCodeGenerator { // r11 = tmp2 address generate_compare_long_string_same_encoding(bool isLL) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = (isLL ? StubGenStubId::compare_long_string_LL_id : StubGenStubId::compare_long_string_UU_id); + StubId stub_id = (isLL ? StubId::stubgen_compare_long_string_LL_id : StubId::stubgen_compare_long_string_UU_id); StubCodeMark mark(this, stub_id); address entry = __ pc(); Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, cnt2 = r4, @@ -9144,12 +9144,12 @@ class StubGenerator: public StubCodeGenerator { // p0 = pgtmp1 // p1 = pgtmp2 address generate_compare_long_string_sve(string_compare_mode mode) { - StubGenStubId stub_id; + StubId stub_id; switch (mode) { - case LL: stub_id = StubGenStubId::compare_long_string_LL_id; break; - case LU: stub_id = StubGenStubId::compare_long_string_LU_id; break; - case UL: stub_id = StubGenStubId::compare_long_string_UL_id; break; - case UU: stub_id = StubGenStubId::compare_long_string_UU_id; break; + case LL: stub_id = StubId::stubgen_compare_long_string_LL_id; break; + case LU: stub_id = StubId::stubgen_compare_long_string_LU_id; break; + case UL: stub_id = StubId::stubgen_compare_long_string_UL_id; break; + case UU: stub_id = StubId::stubgen_compare_long_string_UU_id; break; default: ShouldNotReachHere(); } @@ -9280,18 +9280,18 @@ class StubGenerator: public StubCodeGenerator { // larger and a bit less readable, however, most of extra operations are // issued during loads or branches, so, penalty is minimal address generate_string_indexof_linear(bool str1_isL, bool str2_isL) { - StubGenStubId stub_id; + StubId stub_id; if (str1_isL) { if (str2_isL) { - stub_id = StubGenStubId::string_indexof_linear_ll_id; + stub_id = StubId::stubgen_string_indexof_linear_ll_id; } else { - stub_id = StubGenStubId::string_indexof_linear_ul_id; + stub_id = StubId::stubgen_string_indexof_linear_ul_id; } } else { if (str2_isL) { ShouldNotReachHere(); } else { - stub_id = StubGenStubId::string_indexof_linear_uu_id; + stub_id = StubId::stubgen_string_indexof_linear_uu_id; } } __ align(CodeEntryAlignment); @@ -9593,7 +9593,7 @@ class StubGenerator: public StubCodeGenerator { // Clobbers: r0, r1, r3, rscratch1, rflags, v0-v6 address generate_large_byte_array_inflate() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::large_byte_array_inflate_id; + StubId stub_id = StubId::stubgen_large_byte_array_inflate_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); Label LOOP, LOOP_START, LOOP_PRFM, LOOP_PRFM_START, DONE; @@ -9659,7 +9659,7 @@ class StubGenerator: public StubCodeGenerator { // that) and keep the data in little-endian bit order through the // calculation, bit-reversing the inputs and outputs. - StubGenStubId stub_id = StubGenStubId::ghash_processBlocks_id; + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; StubCodeMark mark(this, stub_id); __ align(wordSize * 2); address p = __ pc(); @@ -9726,7 +9726,7 @@ class StubGenerator: public StubCodeGenerator { address generate_ghash_processBlocks_wide() { address small = generate_ghash_processBlocks(); - StubGenStubId stub_id = StubGenStubId::ghash_processBlocks_wide_id; + StubId stub_id = StubId::stubgen_ghash_processBlocks_wide_id; StubCodeMark mark(this, stub_id); __ align(wordSize * 2); address p = __ pc(); @@ -9838,7 +9838,7 @@ class StubGenerator: public StubCodeGenerator { }; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_encodeBlock_id; + StubId stub_id = StubId::stubgen_base64_encodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10107,7 +10107,7 @@ class StubGenerator: public StubCodeGenerator { }; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_decodeBlock_id; + StubId stub_id = StubId::stubgen_base64_decodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10224,7 +10224,7 @@ class StubGenerator: public StubCodeGenerator { // Support for spin waits. address generate_spin_wait() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::spin_wait_id; + StubId stub_id = StubId::stubgen_spin_wait_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10235,7 +10235,7 @@ class StubGenerator: public StubCodeGenerator { } void generate_lookup_secondary_supers_table_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_id; StubCodeMark mark(this, stub_id); const Register @@ -10264,7 +10264,7 @@ class StubGenerator: public StubCodeGenerator { // Slow path implementation for UseSecondarySupersTable. address generate_lookup_secondary_supers_table_slow_path_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_slow_path_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_slow_path_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10419,7 +10419,7 @@ class StubGenerator: public StubCodeGenerator { return; } __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::atomic_entry_points_id; + StubId stub_id = StubId::stubgen_atomic_entry_points_id; StubCodeMark mark(this, stub_id); address first_entry = __ pc(); @@ -10480,6 +10480,30 @@ class StubGenerator: public StubCodeGenerator { } #endif // LINUX + static void save_return_registers(MacroAssembler* masm) { + if (InlineTypeReturnedAsFields) { + masm->push(RegSet::range(r0, r7), sp); + masm->sub(sp, sp, 4 * wordSize); + masm->st1(v0, v1, v2, v3, masm->T1D, Address(sp)); + masm->sub(sp, sp, 4 * wordSize); + masm->st1(v4, v5, v6, v7, masm->T1D, Address(sp)); + } else { + masm->fmovd(rscratch1, v0); + masm->stp(rscratch1, r0, Address(masm->pre(sp, -2 * wordSize))); + } + } + + static void restore_return_registers(MacroAssembler* masm) { + if (InlineTypeReturnedAsFields) { + masm->ld1(v4, v5, v6, v7, masm->T1D, Address(masm->post(sp, 4 * wordSize))); + masm->ld1(v0, v1, v2, v3, masm->T1D, Address(masm->post(sp, 4 * wordSize))); + masm->pop(RegSet::range(r0, r7), sp); + } else { + masm->ldp(rscratch1, r0, Address(masm->post(sp, 2 * wordSize))); + masm->fmovd(v0, rscratch1); + } + } + address generate_cont_thaw(Continuation::thaw_kind kind) { bool return_barrier = Continuation::is_thaw_return_barrier(kind); bool return_barrier_exception = Continuation::is_thaw_return_barrier_exception(kind); @@ -10494,8 +10518,7 @@ class StubGenerator: public StubCodeGenerator { if (return_barrier) { // preserve possible return value from a method returning to the return barrier - __ fmovd(rscratch1, v0); - __ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize))); + save_return_registers(_masm); } __ movw(c_rarg1, (return_barrier ? 1 : 0)); @@ -10504,8 +10527,7 @@ class StubGenerator: public StubCodeGenerator { if (return_barrier) { // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK) - __ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize))); - __ fmovd(v0, rscratch1); + restore_return_registers(_masm); } assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp"); @@ -10524,8 +10546,7 @@ class StubGenerator: public StubCodeGenerator { if (return_barrier) { // save original return value -- again - __ fmovd(rscratch1, v0); - __ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize))); + save_return_registers(_masm); } // If we want, we can templatize thaw by kind, and have three different entries @@ -10536,8 +10557,7 @@ class StubGenerator: public StubCodeGenerator { if (return_barrier) { // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK) - __ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize))); - __ fmovd(v0, rscratch1); + restore_return_registers(_masm); } else { __ mov(r0, zr); // return 0 (success) from doYield } @@ -10579,7 +10599,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_thaw() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_thaw_id; + StubId stub_id = StubId::stubgen_cont_thaw_id; StubCodeMark mark(this, stub_id); address start = __ pc(); generate_cont_thaw(Continuation::thaw_top); @@ -10590,7 +10610,7 @@ class StubGenerator: public StubCodeGenerator { if (!Continuations::enabled()) return nullptr; // TODO: will probably need multiple return barriers depending on return type - StubGenStubId stub_id = StubGenStubId::cont_returnBarrier_id; + StubId stub_id = StubId::stubgen_cont_returnBarrier_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10602,7 +10622,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_returnBarrier_exception() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_returnBarrierExc_id; + StubId stub_id = StubId::stubgen_cont_returnBarrierExc_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10613,7 +10633,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_preempt_stub() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_preempt_id; + StubId stub_id = StubId::stubgen_cont_preempt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10696,7 +10716,7 @@ class StubGenerator: public StubCodeGenerator { address generate_poly1305_processBlocks() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::poly1305_processBlocks_id; + StubId stub_id = StubId::stubgen_poly1305_processBlocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); Label here; @@ -10811,7 +10831,7 @@ class StubGenerator: public StubCodeGenerator { // exception handler for upcall stubs address generate_upcall_stub_exception_handler() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_exception_handler_id; + StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -10829,7 +10849,7 @@ class StubGenerator: public StubCodeGenerator { // j_rarg0 = jobject receiver // rmethod = result address generate_upcall_stub_load_target() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_load_target_id; + StubId stub_id = StubId::stubgen_upcall_stub_load_target_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -11910,7 +11930,7 @@ class StubGenerator: public StubCodeGenerator { #if COMPILER2_OR_JVMCI if (UseSVE == 0) { - StubRoutines::aarch64::_vector_iota_indices = generate_iota_indices(StubGenStubId::vector_iota_indices_id); + StubRoutines::aarch64::_vector_iota_indices = generate_iota_indices(StubId::stubgen_vector_iota_indices_id); } // array equals stub for large arrays. @@ -11954,14 +11974,14 @@ class StubGenerator: public StubCodeGenerator { } if (UseMontgomeryMultiplyIntrinsic) { - StubGenStubId stub_id = StubGenStubId::montgomeryMultiply_id; + StubId stub_id = StubId::stubgen_montgomeryMultiply_id; StubCodeMark mark(this, stub_id); MontgomeryMultiplyGenerator g(_masm, /*squaring*/false); StubRoutines::_montgomeryMultiply = g.generate_multiply(); } if (UseMontgomerySquareIntrinsic) { - StubGenStubId stub_id = StubGenStubId::montgomerySquare_id; + StubId stub_id = StubId::stubgen_montgomerySquare_id; StubCodeMark mark(this, stub_id); MontgomeryMultiplyGenerator g(_masm, /*squaring*/true); // We use generate_multiply() rather than generate_square() @@ -12018,30 +12038,30 @@ class StubGenerator: public StubCodeGenerator { } if (UseMD5Intrinsics) { - StubRoutines::_md5_implCompress = generate_md5_implCompress(StubGenStubId::md5_implCompress_id); - StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubGenStubId::md5_implCompressMB_id); + StubRoutines::_md5_implCompress = generate_md5_implCompress(StubId::stubgen_md5_implCompress_id); + StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubId::stubgen_md5_implCompressMB_id); } if (UseSHA1Intrinsics) { - StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubGenStubId::sha1_implCompress_id); - StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubGenStubId::sha1_implCompressMB_id); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubId::stubgen_sha1_implCompress_id); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubId::stubgen_sha1_implCompressMB_id); } if (UseSHA256Intrinsics) { - StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubGenStubId::sha256_implCompress_id); - StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubGenStubId::sha256_implCompressMB_id); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubId::stubgen_sha256_implCompressMB_id); } if (UseSHA512Intrinsics) { - StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubGenStubId::sha512_implCompress_id); - StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubGenStubId::sha512_implCompressMB_id); + StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubId::stubgen_sha512_implCompress_id); + StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubId::stubgen_sha512_implCompressMB_id); } if (UseSHA3Intrinsics) { StubRoutines::_double_keccak = generate_double_keccak(); if (UseSIMDForSHA3Intrinsic) { - StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id); - StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id); + StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubId::stubgen_sha3_implCompress_id); + StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubId::stubgen_sha3_implCompressMB_id); } else { - StubRoutines::_sha3_implCompress = generate_sha3_implCompress_gpr(StubGenStubId::sha3_implCompress_id); - StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress_gpr(StubGenStubId::sha3_implCompressMB_id); + StubRoutines::_sha3_implCompress = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompress_id); + StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompressMB_id); } } @@ -12058,31 +12078,31 @@ class StubGenerator: public StubCodeGenerator { } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } }; // end class declaration -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index 15ea5413cd4..8b9b371cf52 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -2772,51 +2772,23 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr } else { // Valhalla if (is_static) { __ load_heap_oop(r0, field, rscratch1, rscratch2); - Label is_null_free_inline_type, uninitialized; - // Issue below if the static field has not been initialized yet - __ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_null_free_inline_type); - // field is not a null free inline type - __ push(atos); - __ b(Done); - // field is a null free inline type, must not return null even if uninitialized - __ bind(is_null_free_inline_type); - __ cbz(r0, uninitialized); - __ push(atos); - __ b(Done); - __ bind(uninitialized); - __ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry)); + __ push(atos); + __ b(Done); } else { - Label is_flat, nonnull, is_inline_type, has_null_marker, rewrite_inline; - __ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_inline_type); - __ test_field_has_null_marker(flags, noreg /*temp*/, has_null_marker); - // Non-inline field case - __ load_heap_oop(r0, field, rscratch1, rscratch2); + Label is_flat, rewrite_inline; + __ test_field_is_flat(flags, noreg /*temp*/, is_flat); + __ load_heap_oop(r0, field, rscratch1, rscratch2); + __ push(atos); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_agetfield, bc, r1); + } + __ b(Done); + __ bind(is_flat); + // field is flat (null-free or nullable with a null-marker) + __ mov(r0, obj); + __ read_flat_field(cache, field_index, off, inline_klass /* temp */, r0); + __ verify_oop(r0); __ push(atos); - if (rc == may_rewrite) { - patch_bytecode(Bytecodes::_fast_agetfield, bc, r1); - } - __ b(Done); - __ bind(is_inline_type); - __ test_field_is_flat(flags, noreg /* temp */, is_flat); - // field is not flat - __ load_heap_oop(r0, field, rscratch1, rscratch2); - __ cbnz(r0, nonnull); - __ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry)); - __ bind(nonnull); - __ verify_oop(r0); - __ push(atos); - __ b(rewrite_inline); - __ bind(is_flat); - // field is flat - __ mov(r0, obj); - __ read_flat_field(cache, field_index, off, inline_klass /* temp */, r0); - __ verify_oop(r0); - __ push(atos); - __ b(rewrite_inline); - __ bind(has_null_marker); - call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), obj, cache); - __ verify_oop(r0); - __ push(atos); __ bind(rewrite_inline); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_vgetfield, bc, r1); @@ -3057,52 +3029,35 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } else { // Valhalla __ pop(atos); if (is_static) { - Label is_inline_type; - __ test_field_is_not_null_free_inline_type(flags, noreg /* temp */, is_inline_type); - __ null_check(r0); - __ bind(is_inline_type); + Label is_nullable; + __ test_field_is_not_null_free_inline_type(flags, noreg /* temp */, is_nullable); + __ null_check(r0); // FIXME JDK-8341120 + __ bind(is_nullable); do_oop_store(_masm, field, r0, IN_HEAP); __ b(Done); } else { - Label is_inline_type, is_flat, has_null_marker, rewrite_not_inline, rewrite_inline; - __ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_inline_type); - __ test_field_has_null_marker(flags, noreg /*temp*/, has_null_marker); - // Not an inline type + Label null_free_reference, is_flat, rewrite_inline; + __ test_field_is_flat(flags, noreg /*temp*/, is_flat); + __ test_field_is_null_free_inline_type(flags, noreg /*temp*/, null_free_reference); pop_and_check_object(obj); // Store into the field // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); - __ bind(rewrite_not_inline); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_aputfield, bc, r19, true, byte_no); } __ b(Done); // Implementation of the inline type semantic - __ bind(is_inline_type); - __ null_check(r0); - __ test_field_is_flat(flags, noreg /*temp*/, is_flat); - // field is not flat + __ bind(null_free_reference); + __ null_check(r0); // FIXME JDK-8341120 pop_and_check_object(obj); // Store into the field // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); __ b(rewrite_inline); __ bind(is_flat); - __ load_field_entry(cache, index); // reload field entry (cache) because it was erased by tos_state - __ load_unsigned_short(index, Address(cache, in_bytes(ResolvedFieldEntry::field_index_offset()))); - __ ldr(r2, Address(cache, in_bytes(ResolvedFieldEntry::field_holder_offset()))); - __ inline_layout_info(r2, index, r6); - pop_and_check_object(obj); - __ load_klass(inline_klass, r0); - __ payload_address(r0, r0, inline_klass); - __ add(obj, obj, off); - // because we use InlineLayoutInfo, we need special value access code specialized for fields (arrays will need a different API) - __ flat_field_copy(IN_HEAP, r0, obj, r6); - __ b(rewrite_inline); - __ bind(has_null_marker); - assert_different_registers(r0, cache, r19); - pop_and_check_object(r19); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), r19, r0, cache); + pop_and_check_object(r7); + __ write_flat_field(cache, off, r3, r6, r7); __ bind(rewrite_inline); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_vputfield, bc, r19, true, byte_no); @@ -3323,29 +3278,18 @@ void TemplateTable::fast_storefield(TosState state) // access field switch (bytecode()) { case Bytecodes::_fast_vputfield: - { + { Label is_flat, has_null_marker, done; - __ test_field_has_null_marker(r5, noreg /* temp */, has_null_marker); - __ null_check(r0); __ test_field_is_flat(r5, noreg /* temp */, is_flat); - // field is not flat + __ null_check(r0); do_oop_store(_masm, field, r0, IN_HEAP); __ b(done); __ bind(is_flat); - // field is flat __ load_field_entry(r4, r5); - __ load_unsigned_short(r5, Address(r4, in_bytes(ResolvedFieldEntry::field_index_offset()))); - __ ldr(r4, Address(r4, in_bytes(ResolvedFieldEntry::field_holder_offset()))); - __ inline_layout_info(r4, r5, r6); - __ load_klass(r4, r0); - __ payload_address(r0, r0, r4); - __ lea(rscratch1, field); - __ flat_field_copy(IN_HEAP, r0, rscratch1, r6); - __ b(done); - __ bind(has_null_marker); - __ load_field_entry(r4, r1); - __ mov(r1, r2); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), r1, r0, r4); + // Re-shuffle registers because of VM calls calling convention + __ mov(r19, r1); + __ mov(r7, r2); + __ write_flat_field(r4, r19, r6, r8, r7); __ bind(done); } break; @@ -3444,27 +3388,11 @@ void TemplateTable::fast_accessfield(TosState state) switch (bytecode()) { case Bytecodes::_fast_vgetfield: { - Register index = r4, klass = r5, inline_klass = r6, tmp = r7; - Label is_flat, has_null_marker, nonnull, Done; - __ test_field_has_null_marker(r3, noreg /*temp*/, has_null_marker); - __ test_field_is_flat(r3, noreg /* temp */, is_flat); - // field is not flat - __ load_heap_oop(r0, field, rscratch1, rscratch2); - __ cbnz(r0, nonnull); - __ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry)); - __ bind(nonnull); - __ verify_oop(r0); - __ b(Done); - __ bind(is_flat); + Register index = r4, tmp = r7; // field is flat - __ load_unsigned_short(index, Address(r2, in_bytes(ResolvedFieldEntry::field_index_offset()))); - __ read_flat_field(r2, index, r1, tmp /* temp */, r0); - __ verify_oop(r0); - __ b(Done); - __ bind(has_null_marker); - call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), r0, r2); - __ verify_oop(r0); - __ bind(Done); + __ load_unsigned_short(index, Address(r2, in_bytes(ResolvedFieldEntry::field_index_offset()))); + __ read_flat_field(r2, index, r1, tmp /* temp */, r0); + __ verify_oop(r0); } break; case Bytecodes::_fast_agetfield: diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 941cb254532..6ee4a0023c6 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -57,8 +57,13 @@ static SpinWait get_spin_wait_desc() { return SpinWait(SpinWait::ISB, OnSpinWaitInstCount); } else if (strcmp(OnSpinWaitInst, "yield") == 0) { return SpinWait(SpinWait::YIELD, OnSpinWaitInstCount); + } else if (strcmp(OnSpinWaitInst, "sb") == 0) { + if (!VM_Version::supports_sb()) { + vm_exit_during_initialization("OnSpinWaitInst is SB but current CPU does not support SB instruction"); + } + return SpinWait(SpinWait::SB, OnSpinWaitInstCount); } else if (strcmp(OnSpinWaitInst, "none") != 0) { - vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, and none", OnSpinWaitInst); + vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, sb, and none", OnSpinWaitInst); } if (!FLAG_IS_DEFAULT(OnSpinWaitInstCount) && OnSpinWaitInstCount > 0) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 373f8da5405..99450d3dde1 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -131,6 +131,7 @@ enum Ampere_CPU_Model { decl(SHA3, sha3, 17) \ decl(SHA512, sha512, 21) \ decl(SVE, sve, 22) \ + decl(SB, sb, 29) \ decl(PACA, paca, 30) \ /* flags above must follow Linux HWCAP */ \ decl(SVEBITPERM, svebitperm, 27) \ diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 4a0b557968c..3b6faa6c81a 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -8888,13 +8888,8 @@ instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{ match(TailCall jump_target method_ptr); ins_cost(CALL_COST); - format %{ "MOV Rexception_pc, LR\n\t" - "jump $jump_target \t! $method_ptr holds method" %} + format %{ "jump $jump_target \t! $method_ptr holds method" %} ins_encode %{ - __ mov(Rexception_pc, LR); // this is used only to call - // StubRoutines::forward_exception_entry() - // which expects PC of exception in - // R5. FIXME? __ jump($jump_target$$Register); %} ins_pipe(tail_call); @@ -8939,8 +8934,10 @@ instruct ForwardExceptionjmp() match(ForwardException); ins_cost(CALL_COST); - format %{ "b forward_exception_stub" %} + format %{ "MOV Rexception_pc, LR\n\t" + "b forward_exception_entry" %} ins_encode %{ + __ mov(Rexception_pc, LR); // OK to trash Rtemp, because Rtemp is used by stub __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); %} diff --git a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp index 5683bc59d5c..efdc190f09a 100644 --- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp +++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp @@ -45,7 +45,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_bci, 0); ce->store_parameter(_method->as_constant_ptr()->as_metadata(), 1); - __ call(Runtime1::entry_for(C1StubId::counter_overflow_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_counter_overflow_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -56,7 +56,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - __ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_predicate_failed_trap_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); DEBUG_ONLY(__ should_not_reach_here()); @@ -72,10 +72,10 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { } if (_throw_index_out_of_bounds_exception) { - __ call(Runtime1::entry_for(C1StubId::throw_index_exception_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_throw_index_exception_id), relocInfo::runtime_call_type); } else { __ str(_array->as_pointer_register(), Address(SP, BytesPerWord)); // ??? Correct offset? Correct instruction? - __ call(Runtime1::entry_for(C1StubId::throw_range_check_failed_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_throw_range_check_failed_id), relocInfo::runtime_call_type); } ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -88,7 +88,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - __ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_predicate_failed_trap_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); DEBUG_ONLY(__ should_not_reach_here()); @@ -99,7 +99,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - __ call(Runtime1::entry_for(C1StubId::throw_div0_exception_id), + __ call(Runtime1::entry_for(StubId::c1_throw_div0_exception_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); DEBUG_ONLY(STOP("DivByZero");) @@ -108,14 +108,14 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { // Implementation of NewInstanceStub -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -147,7 +147,7 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { assert(_klass_reg->as_register() == R1, "runtime call setup"); assert(_length->as_register() == R2, "runtime call setup"); __ bind(_entry); - __ call(Runtime1::entry_for(C1StubId::new_type_array_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_new_type_array_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ b(_continuation); @@ -169,7 +169,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { assert(_klass_reg->as_register() == R1, "runtime call setup"); assert(_length->as_register() == R2, "runtime call setup"); __ bind(_entry); - __ call(Runtime1::entry_for(C1StubId::new_object_array_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_new_object_array_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ b(_continuation); @@ -188,9 +188,9 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) { __ str(lock_reg, Address(SP, BytesPerWord)); } - C1StubId enter_id = ce->compilation()->has_fpu_code() ? - C1StubId::monitorenter_id : - C1StubId::monitorenter_nofpu_id; + StubId enter_id = ce->compilation()->has_fpu_code() ? + StubId::c1_monitorenter_id : + StubId::c1_monitorenter_nofpu_id; __ call(Runtime1::entry_for(enter_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -209,9 +209,9 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { __ str(lock_reg, Address(SP)); // Non-blocking leaf routine - no call info needed - C1StubId exit_id = ce->compilation()->has_fpu_code() ? - C1StubId::monitorexit_id : - C1StubId::monitorexit_nofpu_id; + StubId exit_id = ce->compilation()->has_fpu_code() ? + StubId::c1_monitorexit_id : + StubId::c1_monitorexit_nofpu_id; __ call(Runtime1::entry_for(exit_id), relocInfo::runtime_call_type); __ b(_continuation); } @@ -321,10 +321,10 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { address target = nullptr; relocInfo::relocType reloc_type = relocInfo::none; switch (_id) { - case access_field_id: target = Runtime1::entry_for(C1StubId::access_field_patching_id); break; - case load_klass_id: target = Runtime1::entry_for(C1StubId::load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; - case load_mirror_id: target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; - case load_appendix_id: target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; + case access_field_id: target = Runtime1::entry_for(StubId::c1_access_field_patching_id); break; + case load_klass_id: target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; + case load_mirror_id: target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; + case load_appendix_id: target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } __ bind(call_patch); @@ -350,7 +350,7 @@ void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ mov_slow(Rtemp, _trap_request); ce->verify_reserved_argument_area_size(1); __ str(Rtemp, Address(SP)); - __ call(Runtime1::entry_for(C1StubId::deoptimize_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_deoptimize_id), relocInfo::runtime_call_type); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); } @@ -361,9 +361,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is // probably wrong to do it here. - a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); } ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); __ bind(_entry); diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 10c496f6b34..17fdf180f04 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -212,7 +212,7 @@ int LIR_Assembler::emit_exception_handler() { // check that there is really an exception __ verify_not_null_oop(Rexception_obj); - __ call(Runtime1::entry_for(C1StubId::handle_exception_from_callee_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_handle_exception_from_callee_id), relocInfo::runtime_call_type); __ should_not_reach_here(); assert(code_offset() - offset <= exception_handler_size(), "overflow"); @@ -252,7 +252,7 @@ int LIR_Assembler::emit_unwind_handler() { // remove the activation and dispatch to the unwind handler __ remove_frame(initial_frame_size_in_bytes()); // restores FP and LR - __ jump(Runtime1::entry_for(C1StubId::unwind_exception_id), relocInfo::runtime_call_type, Rtemp); + __ jump(Runtime1::entry_for(StubId::c1_unwind_exception_id), relocInfo::runtime_call_type, Rtemp); // Emit the slow path assembly if (stub != nullptr) { @@ -1136,7 +1136,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ b(*failure_target, ne); // slow case assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup"); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); __ cbz(R0, *failure_target); if (op->should_profile()) { Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtemp; @@ -1210,7 +1210,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ cmp(Rtemp, k_RInfo, ne); __ b(*success_target, eq); assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup"); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); __ cbz(R0, *failure_target); } } else { @@ -1227,7 +1227,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ b(*failure_target, ne); // slow case assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup"); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); __ cbz(R0, *failure_target); } @@ -1303,7 +1303,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } __ b(*success_target, eq); assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup"); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); if (!op->should_profile()) { move_regs(R0, res); } else { @@ -1334,7 +1334,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ b(*failure_target, ne); // slow case assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup"); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); if (!op->should_profile()) { move_regs(R0, res); } @@ -1981,9 +1981,9 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit assert(exceptionPC->as_register() == Rexception_pc, "must match"); info->add_register_oop(exceptionOop); - C1StubId handle_id = compilation()->has_fpu_code() ? - C1StubId::handle_exception_id : - C1StubId::handle_exception_nofpu_id; + StubId handle_id = compilation()->has_fpu_code() ? + StubId::c1_handle_exception_id : + StubId::c1_handle_exception_nofpu_id; Label return_address; __ adr(Rexception_pc, return_address); __ call(Runtime1::entry_for(handle_id), relocInfo::runtime_call_type); @@ -2260,7 +2260,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ mov(altFP_7_11, R1); __ mov(R0, tmp); __ mov(R1, tmp2); - __ call(Runtime1::entry_for(C1StubId::slow_subtype_check_id), relocInfo::runtime_call_type); // does not blow any registers except R0, LR and Rtemp + __ call(Runtime1::entry_for(StubId::c1_slow_subtype_check_id), relocInfo::runtime_call_type); // does not blow any registers except R0, LR and Rtemp __ cmp_32(R0, 0); __ mov(R0, R6); __ mov(R1, altFP_7_11); diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp index ef5691f84a3..c8a3f79960b 100644 --- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp @@ -1057,7 +1057,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); LIR_Opr reg = result_register_for(x->type()); - __ call_runtime(Runtime1::entry_for(C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for(StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); LIR_Opr result = rlock_result(x); @@ -1086,7 +1086,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { CodeStub* stub; if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); @@ -1094,7 +1094,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, LIR_OprFact::illegalOpr, info_for_exception); } diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index 021b47148fa..32da2c24d26 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -64,7 +64,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre reset_last_Java_frame(Rtemp); assert(frame_size() != no_frame_size, "frame must be fixed"); - if (_stub_id != (int)C1StubId::forward_exception_id) { + if (_stub_id != (int)StubId::c1_forward_exception_id) { ldr(R3, Address(Rthread, Thread::pending_exception_offset())); } @@ -80,10 +80,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre // Check for pending exception // unpack_with_exception_in_tls path is taken through // Runtime1::exception_handler_for_pc - if (_stub_id != (int)C1StubId::forward_exception_id) { + if (_stub_id != (int)StubId::c1_forward_exception_id) { assert(frame_size() != no_frame_size, "cannot directly call forward_exception_id"); cmp(R3, 0); - jump(Runtime1::entry_for(C1StubId::forward_exception_id), relocInfo::runtime_call_type, Rtemp, ne); + jump(Runtime1::entry_for(StubId::c1_forward_exception_id), relocInfo::runtime_call_type, Rtemp, ne); } else { #ifdef ASSERT // Should not have pending exception in forward_exception stub @@ -283,7 +283,7 @@ static void restore_sp_for_method_handle(StubAssembler* sasm) { } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) { __ block_comment("generate_handle_exception"); bool save_fpu_registers = false; @@ -293,7 +293,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) OopMap* oop_map = nullptr; switch (id) { - case C1StubId::forward_exception_id: { + case StubId::c1_forward_exception_id: { save_fpu_registers = HaveVFP; oop_map = generate_oop_map(sasm); __ ldr(Rexception_obj, Address(Rthread, Thread::pending_exception_offset())); @@ -302,14 +302,14 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) __ str(zero, Address(Rthread, Thread::pending_exception_offset())); break; } - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_id: save_fpu_registers = HaveVFP; // fall-through - case C1StubId::handle_exception_nofpu_id: + case StubId::c1_handle_exception_nofpu_id: // At this point all registers MAY be live. oop_map = save_live_registers(sasm, save_fpu_registers); break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: // At this point all registers except exception oop (R4/R19) and // exception pc (R5/R20) are dead. oop_map = save_live_registers(sasm); // TODO it's not required to save all registers @@ -331,13 +331,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) // Restore the registers that were saved at the beginning, remove // frame and jump to the exception handler. switch (id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: restore_live_registers(sasm, save_fpu_registers); // Note: the restore live registers includes the jump to LR (patched to R0) break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: restore_live_registers_without_return(sasm); // must not jump immediately to handler restore_sp_for_method_handle(sasm); __ ret(); @@ -406,7 +406,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { const bool must_gc_arguments = true; const bool dont_gc_arguments = false; @@ -414,16 +414,16 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { bool save_fpu_registers = HaveVFP; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); // does not return on ARM } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { const Register result = R0; const Register klass = R1; @@ -439,7 +439,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: { OopMap* oop_map = save_live_registers(sasm); __ ldr(R1, Address(SP, arg1_offset)); @@ -451,10 +451,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: { - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); } else { __ set_info("new_object_array", dont_gc_arguments); @@ -466,7 +466,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { OopMap* map = save_live_registers(sasm); int call_offset; - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); } else { call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); @@ -480,7 +480,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { __ set_info("new_multi_array", dont_gc_arguments); @@ -503,7 +503,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -524,78 +524,78 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { __ set_info("range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { __ set_info("index_range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { __ set_info("throw_div0_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { __ set_info("throw_null_pointer_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { __ set_info("handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { __ set_info("handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { __ set_info("unwind_exception", dont_gc_arguments); generate_unwind_exception(sasm); } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { __ set_info("throw_array_store_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { __ set_info("throw_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // (in) R0 - sub, destroyed, // (in) R1 - super, not changed @@ -628,10 +628,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorenter_nofpu_id: + case StubId::c1_monitorenter_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_id: { __ set_info("monitorenter", dont_gc_arguments); const Register obj = R1; @@ -646,10 +646,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: + case StubId::c1_monitorexit_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_id: { __ set_info("monitorexit", dont_gc_arguments); const Register lock = R1; @@ -662,7 +662,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { __ set_info("deoptimize", dont_gc_arguments); OopMap* oop_map = save_live_registers(sasm); @@ -678,35 +678,35 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { __ set_info("access_field_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { __ set_info("load_klass_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { __ set_info("load_appendix_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { __ set_info("load_mirror_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { __ set_info("predicate_failed_trap", dont_gc_arguments); diff --git a/src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp b/src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp index 4bcff7512e6..6d5faf7a83d 100644 --- a/src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp +++ b/src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp @@ -107,7 +107,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return nullptr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { Unimplemented(); } diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp index 615a63eac19..ea4c9a76381 100644 --- a/src/hotspot/cpu/arm/runtime_arm.cpp +++ b/src/hotspot/cpu/arm/runtime_arm.cpp @@ -47,7 +47,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { ResourceMark rm; // setup code generation tools - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); #ifdef _LP64 CodeBuffer buffer(name, 2700, 512); #else @@ -210,7 +210,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // setup code generation tools // Measured 8/7/03 at 256 in 32bit debug build - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); CodeBuffer buffer(name, 600, 512); if (buffer.blob() == nullptr) { return nullptr; diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 8ba847e7e32..9519c923e22 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -1366,7 +1366,7 @@ VMReg SharedRuntime::thread_register() { //------------------------------generate_deopt_blob---------------------------- void SharedRuntime::generate_deopt_blob() { ResourceMark rm; - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); CodeBuffer buffer(name, 1024, 1024); int frame_size_in_words; OopMapSet* oop_maps; @@ -1608,7 +1608,7 @@ void SharedRuntime::generate_deopt_blob() { // setup oopmap, and calls safepoint code to stop the compiled code for // a safepoint. // -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_polling_page_id(id), "expected a polling page stub id"); @@ -1618,7 +1618,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal int frame_size_words; OopMapSet* oop_maps; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); MacroAssembler* masm = new MacroAssembler(&buffer); address start = __ pc(); @@ -1680,7 +1680,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal return SafepointBlob::create(&buffer, oop_maps, frame_size_words); } -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_resolve_id(id), "expected a resolve stub id"); @@ -1744,7 +1744,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // Continuation point for throwing of implicit exceptions that are not handled in // the current activation. Fabricates an exception oop and initiates normal // exception dispatching in this frame. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); @@ -1808,7 +1808,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { framesize // inclusive of return address }; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_write_checkpoint_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_write_checkpoint_id); CodeBuffer code(name, 512, 64); MacroAssembler* masm = new MacroAssembler(&code); @@ -1852,7 +1852,7 @@ RuntimeStub* SharedRuntime::generate_jfr_return_lease() { framesize // inclusive of return address }; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_return_lease_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_return_lease_id); CodeBuffer code(name, 512, 64); MacroAssembler* masm = new MacroAssembler(&code); diff --git a/src/hotspot/cpu/arm/stubDeclarations_arm.hpp b/src/hotspot/cpu/arm/stubDeclarations_arm.hpp index 93ab16791b5..5f768a205a5 100644 --- a/src/hotspot/cpu/arm/stubDeclarations_arm.hpp +++ b/src/hotspot/cpu/arm/stubDeclarations_arm.hpp @@ -30,7 +30,13 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(preuniverse, 0) \ + do_arch_blob(preuniverse, 500) \ + do_stub(preuniverse, atomic_load_long) \ + do_arch_entry(Arm, preuniverse, atomic_load_long, \ + atomic_load_long_entry, atomic_load_long_entry) \ + do_stub(preuniverse, atomic_store_long) \ + do_arch_entry(Arm, preuniverse, atomic_store_long, \ + atomic_store_long_entry, atomic_store_long_entry) \ #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ @@ -41,12 +47,6 @@ do_stub(initial, idiv_irem) \ do_arch_entry(Arm, initial, idiv_irem, \ idiv_irem_entry, idiv_irem_entry) \ - do_stub(initial, atomic_load_long) \ - do_arch_entry(Arm, initial, atomic_load_long, \ - atomic_load_long_entry, atomic_load_long_entry) \ - do_stub(initial, atomic_store_long) \ - do_arch_entry(Arm, initial, atomic_load_long, \ - atomic_store_long_entry, atomic_store_long_entry) \ #define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ diff --git a/src/hotspot/cpu/arm/stubGenerator_arm.cpp b/src/hotspot/cpu/arm/stubGenerator_arm.cpp index 5f2fd2e3b6d..de5ce221495 100644 --- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp @@ -172,7 +172,7 @@ class StubGenerator: public StubCodeGenerator { private: address generate_call_stub(address& return_address) { - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -252,7 +252,7 @@ class StubGenerator: public StubCodeGenerator { // (in) Rexception_obj: exception oop address generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -265,7 +265,7 @@ class StubGenerator: public StubCodeGenerator { // (in) Rexception_pc: return address address generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -315,7 +315,7 @@ class StubGenerator: public StubCodeGenerator { Register tmp = LR; assert(dividend == remainder, "must be"); - StubGenStubId stub_id = StubGenStubId::idiv_irem_id; + StubId stub_id = StubId::stubgen_idiv_irem_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -458,7 +458,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_add() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_add_id; + StubId stub_id = StubId::stubgen_atomic_add_id; StubCodeMark mark(this, stub_id); Label retry; start = __ pc(); @@ -510,7 +510,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_xchg() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_xchg_id; + StubId stub_id = StubId::stubgen_atomic_xchg_id; StubCodeMark mark(this, stub_id); start = __ pc(); Register newval = R0; @@ -561,7 +561,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_cmpxchg() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_cmpxchg_id; + StubId stub_id = StubId::stubgen_atomic_cmpxchg_id; StubCodeMark mark(this, stub_id); start = __ pc(); Register cmp = R0; @@ -600,7 +600,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_cmpxchg_long() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_cmpxchg_long_id; + StubId stub_id = StubId::stubgen_atomic_cmpxchg_long_id; StubCodeMark mark(this, stub_id); start = __ pc(); Register cmp_lo = R0; @@ -638,7 +638,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_load_long() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_load_long_id; + StubId stub_id = StubId::stubgen_atomic_load_long_id; StubCodeMark mark(this, stub_id); start = __ pc(); Register result_lo = R0; @@ -663,7 +663,7 @@ class StubGenerator: public StubCodeGenerator { address generate_atomic_store_long() { address start; - StubGenStubId stub_id = StubGenStubId::atomic_store_long_id; + StubId stub_id = StubId::stubgen_atomic_store_long_id; StubCodeMark mark(this, stub_id); start = __ pc(); Register newval_lo = R0; @@ -706,7 +706,7 @@ class StubGenerator: public StubCodeGenerator { // raddr: LR, blown by call address generate_partial_subtype_check() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::partial_subtype_check_id; + StubId stub_id = StubId::stubgen_partial_subtype_check_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -796,7 +796,7 @@ class StubGenerator: public StubCodeGenerator { // Non-destructive plausibility checks for oops address generate_verify_oop() { - StubGenStubId stub_id = StubGenStubId::verify_oop_id; + StubId stub_id = StubId::stubgen_verify_oop_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2027,98 +2027,98 @@ class StubGenerator: public StubCodeGenerator { // to: R1 // count: R2 treated as signed 32-bit int // - address generate_primitive_copy(StubGenStubId stub_id, address nooverlap_target = nullptr) { + address generate_primitive_copy(StubId stub_id, address nooverlap_target = nullptr) { bool aligned; bool status; int bytes_per_count; bool disjoint; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: aligned = false; status = true; bytes_per_count = 1; disjoint = true; break; - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: aligned = false; status = true; bytes_per_count = 2; disjoint = true; break; - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: aligned = false; status = true; bytes_per_count = 4; disjoint = true; break; - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: aligned = false; status = true; bytes_per_count = 8; disjoint = true; break; - case arrayof_jbyte_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 1; disjoint = true; break; - case arrayof_jshort_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 2; disjoint = true; break; - case arrayof_jint_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jint_disjoint_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 4; disjoint = true; break; - case arrayof_jlong_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id: aligned = false; status = set_status; bytes_per_count = 8; disjoint = true; break; - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: aligned = false; status = true; bytes_per_count = 1; disjoint = false; break; - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: aligned = false; status = true; bytes_per_count = 2; disjoint = false; break; - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: aligned = false; status = true; bytes_per_count = 4; disjoint = false; break; - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: aligned = false; status = true; bytes_per_count = 8; disjoint = false; break; - case arrayof_jbyte_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 1; disjoint = false; break; - case arrayof_jshort_arraycopy_id: + case StubId::stubgen_arrayof_jshort_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 2; disjoint = false; break; - case arrayof_jint_arraycopy_id: + case StubId::stubgen_arrayof_jint_arraycopy_id: aligned = true; status = set_status; bytes_per_count = 4; @@ -2301,28 +2301,28 @@ class StubGenerator: public StubCodeGenerator { // to: R1 // count: R2 treated as signed 32-bit int // - address generate_oop_copy(StubGenStubId stub_id, address nooverlap_target = nullptr) { + address generate_oop_copy(StubId stub_id, address nooverlap_target = nullptr) { bool aligned; bool status; bool disjoint; switch (stub_id) { - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: aligned = false; status = true; disjoint = true; break; - case arrayof_oop_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_id: aligned = true; status = set_status; disjoint = true; break; - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: aligned = false; status = true; disjoint = false; break; - case arrayof_oop_arraycopy_id: + case StubId::stubgen_arrayof_oop_arraycopy_id: aligned = true; status = set_status; disjoint = false; @@ -2476,7 +2476,7 @@ class StubGenerator: public StubCodeGenerator { const Register R3_bits = R3; // test copy of low bits __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_arraycopy_id; + StubId stub_id = StubId::stubgen_unsafe_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); const Register tmp = Rtemp; @@ -2604,7 +2604,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_checkcast_copy() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::checkcast_arraycopy_id; + StubId stub_id = StubId::stubgen_checkcast_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2772,7 +2772,7 @@ class StubGenerator: public StubCodeGenerator { const Register R8_temp = R8; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::generic_arraycopy_id; + StubId stub_id = StubId::stubgen_generic_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3008,35 +3008,35 @@ class StubGenerator: public StubCodeGenerator { UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit); // these need always status in case they are called from generic_arraycopy - StubRoutines::_jbyte_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::jbyte_disjoint_arraycopy_id); - StubRoutines::_jshort_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::jshort_disjoint_arraycopy_id); - StubRoutines::_jint_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::jint_disjoint_arraycopy_id); - StubRoutines::_jlong_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::jlong_disjoint_arraycopy_id); - StubRoutines::_oop_disjoint_arraycopy = generate_oop_copy (StubGenStubId::oop_disjoint_arraycopy_id); - - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jbyte_disjoint_arraycopy_id); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jshort_disjoint_arraycopy_id); - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jint_disjoint_arraycopy_id); - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jlong_disjoint_arraycopy_id); - StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_oop_copy (StubGenStubId::arrayof_oop_disjoint_arraycopy_id); + StubRoutines::_jbyte_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id); + StubRoutines::_jshort_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jshort_disjoint_arraycopy_id); + StubRoutines::_jint_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jint_disjoint_arraycopy_id); + StubRoutines::_jlong_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jlong_disjoint_arraycopy_id); + StubRoutines::_oop_disjoint_arraycopy = generate_oop_copy (StubId::stubgen_oop_disjoint_arraycopy_id); + + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id); + StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_oop_copy (StubId::stubgen_arrayof_oop_disjoint_arraycopy_id); // these need always status in case they are called from generic_arraycopy - StubRoutines::_jbyte_arraycopy = generate_primitive_copy(StubGenStubId::jbyte_arraycopy_id, StubRoutines::_jbyte_disjoint_arraycopy); - StubRoutines::_jshort_arraycopy = generate_primitive_copy(StubGenStubId::jshort_arraycopy_id, StubRoutines::_jshort_disjoint_arraycopy); - StubRoutines::_jint_arraycopy = generate_primitive_copy(StubGenStubId::jint_arraycopy_id, StubRoutines::_jint_disjoint_arraycopy); - StubRoutines::_jlong_arraycopy = generate_primitive_copy(StubGenStubId::jlong_arraycopy_id, StubRoutines::_jlong_disjoint_arraycopy); - StubRoutines::_oop_arraycopy = generate_oop_copy (StubGenStubId::oop_arraycopy_id, StubRoutines::_oop_disjoint_arraycopy); - - StubRoutines::_arrayof_jbyte_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jbyte_arraycopy_id, StubRoutines::_arrayof_jbyte_disjoint_arraycopy); - StubRoutines::_arrayof_jshort_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jshort_arraycopy_id, StubRoutines::_arrayof_jshort_disjoint_arraycopy); + StubRoutines::_jbyte_arraycopy = generate_primitive_copy(StubId::stubgen_jbyte_arraycopy_id, StubRoutines::_jbyte_disjoint_arraycopy); + StubRoutines::_jshort_arraycopy = generate_primitive_copy(StubId::stubgen_jshort_arraycopy_id, StubRoutines::_jshort_disjoint_arraycopy); + StubRoutines::_jint_arraycopy = generate_primitive_copy(StubId::stubgen_jint_arraycopy_id, StubRoutines::_jint_disjoint_arraycopy); + StubRoutines::_jlong_arraycopy = generate_primitive_copy(StubId::stubgen_jlong_arraycopy_id, StubRoutines::_jlong_disjoint_arraycopy); + StubRoutines::_oop_arraycopy = generate_oop_copy (StubId::stubgen_oop_arraycopy_id, StubRoutines::_oop_disjoint_arraycopy); + + StubRoutines::_arrayof_jbyte_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id, StubRoutines::_arrayof_jbyte_disjoint_arraycopy); + StubRoutines::_arrayof_jshort_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jshort_arraycopy_id, StubRoutines::_arrayof_jshort_disjoint_arraycopy); #ifdef _LP64 // since sizeof(jint) < sizeof(HeapWord), there's a different flavor: - StubRoutines::_arrayof_jint_arraycopy = generate_primitive_copy(StubGenStubId::arrayof_jint_arraycopy_id, StubRoutines::_arrayof_jint_disjoint_arraycopy); + StubRoutines::_arrayof_jint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jint_arraycopy_id, StubRoutines::_arrayof_jint_disjoint_arraycopy); #else StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; #endif if (BytesPerHeapOop < HeapWordSize) { - StubRoutines::_arrayof_oop_arraycopy = generate_oop_copy (StubGenStubId::arrayof_oop_arraycopy_id, StubRoutines::_arrayof_oop_disjoint_arraycopy); + StubRoutines::_arrayof_oop_arraycopy = generate_oop_copy (StubId::stubgen_arrayof_oop_arraycopy_id, StubRoutines::_arrayof_oop_disjoint_arraycopy); } else { StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; } @@ -3051,7 +3051,7 @@ class StubGenerator: public StubCodeGenerator { address generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); Label deoptimize_label; @@ -3105,29 +3105,36 @@ class StubGenerator: public StubCodeGenerator { #undef __ #define __ masm-> - address generate_cont_thaw(StubGenStubId stub_id) { + address generate_cont_thaw(StubId stub_id) { if (!Continuations::enabled()) return nullptr; Unimplemented(); return nullptr; } address generate_cont_thaw() { - return generate_cont_thaw(StubGenStubId::cont_thaw_id); + return generate_cont_thaw(StubId::stubgen_cont_thaw_id); } address generate_cont_returnBarrier() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrier_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrier_id); } address generate_cont_returnBarrier_exception() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrierExc_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrierExc_id); } //--------------------------------------------------------------------------- // Initialization void generate_preuniverse_stubs() { - // preuniverse stubs are not needed for arm + // Atomics are used in universe initialization code (e.g. CDS relocation), + // therefore we need to generate real stubs very early on. + StubRoutines::_atomic_add_entry = generate_atomic_add(); + StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); + StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); + StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); + StubRoutines::Arm::_atomic_load_long_entry = generate_atomic_load_long(); + StubRoutines::Arm::_atomic_store_long_entry = generate_atomic_store_long(); } void generate_initial_stubs() { @@ -3151,14 +3158,6 @@ class StubGenerator: public StubCodeGenerator { // integer division used both by interpreter and compiler StubRoutines::Arm::_idiv_irem_entry = generate_idiv_irem(); - - StubRoutines::_atomic_add_entry = generate_atomic_add(); - StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); - StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); - StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); - StubRoutines::Arm::_atomic_load_long_entry = generate_atomic_load_long(); - StubRoutines::Arm::_atomic_store_long_entry = generate_atomic_store_long(); - } void generate_continuation_stubs() { @@ -3203,31 +3202,31 @@ class StubGenerator: public StubCodeGenerator { } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } }; // end class declaration -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp b/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp index b663cfd9298..eb85b0bddf0 100644 --- a/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp +++ b/src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -119,7 +119,7 @@ void aes_init() { address generate_aescrypt_encryptBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -317,7 +317,7 @@ address generate_aescrypt_encryptBlock() { address generate_aescrypt_decryptBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -538,7 +538,7 @@ address generate_cipherBlockChaining_encryptAESCrypt() { // [sp+4] Transposition Box reference __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_encryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -604,7 +604,7 @@ address generate_cipherBlockChaining_encryptAESCrypt() { address generate_cipherBlockChaining_decryptAESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/ppc/assembler_ppc.hpp b/src/hotspot/cpu/ppc/assembler_ppc.hpp index 314517fd56a..aa330bfa1a7 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp @@ -757,6 +757,7 @@ class Assembler : public AbstractAssembler { VCTZH_OPCODE = (4u << OPCODE_SHIFT | 29u << 16 | 1538u), VCTZW_OPCODE = (4u << OPCODE_SHIFT | 30u << 16 | 1538u), VCTZD_OPCODE = (4u << OPCODE_SHIFT | 31u << 16 | 1538u), + VNEGW_OPCODE = (4u << OPCODE_SHIFT | 6u << 16 | 1538u), // Vector Floating-Point // not implemented yet @@ -2372,6 +2373,7 @@ class Assembler : public AbstractAssembler { inline void vctzh( VectorRegister d, VectorRegister b); inline void vctzw( VectorRegister d, VectorRegister b); inline void vctzd( VectorRegister d, VectorRegister b); + inline void vnegw( VectorRegister d, VectorRegister b); // Vector Floating-Point not implemented yet inline void mtvscr( VectorRegister b); inline void mfvscr( VectorRegister d); diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp index 792e5d6d5ad..24601c5d3b0 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp @@ -1092,6 +1092,9 @@ inline void Assembler::vctzd( VectorRegister d, VectorRegister b) inline void Assembler::mtvscr( VectorRegister b) { emit_int32( MTVSCR_OPCODE | vrb(b)); } inline void Assembler::mfvscr( VectorRegister d) { emit_int32( MFVSCR_OPCODE | vrt(d)); } +// Vector Negate Word (introduced with Power 9) +inline void Assembler::vnegw( VectorRegister d, VectorRegister b) { emit_int32( VNEGW_OPCODE | vrt(d) | vrb(b)); } + // AES (introduced with Power 8) inline void Assembler::vcipher( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCIPHER_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vcipherlast( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCIPHERLAST_OPCODE | vrt(d) | vra(a) | vrb(b)); } diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp index b1cdf38daf3..438521b0a9b 100644 --- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp @@ -50,7 +50,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); //__ load_const_optimized(R0, a); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(a)); __ mtctr(R0); @@ -61,8 +61,8 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { return; } - address stub = _throw_index_out_of_bounds_exception ? Runtime1::entry_for(C1StubId::throw_index_exception_id) - : Runtime1::entry_for(C1StubId::throw_range_check_failed_id); + address stub = _throw_index_out_of_bounds_exception ? Runtime1::entry_for(StubId::c1_throw_index_exception_id) + : Runtime1::entry_for(StubId::c1_throw_range_check_failed_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); __ mtctr(R0); @@ -91,7 +91,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); //__ load_const_optimized(R0, a); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(a)); __ mtctr(R0); @@ -115,7 +115,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { __ load_const_optimized(R0, md.value()); __ std(R0, -8, R1_SP); - address a = Runtime1::entry_for(C1StubId::counter_overflow_id); + address a = Runtime1::entry_for(StubId::c1_counter_overflow_id); //__ load_const_optimized(R0, a); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(a)); __ mtctr(R0); @@ -132,7 +132,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - address stub = Runtime1::entry_for(C1StubId::throw_div0_exception_id); + address stub = Runtime1::entry_for(StubId::c1_throw_div0_exception_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); __ mtctr(R0); @@ -147,9 +147,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { address a; if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is probably wrong to do it here. - a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); } if (ImplicitNullChecks || TrapBasedNullChecks) { @@ -181,14 +181,14 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) { // Implementation of NewInstanceStub -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -218,7 +218,7 @@ NewTypeArrayStub::NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr re void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address entry = Runtime1::entry_for(C1StubId::new_type_array_id); + address entry = Runtime1::entry_for(StubId::c1_new_type_array_id); //__ load_const_optimized(R0, entry); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(entry)); __ mr_if_needed(/*op->tmp1()->as_register()*/ R5_ARG3, _length->as_register()); // already sign-extended @@ -241,7 +241,7 @@ NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Op void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address entry = Runtime1::entry_for(C1StubId::new_object_array_id); + address entry = Runtime1::entry_for(StubId::c1_new_object_array_id); //__ load_const_optimized(R0, entry); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(entry)); __ mr_if_needed(/*op->tmp1()->as_register()*/ R5_ARG3, _length->as_register()); // already sign-extended @@ -254,7 +254,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { void MonitorEnterStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address stub = Runtime1::entry_for(ce->compilation()->has_fpu_code() ? C1StubId::monitorenter_id : C1StubId::monitorenter_nofpu_id); + address stub = Runtime1::entry_for(ce->compilation()->has_fpu_code() ? StubId::c1_monitorenter_id : StubId::c1_monitorenter_nofpu_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); __ mr_if_needed(/*scratch_opr()->as_register()*/ R4_ARG2, _obj_reg->as_register()); @@ -271,7 +271,7 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { if (_compute_lock) { ce->monitor_address(_monitor_ix, _lock_reg); } - address stub = Runtime1::entry_for(ce->compilation()->has_fpu_code() ? C1StubId::monitorexit_id : C1StubId::monitorexit_nofpu_id); + address stub = Runtime1::entry_for(ce->compilation()->has_fpu_code() ? StubId::c1_monitorexit_id : StubId::c1_monitorexit_nofpu_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); assert(_lock_reg->as_register() == R4_ARG2, ""); @@ -385,12 +385,12 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { address target = nullptr; relocInfo::relocType reloc_type = relocInfo::none; switch (_id) { - case access_field_id: target = Runtime1::entry_for(C1StubId::access_field_patching_id); break; - case load_klass_id: target = Runtime1::entry_for(C1StubId::load_klass_patching_id); + case access_field_id: target = Runtime1::entry_for(StubId::c1_access_field_patching_id); break; + case load_klass_id: target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; - case load_mirror_id: target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); + case load_mirror_id: target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; - case load_appendix_id: target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); + case load_appendix_id: target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } @@ -416,7 +416,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address stub = Runtime1::entry_for(C1StubId::deoptimize_id); + address stub = Runtime1::entry_for(StubId::c1_deoptimize_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); __ mtctr(R0); diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index f5ae92789c6..4559c0e49d5 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -191,7 +191,7 @@ int LIR_Assembler::emit_exception_handler() { } int offset = code_offset(); - address entry_point = CAST_FROM_FN_PTR(address, Runtime1::entry_for(C1StubId::handle_exception_from_callee_id)); + address entry_point = CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_handle_exception_from_callee_id)); //__ load_const_optimized(R0, entry_point); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(entry_point)); __ mtctr(R0); @@ -241,7 +241,7 @@ int LIR_Assembler::emit_unwind_handler() { } // Dispatch to the unwind logic. - address unwind_stub = Runtime1::entry_for(C1StubId::unwind_exception_id); + address unwind_stub = Runtime1::entry_for(StubId::c1_unwind_exception_id); //__ load_const_optimized(R0, unwind_stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(unwind_stub)); if (preserve_exception) { __ mr(Rexception, Rexception_save); } @@ -1788,8 +1788,8 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit __ calculate_address_from_global_toc(exceptionPC->as_register(), pc_for_athrow, true, true, /*add_relocation*/ true); add_call_info(pc_for_athrow_offset, info); // for exception handler - address stub = Runtime1::entry_for(compilation()->has_fpu_code() ? C1StubId::handle_exception_id - : C1StubId::handle_exception_nofpu_id); + address stub = Runtime1::entry_for(compilation()->has_fpu_code() ? StubId::c1_handle_exception_id + : StubId::c1_handle_exception_nofpu_id); //__ load_const_optimized(R0, stub); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub)); __ mtctr(R0); @@ -1980,7 +1980,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ check_klass_subtype_fast_path(sub_klass, super_klass, tmp, tmp2, &cont, copyfunc_addr != nullptr ? ©func : &slow, nullptr); - address slow_stc = Runtime1::entry_for(C1StubId::slow_subtype_check_id); + address slow_stc = Runtime1::entry_for(StubId::c1_slow_subtype_check_id); //__ load_const_optimized(tmp, slow_stc, tmp2); __ calculate_address_from_global_toc(tmp, slow_stc, true, true, false); __ mtctr(tmp); @@ -2408,7 +2408,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ b(*success); } else { // Call out-of-line instance of __ check_klass_subtype_slow_path(...): - address entry = Runtime1::entry_for(C1StubId::slow_subtype_check_id); + address entry = Runtime1::entry_for(StubId::c1_slow_subtype_check_id); // Stub needs fixed registers (tmp1-3). Register original_k_RInfo = op->tmp1()->as_register(); Register original_klass_RInfo = op->tmp2()->as_register(); @@ -2499,7 +2499,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, R0, &done, &failure, nullptr); // Call out-of-line instance of __ check_klass_subtype_slow_path(...): - const address slow_path = Runtime1::entry_for(C1StubId::slow_subtype_check_id); + const address slow_path = Runtime1::entry_for(StubId::c1_slow_subtype_check_id); //__ load_const_optimized(R0, slow_path); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(slow_path)); __ mtctr(R0); @@ -2801,9 +2801,9 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) { void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { // Stubs: Called via rt_call, but dest is a stub address (no FunctionDescriptor). - if (dest == Runtime1::entry_for(C1StubId::register_finalizer_id) || - dest == Runtime1::entry_for(C1StubId::new_multi_array_id ) || - dest == Runtime1::entry_for(C1StubId::is_instance_of_id )) { + if (dest == Runtime1::entry_for(StubId::c1_register_finalizer_id) || + dest == Runtime1::entry_for(StubId::c1_new_multi_array_id ) || + dest == Runtime1::entry_for(StubId::c1_is_instance_of_id )) { assert(CodeCache::contains(dest), "simplified call is only for special C1 stubs"); //__ load_const_optimized(R0, dest); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(dest)); diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index 815e5c83a1b..5f030676bcb 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -976,7 +976,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); const LIR_Opr reg = result_register_for(x->type()); - __ call_runtime(Runtime1::entry_for(C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for(StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); @@ -1011,7 +1011,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); @@ -1019,7 +1019,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, obj.result(), info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, obj.result(), info_for_exception); } // Following registers are used by slow_subtype_check: LIR_Opr tmp1 = FrameMap::R4_oop_opr; // super_klass @@ -1053,7 +1053,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { // Intrinsic for Class::isInstance address LIRGenerator::isInstance_entry() { - return Runtime1::entry_for(C1StubId::is_instance_of_id); + return Runtime1::entry_for(StubId::c1_is_instance_of_id); } diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 02e069b6be1..23050bff453 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -307,7 +307,7 @@ void C1_MacroAssembler::initialize_object( if (CURRENT_ENV->dtrace_alloc_probes()) { Unimplemented(); // assert(obj == O0, "must be"); -// call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(C1StubId::dtrace_object_alloc_id)), +// call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id)), // relocInfo::runtime_call_type); } @@ -383,7 +383,7 @@ void C1_MacroAssembler::allocate_array( if (CURRENT_ENV->dtrace_alloc_probes()) { Unimplemented(); //assert(obj == O0, "must be"); - //call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(C1StubId::dtrace_object_alloc_id)), + //call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id)), // relocInfo::runtime_call_type); } @@ -412,7 +412,7 @@ void C1_MacroAssembler::null_check(Register r, Label* Lnull) { if (TrapBasedNullChecks) { // SIGTRAP based trap_null_check(r); } else { // explicit - //const address exception_entry = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + //const address exception_entry = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); assert(Lnull != nullptr, "must have Label for explicit check"); cmpdi(CR0, r, 0); bc_far_optimized(Assembler::bcondCRbiIs1, bi0(CR0, Assembler::equal), *Lnull); diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp index 12cf4b2f97d..78e41cf138c 100644 --- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp @@ -97,12 +97,12 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, //load_const_optimized(R0, StubRoutines::forward_exception_entry()); //mtctr(R0); //bctr(); - } else if (_stub_id == (int)C1StubId::forward_exception_id) { + } else if (_stub_id == (int)StubId::c1_forward_exception_id) { should_not_reach_here(); } else { // keep stub frame for next call_RT - //load_const_optimized(R0, Runtime1::entry_for(C1StubId::forward_exception_id)); - add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(Runtime1::entry_for(C1StubId::forward_exception_id))); + //load_const_optimized(R0, Runtime1::entry_for(StubId::c1_forward_exception_id)); + add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(Runtime1::entry_for(StubId::c1_forward_exception_id))); mtctr(R0); bctr(); } @@ -391,7 +391,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { return oop_maps; } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { OopMapSet* oop_maps = nullptr; // For better readability. @@ -400,22 +400,22 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // Stub code & info for the different stubs. switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { - if (id == C1StubId::new_instance_id) { + if (id == StubId::c1_new_instance_id) { __ set_info("new_instance", dont_gc_arguments); - } else if (id == C1StubId::fast_new_instance_id) { + } else if (id == StubId::c1_fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { - assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId"); + assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId"); __ set_info("fast new_instance init check", dont_gc_arguments); } @@ -425,15 +425,15 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: // Bci and method are on stack. oop_maps = stub_call_with_stack_parms(sasm, noreg, CAST_FROM_FN_PTR(address, counter_overflow), 2); break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: { - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); } else { __ set_info("new_object_array", dont_gc_arguments); @@ -442,7 +442,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { #ifdef ASSERT // Assert object type is really an array of the proper kind. { - int tag = (id == C1StubId::new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value; + int tag = (id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value; Label ok; __ lwz(R0, in_bytes(Klass::layout_helper_offset()), R4_ARG2); __ srawi(R0, R0, Klass::_lh_array_tag_shift); @@ -456,7 +456,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // We don't support eden allocation. - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_type_array), R4_ARG2, R5_ARG3); } else { oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_object_array), R4_ARG2, R5_ARG3); @@ -464,7 +464,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { // R4: klass // R5: rank @@ -474,7 +474,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); // This code is called via rt_call. Hence, caller-save registers have been saved. @@ -504,50 +504,50 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { __ set_info("range_check_failed", dont_gc_arguments); // Arguments will be discarded. oop_maps = generate_exception_throw_with_stack_parms(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), 2); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { __ set_info("index_range_check_failed", dont_gc_arguments); // Arguments will be discarded. oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { __ set_info("throw_div0_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { __ set_info("throw_null_pointer_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { __ set_info("handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { __ set_info("handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { const Register Rexception = R3 /*LIRGenerator::exceptionOopOpr()*/, Rexception_pc = R4 /*LIRGenerator::exceptionPcOpr()*/, @@ -575,28 +575,28 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { __ set_info("throw_array_store_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { __ set_info("throw_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // Support for uint StubRoutine::partial_subtype_check( Klass sub, Klass super ); const Register sub_klass = R5, super_klass = R4, @@ -607,7 +607,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::is_instance_of_id: + case StubId::c1_is_instance_of_id: { // Called like a C function, but without FunctionDescriptor (see LIR_Assembler::rt_call). @@ -674,12 +674,12 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorenter_nofpu_id: - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_nofpu_id: + case StubId::c1_monitorenter_id: { __ set_info("monitorenter", dont_gc_arguments); - int save_fpu_registers = (id == C1StubId::monitorenter_id); + int save_fpu_registers = (id == StubId::c1_monitorenter_id); // Make a frame and preserve the caller's caller-save registers. OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); @@ -693,15 +693,15 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_nofpu_id: + case StubId::c1_monitorexit_id: { // note: Really a leaf routine but must setup last java sp // => use call_RT for now (speed can be improved by // doing last java sp setup manually). __ set_info("monitorexit", dont_gc_arguments); - int save_fpu_registers = (id == C1StubId::monitorexit_id); + int save_fpu_registers = (id == StubId::c1_monitorexit_id); // Make a frame and preserve the caller's caller-save registers. OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); @@ -715,7 +715,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { __ set_info("deoptimize", dont_gc_arguments); __ std(R0, -8, R1_SP); // Pass trap_request on stack. @@ -731,35 +731,35 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { __ set_info("access_field_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { __ set_info("load_klass_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { __ set_info("load_mirror_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { __ set_info("load_appendix_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); } break; - case C1StubId::dtrace_object_alloc_id: + case StubId::c1_dtrace_object_alloc_id: { // O0: object __ unimplemented("stub dtrace_object_alloc_id"); __ set_info("dtrace_object_alloc", dont_gc_arguments); @@ -779,7 +779,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { __ set_info("predicate_failed_trap", dont_gc_arguments); OopMap* oop_map = save_live_registers(sasm); @@ -823,7 +823,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) { __ block_comment("generate_handle_exception"); // Save registers, if required. @@ -833,7 +833,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) Rexception_pc = R4 /*LIRGenerator::exceptionPcOpr()*/; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: // We're handling an exception in the context of a compiled frame. // The registers have been saved in the standard places. Perform // an exception lookup in the caller and dispatch to the handler @@ -849,12 +849,12 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) __ ld(Rexception_pc, _abi0(lr), Rexception_pc); __ std(R0, in_bytes(JavaThread::pending_exception_offset()), R16_thread); break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id, Rexception_pc); + oop_map = save_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id, Rexception_pc); break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: // At this point all registers except exception oop and exception pc are dead. oop_map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); @@ -893,13 +893,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) // Restore the registers that were saved at the beginning, remove // the frame and jump to the exception handler. switch (id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: - restore_live_registers(sasm, noreg, noreg, id != C1StubId::handle_exception_nofpu_id); + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: + restore_live_registers(sasm, noreg, noreg, id != StubId::c1_handle_exception_nofpu_id); __ bctr(); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { __ pop_frame(); __ ld(Rexception_pc, _abi0(lr), R1_SP); __ mtlr(Rexception_pc); diff --git a/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp b/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp index d55bf0da3e3..2ab055f9177 100644 --- a/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp @@ -110,7 +110,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return (address)f.own_abi()->lr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { f.own_abi()->lr = (uint64_t)pc; } diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 5f85ff96664..bf43ecaba79 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2193,6 +2193,7 @@ bool Matcher::match_rule_supported(int opcode) { case Op_DivVD: case Op_AbsVF: case Op_AbsVD: + case Op_NegVI: case Op_NegVF: case Op_NegVD: case Op_SqrtVF: @@ -2203,6 +2204,8 @@ bool Matcher::match_rule_supported(int opcode) { case Op_RoundDoubleModeV: case Op_MinV: case Op_MaxV: + case Op_UMinV: + case Op_UMaxV: case Op_AndV: case Op_OrV: case Op_XorV: @@ -2268,7 +2271,11 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { // MaxV, MinV need types == INT || LONG. case Op_MaxV: case Op_MinV: + case Op_UMinV: + case Op_UMaxV: return bt == T_INT || bt == T_LONG; + case Op_NegVI: + return PowerArchitecturePPC64 >= 9 && bt == T_INT; } return true; // Per default match rules are supported. } @@ -8422,6 +8429,18 @@ instruct mulHighL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ ins_pipe(pipe_class_default); %} +instruct uMulHighL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (UMulHiL src1 src2)); + ins_cost(DEFAULT_COST); + + format %{ "MULHDU $dst $src1, $src2 \t// unsigned long" %} + size(4); + ins_encode %{ + __ mulhdu($dst$$Register, $src1$$Register, $src2$$Register); + %} + ins_pipe(pipe_class_default); +%} + // Immediate Multiplication instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ match(Set dst (MulL src1 src2)); @@ -10783,6 +10802,36 @@ instruct cmpL3_reg_reg(iRegIdst dst, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 c ins_pipe(pipe_class_default); %} +instruct cmpU3_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ + match(Set dst (CmpU3 src1 src2)); + effect(KILL cr0); + ins_cost(DEFAULT_COST * 5); + size((VM_Version::has_brw() ? 16 : 20)); + + format %{ "cmpU3_reg_reg $dst, $src1, $src2" %} + + ins_encode %{ + __ cmplw(CR0, $src1$$Register, $src2$$Register); + __ set_cmp3($dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmpUL3_reg_reg(iRegIdst dst, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 cr0) %{ + match(Set dst (CmpUL3 src1 src2)); + effect(KILL cr0); + ins_cost(DEFAULT_COST * 5); + size((VM_Version::has_brw() ? 16 : 20)); + + format %{ "cmpUL3_reg_reg $dst, $src1, $src2" %} + + ins_encode %{ + __ cmpld(CR0, $src1$$Register, $src2$$Register); + __ set_cmp3($dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + // Implicit range checks. // A range check in the ideal world has one of the following shapes: // - (If le (CmpU length index)), (IfTrue throw exception) @@ -13347,6 +13396,46 @@ instruct vmax_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe(pipe_class_default); %} +instruct vminu_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (UMinV src1 src2)); + format %{ "VMINU $dst,$src1,$src2\t// vector unsigned min" %} + size(4); + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + switch (bt) { + case T_INT: + __ vminuw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + break; + case T_LONG: + __ vminud($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + break; + default: + ShouldNotReachHere(); + } + %} + ins_pipe(pipe_class_default); +%} + +instruct vmaxu_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (UMaxV src1 src2)); + format %{ "VMAXU $dst,$src1,$src2\t// vector unsigned max" %} + size(4); + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + switch (bt) { + case T_INT: + __ vmaxuw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + break; + case T_LONG: + __ vmaxud($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + break; + default: + ShouldNotReachHere(); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vand(vecX dst, vecX src1, vecX src2) %{ match(Set dst (AndV src1 src2)); size(4); @@ -13507,6 +13596,17 @@ instruct vneg2D_reg(vecX dst, vecX src) %{ ins_pipe(pipe_class_default); %} +instruct vneg4I_reg(vecX dst, vecX src) %{ + match(Set dst (NegVI src)); + predicate(PowerArchitecturePPC64 >= 9 && Matcher::vector_element_basic_type(n) == T_INT); + format %{ "VNEGW $dst,$src\t// negate int vector" %} + size(4); + ins_encode %{ + __ vnegw($dst$$VectorRegister, $src$$VectorRegister); + %} + ins_pipe(pipe_class_default); +%} + // Vector Square Root Instructions instruct vsqrt4F_reg(vecX dst, vecX src) %{ diff --git a/src/hotspot/cpu/ppc/runtime_ppc.cpp b/src/hotspot/cpu/ppc/runtime_ppc.cpp index 6d9a1dfcb1e..2654075f702 100644 --- a/src/hotspot/cpu/ppc/runtime_ppc.cpp +++ b/src/hotspot/cpu/ppc/runtime_ppc.cpp @@ -71,7 +71,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 37d6c9e6d51..64bd8dc7812 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -2947,7 +2947,7 @@ void SharedRuntime::generate_deopt_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); CodeBuffer buffer(name, 2048, 1024); InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); Label exec_mode_initialized; @@ -3170,7 +3170,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; @@ -3302,7 +3302,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { #endif // COMPILER2 // Generate a special Compile2Runtime blob that saves all registers, and setup oopmap. -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_polling_page_id(id), "expected a polling page stub id"); @@ -3320,7 +3320,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal int frame_size_in_bytes = 0; RegisterSaver::ReturnPCLocation return_pc_location; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); if (cause_return) { // Nothing to do here. The frame has already been popped in MachEpilogNode. // Register LR already contains the return pc. @@ -3330,7 +3330,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal return_pc_location = RegisterSaver::return_pc_is_thread_saved_exception_pc; } - bool save_vectors = (id == SharedStubId::polling_page_vectors_safepoint_handler_id); + bool save_vectors = (id == StubId::shared_polling_page_vectors_safepoint_handler_id); // Save registers, fpu state, and flags. Set R31 = return pc. map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm, @@ -3417,7 +3417,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // but since this is generic code we don't know what they are and the caller // must do any gc of the args. // -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert(is_resolve_id(id), "expected a resolve stub id"); // allocate space for the code @@ -3521,7 +3521,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // Note: the routine set_pc_not_at_call_for_caller in // SharedRuntime.cpp requires that this code be generated into a // RuntimeStub. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); @@ -3844,7 +3844,7 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, // It returns a jobject handle to the event writer. // The handle is dereferenced and the return value is the event writer oop. RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_write_checkpoint_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_write_checkpoint_id); CodeBuffer code(name, 512, 64); MacroAssembler* masm = new MacroAssembler(&code); @@ -3881,7 +3881,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { // For c2: call to return a leased buffer. RuntimeStub* SharedRuntime::generate_jfr_return_lease() { - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_return_lease_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_return_lease_id); CodeBuffer code(name, 512, 64); MacroAssembler* masm = new MacroAssembler(&code); diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index a2b25376837..c2f290212bd 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -89,7 +89,7 @@ class StubGenerator: public StubCodeGenerator { // Setup a new c frame, copy java arguments, call template interpreter or // native_entry, and process result. - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -365,7 +365,7 @@ class StubGenerator: public StubCodeGenerator { // within the VM. // address generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -421,7 +421,7 @@ class StubGenerator: public StubCodeGenerator { // (LR is unchanged and is live out). // address generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -706,32 +706,32 @@ class StubGenerator: public StubCodeGenerator { // value: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_fill(StubGenStubId stub_id) { + address generate_fill(StubId stub_id) { BasicType t; bool aligned; switch (stub_id) { - case jbyte_fill_id: + case StubId::stubgen_jbyte_fill_id: t = T_BYTE; aligned = false; break; - case jshort_fill_id: + case StubId::stubgen_jshort_fill_id: t = T_SHORT; aligned = false; break; - case jint_fill_id: + case StubId::stubgen_jint_fill_id: t = T_INT; aligned = false; break; - case arrayof_jbyte_fill_id: + case StubId::stubgen_arrayof_jbyte_fill_id: t = T_BYTE; aligned = true; break; - case arrayof_jshort_fill_id: + case StubId::stubgen_arrayof_jshort_fill_id: t = T_SHORT; aligned = true; break; - case arrayof_jint_fill_id: + case StubId::stubgen_arrayof_jint_fill_id: t = T_INT; aligned = true; break; @@ -984,13 +984,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_disjoint_byte_copy(StubGenStubId stub_id) { + address generate_disjoint_byte_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: aligned = false; break; - case arrayof_jbyte_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id: aligned = true; break; default: @@ -1154,13 +1154,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_conjoint_byte_copy(StubGenStubId stub_id) { + address generate_conjoint_byte_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: aligned = false; break; - case arrayof_jbyte_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_arraycopy_id: aligned = true; break; default: @@ -1255,13 +1255,13 @@ class StubGenerator: public StubCodeGenerator { // // 1. check if aligning the backbranch target of loops is beneficial // - address generate_disjoint_short_copy(StubGenStubId stub_id) { + address generate_disjoint_short_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: aligned = false; break; - case arrayof_jshort_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id: aligned = true; break; default: @@ -1432,13 +1432,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_conjoint_short_copy(StubGenStubId stub_id) { + address generate_conjoint_short_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: aligned = false; break; - case arrayof_jshort_arraycopy_id: + case StubId::stubgen_arrayof_jshort_arraycopy_id: aligned = true; break; default: @@ -1595,13 +1595,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_disjoint_int_copy(StubGenStubId stub_id) { + address generate_disjoint_int_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: aligned = false; break; - case arrayof_jint_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jint_disjoint_arraycopy_id: aligned = true; break; default: @@ -1736,13 +1736,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_conjoint_int_copy(StubGenStubId stub_id) { + address generate_conjoint_int_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: aligned = false; break; - case arrayof_jint_arraycopy_id: + case StubId::stubgen_arrayof_jint_arraycopy_id: aligned = true; break; default: @@ -1860,13 +1860,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_disjoint_long_copy(StubGenStubId stub_id) { + address generate_disjoint_long_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: aligned = false; break; - case arrayof_jlong_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id: aligned = true; break; default: @@ -1980,13 +1980,13 @@ class StubGenerator: public StubCodeGenerator { // to: R4_ARG2 // count: R5_ARG3 treated as signed // - address generate_conjoint_long_copy(StubGenStubId stub_id) { + address generate_conjoint_long_copy(StubId stub_id) { bool aligned; switch (stub_id) { - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: aligned = false; break; - case arrayof_jlong_arraycopy_id: + case StubId::stubgen_arrayof_jlong_arraycopy_id: aligned = true; break; default: @@ -2021,23 +2021,23 @@ class StubGenerator: public StubCodeGenerator { // count: R5_ARG3 treated as signed // dest_uninitialized: G1 support // - address generate_conjoint_oop_copy(StubGenStubId stub_id) { + address generate_conjoint_oop_copy(StubId stub_id) { bool aligned; bool dest_uninitialized; switch (stub_id) { - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: aligned = false; dest_uninitialized = false; break; - case arrayof_oop_arraycopy_id: + case StubId::stubgen_arrayof_oop_arraycopy_id: aligned = true; dest_uninitialized = false; break; - case oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: aligned = false; dest_uninitialized = true; break; - case arrayof_oop_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_arraycopy_uninit_id: aligned = true; dest_uninitialized = true; break; @@ -2092,23 +2092,23 @@ class StubGenerator: public StubCodeGenerator { // count: R5_ARG3 treated as signed // dest_uninitialized: G1 support // - address generate_disjoint_oop_copy(StubGenStubId stub_id) { + address generate_disjoint_oop_copy(StubId stub_id) { bool aligned; bool dest_uninitialized; switch (stub_id) { - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: aligned = false; dest_uninitialized = false; break; - case arrayof_oop_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_id: aligned = true; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: aligned = false; dest_uninitialized = true; break; - case arrayof_oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id: aligned = true; dest_uninitialized = true; break; @@ -2184,7 +2184,7 @@ class StubGenerator: public StubCodeGenerator { // ckval: R7 (super_klass) // ret: R3 zero for success; (-1^K) where K is partial transfer count // - address generate_checkcast_copy(StubGenStubId stub_id) { + address generate_checkcast_copy(StubId stub_id) { const Register R3_from = R3_ARG1; // source array address const Register R4_to = R4_ARG2; // destination array address const Register R5_count = R5_ARG3; // elements count @@ -2200,10 +2200,10 @@ class StubGenerator: public StubCodeGenerator { bool dest_uninitialized; switch (stub_id) { - case checkcast_arraycopy_id: + case StubId::stubgen_checkcast_arraycopy_id: dest_uninitialized = false; break; - case checkcast_arraycopy_uninit_id: + case StubId::stubgen_checkcast_arraycopy_uninit_id: dest_uninitialized = true; break; default: @@ -2342,7 +2342,7 @@ class StubGenerator: public StubCodeGenerator { const Register R7_tmp = R7_ARG5; //__ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_arraycopy_id; + StubId stub_id = StubId::stubgen_unsafe_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -2455,7 +2455,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_unsafe_setmemory(address unsafe_byte_fill) { __ align(CodeEntryAlignment); - StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id); + StubCodeMark mark(this, StubId::stubgen_unsafe_setmemory_id); address start = __ function_entry(); // bump this on entry, not on exit: @@ -2548,7 +2548,7 @@ class StubGenerator: public StubCodeGenerator { const Register temp = R2; //__ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::generic_arraycopy_id; + StubId stub_id = StubId::stubgen_generic_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -2751,7 +2751,7 @@ class StubGenerator: public StubCodeGenerator { // R5_ARG3 - round key array address generate_aescrypt_encryptBlock() { assert(UseAES, "need AES instructions and misaligned SSE support"); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -2959,7 +2959,7 @@ class StubGenerator: public StubCodeGenerator { // R5_ARG3 - K (key) in little endian int array address generate_aescrypt_decryptBlock() { assert(UseAES, "need AES instructions and misaligned SSE support"); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -3197,14 +3197,14 @@ class StubGenerator: public StubCodeGenerator { return start; } - address generate_sha256_implCompress(StubGenStubId stub_id) { + address generate_sha256_implCompress(StubId stub_id) { assert(UseSHA, "need SHA instructions"); bool multi_block; switch (stub_id) { - case sha256_implCompress_id: + case StubId::stubgen_sha256_implCompress_id: multi_block = false; break; - case sha256_implCompressMB_id: + case StubId::stubgen_sha256_implCompressMB_id: multi_block = true; break; default: @@ -3219,14 +3219,14 @@ class StubGenerator: public StubCodeGenerator { return start; } - address generate_sha512_implCompress(StubGenStubId stub_id) { + address generate_sha512_implCompress(StubId stub_id) { assert(UseSHA, "need SHA instructions"); bool multi_block; switch (stub_id) { - case sha512_implCompress_id: + case StubId::stubgen_sha512_implCompress_id: multi_block = false; break; - case sha512_implCompressMB_id: + case StubId::stubgen_sha512_implCompressMB_id: multi_block = true; break; default: @@ -3243,7 +3243,7 @@ class StubGenerator: public StubCodeGenerator { address generate_data_cache_writeback() { const Register cacheline = R3_ARG1; - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3257,7 +3257,7 @@ class StubGenerator: public StubCodeGenerator { const Register is_presync = R3_ARG1; Register temp = R4; Label SKIP; - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_sync_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_sync_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3278,40 +3278,40 @@ class StubGenerator: public StubCodeGenerator { UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit); // non-aligned disjoint versions - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubGenStubId::jbyte_disjoint_arraycopy_id); - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(StubGenStubId::jshort_disjoint_arraycopy_id); - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(StubGenStubId::jint_disjoint_arraycopy_id); - StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(StubGenStubId::jlong_disjoint_arraycopy_id); - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(StubGenStubId::oop_disjoint_arraycopy_id); - StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(StubGenStubId::oop_disjoint_arraycopy_uninit_id); + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id); + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(StubId::stubgen_jshort_disjoint_arraycopy_id); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(StubId::stubgen_jint_disjoint_arraycopy_id); + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(StubId::stubgen_jlong_disjoint_arraycopy_id); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_id); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_uninit_id); // aligned disjoint versions - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubGenStubId::arrayof_jbyte_disjoint_arraycopy_id); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(StubGenStubId::arrayof_jshort_disjoint_arraycopy_id); - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(StubGenStubId::arrayof_jint_disjoint_arraycopy_id); - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(StubGenStubId::arrayof_jlong_disjoint_arraycopy_id); - StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(StubGenStubId::arrayof_oop_disjoint_arraycopy_id); - StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(StubGenStubId::oop_disjoint_arraycopy_uninit_id); + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id); + StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id); + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_uninit_id); // non-aligned conjoint versions - StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(StubGenStubId::jbyte_arraycopy_id); - StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(StubGenStubId::jshort_arraycopy_id); - StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(StubGenStubId::jint_arraycopy_id); - StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(StubGenStubId::jlong_arraycopy_id); - StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(StubGenStubId::oop_arraycopy_id); - StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubGenStubId::oop_arraycopy_uninit_id); + StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(StubId::stubgen_jbyte_arraycopy_id); + StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(StubId::stubgen_jshort_arraycopy_id); + StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(StubId::stubgen_jint_arraycopy_id); + StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(StubId::stubgen_jlong_arraycopy_id); + StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(StubId::stubgen_oop_arraycopy_id); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubId::stubgen_oop_arraycopy_uninit_id); // aligned conjoint versions - StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(StubGenStubId::arrayof_jbyte_arraycopy_id); - StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(StubGenStubId::arrayof_jshort_arraycopy_id); - StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(StubGenStubId::arrayof_jint_arraycopy_id); - StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(StubGenStubId::arrayof_jlong_arraycopy_id); - StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_id); - StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_id); + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(StubId::stubgen_arrayof_jshort_arraycopy_id); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(StubId::stubgen_arrayof_jint_arraycopy_id); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(StubId::stubgen_arrayof_jlong_arraycopy_id); + StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(StubId::stubgen_arrayof_oop_arraycopy_id); + StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubId::stubgen_arrayof_oop_arraycopy_id); // special/generic versions - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_id); - StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_uninit_id); + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(STUB_ENTRY(jbyte_arraycopy()), STUB_ENTRY(jshort_arraycopy()), @@ -3328,12 +3328,12 @@ class StubGenerator: public StubCodeGenerator { // fill routines #ifdef COMPILER2 if (OptimizeFill) { - StubRoutines::_jbyte_fill = generate_fill(StubGenStubId::jbyte_fill_id); - StubRoutines::_jshort_fill = generate_fill(StubGenStubId::jshort_fill_id); - StubRoutines::_jint_fill = generate_fill(StubGenStubId::jint_fill_id); - StubRoutines::_arrayof_jbyte_fill = generate_fill(StubGenStubId::arrayof_jbyte_fill_id); - StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); - StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); + StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id); + StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id); + StubRoutines::_jint_fill = generate_fill(StubId::stubgen_jint_fill_id); + StubRoutines::_arrayof_jbyte_fill = generate_fill(StubId::stubgen_arrayof_jbyte_fill_id); + StubRoutines::_arrayof_jshort_fill = generate_fill(StubId::stubgen_arrayof_jshort_fill_id); + StubRoutines::_arrayof_jint_fill = generate_fill(StubId::stubgen_arrayof_jint_fill_id); } StubRoutines::_unsafe_setmemory = generate_unsafe_setmemory(StubRoutines::_jbyte_fill); #endif @@ -3352,7 +3352,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_multiplyToLen() { - StubGenStubId stub_id = StubGenStubId::multiplyToLen_id; + StubId stub_id = StubId::stubgen_multiplyToLen_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -3429,7 +3429,7 @@ class StubGenerator: public StubCodeGenerator { */ address generate_mulAdd() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::mulAdd_id; + StubId stub_id = StubId::stubgen_mulAdd_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -3460,7 +3460,7 @@ class StubGenerator: public StubCodeGenerator { */ address generate_squareToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::squareToLen_id; + StubId stub_id = StubId::stubgen_squareToLen_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -3694,13 +3694,13 @@ class StubGenerator: public StubCodeGenerator { * R3_RET - int crc result */ // Compute CRC32 function. - address generate_CRC32_updateBytes(StubGenStubId stub_id) { + address generate_CRC32_updateBytes(StubId stub_id) { bool is_crc32c; switch (stub_id) { - case updateBytesCRC32_id: + case StubId::stubgen_updateBytesCRC32_id: is_crc32c = false; break; - case updateBytesCRC32C_id: + case StubId::stubgen_updateBytesCRC32C_id: is_crc32c = true; break; default: @@ -3734,7 +3734,7 @@ class StubGenerator: public StubCodeGenerator { address generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); address stub_address = __ pc(); @@ -3832,7 +3832,7 @@ class StubGenerator: public StubCodeGenerator { // Base64 decodeBlock intrinsic address generate_base64_decodeBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_decodeBlock_id; + StubId stub_id = StubId::stubgen_base64_decodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -4421,7 +4421,7 @@ class StubGenerator: public StubCodeGenerator { address generate_base64_encodeBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_encodeBlock_id; + StubId stub_id = StubId::stubgen_base64_encodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ function_entry(); @@ -4712,7 +4712,7 @@ class StubGenerator: public StubCodeGenerator { #endif // VM_LITTLE_ENDIAN void generate_lookup_secondary_supers_table_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_id; StubCodeMark mark(this, stub_id); const Register @@ -4735,7 +4735,7 @@ void generate_lookup_secondary_supers_table_stub() { // Slow path implementation for UseSecondarySupersTable. address generate_lookup_secondary_supers_table_slow_path_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_slow_path_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_slow_path_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4753,7 +4753,7 @@ void generate_lookup_secondary_supers_table_stub() { return start; } - address generate_cont_thaw(StubGenStubId stub_id) { + address generate_cont_thaw(StubId stub_id) { if (!Continuations::enabled()) return nullptr; Continuation::thaw_kind kind; @@ -4761,17 +4761,17 @@ void generate_lookup_secondary_supers_table_stub() { bool return_barrier_exception; switch (stub_id) { - case cont_thaw_id: + case StubId::stubgen_cont_thaw_id: kind = Continuation::thaw_top; return_barrier = false; return_barrier_exception = false; break; - case cont_returnBarrier_id: + case StubId::stubgen_cont_returnBarrier_id: kind = Continuation::thaw_return_barrier; return_barrier = true; return_barrier_exception = false; break; - case cont_returnBarrierExc_id: + case StubId::stubgen_cont_returnBarrierExc_id: kind = Continuation::thaw_return_barrier_exception; return_barrier = true; return_barrier_exception = true; @@ -4868,22 +4868,22 @@ void generate_lookup_secondary_supers_table_stub() { } address generate_cont_thaw() { - return generate_cont_thaw(StubGenStubId::cont_thaw_id); + return generate_cont_thaw(StubId::stubgen_cont_thaw_id); } // TODO: will probably need multiple return barriers depending on return type address generate_cont_returnBarrier() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrier_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrier_id); } address generate_cont_returnBarrier_exception() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrierExc_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrierExc_id); } address generate_cont_preempt_stub() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_preempt_id; + StubId stub_id = StubId::stubgen_cont_preempt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4919,7 +4919,7 @@ void generate_lookup_secondary_supers_table_stub() { // exception handler for upcall stubs address generate_upcall_stub_exception_handler() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_exception_handler_id; + StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4938,7 +4938,7 @@ void generate_lookup_secondary_supers_table_stub() { // R19_method = result Method* address generate_upcall_stub_load_target() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_load_target_id; + StubId stub_id = StubId::stubgen_upcall_stub_load_target_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4983,13 +4983,13 @@ void generate_lookup_secondary_supers_table_stub() { // CRC32 Intrinsics. if (UseCRC32Intrinsics) { StubRoutines::_crc_table_adr = StubRoutines::ppc::generate_crc_constants(REVERSE_CRC32_POLY); - StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes(StubGenStubId::updateBytesCRC32_id); + StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes(StubId::stubgen_updateBytesCRC32_id); } // CRC32C Intrinsics. if (UseCRC32CIntrinsics) { StubRoutines::_crc32c_table_addr = StubRoutines::ppc::generate_crc_constants(REVERSE_CRC32C_POLY); - StubRoutines::_updateBytesCRC32C = generate_CRC32_updateBytes(StubGenStubId::updateBytesCRC32C_id); + StubRoutines::_updateBytesCRC32C = generate_CRC32_updateBytes(StubId::stubgen_updateBytesCRC32C_id); } if (VM_Version::supports_float16()) { @@ -5071,12 +5071,12 @@ void generate_lookup_secondary_supers_table_stub() { } if (UseSHA256Intrinsics) { - StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubGenStubId::sha256_implCompress_id); - StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubGenStubId::sha256_implCompressMB_id); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubId::stubgen_sha256_implCompressMB_id); } if (UseSHA512Intrinsics) { - StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubGenStubId::sha512_implCompress_id); - StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubGenStubId::sha512_implCompressMB_id); + StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubId::stubgen_sha512_implCompress_id); + StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubId::stubgen_sha512_implCompressMB_id); } #ifdef VM_LITTLE_ENDIAN @@ -5090,31 +5090,31 @@ void generate_lookup_secondary_supers_table_stub() { } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } }; -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp index ea299181ca7..0c16e632e5a 100644 --- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp @@ -57,7 +57,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { __ mov_metadata(t0, m); ce->store_parameter(t0, 1); ce->store_parameter(_bci, 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::counter_overflow_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_counter_overflow_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ j(_continuation); @@ -66,7 +66,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ far_call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -79,13 +79,13 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { } else { __ mv(t0, _index->as_jint()); } - C1StubId stub_id; + StubId stub_id; if (_throw_index_out_of_bounds_exception) { - stub_id = C1StubId::throw_index_exception_id; + stub_id = StubId::c1_throw_index_exception_id; } else { assert(_array != LIR_Opr::nullOpr(), "sanity"); __ mv(t1, _array->as_pointer_register()); - stub_id = C1StubId::throw_range_check_failed_id; + stub_id = StubId::c1_throw_range_check_failed_id; } // t0 and t1 are used as args in generate_exception_throw, // so use x1/ra as the tmp register for rt_call. @@ -101,7 +101,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ far_call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -113,7 +113,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_throw_div0_exception_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); #ifdef ASSERT @@ -122,14 +122,14 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { } // Implementation of NewInstanceStub -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -158,7 +158,7 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_length->as_register() == x9, "length must in x9"); assert(_klass_reg->as_register() == x13, "klass_reg must in x13"); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_type_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_type_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == x10, "result must in x10"); @@ -178,7 +178,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_length->as_register() == x9, "length must in x9"); assert(_klass_reg->as_register() == x13, "klass_reg must in x13"); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_object_array_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_object_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == x10, "result must in x10"); @@ -190,11 +190,11 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_obj_reg->as_register(), 1); ce->store_parameter(_lock_reg->as_register(), 0); - C1StubId enter_id; + StubId enter_id; if (ce->compilation()->has_fpu_code()) { - enter_id = C1StubId::monitorenter_id; + enter_id = StubId::c1_monitorenter_id; } else { - enter_id = C1StubId::monitorenter_nofpu_id; + enter_id = StubId::c1_monitorenter_nofpu_id; } __ far_call(RuntimeAddress(Runtime1::entry_for(enter_id))); ce->add_call_info_here(_info); @@ -210,11 +210,11 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { } ce->store_parameter(_lock_reg->as_register(), 0); // note: non-blocking leaf routine => no call info needed - C1StubId exit_id; + StubId exit_id; if (ce->compilation()->has_fpu_code()) { - exit_id = C1StubId::monitorexit_id; + exit_id = StubId::c1_monitorexit_id; } else { - exit_id = C1StubId::monitorexit_nofpu_id; + exit_id = StubId::c1_monitorexit_nofpu_id; } __ la(ra, _continuation); __ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id))); @@ -239,7 +239,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_trap_request, 0); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::deoptimize_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_deoptimize_id))); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); } @@ -248,9 +248,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { address a = nullptr; if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is probably wrong to do it here. - a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); } ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp index 5aa213fba7a..819d6c05654 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -225,7 +225,7 @@ void LIR_Assembler::arraycopy_type_check(Register src, Register src_pos, Registe __ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, nullptr); PUSH(src, dst); - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); POP(src, dst); __ bnez(dst, cont); diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index c7587765da0..81b829bde9a 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -304,7 +304,7 @@ int LIR_Assembler::emit_exception_handler() { __ verify_not_null_oop(x10); // search an exception handler (x10: exception oop, x13: throwing pc) - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::handle_exception_from_callee_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_handle_exception_from_callee_id))); __ should_not_reach_here(); guarantee(code_offset() - offset <= exception_handler_size(), "overflow"); __ end_a_stub(); @@ -360,7 +360,7 @@ int LIR_Assembler::emit_unwind_handler() { // remove the activation and dispatch to the unwind handler __ block_comment("remove_frame and dispatch to the unwind handler"); __ remove_frame(initial_frame_size_in_bytes()); - __ far_jump(RuntimeAddress(Runtime1::entry_for(C1StubId::unwind_exception_id))); + __ far_jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_unwind_exception_id))); // Emit the slow path assembly if (stub != nullptr) { @@ -1096,7 +1096,7 @@ void LIR_Assembler::typecheck_helper_slowcheck(ciKlass *k, Register obj, Registe __ subi(sp, sp, 2 * wordSize); // 2: store k_RInfo and klass_RInfo __ sd(k_RInfo, Address(sp, 0)); // sub klass __ sd(klass_RInfo, Address(sp, wordSize)); // super klass - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); // load result to k_RInfo __ ld(k_RInfo, Address(sp, 0)); __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo @@ -1111,7 +1111,7 @@ void LIR_Assembler::typecheck_helper_slowcheck(ciKlass *k, Register obj, Registe __ subi(sp, sp, 2 * wordSize); // 2: store k_RInfo and klass_RInfo __ sd(klass_RInfo, Address(sp, wordSize)); // sub klass __ sd(k_RInfo, Address(sp, 0)); // super klass - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); // load result to k_RInfo __ ld(k_RInfo, Address(sp, 0)); __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo @@ -1399,7 +1399,7 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit // exception object is not added to oop map by LinearScan // (LinearScan assumes that no oops are in fixed registers) info->add_register_oop(exceptionOop); - C1StubId unwind_id; + StubId unwind_id; // get current pc information // pc is only needed if the method has an exception handler, the unwind code does not need it. @@ -1418,9 +1418,9 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit __ verify_not_null_oop(x10); // search an exception handler (x10: exception oop, x13: throwing pc) if (compilation()->has_fpu_code()) { - unwind_id = C1StubId::handle_exception_id; + unwind_id = StubId::c1_handle_exception_id; } else { - unwind_id = C1StubId::handle_exception_nofpu_id; + unwind_id = StubId::c1_handle_exception_nofpu_id; } __ far_call(RuntimeAddress(Runtime1::entry_for(unwind_id))); __ nop(); @@ -2053,16 +2053,16 @@ void LIR_Assembler::deoptimize_trap(CodeEmitInfo *info) { switch (patching_id(info)) { case PatchingStub::access_field_id: - target = Runtime1::entry_for(C1StubId::access_field_patching_id); + target = Runtime1::entry_for(StubId::c1_access_field_patching_id); break; case PatchingStub::load_klass_id: - target = Runtime1::entry_for(C1StubId::load_klass_patching_id); + target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); break; case PatchingStub::load_mirror_id: - target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); + target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); break; case PatchingStub::load_appendix_id: - target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); + target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); break; default: ShouldNotReachHere(); } @@ -2151,7 +2151,7 @@ void LIR_Assembler::lir_store_slowcheck(Register k_RInfo, Register klass_RInfo, __ subi(sp, sp, 2 * wordSize); // 2: store k_RInfo and klass_RInfo __ sd(klass_RInfo, Address(sp, wordSize)); // sub klass __ sd(k_RInfo, Address(sp, 0)); // super klass - __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); // load result to k_RInfo __ ld(k_RInfo, Address(sp, 0)); __ addi(sp, sp, 2 * wordSize); // 2: pop out k_RInfo and klass_RInfo diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp index b9ebd49779e..4c3a6653731 100644 --- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp @@ -1029,7 +1029,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); LIR_Opr reg = result_register_for(x->type()); - __ call_runtime(Runtime1::entry_for(C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for(StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); @@ -1061,7 +1061,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { CodeStub* stub = nullptr; if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); @@ -1069,7 +1069,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, obj.result(), info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, obj.result(), info_for_exception); } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; @@ -1104,7 +1104,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { // Intrinsic for Class::isInstance address LIRGenerator::isInstance_entry() { - return Runtime1::entry_for(C1StubId::is_instance_of_id); + return Runtime1::entry_for(StubId::c1_is_instance_of_id); } void LIRGenerator::do_If(If* x) { diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index 32b99f56909..3ce764b1861 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -281,7 +281,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == x10, "must be"); - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); @@ -321,7 +321,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1 if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == x10, "must be"); - far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index fa27369baf6..90ad98c34d0 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -97,10 +97,10 @@ int StubAssembler::call_RT(Register oop_result, Register metadata_result, addres if (frame_size() == no_frame_size) { leave(); far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - } else if (_stub_id == (int)C1StubId::forward_exception_id) { + } else if (_stub_id == (int)StubId::c1_forward_exception_id) { should_not_reach_here(); } else { - far_jump(RuntimeAddress(Runtime1::entry_for(C1StubId::forward_exception_id))); + far_jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_forward_exception_id))); } bind(L); } @@ -370,8 +370,8 @@ void Runtime1::initialize_pd() { // return: offset in 64-bit words. uint Runtime1::runtime_blob_current_thread_offset(frame f) { CodeBlob* cb = f.cb(); - assert(cb == Runtime1::blob_for(C1StubId::monitorenter_id) || - cb == Runtime1::blob_for(C1StubId::monitorenter_nofpu_id), "must be"); + assert(cb == Runtime1::blob_for(StubId::c1_monitorenter_id) || + cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id), "must be"); assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame"); int offset = cpu_reg_save_offsets[xthread->encoding()]; return offset / 2; // SP offsets are in halfwords @@ -399,7 +399,7 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe return oop_maps; } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler *sasm) { __ block_comment("generate_handle_exception"); // incoming parameters @@ -411,7 +411,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) OopMap* oop_map = nullptr; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: // We're handling an exception in the context of a compiled frame. // The registers have been saved in the standard places. Perform // an exception lookup in the caller and dispatch to the handler @@ -430,12 +430,12 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ sd(zr, Address(xthread, JavaThread::vm_result_oop_offset())); __ sd(zr, Address(xthread, JavaThread::vm_result_metadata_offset())); break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { // At this point all registers except exception oop (x10) and // exception pc (ra) are dead. const int frame_size = 2 /* fp, return address */; @@ -492,13 +492,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ sd(x10, Address(fp, frame::return_addr_offset * BytesPerWord)); switch (id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); + restore_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: break; default: ShouldNotReachHere(); } @@ -644,7 +644,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { return oop_maps; } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { // for better readability const bool dont_gc_arguments = false; @@ -655,7 +655,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { OopMapSet* oop_maps = nullptr; switch (id) { { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); __ leave(); @@ -663,32 +663,32 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { Register klass = x13; // Incoming Register obj = x10; // Result - if (id == C1StubId::new_instance_id) { + if (id == StubId::c1_new_instance_id) { __ set_info("new_instance", dont_gc_arguments); - } else if (id == C1StubId::fast_new_instance_id) { + } else if (id == StubId::c1_fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { - assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId"); + assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId"); __ set_info("fast new_instance init check", dont_gc_arguments); } @@ -709,7 +709,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: { Register bci = x10; Register method = x11; @@ -733,14 +733,14 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: { Register length = x9; // Incoming Register klass = x13; // Incoming Register obj = x10; // Result - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); } else { __ set_info("new_object_array", dont_gc_arguments); @@ -753,7 +753,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { Register tmp = obj; __ lwu(tmp, Address(klass, Klass::layout_helper_offset())); __ sraiw(tmp, tmp, Klass::_lh_array_tag_shift); - int tag = ((id == C1StubId::new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value); + int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value); __ mv(t0, tag); __ beq(t0, tmp, ok); __ stop("assert(is an array klass)"); @@ -766,7 +766,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { OopMap* map = save_live_registers(sasm); assert_cond(map != nullptr); int call_offset = 0; - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); } else { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); @@ -785,7 +785,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { StubFrame f(sasm, "new_multi_array", dont_gc_arguments); // x10: klass @@ -808,7 +808,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -842,14 +842,14 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, @@ -857,7 +857,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // Typical calling sequence: // push klass_RInfo (object klass or other subclass) @@ -903,10 +903,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorenter_nofpu_id: + case StubId::c1_monitorenter_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_id: { StubFrame f(sasm, "monitorenter", dont_gc_arguments, requires_pop_epilogue_return); OopMap* map = save_live_registers(sasm, save_fpu_registers); @@ -925,7 +925,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::is_instance_of_id: + case StubId::c1_is_instance_of_id: { // Mirror: x10 // Object: x11 @@ -971,10 +971,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: + case StubId::c1_monitorexit_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_id: { StubFrame f(sasm, "monitorexit", dont_gc_arguments); OopMap* map = save_live_registers(sasm, save_fpu_registers); @@ -995,7 +995,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { StubFrame f(sasm, "deoptimize", dont_gc_arguments, does_not_return); OopMap* oop_map = save_live_registers(sasm); @@ -1014,14 +1014,14 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { StubFrame f(sasm, "range_check_failed", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { __ set_info("unwind_exception", dont_gc_arguments); // note: no stubframe since we are about to leave the current @@ -1030,7 +1030,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { StubFrame f(sasm, "access_field_patching", dont_gc_arguments, does_not_return); // we should set up register map @@ -1038,7 +1038,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { StubFrame f(sasm, "load_klass_patching", dont_gc_arguments, does_not_return); // we should set up register map @@ -1046,7 +1046,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments, does_not_return); // we should set up register map @@ -1054,7 +1054,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments, does_not_return); // we should set up register map @@ -1062,29 +1062,29 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { StubFrame f(sasm, "handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments, does_not_return); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments, does_not_return); // tos + 0: link @@ -1093,7 +1093,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments, does_not_return); @@ -1113,7 +1113,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::dtrace_object_alloc_id: + case StubId::c1_dtrace_object_alloc_id: { // c_rarg0: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); save_live_registers(sasm); diff --git a/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp b/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp index 424d56edf5a..28b3460232e 100644 --- a/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp @@ -128,7 +128,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return *pc_addr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { address* pc_addr = &(((address*) f.sp())[-1]); *pc_addr = pc; } diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp index e77375434c2..b677c980c78 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.cpp +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -414,8 +414,8 @@ JavaThread** frame::saved_thread_address(const frame& f) { JavaThread** thread_addr; #ifdef COMPILER1 - if (cb == Runtime1::blob_for(C1StubId::monitorenter_id) || - cb == Runtime1::blob_for(C1StubId::monitorenter_nofpu_id)) { + if (cb == Runtime1::blob_for(StubId::c1_monitorenter_id) || + cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id)) { thread_addr = (JavaThread**)(f.sp() + Runtime1::runtime_blob_current_thread_offset(f)); } else #endif diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 3834a0d3d3d..e58b0cfcf76 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -60,13 +60,13 @@ class NativeFarCall: public NativeInstruction { address next_instruction_address() const { return addr_at(return_address_offset); } address return_address() const { return addr_at(return_address_offset); } address destination() const; - address reloc_destination(address orig_address); + address reloc_destination(); void set_destination(address dest); void verify(); void print(); - bool set_destination_mt_safe(address dest, bool assert_lock = true); + bool set_destination_mt_safe(address dest); bool reloc_set_destination(address dest); private: @@ -88,7 +88,7 @@ address NativeFarCall::destination() const { address destination = MacroAssembler::target_addr_for_insn(addr); CodeBlob* cb = CodeCache::find_blob(addr); - assert(cb && cb->is_nmethod(), "sanity"); + assert(cb != nullptr && cb->is_nmethod(), "nmethod expected"); nmethod *nm = (nmethod *)cb; assert(nm != nullptr, "Sanity"); assert(nm->stub_contains(destination), "Sanity"); @@ -96,20 +96,22 @@ address NativeFarCall::destination() const { return stub_address_destination_at(destination); } -address NativeFarCall::reloc_destination(address orig_address) { +address NativeFarCall::reloc_destination() { address call_addr = instruction_address(); + assert(NativeFarCall::is_at(call_addr), "unexpected code at call site"); CodeBlob *code = CodeCache::find_blob(call_addr); assert(code != nullptr, "Could not find the containing code blob"); address stub_addr = nullptr; - if (code != nullptr && code->is_nmethod()) { - stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + if (code->is_nmethod()) { + stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()); } if (stub_addr != nullptr) { stub_addr = MacroAssembler::target_addr_for_insn(call_addr); } + return stub_addr; } @@ -128,18 +130,13 @@ void NativeFarCall::print() { tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(addr_at(0))); } -bool NativeFarCall::set_destination_mt_safe(address dest, bool assert_lock) { +bool NativeFarCall::set_destination_mt_safe(address dest) { assert(NativeFarCall::is_at(addr_at(0)), "unexpected code at call site"); - assert(!assert_lock || - (CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || + assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || CompiledICLocker::is_safe(addr_at(0)), "concurrent code patching"); - address call_addr = addr_at(0); - assert(NativeFarCall::is_at(call_addr), "unexpected code at call site"); - address stub_addr = stub_address(); - if (stub_addr != nullptr) { set_stub_address_destination_at(stub_addr, dest); return true; @@ -156,10 +153,9 @@ bool NativeFarCall::reloc_set_destination(address dest) { assert(code != nullptr, "Could not find the containing code blob"); address stub_addr = nullptr; - if (code != nullptr && code->is_nmethod()) { - stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + if (code->is_nmethod()) { + stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()); } - if (stub_addr != nullptr) { MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); } @@ -209,7 +205,7 @@ bool NativeFarCall::is_at(address addr) { (MacroAssembler::extract_rd(addr + instr_size) == x6) && (MacroAssembler::extract_rs1(addr + instr_size) == x6) && (MacroAssembler::extract_rs1(addr + 2 * instr_size) == x6) && - (MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) { + (MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) { return true; } return false; @@ -238,8 +234,8 @@ address NativeCall::destination() const { return NativeFarCall::at(addr_at(0))->destination(); } -address NativeCall::reloc_destination(address orig_address) { - return NativeFarCall::at(addr_at(0))->reloc_destination(orig_address); +address NativeCall::reloc_destination() { + return NativeFarCall::at(addr_at(0))->reloc_destination(); } void NativeCall::set_destination(address dest) { @@ -254,8 +250,8 @@ void NativeCall::print() { NativeFarCall::at(addr_at(0))->print();; } -bool NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { - return NativeFarCall::at(addr_at(0))->set_destination_mt_safe(dest, assert_lock); +bool NativeCall::set_destination_mt_safe(address dest) { + return NativeFarCall::at(addr_at(0))->set_destination_mt_safe(dest); } bool NativeCall::reloc_set_destination(address dest) { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index 1598dfb8398..a6462e6bb8e 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -134,14 +134,14 @@ class NativeCall: private NativeInstruction { address next_instruction_address() const; address return_address() const; address destination() const; - address reloc_destination(address orig_address); + address reloc_destination(); void verify_alignment() {} // do nothing on riscv void verify(); void print(); void set_destination(address dest); - bool set_destination_mt_safe(address dest, bool assert_lock = true); + bool set_destination_mt_safe(address dest); bool reloc_set_destination(address dest); static bool is_at(address addr); diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp index 7bee372b0ef..ccd8b891996 100644 --- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp @@ -72,13 +72,12 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { } address Relocation::pd_call_destination(address orig_addr) { - assert(is_call(), "should be an address instruction here"); + assert(is_call(), "should be a call here"); if (NativeCall::is_at(addr())) { - return nativeCall_at(addr())->reloc_destination(orig_addr); + return nativeCall_at(addr())->reloc_destination(); } - // Non call reloc + if (orig_addr != nullptr) { - // the extracted address from the instructions in address orig_addr address new_addr = MacroAssembler::pd_call_destination(orig_addr); // If call is branch to self, don't try to relocate it, just leave it // as branch to self. This happens during code generation if the code @@ -87,20 +86,19 @@ address Relocation::pd_call_destination(address orig_addr) { new_addr = (new_addr == orig_addr) ? addr() : new_addr; return new_addr; } + return MacroAssembler::pd_call_destination(addr()); } void Relocation::pd_set_call_destination(address x) { - assert(is_call(), "should be an address instruction here"); + assert(is_call(), "should be a call here"); if (NativeCall::is_at(addr())) { - NativeCall* nc = nativeCall_at(addr()); - if (nc->reloc_set_destination(x)) { - return; - } + NativeCall* call = nativeCall_at(addr()); + call->reloc_set_destination(x); + } else { + MacroAssembler::pd_patch_instruction_size(addr(), x); + assert(pd_call_destination(addr()) == x, "fail in reloc"); } - MacroAssembler::pd_patch_instruction_size(addr(), x); - address pd_call = pd_call_destination(addr()); - assert(pd_call == x, "fail in reloc"); } address* Relocation::pd_address_in_code() { diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 716ffae27b5..cc59af8fae1 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1985,17 +1985,31 @@ int Matcher::max_vector_size(const BasicType bt) { } int Matcher::min_vector_size(const BasicType bt) { - int max_size = max_vector_size(bt); - // Limit the min vector size to 8 bytes. - int size = 8 / type2aelembytes(bt); - if (bt == T_BYTE) { - // To support vector api shuffle/rearrange. - size = 4; - } else if (bt == T_BOOLEAN) { - // To support vector api load/store mask. - size = 2; + int size; + switch(bt) { + case T_BOOLEAN: + // Load/store a vector mask with only 2 elements for vector types + // such as "2I/2F/2L/2D". + size = 2; + break; + case T_BYTE: + // Generate a "4B" vector, to support vector cast between "8B/16B" + // and "4S/4I/4L/4F/4D". + size = 4; + break; + case T_SHORT: + // Generate a "2S" vector, to support vector cast between "4S/8S" + // and "2I/2L/2F/2D". + size = 2; + break; + default: + // Limit the min vector length to 64-bit. + size = 8 / type2aelembytes(bt); + // The number of elements in a vector should be at least 2. + size = MAX2(size, 2); } - if (size < 2) size = 2; + + int max_size = max_vector_size(bt); return MIN2(size, max_size); } @@ -8426,6 +8440,17 @@ instruct castVV(vReg dst) ins_pipe(pipe_class_empty); %} +instruct castVVMask(vRegMask dst) +%{ + match(Set dst (CastVV dst)); + + size(0); + format %{ "# castVV of $dst" %} + ins_encode(/* empty encoding */); + ins_cost(0); + ins_pipe(pipe_class_empty); +%} + // ============================================================================ // Convert Instructions diff --git a/src/hotspot/cpu/riscv/runtime_riscv.cpp b/src/hotspot/cpu/riscv/runtime_riscv.cpp index 7c8ca853bc4..e1add8dbb82 100644 --- a/src/hotspot/cpu/riscv/runtime_riscv.cpp +++ b/src/hotspot/cpu/riscv/runtime_riscv.cpp @@ -61,7 +61,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; @@ -283,7 +283,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 216323c55fc..c4e5a871a88 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -2100,7 +2100,7 @@ void SharedRuntime::generate_deopt_blob() { pad += 512; // Increase the buffer size when compiling for JVMCI } #endif - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); CodeBuffer buffer(name, 2048 + pad, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words = -1; @@ -2483,7 +2483,7 @@ VMReg SharedRuntime::thread_register() { // Generate a special Compile2Runtime blob that saves all registers, // and setup oopmap. // -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(is_polling_page_id(id), "expected a polling page stub id"); ResourceMark rm; @@ -2500,8 +2500,8 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal address start = __ pc(); address call_pc = nullptr; int frame_size_in_words = -1; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); - RegisterSaver reg_saver(id == SharedStubId::polling_page_vectors_safepoint_handler_id /* save_vectors */); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); + RegisterSaver reg_saver(id == StubId::shared_polling_page_vectors_safepoint_handler_id /* save_vectors */); // Save Integer and Float registers. map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); @@ -2608,7 +2608,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // but since this is generic code we don't know what they are and the caller // must do any gc of the args. // -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_resolve_id(id), "expected a resolve stub id"); @@ -2705,7 +2705,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // otherwise assume that stack unwinding will be initiated, so // caller saved registers were assumed volatile in the compiler. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); @@ -2816,7 +2816,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { int insts_size = 1024; int locs_size = 64; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_write_checkpoint_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_write_checkpoint_id); CodeBuffer code(name, insts_size, locs_size); OopMapSet* oop_maps = new OopMapSet(); MacroAssembler* masm = new MacroAssembler(&code); @@ -2855,7 +2855,7 @@ RuntimeStub* SharedRuntime::generate_jfr_return_lease() { int insts_size = 1024; int locs_size = 64; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_return_lease_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_return_lease_id); CodeBuffer code(name, insts_size, locs_size); OopMapSet* oop_maps = new OopMapSet(); MacroAssembler* masm = new MacroAssembler(&code); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index f7d13578caf..a44fe39917c 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -207,7 +207,7 @@ class StubGenerator: public StubCodeGenerator { (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, "adjust this code"); - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -476,7 +476,7 @@ class StubGenerator: public StubCodeGenerator { // x10: exception oop address generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -529,7 +529,7 @@ class StubGenerator: public StubCodeGenerator { // so it just needs to be generated code with no x86 prolog address generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -616,7 +616,7 @@ class StubGenerator: public StubCodeGenerator { // [tos + 5]: saved t0 address generate_verify_oop() { - StubGenStubId stub_id = StubGenStubId::verify_oop_id; + StubId stub_id = StubId::stubgen_verify_oop_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -678,7 +678,7 @@ class StubGenerator: public StubCodeGenerator { const Register base = x28, cnt = x29, tmp1 = x30, tmp2 = x31; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::zero_blocks_id; + StubId stub_id = StubId::stubgen_zero_blocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -731,16 +731,16 @@ class StubGenerator: public StubCodeGenerator { // // s and d are adjusted to point to the remaining words to copy // - void generate_copy_longs(StubGenStubId stub_id, Label &start, + void generate_copy_longs(StubId stub_id, Label &start, Register s, Register d, Register count) { BasicType type; copy_direction direction; switch (stub_id) { - case copy_byte_f_id: + case StubId::stubgen_copy_byte_f_id: direction = copy_forwards; type = T_BYTE; break; - case copy_byte_b_id: + case StubId::stubgen_copy_byte_b_id: direction = copy_backwards; type = T_BYTE; break; @@ -1114,78 +1114,78 @@ class StubGenerator: public StubCodeGenerator { // can be used by the corresponding conjoint copy // method // - address generate_disjoint_copy(StubGenStubId stub_id, address* entry) { + address generate_disjoint_copy(StubId stub_id, address* entry) { size_t size; bool aligned; bool is_oop; bool dest_uninitialized; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: size = sizeof(jbyte); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jbyte_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id: size = sizeof(jbyte); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: size = sizeof(jshort); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jshort_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id: size = sizeof(jshort); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: size = sizeof(jint); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jint_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jint_disjoint_arraycopy_id: size = sizeof(jint); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: // since this is always aligned we can (should!) use the same // stub as for case arrayof_jlong_disjoint_arraycopy ShouldNotReachHere(); break; - case arrayof_jlong_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id: size = sizeof(jlong); aligned = true; is_oop = false; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case arrayof_oop_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = true; break; - case arrayof_oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; @@ -1271,7 +1271,7 @@ class StubGenerator: public StubCodeGenerator { // entry is set to the no-overlap entry point so it can be used by // some other conjoint copy method // - address generate_conjoint_copy(StubGenStubId stub_id, address nooverlap_target, address *entry) { + address generate_conjoint_copy(StubId stub_id, address nooverlap_target, address *entry) { const Register s = c_rarg0, d = c_rarg1, count = c_rarg2; RegSet saved_regs = RegSet::of(s, d, count); int size; @@ -1279,72 +1279,72 @@ class StubGenerator: public StubCodeGenerator { bool is_oop; bool dest_uninitialized; switch (stub_id) { - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: size = sizeof(jbyte); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jbyte_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_arraycopy_id: size = sizeof(jbyte); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: size = sizeof(jshort); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jshort_arraycopy_id: + case StubId::stubgen_arrayof_jshort_arraycopy_id: size = sizeof(jshort); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: size = sizeof(jint); aligned = false; is_oop = false; dest_uninitialized = false; break; - case arrayof_jint_arraycopy_id: + case StubId::stubgen_arrayof_jint_arraycopy_id: size = sizeof(jint); aligned = true; is_oop = false; dest_uninitialized = false; break; - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: // since this is always aligned we can (should!) use the same // stub as for case arrayof_jlong_disjoint_arraycopy ShouldNotReachHere(); break; - case arrayof_jlong_arraycopy_id: + case StubId::stubgen_arrayof_jlong_arraycopy_id: size = sizeof(jlong); aligned = true; is_oop = false; dest_uninitialized = false; break; - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case arrayof_oop_arraycopy_id: + case StubId::stubgen_arrayof_oop_arraycopy_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = false; break; - case oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; dest_uninitialized = true; break; - case arrayof_oop_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_arraycopy_uninit_id: size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); aligned = !UseCompressedOops; is_oop = true; @@ -1444,13 +1444,13 @@ class StubGenerator: public StubCodeGenerator { // x10 == 0 - success // x10 == -1^K - failure, where K is partial transfer count // - address generate_checkcast_copy(StubGenStubId stub_id, address* entry) { + address generate_checkcast_copy(StubId stub_id, address* entry) { bool dest_uninitialized; switch (stub_id) { - case checkcast_arraycopy_id: + case StubId::stubgen_checkcast_arraycopy_id: dest_uninitialized = false; break; - case checkcast_arraycopy_uninit_id: + case StubId::stubgen_checkcast_arraycopy_uninit_id: dest_uninitialized = true; break; default: @@ -1653,7 +1653,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_unsafe_setmemory() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_setmemory_id; + StubId stub_id = StubId::stubgen_unsafe_setmemory_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1776,7 +1776,7 @@ class StubGenerator: public StubCodeGenerator { const Register s = c_rarg0, d = c_rarg1, count = c_rarg2; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_arraycopy_id; + StubId stub_id = StubId::stubgen_unsafe_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); // required for proper stackwalking of RuntimeStub frame @@ -1843,7 +1843,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::generic_arraycopy_id; + StubId stub_id = StubId::stubgen_generic_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2100,32 +2100,32 @@ class StubGenerator: public StubCodeGenerator { // value: c_rarg1 // count: c_rarg2 treated as signed // - address generate_fill(StubGenStubId stub_id) { + address generate_fill(StubId stub_id) { BasicType t; bool aligned; switch (stub_id) { - case jbyte_fill_id: + case StubId::stubgen_jbyte_fill_id: t = T_BYTE; aligned = false; break; - case jshort_fill_id: + case StubId::stubgen_jshort_fill_id: t = T_SHORT; aligned = false; break; - case jint_fill_id: + case StubId::stubgen_jint_fill_id: t = T_INT; aligned = false; break; - case arrayof_jbyte_fill_id: + case StubId::stubgen_arrayof_jbyte_fill_id: t = T_BYTE; aligned = true; break; - case arrayof_jshort_fill_id: + case StubId::stubgen_arrayof_jshort_fill_id: t = T_SHORT; aligned = true; break; - case arrayof_jint_fill_id: + case StubId::stubgen_arrayof_jint_fill_id: t = T_INT; aligned = true; break; @@ -2301,8 +2301,8 @@ class StubGenerator: public StubCodeGenerator { address entry_jlong_arraycopy = nullptr; address entry_checkcast_arraycopy = nullptr; - generate_copy_longs(StubGenStubId::copy_byte_f_id, copy_f, c_rarg0, c_rarg1, t1); - generate_copy_longs(StubGenStubId::copy_byte_b_id, copy_b, c_rarg0, c_rarg1, t1); + generate_copy_longs(StubId::stubgen_copy_byte_f_id, copy_f, c_rarg0, c_rarg1, t1); + generate_copy_longs(StubId::stubgen_copy_byte_b_id, copy_b, c_rarg0, c_rarg1, t1); address ucm_common_error_exit = generate_unsafecopy_common_error_exit(); UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit); @@ -2311,52 +2311,52 @@ class StubGenerator: public StubCodeGenerator { //*** jbyte // Always need aligned and unaligned versions - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jbyte_disjoint_arraycopy_id, &entry); - StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubGenStubId::jbyte_arraycopy_id, entry, &entry_jbyte_arraycopy); - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jbyte_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jbyte_arraycopy_id, entry, nullptr); + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id, &entry); + StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_jbyte_arraycopy_id, entry, &entry_jbyte_arraycopy); + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id, entry, nullptr); //*** jshort // Always need aligned and unaligned versions - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jshort_disjoint_arraycopy_id, &entry); - StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubGenStubId::jshort_arraycopy_id, entry, &entry_jshort_arraycopy); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jshort_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jshort_arraycopy_id, entry, nullptr); + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jshort_disjoint_arraycopy_id, &entry); + StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_jshort_arraycopy_id, entry, &entry_jshort_arraycopy); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jshort_arraycopy_id, entry, nullptr); //*** jint // Aligned versions - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jint_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jint_arraycopy_id, entry, &entry_jint_arraycopy); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jint_arraycopy_id, entry, &entry_jint_arraycopy); // In 64 bit we need both aligned and unaligned versions of jint arraycopy. // entry_jint_arraycopy always points to the unaligned version - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::jint_disjoint_arraycopy_id, &entry); - StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubGenStubId::jint_arraycopy_id, entry, &entry_jint_arraycopy); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jint_disjoint_arraycopy_id, &entry); + StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_jint_arraycopy_id, entry, &entry_jint_arraycopy); //*** jlong // It is always aligned - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubGenStubId::arrayof_jlong_disjoint_arraycopy_id, &entry); - StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubGenStubId::arrayof_jlong_arraycopy_id, entry, &entry_jlong_arraycopy); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id, &entry); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jlong_arraycopy_id, entry, &entry_jlong_arraycopy); StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy; StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy; //*** oops StubRoutines::_arrayof_oop_disjoint_arraycopy - = generate_disjoint_copy(StubGenStubId::arrayof_oop_disjoint_arraycopy_id, &entry); + = generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id, &entry); StubRoutines::_arrayof_oop_arraycopy - = generate_conjoint_copy(StubGenStubId::arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy); + = generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy); // Aligned versions without pre-barriers StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit - = generate_disjoint_copy(StubGenStubId::arrayof_oop_disjoint_arraycopy_uninit_id, &entry); + = generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id, &entry); StubRoutines::_arrayof_oop_arraycopy_uninit - = generate_conjoint_copy(StubGenStubId::arrayof_oop_arraycopy_uninit_id, entry, nullptr); + = generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, entry, nullptr); StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy; StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit; StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit; - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_id, &entry_checkcast_arraycopy); - StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_uninit_id, nullptr); + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id, nullptr); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(entry_jbyte_arraycopy, @@ -2371,12 +2371,12 @@ class StubGenerator: public StubCodeGenerator { entry_jlong_arraycopy, entry_checkcast_arraycopy); - StubRoutines::_jbyte_fill = generate_fill(StubGenStubId::jbyte_fill_id); - StubRoutines::_jshort_fill = generate_fill(StubGenStubId::jshort_fill_id); - StubRoutines::_jint_fill = generate_fill(StubGenStubId::jint_fill_id); - StubRoutines::_arrayof_jbyte_fill = generate_fill(StubGenStubId::arrayof_jbyte_fill_id); - StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); - StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); + StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id); + StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id); + StubRoutines::_jint_fill = generate_fill(StubId::stubgen_jint_fill_id); + StubRoutines::_arrayof_jbyte_fill = generate_fill(StubId::stubgen_arrayof_jbyte_fill_id); + StubRoutines::_arrayof_jshort_fill = generate_fill(StubId::stubgen_arrayof_jshort_fill_id); + StubRoutines::_arrayof_jint_fill = generate_fill(StubId::stubgen_arrayof_jint_fill_id); StubRoutines::_unsafe_setmemory = generate_unsafe_setmemory(); } @@ -2414,7 +2414,7 @@ class StubGenerator: public StubCodeGenerator { assert(UseAESIntrinsics, "need AES instructions (Zvkned extension) support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); Label L_aes128, L_aes192; @@ -2493,7 +2493,7 @@ class StubGenerator: public StubCodeGenerator { assert(UseAESIntrinsics, "need AES instructions (Zvkned extension) support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); Label L_aes128, L_aes192; @@ -2595,13 +2595,13 @@ class StubGenerator: public StubCodeGenerator { // x28 = tmp1 // x29 = tmp2 // x30 = tmp3 - address generate_compare_long_string_different_encoding(StubGenStubId stub_id) { + address generate_compare_long_string_different_encoding(StubId stub_id) { bool isLU; switch (stub_id) { - case compare_long_string_LU_id: + case StubId::stubgen_compare_long_string_LU_id: isLU = true; break; - case compare_long_string_UL_id: + case StubId::stubgen_compare_long_string_UL_id: isLU = false; break; default: @@ -2697,7 +2697,7 @@ class StubGenerator: public StubCodeGenerator { address generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); Label deoptimize_label; @@ -2768,13 +2768,13 @@ class StubGenerator: public StubCodeGenerator { // x29 = tmp2 // x30 = tmp3 // x31 = tmp4 - address generate_compare_long_string_same_encoding(StubGenStubId stub_id) { + address generate_compare_long_string_same_encoding(StubId stub_id) { bool isLL; switch (stub_id) { - case compare_long_string_LL_id: + case StubId::stubgen_compare_long_string_LL_id: isLL = true; break; - case compare_long_string_UU_id: + case StubId::stubgen_compare_long_string_UU_id: isLL = false; break; default: @@ -2880,10 +2880,10 @@ class StubGenerator: public StubCodeGenerator { } void generate_compare_long_strings() { - StubRoutines::riscv::_compare_long_string_LL = generate_compare_long_string_same_encoding(StubGenStubId::compare_long_string_LL_id); - StubRoutines::riscv::_compare_long_string_UU = generate_compare_long_string_same_encoding(StubGenStubId::compare_long_string_UU_id); - StubRoutines::riscv::_compare_long_string_LU = generate_compare_long_string_different_encoding(StubGenStubId::compare_long_string_LU_id); - StubRoutines::riscv::_compare_long_string_UL = generate_compare_long_string_different_encoding(StubGenStubId::compare_long_string_UL_id); + StubRoutines::riscv::_compare_long_string_LL = generate_compare_long_string_same_encoding(StubId::stubgen_compare_long_string_LL_id); + StubRoutines::riscv::_compare_long_string_UU = generate_compare_long_string_same_encoding(StubId::stubgen_compare_long_string_UU_id); + StubRoutines::riscv::_compare_long_string_LU = generate_compare_long_string_different_encoding(StubId::stubgen_compare_long_string_LU_id); + StubRoutines::riscv::_compare_long_string_UL = generate_compare_long_string_different_encoding(StubId::stubgen_compare_long_string_UL_id); } // x10 result @@ -2891,20 +2891,20 @@ class StubGenerator: public StubCodeGenerator { // x12 src count // x13 pattern // x14 pattern count - address generate_string_indexof_linear(StubGenStubId stub_id) + address generate_string_indexof_linear(StubId stub_id) { bool needle_isL; bool haystack_isL; switch (stub_id) { - case string_indexof_linear_ll_id: + case StubId::stubgen_string_indexof_linear_ll_id: needle_isL = true; haystack_isL = true; break; - case string_indexof_linear_ul_id: + case StubId::stubgen_string_indexof_linear_ul_id: needle_isL = true; haystack_isL = false; break; - case string_indexof_linear_uu_id: + case StubId::stubgen_string_indexof_linear_uu_id: needle_isL = false; haystack_isL = false; break; @@ -3140,14 +3140,14 @@ class StubGenerator: public StubCodeGenerator { void generate_string_indexof_stubs() { - StubRoutines::riscv::_string_indexof_linear_ll = generate_string_indexof_linear(StubGenStubId::string_indexof_linear_ll_id); - StubRoutines::riscv::_string_indexof_linear_uu = generate_string_indexof_linear(StubGenStubId::string_indexof_linear_uu_id); - StubRoutines::riscv::_string_indexof_linear_ul = generate_string_indexof_linear(StubGenStubId::string_indexof_linear_ul_id); + StubRoutines::riscv::_string_indexof_linear_ll = generate_string_indexof_linear(StubId::stubgen_string_indexof_linear_ll_id); + StubRoutines::riscv::_string_indexof_linear_uu = generate_string_indexof_linear(StubId::stubgen_string_indexof_linear_uu_id); + StubRoutines::riscv::_string_indexof_linear_ul = generate_string_indexof_linear(StubId::stubgen_string_indexof_linear_ul_id); } #ifdef COMPILER2 void generate_lookup_secondary_supers_table_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_id; StubCodeMark mark(this, stub_id); const Register @@ -3173,7 +3173,7 @@ class StubGenerator: public StubCodeGenerator { // Slow path implementation for UseSecondarySupersTable. address generate_lookup_secondary_supers_table_slow_path_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_slow_path_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_slow_path_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3195,7 +3195,7 @@ class StubGenerator: public StubCodeGenerator { address generate_mulAdd() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::mulAdd_id; + StubId stub_id = StubId::stubgen_mulAdd_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -3229,7 +3229,7 @@ class StubGenerator: public StubCodeGenerator { address generate_multiplyToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::multiplyToLen_id; + StubId stub_id = StubId::stubgen_multiplyToLen_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -3260,7 +3260,7 @@ class StubGenerator: public StubCodeGenerator { address generate_squareToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::squareToLen_id; + StubId stub_id = StubId::stubgen_squareToLen_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -3301,7 +3301,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_bigIntegerLeftShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerLeftShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerLeftShiftWorker_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -3353,7 +3353,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_bigIntegerRightShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerRightShiftWorker_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); @@ -4180,7 +4180,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_thaw() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_thaw_id; + StubId stub_id = StubId::stubgen_cont_thaw_id; StubCodeMark mark(this, stub_id); address start = __ pc(); generate_cont_thaw(Continuation::thaw_top); @@ -4191,7 +4191,7 @@ class StubGenerator: public StubCodeGenerator { if (!Continuations::enabled()) return nullptr; // TODO: will probably need multiple return barriers depending on return type - StubGenStubId stub_id = StubGenStubId::cont_returnBarrier_id; + StubId stub_id = StubId::stubgen_cont_returnBarrier_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4203,7 +4203,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_returnBarrier_exception() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_returnBarrierExc_id; + StubId stub_id = StubId::stubgen_cont_returnBarrierExc_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4214,7 +4214,7 @@ class StubGenerator: public StubCodeGenerator { address generate_cont_preempt_stub() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_preempt_id; + StubId stub_id = StubId::stubgen_cont_preempt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4252,10 +4252,10 @@ class StubGenerator: public StubCodeGenerator { StubCodeGenerator* _cgen; public: Sha2Generator(MacroAssembler* masm, StubCodeGenerator* cgen) : MacroAssembler(masm->code()), _cgen(cgen) {} - address generate_sha256_implCompress(StubGenStubId stub_id) { + address generate_sha256_implCompress(StubId stub_id) { return generate_sha2_implCompress(Assembler::e32, stub_id); } - address generate_sha512_implCompress(StubGenStubId stub_id) { + address generate_sha512_implCompress(StubId stub_id) { return generate_sha2_implCompress(Assembler::e64, stub_id); } private: @@ -4389,7 +4389,7 @@ class StubGenerator: public StubCodeGenerator { // c_rarg2 - int offset // c_rarg3 - int limit // - address generate_sha2_implCompress(Assembler::SEW vset_sew, StubGenStubId stub_id) { + address generate_sha2_implCompress(Assembler::SEW vset_sew, StubId stub_id) { alignas(64) static const uint32_t round_consts_256[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -4441,19 +4441,19 @@ class StubGenerator: public StubCodeGenerator { bool multi_block; switch (stub_id) { - case sha256_implCompress_id: + case StubId::stubgen_sha256_implCompress_id: assert (vset_sew == Assembler::e32, "wrong macroassembler for stub"); multi_block = false; break; - case sha256_implCompressMB_id: + case StubId::stubgen_sha256_implCompressMB_id: assert (vset_sew == Assembler::e32, "wrong macroassembler for stub"); multi_block = true; break; - case sha512_implCompress_id: + case StubId::stubgen_sha512_implCompress_id: assert (vset_sew == Assembler::e64, "wrong macroassembler for stub"); multi_block = false; break; - case sha512_implCompressMB_id: + case StubId::stubgen_sha512_implCompressMB_id: assert (vset_sew == Assembler::e64, "wrong macroassembler for stub"); multi_block = true; break; @@ -4808,14 +4808,14 @@ class StubGenerator: public StubCodeGenerator { // x29 t4 buf5 // x30 t5 buf6 // x31 t6 buf7 - address generate_md5_implCompress(StubGenStubId stub_id) { + address generate_md5_implCompress(StubId stub_id) { __ align(CodeEntryAlignment); bool multi_block; switch (stub_id) { - case md5_implCompress_id: + case StubId::stubgen_md5_implCompress_id: multi_block = false; break; - case md5_implCompressMB_id: + case StubId::stubgen_md5_implCompressMB_id: multi_block = true; break; default: @@ -5075,7 +5075,7 @@ class StubGenerator: public StubCodeGenerator { Label L_Rounds; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::chacha20Block_id; + StubId stub_id = StubId::stubgen_chacha20Block_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5375,13 +5375,13 @@ class StubGenerator: public StubCodeGenerator { // - - - - - - below are only for implCompressMultiBlock0 - - - - - - // c_rarg0: int offset, when (multi_block == true) // - address generate_sha1_implCompress(StubGenStubId stub_id) { + address generate_sha1_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha1_implCompress_id: + case StubId::stubgen_sha1_implCompress_id: multi_block = false; break; - case sha1_implCompressMB_id: + case StubId::stubgen_sha1_implCompressMB_id: multi_block = true; break; default: @@ -5598,7 +5598,7 @@ class StubGenerator: public StubCodeGenerator { }; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_encodeBlock_id; + StubId stub_id = StubId::stubgen_base64_encodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -5855,7 +5855,7 @@ class StubGenerator: public StubCodeGenerator { }; __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_decodeBlock_id; + StubId stub_id = StubId::stubgen_base64_decodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6100,7 +6100,7 @@ class StubGenerator: public StubCodeGenerator { */ address generate_updateBytesAdler32() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesAdler32_id; + StubId stub_id = StubId::stubgen_updateBytesAdler32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -6278,7 +6278,7 @@ class StubGenerator: public StubCodeGenerator { // t1 = temporary register address generate_float16ToFloat() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::hf2f_id; + StubId stub_id = StubId::stubgen_hf2f_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); BLOCK_COMMENT("float16ToFloat:"); @@ -6329,7 +6329,7 @@ class StubGenerator: public StubCodeGenerator { // t1 = temporary register address generate_floatToFloat16() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::f2hf_id; + StubId stub_id = StubId::stubgen_f2hf_id; StubCodeMark mark(this, stub_id); address entry = __ pc(); BLOCK_COMMENT("floatToFloat16:"); @@ -6457,7 +6457,7 @@ static const int64_t right_3_bits = right_n_bits(3); address generate_poly1305_processBlocks() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::poly1305_processBlocks_id; + StubId stub_id = StubId::stubgen_poly1305_processBlocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -6595,7 +6595,7 @@ static const int64_t right_3_bits = right_n_bits(3); assert(UseCRC32Intrinsics, "what are we doing here?"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -6620,7 +6620,7 @@ static const int64_t right_3_bits = right_n_bits(3); // exception handler for upcall stubs address generate_upcall_stub_exception_handler() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_exception_handler_id; + StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -6638,7 +6638,7 @@ static const int64_t right_3_bits = right_n_bits(3); // xmethod = Method* result address generate_upcall_stub_load_target() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_load_target_id; + StubId stub_id = StubId::stubgen_upcall_stub_load_target_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -6747,14 +6747,14 @@ static const int64_t right_3_bits = right_n_bits(3); } if (UseMontgomeryMultiplyIntrinsic) { - StubGenStubId stub_id = StubGenStubId::montgomeryMultiply_id; + StubId stub_id = StubId::stubgen_montgomeryMultiply_id; StubCodeMark mark(this, stub_id); MontgomeryMultiplyGenerator g(_masm, /*squaring*/false); StubRoutines::_montgomeryMultiply = g.generate_multiply(); } if (UseMontgomerySquareIntrinsic) { - StubGenStubId stub_id = StubGenStubId::montgomerySquare_id; + StubId stub_id = StubId::stubgen_montgomerySquare_id; StubCodeMark mark(this, stub_id); MontgomeryMultiplyGenerator g(_masm, /*squaring*/true); StubRoutines::_montgomerySquare = g.generate_square(); @@ -6776,19 +6776,19 @@ static const int64_t right_3_bits = right_n_bits(3); if (UseSHA256Intrinsics) { Sha2Generator sha2(_masm, this); - StubRoutines::_sha256_implCompress = sha2.generate_sha256_implCompress(StubGenStubId::sha256_implCompress_id); - StubRoutines::_sha256_implCompressMB = sha2.generate_sha256_implCompress(StubGenStubId::sha256_implCompressMB_id); + StubRoutines::_sha256_implCompress = sha2.generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id); + StubRoutines::_sha256_implCompressMB = sha2.generate_sha256_implCompress(StubId::stubgen_sha256_implCompressMB_id); } if (UseSHA512Intrinsics) { Sha2Generator sha2(_masm, this); - StubRoutines::_sha512_implCompress = sha2.generate_sha512_implCompress(StubGenStubId::sha512_implCompress_id); - StubRoutines::_sha512_implCompressMB = sha2.generate_sha512_implCompress(StubGenStubId::sha512_implCompressMB_id); + StubRoutines::_sha512_implCompress = sha2.generate_sha512_implCompress(StubId::stubgen_sha512_implCompress_id); + StubRoutines::_sha512_implCompressMB = sha2.generate_sha512_implCompress(StubId::stubgen_sha512_implCompressMB_id); } if (UseMD5Intrinsics) { - StubRoutines::_md5_implCompress = generate_md5_implCompress(StubGenStubId::md5_implCompress_id); - StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubGenStubId::md5_implCompressMB_id); + StubRoutines::_md5_implCompress = generate_md5_implCompress(StubId::stubgen_md5_implCompress_id); + StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubId::stubgen_md5_implCompressMB_id); } if (UseChaCha20Intrinsics) { @@ -6796,8 +6796,8 @@ static const int64_t right_3_bits = right_n_bits(3); } if (UseSHA1Intrinsics) { - StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubGenStubId::sha1_implCompress_id); - StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubGenStubId::sha1_implCompressMB_id); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubId::stubgen_sha1_implCompress_id); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubId::stubgen_sha1_implCompressMB_id); } if (UseBASE64Intrinsics) { @@ -6817,30 +6817,30 @@ static const int64_t right_3_bits = right_n_bits(3); } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } }; // end class declaration -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp index 430928a66ed..68e7114b3b6 100644 --- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp +++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp @@ -47,7 +47,7 @@ void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - address a = Runtime1::entry_for (C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for (StubId::c1_predicate_failed_trap_id); ce->emit_call_c(a); CHECK_BAILOUT(); ce->add_call_info_here(_info); @@ -63,11 +63,11 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ load_const_optimized(Z_R1_scratch, _index->as_jint()); } - C1StubId stub_id; + StubId stub_id; if (_throw_index_out_of_bounds_exception) { - stub_id = C1StubId::throw_index_exception_id; + stub_id = StubId::c1_throw_index_exception_id; } else { - stub_id = C1StubId::throw_range_check_failed_id; + stub_id = StubId::c1_throw_range_check_failed_id; __ lgr_if_needed(Z_R0_scratch, _array->as_pointer_register()); } ce->emit_call_c(Runtime1::entry_for (stub_id)); @@ -83,7 +83,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address a = Runtime1::entry_for (C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for (StubId::c1_predicate_failed_trap_id); ce->emit_call_c(a); CHECK_BAILOUT(); ce->add_call_info_here(_info); @@ -101,7 +101,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { } ce->store_parameter(/*_method->as_register()*/ Z_R1_scratch, 1); ce->store_parameter(_bci, 0); - ce->emit_call_c(Runtime1::entry_for (C1StubId::counter_overflow_id)); + ce->emit_call_c(Runtime1::entry_for (StubId::c1_counter_overflow_id)); CHECK_BAILOUT(); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -113,7 +113,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - ce->emit_call_c(Runtime1::entry_for (C1StubId::throw_div0_exception_id)); + ce->emit_call_c(Runtime1::entry_for (StubId::c1_throw_div0_exception_id)); CHECK_BAILOUT(); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); @@ -123,9 +123,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { address a; if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is probably wrong to do it here. - a = Runtime1::entry_for (C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for (StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for (C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for (StubId::c1_throw_null_pointer_exception_id); } ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); @@ -150,14 +150,14 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) { DEBUG_ONLY(__ should_not_reach_here()); } -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -185,7 +185,7 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_klass_reg->as_register() == Z_R11, "call target expects klass in Z_R11"); __ lgr_if_needed(Z_R13, _length->as_register()); - address a = Runtime1::entry_for (C1StubId::new_type_array_id); + address a = Runtime1::entry_for (StubId::c1_new_type_array_id); ce->emit_call_c(a); CHECK_BAILOUT(); ce->add_call_info_here(_info); @@ -205,7 +205,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_klass_reg->as_register() == Z_R11, "call target expects klass in Z_R11"); __ lgr_if_needed(Z_R13, _length->as_register()); - address a = Runtime1::entry_for (C1StubId::new_object_array_id); + address a = Runtime1::entry_for (StubId::c1_new_object_array_id); ce->emit_call_c(a); CHECK_BAILOUT(); ce->add_call_info_here(_info); @@ -216,11 +216,11 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { void MonitorEnterStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - C1StubId enter_id; + StubId enter_id; if (ce->compilation()->has_fpu_code()) { - enter_id = C1StubId::monitorenter_id; + enter_id = StubId::c1_monitorenter_id; } else { - enter_id = C1StubId::monitorenter_nofpu_id; + enter_id = StubId::c1_monitorenter_nofpu_id; } __ lgr_if_needed(Z_R1_scratch, _obj_reg->as_register()); __ lgr_if_needed(Z_R13, _lock_reg->as_register()); // See LIRGenerator::syncTempOpr(). @@ -241,11 +241,11 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { __ lgr_if_needed(Z_R1_scratch, _lock_reg->as_register()); } // Note: non-blocking leaf routine => no call info needed. - C1StubId exit_id; + StubId exit_id; if (ce->compilation()->has_fpu_code()) { - exit_id = C1StubId::monitorexit_id; + exit_id = StubId::c1_monitorexit_id; } else { - exit_id = C1StubId::monitorexit_nofpu_id; + exit_id = StubId::c1_monitorexit_nofpu_id; } ce->emit_call_c(Runtime1::entry_for (exit_id)); CHECK_BAILOUT(); @@ -377,10 +377,10 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { address target = nullptr; relocInfo::relocType reloc_type = relocInfo::none; switch (_id) { - case access_field_id: target = Runtime1::entry_for (C1StubId::access_field_patching_id); break; - case load_klass_id: target = Runtime1::entry_for (C1StubId::load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; - case load_mirror_id: target = Runtime1::entry_for (C1StubId::load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; - case load_appendix_id: target = Runtime1::entry_for (C1StubId::load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; + case access_field_id: target = Runtime1::entry_for (StubId::c1_access_field_patching_id); break; + case load_klass_id: target = Runtime1::entry_for (StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; + case load_mirror_id: target = Runtime1::entry_for (StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; + case load_appendix_id: target = Runtime1::entry_for (StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } __ bind(call_patch); @@ -405,7 +405,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); __ load_const_optimized(Z_R1_scratch, _trap_request); // Pass trap request in Z_R1_scratch. - ce->emit_call_c(Runtime1::entry_for (C1StubId::deoptimize_id)); + ce->emit_call_c(Runtime1::entry_for (StubId::c1_deoptimize_id)); CHECK_BAILOUT(); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index b4779a19457..cef6ad8af73 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -185,7 +185,7 @@ int LIR_Assembler::emit_exception_handler() { int offset = code_offset(); - address a = Runtime1::entry_for (C1StubId::handle_exception_from_callee_id); + address a = Runtime1::entry_for (StubId::c1_handle_exception_from_callee_id); address call_addr = emit_call_c(a); CHECK_BAILOUT_(-1); __ should_not_reach_here(); @@ -225,7 +225,7 @@ int LIR_Assembler::emit_unwind_handler() { // Perform needed unlocking. MonitorExitStub* stub = nullptr; if (method()->is_synchronized()) { - // C1StubId::monitorexit_id expects lock address in Z_R1_scratch. + // StubId::c1_monitorexit_id expects lock address in Z_R1_scratch. LIR_Opr lock = FrameMap::as_opr(Z_R1_scratch); monitor_address(0, lock); stub = new MonitorExitStub(lock, true, 0); @@ -258,7 +258,7 @@ int LIR_Assembler::emit_unwind_handler() { // Z_EXC_PC: exception pc // Dispatch to the unwind logic. - __ load_const_optimized(Z_R5, Runtime1::entry_for (C1StubId::unwind_exception_id)); + __ load_const_optimized(Z_R5, Runtime1::entry_for (StubId::c1_unwind_exception_id)); __ z_br(Z_R5); // Emit the slow path assembly. @@ -1931,8 +1931,8 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit // Reuse the debug info from the safepoint poll for the throw op itself. __ get_PC(Z_EXC_PC); add_call_info(__ offset(), info); // for exception handler - address stub = Runtime1::entry_for (compilation()->has_fpu_code() ? C1StubId::handle_exception_id - : C1StubId::handle_exception_nofpu_id); + address stub = Runtime1::entry_for (compilation()->has_fpu_code() ? StubId::c1_handle_exception_id + : StubId::c1_handle_exception_nofpu_id); emit_call_c(stub); } @@ -2129,7 +2129,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { store_parameter(src_klass, 0); // sub store_parameter(dst_klass, 1); // super - emit_call_c(Runtime1::entry_for (C1StubId::slow_subtype_check_id)); + emit_call_c(Runtime1::entry_for (StubId::c1_slow_subtype_check_id)); CHECK_BAILOUT2(cont, slow); // Sets condition code 0 for match (2 otherwise). __ branch_optimized(Assembler::bcondEqual, cont); @@ -2549,7 +2549,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L failure_target, nullptr); if (need_slow_path) { // Call out-of-line instance of __ check_klass_subtype_slow_path(...): - address a = Runtime1::entry_for (C1StubId::slow_subtype_check_id); + address a = Runtime1::entry_for (StubId::c1_slow_subtype_check_id); store_parameter(klass_RInfo, 0); // sub store_parameter(k_RInfo, 1); // super emit_call_c(a); // Sets condition code 0 for match (2 otherwise). @@ -2624,7 +2624,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { // Perform the fast part of the checking logic. __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, nullptr); // Call out-of-line instance of __ check_klass_subtype_slow_path(...): - address a = Runtime1::entry_for (C1StubId::slow_subtype_check_id); + address a = Runtime1::entry_for (StubId::c1_slow_subtype_check_id); store_parameter(klass_RInfo, 0); // sub store_parameter(k_RInfo, 1); // super emit_call_c(a); // Sets condition code 0 for match (2 otherwise). diff --git a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp index 94a528a7467..5a0fd5f9561 100644 --- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp @@ -890,7 +890,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); LIR_Opr reg = result_register_for (x->type()); - __ call_runtime(Runtime1::entry_for (C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for (StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); @@ -921,14 +921,14 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { CodeStub* stub; if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); stub = new DeoptimizeStub(info_for_exception, Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, obj.result(), info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, obj.result(), info_for_exception); } LIR_Opr reg = rlock_result(x); LIR_Opr tmp1 = new_register(objectType); @@ -961,7 +961,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { // Intrinsic for Class::isInstance address LIRGenerator::isInstance_entry() { - return Runtime1::entry_for(C1StubId::is_instance_of_id); + return Runtime1::entry_for(StubId::c1_is_instance_of_id); } diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp index 0e873250dca..519884c8212 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp @@ -262,7 +262,7 @@ void C1_MacroAssembler::initialize_object( // Dtrace support is unimplemented. // if (CURRENT_ENV->dtrace_alloc_probes()) { // assert(obj == rax, "must be"); - // call(RuntimeAddress(Runtime1::entry_for (C1StubId::dtrace_object_alloc_id))); + // call(RuntimeAddress(Runtime1::entry_for (StubId::c1_dtrace_object_alloc_id))); // } verify_oop(obj, FILE_AND_LINE); @@ -323,7 +323,7 @@ void C1_MacroAssembler::allocate_array( // Dtrace support is unimplemented. // if (CURRENT_ENV->dtrace_alloc_probes()) { // assert(obj == rax, "must be"); - // call(RuntimeAddress(Runtime1::entry_for (C1StubId::dtrace_object_alloc_id))); + // call(RuntimeAddress(Runtime1::entry_for (StubId::c1_dtrace_object_alloc_id))); // } verify_oop(obj, FILE_AND_LINE); diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp index 47ed57d4008..01fe91928f4 100644 --- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp +++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp @@ -97,10 +97,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre restore_return_pc(); load_const_optimized(Z_R1, StubRoutines::forward_exception_entry()); z_br(Z_R1); - } else if (_stub_id == (int)C1StubId::forward_exception_id) { + } else if (_stub_id == (int)StubId::c1_forward_exception_id) { should_not_reach_here(); } else { - load_const_optimized(Z_R1, Runtime1::entry_for (C1StubId::forward_exception_id)); + load_const_optimized(Z_R1, Runtime1::entry_for (StubId::c1_forward_exception_id)); z_br(Z_R1); } @@ -309,7 +309,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { return oop_maps; } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { // for better readability const bool must_gc_arguments = true; @@ -322,26 +322,26 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // Stub code and info for the different stubs. OopMapSet* oop_maps = nullptr; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); // will not return } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { Register klass = Z_R11; // Incoming Register obj = Z_R2; // Result - if (id == C1StubId::new_instance_id) { + if (id == StubId::c1_new_instance_id) { __ set_info("new_instance", dont_gc_arguments); - } else if (id == C1StubId::fast_new_instance_id) { + } else if (id == StubId::c1_fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { - assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId"); + assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId"); __ set_info("fast new_instance init check", dont_gc_arguments); } @@ -356,7 +356,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: { // Arguments : // bci : stack param 0 @@ -375,14 +375,14 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ z_br(Z_R14); } break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: { Register length = Z_R13; // Incoming Register klass = Z_R11; // Incoming Register obj = Z_R2; // Result - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); } else { __ set_info("new_object_array", dont_gc_arguments); @@ -395,7 +395,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { Register t0 = obj; __ mem2reg_opt(t0, Address(klass, Klass::layout_helper_offset()), false); __ z_sra(t0, Klass::_lh_array_tag_shift); - int tag = ((id == C1StubId::new_type_array_id) + int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value); __ compare32_and_branch(t0, tag, Assembler::bcondEqual, ok); __ stop("assert(is an array klass)"); @@ -406,7 +406,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { OopMap* map = save_live_registers_except_r2(sasm); int call_offset; - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); } else { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); @@ -421,7 +421,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { __ set_info("new_multi_array", dont_gc_arguments); // Z_R3,: klass // Z_R4,: rank @@ -439,7 +439,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -462,62 +462,62 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { __ set_info("range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { __ set_info("index_range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { __ set_info("throw_div0_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { __ set_info("throw_null_pointer_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { __ set_info("handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { __ set_info("handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { __ set_info("unwind_exception", dont_gc_arguments); // Note: no stubframe since we are about to leave the current // activation and we are calling a leaf VM function only. generate_unwind_exception(sasm); } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { __ set_info("throw_array_store_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { // Z_R1_scratch: object __ set_info("throw_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // Arguments : // sub : stack param 0 @@ -588,7 +588,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ z_br(Z_R14); } break; - case C1StubId::is_instance_of_id: + case StubId::c1_is_instance_of_id: { // Mirror: Z_ARG1(R2) // Object: Z_ARG2 @@ -649,13 +649,13 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ z_br(Z_R14); } - case C1StubId::monitorenter_nofpu_id: - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_nofpu_id: + case StubId::c1_monitorenter_id: { // Z_R1_scratch : object // Z_R13 : lock address (see LIRGenerator::syncTempOpr()) __ set_info("monitorenter", dont_gc_arguments); - int save_fpu_registers = (id == C1StubId::monitorenter_id); + int save_fpu_registers = (id == StubId::c1_monitorenter_id); // Make a frame and preserve the caller's caller-save registers. OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); @@ -669,15 +669,15 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_nofpu_id: + case StubId::c1_monitorexit_id: { // Z_R1_scratch : lock address // Note: really a leaf routine but must setup last java sp // => Use call_RT for now (speed can be improved by // doing last java sp setup manually). __ set_info("monitorexit", dont_gc_arguments); - int save_fpu_registers = (id == C1StubId::monitorexit_id); + int save_fpu_registers = (id == StubId::c1_monitorexit_id); // Make a frame and preserve the caller's caller-save registers. OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); @@ -691,7 +691,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { // Args: Z_R1_scratch: trap request __ set_info("deoptimize", dont_gc_arguments); Register trap_request = Z_R1_scratch; @@ -708,32 +708,32 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { __ set_info("access_field_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { __ set_info("load_klass_patching", dont_gc_arguments); // We should set up register map. oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { __ set_info("load_mirror_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { __ set_info("load_appendix_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); } break; #if 0 - case C1StubId::dtrace_object_alloc_id: + case StubId::c1_dtrace_object_alloc_id: { // rax,: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); // We can't gc here so skip the oopmap but make sure that all @@ -748,7 +748,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::fpu2long_stub_id: + case StubId::c1_fpu2long_stub_id: { // rax, and rdx are destroyed, but should be free since the result is returned there // preserve rsi,ecx @@ -823,7 +823,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { break; #endif // TODO - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { __ set_info("predicate_failed_trap", dont_gc_arguments); @@ -851,7 +851,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { return oop_maps; } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler *sasm) { __ block_comment("generate_handle_exception"); // incoming parameters: Z_EXC_OOP, Z_EXC_PC @@ -862,7 +862,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) Register reg_fp = Z_R1_scratch; switch (id) { - case C1StubId::forward_exception_id: { + case StubId::c1_forward_exception_id: { // We're handling an exception in the context of a compiled frame. // The registers have been saved in the standard places. Perform // an exception lookup in the caller and dispatch to the handler @@ -889,13 +889,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ clear_mem(Address(Z_thread, JavaThread::vm_result_metadata_offset()), sizeof(Metadata*)); break; } - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // At this point all registers MAY be live. DEBUG_ONLY(__ z_lgr(reg_fp, Z_SP);) - oop_map = save_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id, Z_EXC_PC); + oop_map = save_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id, Z_EXC_PC); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { // At this point all registers except Z_EXC_OOP and Z_EXC_PC are dead. DEBUG_ONLY(__ z_lgr(reg_fp, Z_SP);) __ save_return_pc(Z_EXC_PC); @@ -944,15 +944,15 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ invalidate_registers(Z_R2); switch(id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // Restore the registers that were saved at the beginning. __ z_lgr(Z_R1_scratch, Z_R2); // Restoring live registers kills Z_R2. - restore_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); // Pops as well the frame. + restore_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); // Pops as well the frame. __ z_br(Z_R1_scratch); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { __ pop_frame(); __ z_br(Z_R2); // Jump to exception handler. } diff --git a/src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp b/src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp index fb7d998c458..b0e5c6805b4 100644 --- a/src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp +++ b/src/hotspot/cpu/s390/continuationHelper_s390.inline.hpp @@ -107,7 +107,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return nullptr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { Unimplemented(); } diff --git a/src/hotspot/cpu/s390/runtime_s390.cpp b/src/hotspot/cpu/s390/runtime_s390.cpp index 99a33716b8b..314c407af91 100644 --- a/src/hotspot/cpu/s390/runtime_s390.cpp +++ b/src/hotspot/cpu/s390/runtime_s390.cpp @@ -70,7 +70,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index cb1f12504fd..90f54b60611 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -2544,7 +2544,7 @@ void SharedRuntime::generate_deopt_blob() { // Allocate space for the code. ResourceMark rm; // Setup code generation tools. - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); CodeBuffer buffer(name, 2048, 1024); InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); Label exec_mode_initialized; @@ -2767,7 +2767,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); CodeBuffer buffer(name, 2048, 1024); if (buffer.blob() == nullptr) { return nullptr; @@ -2895,7 +2895,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { // // Generate a special Compile2Runtime blob that saves all registers, // and setup oopmap. -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_polling_page_id(id), "expected a polling page stub id"); @@ -2913,13 +2913,13 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal address call_pc = nullptr; int frame_size_in_bytes; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); // Make room for return address (or push it again) if (!cause_return) { __ z_lg(Z_R14, Address(Z_thread, JavaThread::saved_exception_pc_offset())); } - bool save_vectors = (id == SharedStubId::polling_page_vectors_safepoint_handler_id); + bool save_vectors = (id == StubId::shared_polling_page_vectors_safepoint_handler_id); // Save registers, fpu state, and flags map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R14, save_vectors); @@ -2999,7 +2999,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // but since this is generic code we don't know what they are and the caller // must do any gc of the args. // -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert (StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_resolve_id(id), "expected a resolve stub id"); @@ -3098,7 +3098,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // SharedRuntime.cpp requires that this code be generated into a // RuntimeStub. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); diff --git a/src/hotspot/cpu/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index 45a9e02ac27..aaed67fd269 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -118,7 +118,7 @@ class StubGenerator: public StubCodeGenerator { // Set up a new C frame, copy Java arguments, call template interpreter // or native_entry, and process result. - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -459,7 +459,7 @@ class StubGenerator: public StubCodeGenerator { // pending exception stored in JavaThread that can be tested from // within the VM. address generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -511,7 +511,7 @@ class StubGenerator: public StubCodeGenerator { // (Z_R14 is unchanged and is live out). // address generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -592,7 +592,7 @@ class StubGenerator: public StubCodeGenerator { // raddr: Z_R14, blown by call // address generate_partial_subtype_check() { - StubGenStubId stub_id = StubGenStubId::partial_subtype_check_id; + StubId stub_id = StubId::stubgen_partial_subtype_check_id; StubCodeMark mark(this, stub_id); Label miss; @@ -626,7 +626,7 @@ class StubGenerator: public StubCodeGenerator { } void generate_lookup_secondary_supers_table_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_id; StubCodeMark mark(this, stub_id); const Register @@ -649,7 +649,7 @@ class StubGenerator: public StubCodeGenerator { // Slow path implementation for UseSecondarySupersTable. address generate_lookup_secondary_supers_table_slow_path_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_slow_path_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_slow_path_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1265,39 +1265,39 @@ class StubGenerator: public StubCodeGenerator { } } - address generate_disjoint_nonoop_copy(StubGenStubId stub_id) { + address generate_disjoint_nonoop_copy(StubId stub_id) { bool aligned; int element_size; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: aligned = false; element_size = 1; break; - case arrayof_jbyte_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id: aligned = true; element_size = 1; break; - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: aligned = false; element_size = 2; break; - case arrayof_jshort_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id: aligned = true; element_size = 2; break; - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: aligned = false; element_size = 4; break; - case arrayof_jint_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jint_disjoint_arraycopy_id: aligned = true; element_size = 4; break; - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: aligned = false; element_size = 8; break; - case arrayof_jlong_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id: aligned = true; element_size = 8; break; @@ -1310,23 +1310,23 @@ class StubGenerator: public StubCodeGenerator { return __ addr_at(start_off); } - address generate_disjoint_oop_copy(StubGenStubId stub_id) { + address generate_disjoint_oop_copy(StubId stub_id) { bool aligned; bool dest_uninitialized; switch (stub_id) { - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: aligned = false; dest_uninitialized = false; break; - case arrayof_oop_disjoint_arraycopy_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_id: aligned = true; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: aligned = false; dest_uninitialized = true; break; - case arrayof_oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id: aligned = true; dest_uninitialized = true; break; @@ -1357,47 +1357,47 @@ class StubGenerator: public StubCodeGenerator { return __ addr_at(start_off); } - address generate_conjoint_nonoop_copy(StubGenStubId stub_id) { + address generate_conjoint_nonoop_copy(StubId stub_id) { bool aligned; int shift; // i.e. log2(element size) address nooverlap_target; switch (stub_id) { - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: aligned = false; shift = 0; nooverlap_target = StubRoutines::jbyte_disjoint_arraycopy(); break; - case arrayof_jbyte_arraycopy_id: + case StubId::stubgen_arrayof_jbyte_arraycopy_id: aligned = true; shift = 0; nooverlap_target = StubRoutines::arrayof_jbyte_disjoint_arraycopy(); break; - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: aligned = false; shift = 1; nooverlap_target = StubRoutines::jshort_disjoint_arraycopy(); break; - case arrayof_jshort_arraycopy_id: + case StubId::stubgen_arrayof_jshort_arraycopy_id: aligned = true; shift = 1; nooverlap_target = StubRoutines::arrayof_jshort_disjoint_arraycopy(); break; - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: aligned = false; shift = 2; nooverlap_target = StubRoutines::jint_disjoint_arraycopy(); break; - case arrayof_jint_arraycopy_id: + case StubId::stubgen_arrayof_jint_arraycopy_id: aligned = true; shift = 2; nooverlap_target = StubRoutines::arrayof_jint_disjoint_arraycopy(); break; - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: aligned = false; shift = 3; nooverlap_target = StubRoutines::jlong_disjoint_arraycopy(); break; - case arrayof_jlong_arraycopy_id: + case StubId::stubgen_arrayof_jlong_arraycopy_id: aligned = true; shift = 3; nooverlap_target = StubRoutines::arrayof_jlong_disjoint_arraycopy(); @@ -1412,27 +1412,27 @@ class StubGenerator: public StubCodeGenerator { return __ addr_at(start_off); } - address generate_conjoint_oop_copy(StubGenStubId stub_id) { + address generate_conjoint_oop_copy(StubId stub_id) { bool aligned; bool dest_uninitialized; address nooverlap_target; switch (stub_id) { - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: aligned = false; dest_uninitialized = false; nooverlap_target = StubRoutines::oop_disjoint_arraycopy(dest_uninitialized); break; - case arrayof_oop_arraycopy_id: + case StubId::stubgen_arrayof_oop_arraycopy_id: aligned = true; dest_uninitialized = false; nooverlap_target = StubRoutines::arrayof_oop_disjoint_arraycopy(dest_uninitialized); break; - case oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: aligned = false; dest_uninitialized = true; nooverlap_target = StubRoutines::oop_disjoint_arraycopy(dest_uninitialized); break; - case arrayof_oop_arraycopy_uninit_id: + case StubId::stubgen_arrayof_oop_arraycopy_uninit_id: aligned = true; dest_uninitialized = true; nooverlap_target = StubRoutines::arrayof_oop_disjoint_arraycopy(dest_uninitialized); @@ -1480,7 +1480,7 @@ class StubGenerator: public StubCodeGenerator { // address generate_unsafe_setmemory(address unsafe_byte_fill) { __ align(CodeEntryAlignment); - StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id); + StubCodeMark mark(this, StubId::stubgen_unsafe_setmemory_id); unsigned int start_off = __ offset(); // bump this on entry, not on exit: @@ -1582,33 +1582,33 @@ class StubGenerator: public StubCodeGenerator { address ucm_common_error_exit = generate_unsafecopy_common_error_exit(); UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit); - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::jbyte_disjoint_arraycopy_id); - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_nonoop_copy(StubGenStubId::jshort_disjoint_arraycopy_id); - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::jint_disjoint_arraycopy_id); - StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::jlong_disjoint_arraycopy_id); - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy (StubGenStubId::oop_disjoint_arraycopy_id); - StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy (StubGenStubId::oop_disjoint_arraycopy_uninit_id); - - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::arrayof_jbyte_disjoint_arraycopy_id); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_nonoop_copy(StubGenStubId::arrayof_jshort_disjoint_arraycopy_id); - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::arrayof_jint_disjoint_arraycopy_id); - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::arrayof_jlong_disjoint_arraycopy_id); - StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy (StubGenStubId::arrayof_oop_disjoint_arraycopy_id); - StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy (StubGenStubId::arrayof_oop_disjoint_arraycopy_uninit_id); - - StubRoutines::_jbyte_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::jbyte_arraycopy_id); - StubRoutines::_jshort_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::jshort_arraycopy_id); - StubRoutines::_jint_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::jint_arraycopy_id); - StubRoutines::_jlong_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::jlong_arraycopy_id); - StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(StubGenStubId::oop_arraycopy_id); - StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubGenStubId::oop_arraycopy_uninit_id); - - StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::arrayof_jbyte_arraycopy_id); - StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::arrayof_jshort_arraycopy_id); - StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_nonoop_copy (StubGenStubId::arrayof_jint_arraycopy_id); - StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::arrayof_jlong_arraycopy_id); - StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_id); - StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_uninit_id); + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_jbyte_disjoint_arraycopy_id); + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_nonoop_copy(StubId::stubgen_jshort_disjoint_arraycopy_id); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_jint_disjoint_arraycopy_id); + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_jlong_disjoint_arraycopy_id); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy (StubId::stubgen_oop_disjoint_arraycopy_id); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy (StubId::stubgen_oop_disjoint_arraycopy_uninit_id); + + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_nonoop_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_arrayof_jint_disjoint_arraycopy_id); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id); + StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy (StubId::stubgen_arrayof_oop_disjoint_arraycopy_id); + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy (StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id); + + StubRoutines::_jbyte_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_jbyte_arraycopy_id); + StubRoutines::_jshort_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_jshort_arraycopy_id); + StubRoutines::_jint_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_jint_arraycopy_id); + StubRoutines::_jlong_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_jlong_arraycopy_id); + StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(StubId::stubgen_oop_arraycopy_id); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubId::stubgen_oop_arraycopy_uninit_id); + + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_arrayof_jshort_arraycopy_id); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_nonoop_copy (StubId::stubgen_arrayof_jint_arraycopy_id); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_nonoop_copy(StubId::stubgen_arrayof_jlong_arraycopy_id); + StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(StubId::stubgen_arrayof_oop_arraycopy_id); + StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id); #ifdef COMPILER2 StubRoutines::_unsafe_setmemory = @@ -1898,7 +1898,7 @@ class StubGenerator: public StubCodeGenerator { // Compute AES encrypt function. address generate_AES_encryptBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -1910,7 +1910,7 @@ class StubGenerator: public StubCodeGenerator { // Compute AES decrypt function. address generate_AES_decryptBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -1971,7 +1971,7 @@ class StubGenerator: public StubCodeGenerator { // Compute chained AES encrypt function. address generate_cipherBlockChaining_AES_encrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_encryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -1983,7 +1983,7 @@ class StubGenerator: public StubCodeGenerator { // Compute chained AES decrypt function. address generate_cipherBlockChaining_AES_decrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -2690,7 +2690,7 @@ class StubGenerator: public StubCodeGenerator { // Encrypt or decrypt is selected via parameters. Only one stub is necessary. address generate_counterMode_AESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::counterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_counterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -2704,7 +2704,7 @@ class StubGenerator: public StubCodeGenerator { // Compute GHASH function. address generate_ghash_processBlocks() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::ghash_processBlocks_id; + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -2782,13 +2782,13 @@ class StubGenerator: public StubCodeGenerator { // provides for a large enough source data buffer. // // Compute SHA-1 function. - address generate_SHA1_stub(StubGenStubId stub_id) { + address generate_SHA1_stub(StubId stub_id) { bool multiBlock; switch (stub_id) { - case sha1_implCompress_id: + case StubId::stubgen_sha1_implCompress_id: multiBlock = false; break; - case sha1_implCompressMB_id: + case StubId::stubgen_sha1_implCompressMB_id: multiBlock = true; break; default: @@ -2875,13 +2875,13 @@ class StubGenerator: public StubCodeGenerator { } // Compute SHA-256 function. - address generate_SHA256_stub(StubGenStubId stub_id) { + address generate_SHA256_stub(StubId stub_id) { bool multiBlock; switch (stub_id) { - case sha256_implCompress_id: + case StubId::stubgen_sha256_implCompress_id: multiBlock = false; break; - case sha256_implCompressMB_id: + case StubId::stubgen_sha256_implCompressMB_id: multiBlock = true; break; default: @@ -2966,13 +2966,13 @@ class StubGenerator: public StubCodeGenerator { } // Compute SHA-512 function. - address generate_SHA512_stub(StubGenStubId stub_id) { + address generate_SHA512_stub(StubId stub_id) { bool multiBlock; switch (stub_id) { - case sha512_implCompress_id: + case StubId::stubgen_sha512_implCompress_id: multiBlock = false; break; - case sha512_implCompressMB_id: + case StubId::stubgen_sha512_implCompressMB_id: multiBlock = true; break; default: @@ -3102,7 +3102,7 @@ class StubGenerator: public StubCodeGenerator { // Compute CRC32 function. address generate_CRC32_updateBytes() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -3122,7 +3122,7 @@ class StubGenerator: public StubCodeGenerator { // Compute CRC32C function. address generate_CRC32C_updateBytes() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32C_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32C_id; StubCodeMark mark(this, stub_id); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). @@ -3147,7 +3147,7 @@ class StubGenerator: public StubCodeGenerator { // Z_ARG5 - z address address generate_multiplyToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::multiplyToLen_id; + StubId stub_id = StubId::stubgen_multiplyToLen_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3179,7 +3179,7 @@ class StubGenerator: public StubCodeGenerator { address generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3245,7 +3245,7 @@ class StubGenerator: public StubCodeGenerator { // exception handler for upcall stubs address generate_upcall_stub_exception_handler() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_exception_handler_id; + StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3263,7 +3263,7 @@ class StubGenerator: public StubCodeGenerator { // Z_ARG1 = jobject receiver // Z_method = Method* result address generate_upcall_stub_load_target() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_load_target_id; + StubId stub_id = StubId::stubgen_upcall_stub_load_target_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3391,16 +3391,16 @@ class StubGenerator: public StubCodeGenerator { // Generate SHA1/SHA256/SHA512 intrinsics code. if (UseSHA1Intrinsics) { - StubRoutines::_sha1_implCompress = generate_SHA1_stub(StubGenStubId::sha1_implCompress_id); - StubRoutines::_sha1_implCompressMB = generate_SHA1_stub(StubGenStubId::sha1_implCompressMB_id); + StubRoutines::_sha1_implCompress = generate_SHA1_stub(StubId::stubgen_sha1_implCompress_id); + StubRoutines::_sha1_implCompressMB = generate_SHA1_stub(StubId::stubgen_sha1_implCompressMB_id); } if (UseSHA256Intrinsics) { - StubRoutines::_sha256_implCompress = generate_SHA256_stub(StubGenStubId::sha256_implCompress_id); - StubRoutines::_sha256_implCompressMB = generate_SHA256_stub(StubGenStubId::sha256_implCompressMB_id); + StubRoutines::_sha256_implCompress = generate_SHA256_stub(StubId::stubgen_sha256_implCompress_id); + StubRoutines::_sha256_implCompressMB = generate_SHA256_stub(StubId::stubgen_sha256_implCompressMB_id); } if (UseSHA512Intrinsics) { - StubRoutines::_sha512_implCompress = generate_SHA512_stub(StubGenStubId::sha512_implCompress_id); - StubRoutines::_sha512_implCompressMB = generate_SHA512_stub(StubGenStubId::sha512_implCompressMB_id); + StubRoutines::_sha512_implCompress = generate_SHA512_stub(StubId::stubgen_sha512_implCompress_id); + StubRoutines::_sha512_implCompressMB = generate_SHA512_stub(StubId::stubgen_sha512_implCompressMB_id); } #ifdef COMPILER2 @@ -3420,25 +3420,25 @@ class StubGenerator: public StubCodeGenerator { } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } @@ -3477,6 +3477,6 @@ class StubGenerator: public StubCodeGenerator { }; -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 897b06e94df..d1b6897f287 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -8257,6 +8257,14 @@ void Assembler::vmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src) { emit_int16(0x5F, (0xC0 | encode)); } +void Assembler::eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x53, (0xC0 | encode), imm8); +} + void Assembler::vminsh(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -8771,12 +8779,68 @@ void Assembler::vmaxps(XMMRegister dst, XMMRegister nds, XMMRegister src, int ve emit_int16(0x5F, (0xC0 | encode)); } +void Assembler::evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x52, (0xC0 | encode), imm8); +} + +void Assembler::evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit); + if (merge) { + attributes.reset_is_clear_context(); + } + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x52); + emit_operand(dst, src, 0); + emit_int8(imm8); +} + void Assembler::maxpd(XMMRegister dst, XMMRegister src) { InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes); emit_int16(0x5F, (0xC0 | encode)); } +void Assembler::evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x52, (0xC0 | encode), imm8); +} + +void Assembler::evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit); + if (merge) { + attributes.reset_is_clear_context(); + } + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x52); + emit_operand(dst, src, 0); + emit_int8(imm8); +} + void Assembler::vmaxpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(vector_len >= AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx(), ""); InstructionAttr attributes(vector_len, /* vex_w */true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -13119,6 +13183,14 @@ void Assembler::vminss(XMMRegister dst, XMMRegister nds, XMMRegister src) { emit_int16(0x5D, (0xC0 | encode)); } +void Assembler::eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x53, (0xC0 | encode), imm8); +} + void Assembler::vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -13127,6 +13199,14 @@ void Assembler::vminsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { emit_int16(0x5D, (0xC0 | encode)); } +void Assembler::eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x53, (0xC0 | encode), imm8); +} + void Assembler::vcmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) { assert(VM_Version::supports_avx(), ""); assert(vector_len <= AVX_256bit, ""); @@ -15681,6 +15761,8 @@ void Assembler::pusha_uncached() { // 64bit // Push pair of original stack pointer along with remaining registers // at 16B aligned boundary. push2p(rax, r31); + // Restore the original contents of RAX register. + movq(rax, Address(rax)); push2p(r30, r29); push2p(r28, r27); push2p(r26, r25); @@ -16526,6 +16608,34 @@ void Assembler::evminph(XMMRegister dst, XMMRegister nds, Address src, int vecto emit_operand(dst, src, 0); } +void Assembler::evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x52, (0xC0 | encode), imm8); +} + +void Assembler::evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len) { + assert(VM_Version::supports_avx10_2(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x52); + emit_operand(dst, src, 0); + emit_int8(imm8); +} + void Assembler::evmaxph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index b1959e23722..45c24f8c832 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -441,6 +441,17 @@ class InstructionAttr; // See fxsave and xsave(EVEX enabled) documentation for layout const int FPUStateSizeInWords = 2688 / wordSize; + +// AVX10 new minmax instruction control mask encoding. +// +// imm8[4] = 0 (please refer to Table 11.1 of section 11.2 of AVX10 manual[1] for details) +// imm8[3:2] (sign control) = 01 (select sign, please refer to Table 11.5 of section 11.2 of AVX10 manual[1] for details) +// imm8[1:0] = 00 (min) / 01 (max) +// +// [1] https://www.intel.com/content/www/us/en/content-details/856721/intel-advanced-vector-extensions-10-2-intel-avx10-2-architecture-specification.html?wapkw=AVX10 +const int AVX10_MINMAX_MAX_COMPARE_SIGN = 0x5; +const int AVX10_MINMAX_MIN_COMPARE_SIGN = 0x4; + // The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction // level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write // is what you get. The Assembler is generating code into a CodeBuffer. @@ -2745,6 +2756,17 @@ class Assembler : public AbstractAssembler { void minpd(XMMRegister dst, XMMRegister src); void vminpd(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len); + // AVX10.2 floating point minmax instructions + void eminmaxsh(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); + void eminmaxss(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); + void eminmaxsd(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); + void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len); + void evminmaxph(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len); + void evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len); + void evminmaxps(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len); + void evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int imm8, int vector_len); + void evminmaxpd(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int imm8, int vector_len); + // Maximum of packed integers void pmaxsb(XMMRegister dst, XMMRegister src); void vpmaxsb(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len); diff --git a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp index f9ebb4b113b..41a4cc1556e 100644 --- a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp @@ -56,7 +56,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { Metadata *m = _method->as_constant_ptr()->as_metadata(); ce->store_parameter(m, 1); ce->store_parameter(_bci, 0); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::counter_overflow_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_counter_overflow_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ jmp(_continuation); @@ -65,7 +65,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); if (_info->deoptimize_on_exception()) { - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -79,11 +79,11 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { } else { ce->store_parameter(_index->as_jint(), 0); } - C1StubId stub_id; + StubId stub_id; if (_throw_index_out_of_bounds_exception) { - stub_id = C1StubId::throw_index_exception_id; + stub_id = StubId::c1_throw_index_exception_id; } else { - stub_id = C1StubId::throw_range_check_failed_id; + stub_id = StubId::c1_throw_range_check_failed_id; ce->store_parameter(_array->as_pointer_register(), 1); } __ call(RuntimeAddress(Runtime1::entry_for(stub_id))); @@ -98,7 +98,7 @@ PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) { void PredicateFailedStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); - address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + address a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); __ call(RuntimeAddress(a)); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -110,7 +110,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_throw_div0_exception_id))); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); } @@ -132,7 +132,7 @@ void LoadFlattenedArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_array->as_register(), 1); ce->store_parameter(_index->as_register(), 0); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::load_flat_array_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_load_flat_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); if (_result->as_register() != rax) { @@ -160,7 +160,7 @@ void StoreFlattenedArrayStub::emit_code(LIR_Assembler* ce) { ce->store_parameter(_array->as_register(), 2); ce->store_parameter(_index->as_register(), 1); ce->store_parameter(_value->as_register(), 0); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::store_flat_array_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_store_flat_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ jmp(_continuation); @@ -182,7 +182,7 @@ void SubstitutabilityCheckStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_left->as_register(), 1); ce->store_parameter(_right->as_register(), 0); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::substitutability_check_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_substitutability_check_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ jmp(_continuation); @@ -191,14 +191,14 @@ void SubstitutabilityCheckStub::emit_code(LIR_Assembler* ce) { // Implementation of NewInstanceStub -NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) { +NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id) { _result = result; _klass = klass; _klass_reg = klass_reg; _info = new CodeEmitInfo(info); - assert(stub_id == C1StubId::new_instance_id || - stub_id == C1StubId::fast_new_instance_id || - stub_id == C1StubId::fast_new_instance_init_check_id, + assert(stub_id == StubId::c1_new_instance_id || + stub_id == StubId::c1_fast_new_instance_id || + stub_id == StubId::c1_fast_new_instance_init_check_id, "need new_instance id"); _stub_id = stub_id; } @@ -231,7 +231,7 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); assert(_length->as_register() == rbx, "length must in rbx,"); assert(_klass_reg->as_register() == rdx, "klass_reg must in rdx"); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_type_array_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_type_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == rax, "result must in rax,"); @@ -257,9 +257,9 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) { assert(_length->as_register() == rbx, "length must in rbx,"); assert(_klass_reg->as_register() == rdx, "klass_reg must in rdx"); if (_is_null_free) { - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_null_free_array_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_null_free_array_id))); } else { - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_object_array_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_new_object_array_id))); } ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -281,11 +281,11 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) { } ce->store_parameter(_obj_reg->as_register(), 1); ce->store_parameter(_lock_reg->as_register(), 0); - C1StubId enter_id; + StubId enter_id; if (ce->compilation()->has_fpu_code()) { - enter_id = C1StubId::monitorenter_id; + enter_id = StubId::c1_monitorenter_id; } else { - enter_id = C1StubId::monitorenter_nofpu_id; + enter_id = StubId::c1_monitorenter_nofpu_id; } __ call(RuntimeAddress(Runtime1::entry_for(enter_id))); ce->add_call_info_here(_info); @@ -302,11 +302,11 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) { } ce->store_parameter(_lock_reg->as_register(), 0); // note: non-blocking leaf routine => no call info needed - C1StubId exit_id; + StubId exit_id; if (ce->compilation()->has_fpu_code()) { - exit_id = C1StubId::monitorexit_id; + exit_id = StubId::c1_monitorexit_id; } else { - exit_id = C1StubId::monitorexit_nofpu_id; + exit_id = StubId::c1_monitorexit_nofpu_id; } __ call(RuntimeAddress(Runtime1::entry_for(exit_id))); __ jmp(_continuation); @@ -435,10 +435,10 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { address target = nullptr; relocInfo::relocType reloc_type = relocInfo::none; switch (_id) { - case access_field_id: target = Runtime1::entry_for(C1StubId::access_field_patching_id); break; - case load_klass_id: target = Runtime1::entry_for(C1StubId::load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; - case load_mirror_id: target = Runtime1::entry_for(C1StubId::load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; - case load_appendix_id: target = Runtime1::entry_for(C1StubId::load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; + case access_field_id: target = Runtime1::entry_for(StubId::c1_access_field_patching_id); break; + case load_klass_id: target = Runtime1::entry_for(StubId::c1_load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; + case load_mirror_id: target = Runtime1::entry_for(StubId::c1_load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; + case load_appendix_id: target = Runtime1::entry_for(StubId::c1_load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } __ bind(call_patch); @@ -468,7 +468,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { void DeoptimizeStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_trap_request, 0); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::deoptimize_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_deoptimize_id))); ce->add_call_info_here(_info); DEBUG_ONLY(__ should_not_reach_here()); } @@ -478,9 +478,9 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { address a; if (_info->deoptimize_on_exception()) { // Deoptimize, do not throw the exception, because it is probably wrong to do it here. - a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id); + a = Runtime1::entry_for(StubId::c1_predicate_failed_trap_id); } else { - a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id); + a = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id); } ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index 2e3a1a5cb59..d7a533dc323 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -379,7 +379,7 @@ int LIR_Assembler::emit_exception_handler() { __ verify_not_null_oop(rax); // search an exception handler (rax: exception oop, rdx: throwing pc) - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::handle_exception_from_callee_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_handle_exception_from_callee_id))); __ should_not_reach_here(); guarantee(code_offset() - offset <= exception_handler_size(), "overflow"); __ end_a_stub(); @@ -435,7 +435,7 @@ int LIR_Assembler::emit_unwind_handler() { // remove the activation and dispatch to the unwind handler __ remove_frame(initial_frame_size_in_bytes(), needs_stack_repair()); - __ jump(RuntimeAddress(Runtime1::entry_for(C1StubId::unwind_exception_id))); + __ jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_unwind_exception_id))); // Emit the slow path assembly if (stub != nullptr) { @@ -1440,7 +1440,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ push(klass_RInfo); __ push(k_RInfo); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ pop(klass_RInfo); __ pop(klass_RInfo); // result is a boolean @@ -1454,7 +1454,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ push(klass_RInfo); __ push(k_RInfo); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ pop(klass_RInfo); __ pop(k_RInfo); // result is a boolean @@ -1533,7 +1533,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ push(klass_RInfo); __ push(k_RInfo); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ pop(klass_RInfo); __ pop(k_RInfo); // result is a boolean @@ -2388,7 +2388,7 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit // exception object is not added to oop map by LinearScan // (LinearScan assumes that no oops are in fixed registers) info->add_register_oop(exceptionOop); - C1StubId unwind_id; + StubId unwind_id; // get current pc information // pc is only needed if the method has an exception handler, the unwind code does not need it. @@ -2400,9 +2400,9 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit __ verify_not_null_oop(rax); // search an exception handler (rax: exception oop, rdx: throwing pc) if (compilation()->has_fpu_code()) { - unwind_id = C1StubId::handle_exception_id; + unwind_id = StubId::c1_handle_exception_id; } else { - unwind_id = C1StubId::handle_exception_nofpu_id; + unwind_id = StubId::c1_handle_exception_nofpu_id; } __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); @@ -2746,7 +2746,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ push(src); __ push(dst); - __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); + __ call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id))); __ pop(dst); __ pop(src); diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index 1ab624fa821..72a66e12044 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -308,7 +308,7 @@ void LIRGenerator::do_MonitorEnter(MonitorEnter* x) { } CodeStub* throw_ie_stub = x->maybe_inlinetype() ? - new SimpleExceptionStub(C1StubId::throw_identity_exception_id, + new SimpleExceptionStub(StubId::c1_throw_identity_exception_id, obj.result(), state_for(x)) : nullptr; @@ -1273,7 +1273,7 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { args->append(rank); args->append(varargs); LIR_Opr reg = result_register_for(x->type()); - __ call_runtime(Runtime1::entry_for(C1StubId::new_multi_array_id), + __ call_runtime(Runtime1::entry_for(StubId::c1_new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); @@ -1306,12 +1306,12 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { CodeStub* stub; if (x->is_incompatible_class_change_check()) { assert(patching_info == nullptr, "can't patch this"); - stub = new SimpleExceptionStub(C1StubId::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); } else if (x->is_invokespecial_receiver_check()) { assert(patching_info == nullptr, "can't patch this"); stub = new DeoptimizeStub(info_for_exception, Deoptimization::Reason_class_check, Deoptimization::Action_none); } else { - stub = new SimpleExceptionStub(C1StubId::throw_class_cast_exception_id, obj.result(), info_for_exception); + stub = new SimpleExceptionStub(StubId::c1_throw_class_cast_exception_id, obj.result(), info_for_exception); } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; @@ -1347,7 +1347,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { // Intrinsic for Class::isInstance address LIRGenerator::isInstance_entry() { - return Runtime1::entry_for(C1StubId::is_instance_of_id); + return Runtime1::entry_for(StubId::c1_is_instance_of_id); } diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 3e7bd076816..4eed070d115 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -259,7 +259,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == rax, "must be"); - call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); @@ -297,7 +297,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == rax, "must be"); - call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id))); + call(RuntimeAddress(Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id))); } verify_oop(obj); @@ -377,9 +377,9 @@ int C1_MacroAssembler::scalarized_entry(const CompiledEntrySignature* ces, int f // FIXME -- call runtime only if we cannot in-line allocate all the incoming inline type args. movptr(rbx, (intptr_t)(ces->method())); if (is_inline_ro_entry) { - call(RuntimeAddress(Runtime1::entry_for(C1StubId::buffer_inline_args_no_receiver_id))); + call(RuntimeAddress(Runtime1::entry_for(StubId::c1_buffer_inline_args_no_receiver_id))); } else { - call(RuntimeAddress(Runtime1::entry_for(C1StubId::buffer_inline_args_id))); + call(RuntimeAddress(Runtime1::entry_for(StubId::c1_buffer_inline_args_id))); } int rt_call_offset = offset(); diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index 718939f518d..bd84298f80a 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -59,7 +59,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre // At a method handle call, the stack may not be properly aligned // when returning with an exception. - align_stack = (stub_id() == (int)C1StubId::handle_exception_from_callee_id); + align_stack = (stub_id() == (int)StubId::c1_handle_exception_from_callee_id); mov(c_rarg0, thread); set_num_rt_args(0); // Nothing on stack @@ -111,10 +111,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre if (frame_size() == no_frame_size) { leave(); jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - } else if (_stub_id == (int)C1StubId::forward_exception_id) { + } else if (_stub_id == (int)StubId::c1_forward_exception_id) { should_not_reach_here(); } else { - jump(RuntimeAddress(Runtime1::entry_for(C1StubId::forward_exception_id))); + jump(RuntimeAddress(Runtime1::entry_for(StubId::c1_forward_exception_id))); } bind(L); } @@ -503,7 +503,7 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe } -OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) { +OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler *sasm) { __ block_comment("generate_handle_exception"); // incoming parameters @@ -516,7 +516,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) OopMapSet* oop_maps = new OopMapSet(); OopMap* oop_map = nullptr; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: // We're handling an exception in the context of a compiled frame. // The registers have been saved in the standard places. Perform // an exception lookup in the caller and dispatch to the handler @@ -535,12 +535,12 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ movptr(Address(thread, JavaThread::vm_result_oop_offset()), NULL_WORD); __ movptr(Address(thread, JavaThread::vm_result_metadata_offset()), NULL_WORD); break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, 1 /*thread*/, id != C1StubId::handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, 1 /*thread*/, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: { + case StubId::c1_handle_exception_from_callee_id: { // At this point all registers except exception oop (RAX) and // exception pc (RDX) are dead. const int frame_size = 2 /*BP, return address*/ WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord); @@ -597,13 +597,13 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ movptr(Address(rbp, 1*BytesPerWord), rax); switch (id) { - case C1StubId::forward_exception_id: - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_forward_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id != C1StubId::handle_exception_nofpu_id); + restore_live_registers(sasm, id != StubId::c1_handle_exception_nofpu_id); break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: // WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP // since we do a leave anyway. @@ -739,7 +739,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { __ testptr(rax, rax); // have we deoptimized? __ jump_cc(Assembler::equal, - RuntimeAddress(Runtime1::entry_for(C1StubId::forward_exception_id))); + RuntimeAddress(Runtime1::entry_for(StubId::c1_forward_exception_id))); // the deopt blob expects exceptions in the special fields of // JavaThread, so copy and clear pending exception. @@ -811,7 +811,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { } -OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { +OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) { // for better readability const bool must_gc_arguments = true; @@ -823,7 +823,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // stub code & info for the different stubs OopMapSet* oop_maps = nullptr; switch (id) { - case C1StubId::forward_exception_id: + case StubId::c1_forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); __ leave(); @@ -831,19 +831,19 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_instance_id: - case C1StubId::fast_new_instance_id: - case C1StubId::fast_new_instance_init_check_id: + case StubId::c1_new_instance_id: + case StubId::c1_fast_new_instance_id: + case StubId::c1_fast_new_instance_init_check_id: { Register klass = rdx; // Incoming Register obj = rax; // Result - if (id == C1StubId::new_instance_id) { + if (id == StubId::c1_new_instance_id) { __ set_info("new_instance", dont_gc_arguments); - } else if (id == C1StubId::fast_new_instance_id) { + } else if (id == StubId::c1_fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { - assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId"); + assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId"); __ set_info("fast new_instance init check", dont_gc_arguments); } @@ -863,7 +863,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { break; - case C1StubId::counter_overflow_id: + case StubId::c1_counter_overflow_id: { Register bci = rax, method = rbx; __ enter(); @@ -881,17 +881,17 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_type_array_id: - case C1StubId::new_object_array_id: - case C1StubId::new_null_free_array_id: + case StubId::c1_new_type_array_id: + case StubId::c1_new_object_array_id: + case StubId::c1_new_null_free_array_id: { Register length = rbx; // Incoming Register klass = rdx; // Incoming Register obj = rax; // Result - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); - } else if (id == C1StubId::new_object_array_id) { + } else if (id == StubId::c1_new_object_array_id) { __ set_info("new_object_array", dont_gc_arguments); } else { __ set_info("new_null_free_array", dont_gc_arguments); @@ -905,19 +905,19 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ movl(t0, Address(klass, Klass::layout_helper_offset())); __ sarl(t0, Klass::_lh_array_tag_shift); switch (id) { - case C1StubId::new_type_array_id: + case StubId::c1_new_type_array_id: __ cmpl(t0, Klass::_lh_array_tag_type_value); __ jcc(Assembler::equal, ok); __ stop("assert(is a type array klass)"); break; - case C1StubId::new_object_array_id: + case StubId::c1_new_object_array_id: __ cmpl(t0, (Klass::_lh_array_tag_ref_value)); // new "[Ljava/lang/Object;" __ jcc(Assembler::equal, ok); __ cmpl(t0, Klass::_lh_array_tag_flat_value); // new "[LVT;" __ jcc(Assembler::equal, ok); __ stop("assert(is an object or inline type array klass)"); break; - case C1StubId::new_null_free_array_id: + case StubId::c1_new_null_free_array_id: __ cmpl(t0, Klass::_lh_array_tag_flat_value); // the array can be a flat array. __ jcc(Assembler::equal, ok); __ cmpl(t0, (Klass::_lh_array_tag_ref_value)); // the array cannot be a flat array (due to InlineArrayElementMaxFlatSize, etc) @@ -934,12 +934,12 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ enter(); OopMap* map = save_live_registers(sasm, 3); int call_offset; - if (id == C1StubId::new_type_array_id) { + if (id == StubId::c1_new_type_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); - } else if (id == C1StubId::new_object_array_id) { + } else if (id == StubId::c1_new_object_array_id) { call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); } else { - assert(id == C1StubId::new_null_free_array_id, "must be"); + assert(id == StubId::c1_new_null_free_array_id, "must be"); call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length); } @@ -955,7 +955,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::new_multi_array_id: + case StubId::c1_new_multi_array_id: { StubFrame f(sasm, "new_multi_array", dont_gc_arguments); // rax,: klass // rbx,: rank @@ -972,7 +972,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::load_flat_array_id: + case StubId::c1_load_flat_array_id: { StubFrame f(sasm, "load_flat_array", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 3); @@ -992,7 +992,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::store_flat_array_id: + case StubId::c1_store_flat_array_id: { StubFrame f(sasm, "store_flat_array", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 4); @@ -1010,7 +1010,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::substitutability_check_id: + case StubId::c1_substitutability_check_id: { StubFrame f(sasm, "substitutability_check", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 3); @@ -1030,15 +1030,15 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { break; - case C1StubId::buffer_inline_args_id: - case C1StubId::buffer_inline_args_no_receiver_id: + case StubId::c1_buffer_inline_args_id: + case StubId::c1_buffer_inline_args_no_receiver_id: { - const char* name = (id == C1StubId::buffer_inline_args_id) ? + const char* name = (id == StubId::c1_buffer_inline_args_id) ? "buffer_inline_args" : "buffer_inline_args_no_receiver"; StubFrame f(sasm, name, dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2); Register method = rbx; - address entry = (id == C1StubId::buffer_inline_args_id) ? + address entry = (id == StubId::c1_buffer_inline_args_id) ? CAST_FROM_FN_PTR(address, buffer_inline_args) : CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver); int call_offset = __ call_RT(rax, noreg, entry, method); @@ -1049,7 +1049,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::register_finalizer_id: + case StubId::c1_register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -1082,44 +1082,44 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_range_check_failed_id: + case StubId::c1_throw_range_check_failed_id: { StubFrame f(sasm, "range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; - case C1StubId::throw_index_exception_id: + case StubId::c1_throw_index_exception_id: { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; - case C1StubId::throw_div0_exception_id: + case StubId::c1_throw_div0_exception_id: { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; - case C1StubId::throw_null_pointer_exception_id: + case StubId::c1_throw_null_pointer_exception_id: { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; - case C1StubId::handle_exception_nofpu_id: - case C1StubId::handle_exception_id: + case StubId::c1_handle_exception_nofpu_id: + case StubId::c1_handle_exception_id: { StubFrame f(sasm, "handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::handle_exception_from_callee_id: + case StubId::c1_handle_exception_from_callee_id: { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case C1StubId::unwind_exception_id: + case StubId::c1_unwind_exception_id: { __ set_info("unwind_exception", dont_gc_arguments); // note: no stubframe since we are about to leave the current // activation and we are calling a leaf VM function only. @@ -1127,7 +1127,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_array_store_exception_id: + case StubId::c1_throw_array_store_exception_id: { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); // tos + 0: link // + 1: return address @@ -1135,31 +1135,31 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::throw_class_cast_exception_id: + case StubId::c1_throw_class_cast_exception_id: { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; - case C1StubId::throw_incompatible_class_change_error_id: + case StubId::c1_throw_incompatible_class_change_error_id: { StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; - case C1StubId::throw_illegal_monitor_state_exception_id: + case StubId::c1_throw_illegal_monitor_state_exception_id: { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false); } break; - case C1StubId::throw_identity_exception_id: + case StubId::c1_throw_identity_exception_id: { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true); } break; - case C1StubId::slow_subtype_check_id: + case StubId::c1_slow_subtype_check_id: { // Typical calling sequence: // __ push(klass_RInfo); // object klass or other subclass @@ -1212,7 +1212,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::is_instance_of_id: + case StubId::c1_is_instance_of_id: { // Mirror: c_rarg0 (Windows: rcx, SysV: rdi) // Object: c_rarg1 (Windows: rdx, SysV: rsi) @@ -1266,10 +1266,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorenter_nofpu_id: + case StubId::c1_monitorenter_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorenter_id: + case StubId::c1_monitorenter_id: { StubFrame f(sasm, "monitorenter", dont_gc_arguments, true /* use_pop_on_epilog */); OopMap* map = save_live_registers(sasm, 3, save_fpu_registers); @@ -1287,10 +1287,10 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::monitorexit_nofpu_id: + case StubId::c1_monitorexit_nofpu_id: save_fpu_registers = false; // fall through - case C1StubId::monitorexit_id: + case StubId::c1_monitorexit_id: { StubFrame f(sasm, "monitorexit", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); @@ -1310,7 +1310,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::deoptimize_id: + case StubId::c1_deoptimize_id: { StubFrame f(sasm, "deoptimize", dont_gc_arguments); const int num_rt_args = 2; // thread, trap_request @@ -1327,35 +1327,35 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::access_field_patching_id: + case StubId::c1_access_field_patching_id: { StubFrame f(sasm, "access_field_patching", dont_gc_arguments); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; - case C1StubId::load_klass_patching_id: + case StubId::c1_load_klass_patching_id: { StubFrame f(sasm, "load_klass_patching", dont_gc_arguments); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; - case C1StubId::load_mirror_patching_id: + case StubId::c1_load_mirror_patching_id: { StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; - case C1StubId::load_appendix_patching_id: + case StubId::c1_load_appendix_patching_id: { StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments); // we should set up register map oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); } break; - case C1StubId::dtrace_object_alloc_id: + case StubId::c1_dtrace_object_alloc_id: { // rax,: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); // we can't gc here so skip the oopmap but make sure that all @@ -1369,7 +1369,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::fpu2long_stub_id: + case StubId::c1_fpu2long_stub_id: { Label done; __ cvttsd2siq(rax, Address(rsp, wordSize)); @@ -1385,7 +1385,7 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; - case C1StubId::predicate_failed_trap_id: + case StubId::c1_predicate_failed_trap_id: { StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 354a6b1df50..e86057f6335 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1260,6 +1260,21 @@ void C2_MacroAssembler::evminmax_fp(int opcode, BasicType elem_bt, } } +void C2_MacroAssembler::vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2, int vlen_enc) { + assert(opc == Op_MinV || opc == Op_MinReductionV || + opc == Op_MaxV || opc == Op_MaxReductionV, "sanity"); + + int imm8 = (opc == Op_MinV || opc == Op_MinReductionV) ? AVX10_MINMAX_MIN_COMPARE_SIGN + : AVX10_MINMAX_MAX_COMPARE_SIGN; + if (elem_bt == T_FLOAT) { + evminmaxps(dst, mask, src1, src2, true, imm8, vlen_enc); + } else { + assert(elem_bt == T_DOUBLE, ""); + evminmaxpd(dst, mask, src1, src2, true, imm8, vlen_enc); + } +} + // Float/Double signum void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero, XMMRegister one) { assert(opcode == Op_SignumF || opcode == Op_SignumD, "sanity"); @@ -1613,23 +1628,18 @@ void C2_MacroAssembler::vinsert(BasicType typ, XMMRegister dst, XMMRegister src, } } -void C2_MacroAssembler::vgather8b_masked_offset(BasicType elem_bt, - XMMRegister dst, Register base, - Register idx_base, - Register offset, Register mask, - Register mask_idx, Register rtmp, - int vlen_enc) { +void C2_MacroAssembler::vgather8b_masked(BasicType elem_bt, XMMRegister dst, + Register base, Register idx_base, + Register mask, Register mask_idx, + Register rtmp, int vlen_enc) { vpxor(dst, dst, dst, vlen_enc); if (elem_bt == T_SHORT) { for (int i = 0; i < 4; i++) { - // dst[i] = mask[i] ? src[offset + idx_base[i]] : 0 + // dst[i] = mask[i] ? src[idx_base[i]] : 0 Label skip_load; btq(mask, mask_idx); jccb(Assembler::carryClear, skip_load); movl(rtmp, Address(idx_base, i * 4)); - if (offset != noreg) { - addl(rtmp, offset); - } pinsrw(dst, Address(base, rtmp, Address::times_2), i); bind(skip_load); incq(mask_idx); @@ -1637,14 +1647,11 @@ void C2_MacroAssembler::vgather8b_masked_offset(BasicType elem_bt, } else { assert(elem_bt == T_BYTE, ""); for (int i = 0; i < 8; i++) { - // dst[i] = mask[i] ? src[offset + idx_base[i]] : 0 + // dst[i] = mask[i] ? src[idx_base[i]] : 0 Label skip_load; btq(mask, mask_idx); jccb(Assembler::carryClear, skip_load); movl(rtmp, Address(idx_base, i * 4)); - if (offset != noreg) { - addl(rtmp, offset); - } pinsrb(dst, Address(base, rtmp), i); bind(skip_load); incq(mask_idx); @@ -1652,28 +1659,21 @@ void C2_MacroAssembler::vgather8b_masked_offset(BasicType elem_bt, } } -void C2_MacroAssembler::vgather8b_offset(BasicType elem_bt, XMMRegister dst, - Register base, Register idx_base, - Register offset, Register rtmp, - int vlen_enc) { +void C2_MacroAssembler::vgather8b(BasicType elem_bt, XMMRegister dst, + Register base, Register idx_base, + Register rtmp, int vlen_enc) { vpxor(dst, dst, dst, vlen_enc); if (elem_bt == T_SHORT) { for (int i = 0; i < 4; i++) { - // dst[i] = src[offset + idx_base[i]] + // dst[i] = src[idx_base[i]] movl(rtmp, Address(idx_base, i * 4)); - if (offset != noreg) { - addl(rtmp, offset); - } pinsrw(dst, Address(base, rtmp, Address::times_2), i); } } else { assert(elem_bt == T_BYTE, ""); for (int i = 0; i < 8; i++) { - // dst[i] = src[offset + idx_base[i]] + // dst[i] = src[idx_base[i]] movl(rtmp, Address(idx_base, i * 4)); - if (offset != noreg) { - addl(rtmp, offset); - } pinsrb(dst, Address(base, rtmp), i); } } @@ -1702,11 +1702,10 @@ void C2_MacroAssembler::vgather8b_offset(BasicType elem_bt, XMMRegister dst, */ void C2_MacroAssembler::vgather_subword(BasicType elem_ty, XMMRegister dst, Register base, Register idx_base, - Register offset, Register mask, - XMMRegister xtmp1, XMMRegister xtmp2, - XMMRegister temp_dst, Register rtmp, - Register mask_idx, Register length, - int vector_len, int vlen_enc) { + Register mask, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister temp_dst, + Register rtmp, Register mask_idx, + Register length, int vector_len, int vlen_enc) { Label GATHER8_LOOP; assert(is_subword_type(elem_ty), ""); movl(length, vector_len); @@ -1720,9 +1719,9 @@ void C2_MacroAssembler::vgather_subword(BasicType elem_ty, XMMRegister dst, bind(GATHER8_LOOP); // TMP_VEC_64(temp_dst) = PICK_SUB_WORDS_FROM_GATHER_INDICES if (mask == noreg) { - vgather8b_offset(elem_ty, temp_dst, base, idx_base, offset, rtmp, vlen_enc); + vgather8b(elem_ty, temp_dst, base, idx_base, rtmp, vlen_enc); } else { - vgather8b_masked_offset(elem_ty, temp_dst, base, idx_base, offset, mask, mask_idx, rtmp, vlen_enc); + vgather8b_masked(elem_ty, temp_dst, base, idx_base, mask, mask_idx, rtmp, vlen_enc); } // TEMP_PERM_VEC(temp_dst) = PERMUTE TMP_VEC_64(temp_dst) PERM_INDEX(xtmp1) vpermd(temp_dst, xtmp1, temp_dst, vlen_enc == Assembler::AVX_512bit ? vlen_enc : Assembler::AVX_256bit); @@ -2567,12 +2566,21 @@ void C2_MacroAssembler::reduceFloatMinMax(int opcode, int vlen, bool is_dst_vali } else { // i = [0,1] vpermilps(wtmp, wsrc, permconst[i], vlen_enc); } - vminmax_fp(opcode, T_FLOAT, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); + + if (VM_Version::supports_avx10_2()) { + vminmax_fp(opcode, T_FLOAT, wdst, k0, wtmp, wsrc, vlen_enc); + } else { + vminmax_fp(opcode, T_FLOAT, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); + } wsrc = wdst; vlen_enc = Assembler::AVX_128bit; } if (is_dst_valid) { - vminmax_fp(opcode, T_FLOAT, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); + if (VM_Version::supports_avx10_2()) { + vminmax_fp(opcode, T_FLOAT, dst, k0, wdst, dst, Assembler::AVX_128bit); + } else { + vminmax_fp(opcode, T_FLOAT, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); + } } } @@ -2598,12 +2606,23 @@ void C2_MacroAssembler::reduceDoubleMinMax(int opcode, int vlen, bool is_dst_val assert(i == 0, "%d", i); vpermilpd(wtmp, wsrc, 1, vlen_enc); } - vminmax_fp(opcode, T_DOUBLE, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); + + if (VM_Version::supports_avx10_2()) { + vminmax_fp(opcode, T_DOUBLE, wdst, k0, wtmp, wsrc, vlen_enc); + } else { + vminmax_fp(opcode, T_DOUBLE, wdst, wtmp, wsrc, tmp, atmp, btmp, vlen_enc); + } + wsrc = wdst; vlen_enc = Assembler::AVX_128bit; } + if (is_dst_valid) { - vminmax_fp(opcode, T_DOUBLE, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); + if (VM_Version::supports_avx10_2()) { + vminmax_fp(opcode, T_DOUBLE, dst, k0, wdst, dst, Assembler::AVX_128bit); + } else { + vminmax_fp(opcode, T_DOUBLE, dst, wdst, dst, tmp, atmp, btmp, Assembler::AVX_128bit); + } } } diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 8d50ef409be..d31acf4cd63 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -73,6 +73,9 @@ XMMRegister tmp, XMMRegister atmp, XMMRegister btmp, int vlen_enc); + void vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, KRegister mask, + XMMRegister src1, XMMRegister src2, int vlen_enc); + void vpuminmaxq(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); void evminmax_fp(int opcode, BasicType elem_bt, @@ -493,15 +496,14 @@ void efp16sh(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2); - void vgather_subword(BasicType elem_ty, XMMRegister dst, Register base, Register idx_base, Register offset, - Register mask, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, + void vgather_subword(BasicType elem_ty, XMMRegister dst, Register base, Register idx_base, Register mask, + XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, Register midx, Register length, int vector_len, int vlen_enc); - void vgather8b_masked_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, - Register offset, Register mask, Register midx, Register rtmp, int vlen_enc); - - void vgather8b_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, - Register offset, Register rtmp, int vlen_enc); + void vgather8b_masked(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, + Register mask, Register midx, Register rtmp, int vlen_enc); + void vgather8b(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, + Register rtmp, int vlen_enc); void vector_saturating_op(int opc, BasicType elem_bt, XMMRegister dst, XMMRegister src1, XMMRegister src2, bool is_unsigned, int vlen_enc); diff --git a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp index ee2d6d8a0be..23dd9f908b5 100644 --- a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp +++ b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2024, 2025, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -205,7 +205,7 @@ static void generate_string_indexof_stubs(StubGenerator *stubgen, address *fnptr bool isU = isUL || isUU; // At least one is UTF-16 assert(isLL || isUL || isUU, "Encoding not recognized"); - StubGenStubId stub_id = (isLL ? StubGenStubId::string_indexof_linear_ll_id : (isUL ? StubGenStubId::string_indexof_linear_ul_id : StubGenStubId::string_indexof_linear_uu_id)); + StubId stub_id = (isLL ? StubId::stubgen_string_indexof_linear_ll_id : (isUL ? StubId::stubgen_string_indexof_linear_ul_id : StubId::stubgen_string_indexof_linear_uu_id)); StubCodeMark mark(stubgen, stub_id); // Keep track of isUL since we need to generate UU code in the main body // for the case where we expand the needle from bytes to words on the stack. diff --git a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp index 9591c9f2c96..86a3bb6750c 100644 --- a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp +++ b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp @@ -65,6 +65,12 @@ inline frame FreezeBase::sender(const frame& f) { int slot = 0; CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap(sender_pc, slot); + + // Repair the sender sp if the frame has been extended + if (sender_cb->is_nmethod()) { + sender_sp = f.repair_sender_sp(sender_sp, link_addr); + } + return sender_cb != nullptr ? frame(sender_sp, sender_sp, *link_addr, sender_pc, sender_cb, slot == -1 ? nullptr : sender_cb->oop_map_for_slot(slot, sender_pc), false) @@ -72,7 +78,7 @@ inline frame FreezeBase::sender(const frame& f) { } template -frame FreezeBase::new_heap_frame(frame& f, frame& caller) { +frame FreezeBase::new_heap_frame(frame& f, frame& caller, int size_adjust) { assert(FKind::is_instance(f), ""); assert(!caller.is_interpreted_frame() || caller.unextended_sp() == (intptr_t*)caller.at(frame::interpreter_frame_last_sp_offset), ""); @@ -103,8 +109,8 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) { fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset); int fsize = FKind::size(f); - sp = caller.unextended_sp() - fsize; - if (caller.is_interpreted_frame()) { + sp = caller.unextended_sp() - fsize - size_adjust; + if (caller.is_interpreted_frame() && size_adjust == 0) { // If the caller is interpreted, our stackargs are not supposed to overlap with it // so we make more room by moving sp down by argsize int argsize = FKind::stack_argsize(f); @@ -171,11 +177,12 @@ inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) { assert(frame_pc == ContinuationHelper::Frame::real_pc(hf), ""); } -inline void FreezeBase::patch_pd(frame& hf, const frame& caller) { +inline void FreezeBase::patch_pd(frame& hf, const frame& caller, bool is_bottom_frame) { if (caller.is_interpreted_frame()) { assert(!caller.is_empty(), ""); patch_callee_link_relative(caller, caller.fp()); - } else { + } else if (is_bottom_frame && caller.pc() != nullptr) { + assert(caller.is_compiled_frame(), ""); // If we're the bottom-most frame frozen in this freeze, the caller might have stayed frozen in the chunk, // and its oop-containing fp fixed. We've now just overwritten it, so we must patch it back to its value // as read from the chunk. @@ -206,7 +213,7 @@ inline frame ThawBase::new_entry_frame() { return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state } -template frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) { +template frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom, int size_adjust) { assert(FKind::is_instance(hf), ""); // The values in the returned frame object will be written into the callee's stack in patch. @@ -233,24 +240,23 @@ template frame ThawBase::new_stack_frame(const frame& hf, frame& return f; } else { int fsize = FKind::size(hf); - intptr_t* frame_sp = caller.unextended_sp() - fsize; + intptr_t* frame_sp = caller.unextended_sp() - fsize - size_adjust; if (bottom || caller.is_interpreted_frame()) { - int argsize = FKind::stack_argsize(hf); - - fsize += argsize; - frame_sp -= argsize; - caller.set_sp(caller.sp() - argsize); - assert(caller.sp() == frame_sp + (fsize-argsize), ""); - + if (size_adjust == 0) { + int argsize = FKind::stack_argsize(hf); + frame_sp -= argsize; + } frame_sp = align(hf, frame_sp, caller, bottom); } + caller.set_sp(frame_sp + fsize); + assert(is_aligned(frame_sp, frame::frame_alignment), ""); assert(hf.cb() != nullptr, ""); assert(hf.oop_map() != nullptr, ""); intptr_t* fp; if (PreserveFramePointer) { // we need to recreate a "real" frame pointer, pointing into the stack - fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset; + fp = frame_sp + fsize - frame::sender_sp_offset; } else { fp = FKind::stub || FKind::native ? frame_sp + fsize - frame::sender_sp_offset // fp always points to the address below the pushed return pc. We need correct address. @@ -264,14 +270,15 @@ inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& cal if (((intptr_t)frame_sp & 0xf) != 0) { assert(caller.is_interpreted_frame() || (bottom && hf.compiled_frame_stack_argsize() % 2 != 0), ""); frame_sp--; - caller.set_sp(caller.sp() - 1); } assert(is_aligned(frame_sp, frame::frame_alignment), ""); return frame_sp; } inline void ThawBase::patch_pd(frame& f, const frame& caller) { - patch_callee_link(caller, caller.fp()); + if (caller.is_interpreted_frame() || PreserveFramePointer) { + patch_callee_link(caller, caller.fp()); + } } inline void ThawBase::patch_pd(frame& f, intptr_t* caller_sp) { diff --git a/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp b/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp index 6d72e1b80e8..84a5a8f96fa 100644 --- a/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp +++ b/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp @@ -119,8 +119,8 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return *pc_addr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { - address* pc_addr = &(((address*) f.sp())[-1]); +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { + address* pc_addr = &(((address*) (callee_augmented ? f.unextended_sp() : f.sp()))[-1]); *pc_addr = pc; } diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 821ccbafb5d..26420313d4f 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -433,8 +433,8 @@ JavaThread** frame::saved_thread_address(const frame& f) { JavaThread** thread_addr; #ifdef COMPILER1 - if (cb == Runtime1::blob_for(C1StubId::monitorenter_id) || - cb == Runtime1::blob_for(C1StubId::monitorenter_nofpu_id)) { + if (cb == Runtime1::blob_for(StubId::c1_monitorenter_id) || + cb == Runtime1::blob_for(StubId::c1_monitorenter_nofpu_id)) { thread_addr = (JavaThread**)(f.sp() + Runtime1::runtime_blob_current_thread_offset(f)); } else #endif @@ -676,6 +676,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } else { ret_pc_loc = real_fp() - return_addr_offset; fp_loc = real_fp() - sender_sp_offset; + if (cb()->is_nmethod() && cb()->as_nmethod_or_null()->needs_stack_repair()) { + values.describe(frame_no, fp_loc - 1, err_msg("fsize for #%d", frame_no), 1); + } } address ret_pc = *(address*)ret_pc_loc; values.describe(frame_no, ret_pc_loc, @@ -714,6 +717,28 @@ intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) return sender_sp; } +intptr_t* frame::repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr) { + assert(nm != nullptr && nm->needs_stack_repair(), ""); + // The stack increment resides just below the saved rbp on the stack + // and does not account for the return address. + intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1); + int real_frame_size = ((*real_frame_size_addr) + wordSize) / wordSize; + assert(real_frame_size >= nm->frame_size() && real_frame_size <= 1000000, "invalid frame size"); + return sp + real_frame_size; +} + +bool frame::was_augmented_on_entry(int& real_size) const { + assert(is_compiled_frame(), ""); + if (_cb->as_nmethod_or_null()->needs_stack_repair()) { + intptr_t* real_frame_size_addr = unextended_sp() + _cb->frame_size() - sender_sp_offset - 1; + log_trace(continuations)("real_frame_size is addr is " INTPTR_FORMAT, p2i(real_frame_size_addr)); + real_size = ((*real_frame_size_addr) + wordSize) / wordSize; + return real_size != _cb->frame_size(); + } + real_size = _cb->frame_size(); + return false; +} + void JavaFrameAnchor::make_walkable() { // last frame set? if (last_Java_sp() == nullptr) return; diff --git a/src/hotspot/cpu/x86/frame_x86.hpp b/src/hotspot/cpu/x86/frame_x86.hpp index 18531d74eef..c3cfc3c6e82 100644 --- a/src/hotspot/cpu/x86/frame_x86.hpp +++ b/src/hotspot/cpu/x86/frame_x86.hpp @@ -144,9 +144,13 @@ return (intptr_t*) addr_at(offset); } + public: // Support for scalarized inline type calling convention intptr_t* repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) const; + static intptr_t* repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr); + bool was_augmented_on_entry(int& real_size) const; + private: #ifdef ASSERT // Used in frame::sender_for_{interpreter,compiled}_frame static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp); diff --git a/src/hotspot/cpu/x86/frame_x86.inline.hpp b/src/hotspot/cpu/x86/frame_x86.inline.hpp index c9e00b47065..82bff174408 100644 --- a/src/hotspot/cpu/x86/frame_x86.inline.hpp +++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp @@ -469,7 +469,7 @@ inline frame frame::sender_for_compiled_frame(RegisterMap* map) const { nmethod* nm = _cb->as_nmethod_or_null(); if (nm != nullptr && nm->is_compiled_by_c1() && nm->method()->has_scalarized_args() && pc() < nm->verified_inline_entry_point()) { - // TODO 8284443 Can't we do that by not passing 'dont_gc_arguments' in case 'C1StubId::buffer_inline_args_id' in 'Runtime1::generate_code_for'? + // TODO 8284443 Can't we do that by not passing 'dont_gc_arguments' in case 'StubId::c1_buffer_inline_args_id' in 'Runtime1::generate_code_for'? // The VEP and VIEP(RO) of C1-compiled methods call buffer_inline_args_xxx // before doing any argument shuffling, so we need to scan the oops // as the caller passes them. @@ -477,8 +477,8 @@ inline frame frame::sender_for_compiled_frame(RegisterMap* map) const { #ifdef ASSERT NativeCall* call = nativeCall_before(pc()); address dest = call->destination(); - assert(dest == Runtime1::entry_for(C1StubId::buffer_inline_args_no_receiver_id) || - dest == Runtime1::entry_for(C1StubId::buffer_inline_args_id), "unexpected safepoint in entry point"); + assert(dest == Runtime1::entry_for(StubId::c1_buffer_inline_args_no_receiver_id) || + dest == Runtime1::entry_for(StubId::c1_buffer_inline_args_id), "unexpected safepoint in entry point"); #endif } #endif diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index deb8111adad..d043c8af68a 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -353,7 +353,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, // The rest is saved with the optimized path - uint num_saved_regs = 4 + (dst != rax ? 1 : 0) + 4; + uint num_saved_regs = 4 + (dst != rax ? 1 : 0) + 4 + (UseAPX ? 16 : 0); __ subptr(rsp, num_saved_regs * wordSize); uint slot = num_saved_regs; if (dst != rax) { @@ -367,6 +367,25 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ movptr(Address(rsp, (--slot) * wordSize), r9); __ movptr(Address(rsp, (--slot) * wordSize), r10); __ movptr(Address(rsp, (--slot) * wordSize), r11); + // Save APX extended registers r16–r31 if enabled + if (UseAPX) { + __ movptr(Address(rsp, (--slot) * wordSize), r16); + __ movptr(Address(rsp, (--slot) * wordSize), r17); + __ movptr(Address(rsp, (--slot) * wordSize), r18); + __ movptr(Address(rsp, (--slot) * wordSize), r19); + __ movptr(Address(rsp, (--slot) * wordSize), r20); + __ movptr(Address(rsp, (--slot) * wordSize), r21); + __ movptr(Address(rsp, (--slot) * wordSize), r22); + __ movptr(Address(rsp, (--slot) * wordSize), r23); + __ movptr(Address(rsp, (--slot) * wordSize), r24); + __ movptr(Address(rsp, (--slot) * wordSize), r25); + __ movptr(Address(rsp, (--slot) * wordSize), r26); + __ movptr(Address(rsp, (--slot) * wordSize), r27); + __ movptr(Address(rsp, (--slot) * wordSize), r28); + __ movptr(Address(rsp, (--slot) * wordSize), r29); + __ movptr(Address(rsp, (--slot) * wordSize), r30); + __ movptr(Address(rsp, (--slot) * wordSize), r31); + } // r12-r15 are callee saved in all calling conventions assert(slot == 0, "must use all slots"); @@ -398,6 +417,25 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom), arg0, arg1); } + // Restore APX extended registers r31–r16 if previously saved + if (UseAPX) { + __ movptr(r31, Address(rsp, (slot++) * wordSize)); + __ movptr(r30, Address(rsp, (slot++) * wordSize)); + __ movptr(r29, Address(rsp, (slot++) * wordSize)); + __ movptr(r28, Address(rsp, (slot++) * wordSize)); + __ movptr(r27, Address(rsp, (slot++) * wordSize)); + __ movptr(r26, Address(rsp, (slot++) * wordSize)); + __ movptr(r25, Address(rsp, (slot++) * wordSize)); + __ movptr(r24, Address(rsp, (slot++) * wordSize)); + __ movptr(r23, Address(rsp, (slot++) * wordSize)); + __ movptr(r22, Address(rsp, (slot++) * wordSize)); + __ movptr(r21, Address(rsp, (slot++) * wordSize)); + __ movptr(r20, Address(rsp, (slot++) * wordSize)); + __ movptr(r19, Address(rsp, (slot++) * wordSize)); + __ movptr(r18, Address(rsp, (slot++) * wordSize)); + __ movptr(r17, Address(rsp, (slot++) * wordSize)); + __ movptr(r16, Address(rsp, (slot++) * wordSize)); + } __ movptr(r11, Address(rsp, (slot++) * wordSize)); __ movptr(r10, Address(rsp, (slot++) * wordSize)); __ movptr(r9, Address(rsp, (slot++) * wordSize)); diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index 43b19c1da96..2443b84bff5 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1081,22 +1081,25 @@ void InterpreterMacroAssembler::allocate_instance(Register klass, Register new_o } void InterpreterMacroAssembler::read_flat_field(Register entry, Register tmp1, Register tmp2, Register obj) { - Label alloc_failed, done; + Label alloc_failed, slow_path, done; const Register alloc_temp = LP64_ONLY(rscratch1) NOT_LP64(rsi); const Register dst_temp = LP64_ONLY(rscratch2) NOT_LP64(rdi); assert_different_registers(obj, entry, tmp1, tmp2, dst_temp, r8, r9); - // FIXME: code below could be re-written to better use InlineLayoutInfo data structure - // see aarch64 version + // If the field is nullable, jump to slow path + load_unsigned_byte(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset()))); + testl(tmp1, 1 << ResolvedFieldEntry::is_null_free_inline_type_shift); + jcc(Assembler::equal, slow_path); // Grap the inline field klass const Register field_klass = tmp1; load_unsigned_short(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset()))); + movptr(tmp1, Address(entry, ResolvedFieldEntry::field_holder_offset())); get_inline_type_field_klass(tmp1, tmp2, field_klass); // allocate buffer - push(obj); // push object being read from // FIXME spilling on stack could probably be avoided by using tmp2 + push(obj); // push object being read from allocate_instance(field_klass, obj, alloc_temp, dst_temp, false, alloc_failed); // Have an oop instance buffer, copy into it @@ -1110,19 +1113,51 @@ void InterpreterMacroAssembler::read_flat_field(Register entry, Register tmp1, R lea(tmp2, Address(alloc_temp, tmp2)); // call_VM_leaf, clobbers a few regs, save restore new obj push(obj); - // access_value_copy(IS_DEST_UNINITIALIZED, tmp2, dst_temp, field_klass); flat_field_copy(IS_DEST_UNINITIALIZED, tmp2, dst_temp, r8); pop(obj); jmp(done); bind(alloc_failed); pop(obj); + bind(slow_path); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field), obj, entry); get_vm_result_oop(obj); bind(done); } +void InterpreterMacroAssembler::write_flat_field(Register entry, Register tmp1, Register tmp2, + Register obj, Register off, Register value) { + assert_different_registers(entry, tmp1, tmp2, obj, off, value); + + Label slow_path, done; + + load_unsigned_byte(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset()))); + test_field_is_not_null_free_inline_type(tmp2, tmp1, slow_path); + + null_check(value); // FIXME JDK-8341120 + + lea(obj, Address(obj, off, Address::times_1)); + + load_klass(tmp2, value, tmp1); + payload_addr(value, value, tmp2); + + Register idx = tmp1; + load_unsigned_short(idx, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset()))); + movptr(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset()))); + + Register layout_info = off; + inline_layout_info(tmp2, idx, layout_info); + + flat_field_copy(IN_HEAP, value, obj, layout_info); + jmp(done); + + bind(slow_path); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, value, entry); + + bind(done); +} + // Lock object // // Args: diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index 0466a91a769..fa4d3d49dc3 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -215,6 +215,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void read_flat_field(Register entry, Register tmp1, Register tmp2, Register obj = rax); + void write_flat_field(Register entry, + Register tmp1, Register tmp2, + Register obj, Register off, Register value); // Object locking void lock_object (Register lock_reg); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index aee8d613efa..1296f745c5a 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -9575,6 +9575,10 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM evpminsd(dst, mask, nds, src, merge, vector_len); break; case T_LONG: evpminsq(dst, mask, nds, src, merge, vector_len); break; + case T_FLOAT: + evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + case T_DOUBLE: + evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -9590,6 +9594,10 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM evpmaxsd(dst, mask, nds, src, merge, vector_len); break; case T_LONG: evpmaxsq(dst, mask, nds, src, merge, vector_len); break; + case T_FLOAT: + evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + case T_DOUBLE: + evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -9605,6 +9613,10 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM evpminsd(dst, mask, nds, src, merge, vector_len); break; case T_LONG: evpminsq(dst, mask, nds, src, merge, vector_len); break; + case T_FLOAT: + evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + case T_DOUBLE: + evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -9620,6 +9632,10 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM evpmaxsd(dst, mask, nds, src, merge, vector_len); break; case T_LONG: evpmaxsq(dst, mask, nds, src, merge, vector_len); break; + case T_FLOAT: + evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + case T_DOUBLE: + evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp index 59188962d0c..5fc39e163e1 100644 --- a/src/hotspot/cpu/x86/peephole_x86_64.cpp +++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp @@ -346,7 +346,7 @@ bool Peephole::lea_remove_redundant(Block* block, int block_index, PhaseCFG* cfg for (DUIterator_Fast imax, i = decode->fast_outs(imax); i < imax; i++) { Node* dependant_lea = decode->fast_out(i); if (dependant_lea->is_Mach() && dependant_lea->as_Mach()->ideal_Opcode() == Op_AddP) { - dependant_lea->set_req(AddPNode::Base, decode_address); + dependant_lea->set_req(AddPNode::Base, lea_derived_oop->in(AddPNode::Address)); // This deleted something in the out array, hence adjust i, imax. --i; --imax; diff --git a/src/hotspot/cpu/x86/runtime_x86_64.cpp b/src/hotspot/cpu/x86/runtime_x86_64.cpp index 5865bec2e39..68a8c224659 100644 --- a/src/hotspot/cpu/x86/runtime_x86_64.cpp +++ b/src/hotspot/cpu/x86/runtime_x86_64.cpp @@ -57,8 +57,8 @@ class SimpleRuntimeFrame { //------------------------------generate_uncommon_trap_blob-------------------- UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { - const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name); + const char* name = OptoRuntime::stub_name(StubId::c2_uncommon_trap_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, BlobId::c2_uncommon_trap_id); if (blob != nullptr) { return blob->as_uncommon_trap_blob(); } @@ -236,7 +236,7 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() { UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); - AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name); + AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, BlobId::c2_uncommon_trap_id); return ut_blob; } @@ -273,8 +273,8 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned"); - const char* name = OptoRuntime::stub_name(OptoStubId::exception_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name); + const char* name = OptoRuntime::stub_name(StubId::c2_exception_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, BlobId::c2_exception_id); if (blob != nullptr) { return blob->as_exception_blob(); } @@ -377,7 +377,7 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { // Set exception blob ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); - AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name); + AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, BlobId::c2_exception_id); return ex_blob; } #endif // COMPILER2 diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index cb50dcd3528..0719575ba49 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -2892,8 +2892,8 @@ void SharedRuntime::generate_deopt_blob() { pad += 512; // Increase the buffer size when compiling for JVMCI } #endif - const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name); + const char* name = SharedRuntime::stub_name(StubId::shared_deopt_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, BlobId::shared_deopt_id); if (blob != nullptr) { _deopt_blob = blob->as_deoptimization_blob(); return; @@ -3251,7 +3251,7 @@ void SharedRuntime::generate_deopt_blob() { } #endif - AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name); + AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, BlobId::shared_deopt_id); } //------------------------------generate_handler_blob------ @@ -3259,14 +3259,14 @@ void SharedRuntime::generate_deopt_blob() { // Generate a special Compile2Runtime blob that saves all registers, // and setup oopmap. // -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { assert(StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_polling_page_id(id), "expected a polling page stub id"); // Allocate space for the code. Setup code generation tools. const char* name = SharedRuntime::stub_name(id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_safepoint_blob(); } @@ -3280,8 +3280,8 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal address start = __ pc(); address call_pc = nullptr; int frame_size_in_words; - bool cause_return = (id == SharedStubId::polling_page_return_handler_id); - bool save_wide_vectors = (id == SharedStubId::polling_page_vectors_safepoint_handler_id); + bool cause_return = (id == StubId::shared_polling_page_return_handler_id); + bool save_wide_vectors = (id == StubId::shared_polling_page_vectors_safepoint_handler_id); // Make room for return address (or push it again) if (!cause_return) { @@ -3435,7 +3435,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // Fill-out other meta info SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); - AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return sp_blob; } @@ -3447,12 +3447,12 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // but since this is generic code we don't know what they are and the caller // must do any gc of the args. // -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { assert (StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); assert(is_resolve_id(id), "expected a resolve stub id"); const char* name = SharedRuntime::stub_name(id); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_runtime_stub(); } @@ -3529,7 +3529,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // frame_size_words or bytes?? RuntimeStub* rs_blob = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); - AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return rs_blob; } @@ -3548,7 +3548,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // AbstractMethodError on entry) are either at call sites or // otherwise assume that stack unwinding will be initiated, so // caller saved registers were assumed volatile in the compiler. -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { assert(is_throw_id(id), "expected a throw stub id"); const char* name = SharedRuntime::stub_name(id); @@ -3571,7 +3571,7 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru const char* timer_msg = "SharedRuntime generate_throw_exception"; TraceTime timer(timer_msg, TRACETIME_LOG(Info, startuptime)); - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, StubInfo::blob(id)); if (blob != nullptr) { return blob->as_runtime_stub(); } @@ -3634,7 +3634,7 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru frame_complete, (framesize >> (LogBytesPerWord - LogBytesPerInt)), oop_maps, false); - AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, (uint)id, name); + AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, StubInfo::blob(id)); return stub; } @@ -4056,7 +4056,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { framesize // inclusive of return address }; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_write_checkpoint_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_write_checkpoint_id); CodeBuffer code(name, 1024, 64); MacroAssembler* masm = new MacroAssembler(&code); address start = __ pc(); @@ -4101,7 +4101,7 @@ RuntimeStub* SharedRuntime::generate_jfr_return_lease() { framesize // inclusive of return address }; - const char* name = SharedRuntime::stub_name(SharedStubId::jfr_return_lease_id); + const char* name = SharedRuntime::stub_name(StubId::shared_jfr_return_lease_id); CodeBuffer code(name, 1024, 64); MacroAssembler* masm = new MacroAssembler(&code); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp index 6289b903ab1..32fcd5d4037 100644 --- a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp +++ b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp @@ -34,8 +34,30 @@ template inline bool StackChunkFrameStream::is_in_frame(void* p0) const { assert(!is_done(), ""); intptr_t* p = (intptr_t*)p0; - int argsize = is_compiled() ? (_cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0; - int frame_size = _cb->frame_size() + argsize; + int frame_size = _cb->frame_size(); + if (is_compiled()) { + nmethod* nm = _cb->as_nmethod_or_null(); + if (nm->needs_stack_repair() && nm->is_compiled_by_c2()) { + frame f = to_frame(); + bool augmented = f.was_augmented_on_entry(frame_size); + if (!augmented) { + // Fix: C2 caller, so frame was not extended and thus the + // size read from the frame does not include the arguments. + // Ideally we have to count the arg size for the scalarized + // convention. For now we include the size of the caller frame + // which would at least be equal to that. + RegisterMap map(nullptr, + RegisterMap::UpdateMap::skip, + RegisterMap::ProcessFrames::skip, + RegisterMap::WalkContinuation::skip); + frame caller = to_frame().sender(&map); + assert(caller.is_compiled_frame() && caller.cb()->as_nmethod()->is_compiled_by_c2(), "needs stack repair but was not extended with c1/interpreter caller"); + frame_size += (caller.real_fp() - caller.sp()); + } + } else { + frame_size += _cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size >> LogBytesPerWord; + } + } return p == sp() - frame::sender_sp_offset || ((p - unextended_sp()) >= 0 && (p - unextended_sp()) < frame_size); } #endif @@ -52,7 +74,7 @@ inline frame StackChunkFrameStream::to_frame() const { template inline address StackChunkFrameStream::get_pc() const { assert(!is_done(), ""); - return *(address*)(_sp - 1); + return *(address*)((_callee_augmented ? _unextended_sp : _sp) - 1); } template diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index 7cbe3829783..ae947135f78 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -115,10 +115,10 @@ do_arch_entry(x86, compiler, vector_64_bit_mask, \ vector_64_bit_mask, vector_64_bit_mask) \ do_stub(compiler, vector_byte_shuffle_mask) \ - do_arch_entry(x86, compiler, vector_int_shuffle_mask, \ + do_arch_entry(x86, compiler, vector_byte_shuffle_mask, \ vector_byte_shuffle_mask, vector_byte_shuffle_mask) \ do_stub(compiler, vector_short_shuffle_mask) \ - do_arch_entry(x86, compiler, vector_int_shuffle_mask, \ + do_arch_entry(x86, compiler, vector_short_shuffle_mask, \ vector_short_shuffle_mask, vector_short_shuffle_mask) \ do_stub(compiler, vector_int_shuffle_mask) \ do_arch_entry(x86, compiler, vector_int_shuffle_mask, \ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index e78c17d56a9..fe5cfab8811 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -190,7 +190,7 @@ address StubGenerator::generate_call_stub(address& return_address) { assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 && (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, "adjust this code"); - StubGenStubId stub_id = StubGenStubId::call_stub_id; + StubId stub_id = StubId::stubgen_call_stub_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -426,7 +426,7 @@ address StubGenerator::generate_call_stub(address& return_address) { // rax: exception oop address StubGenerator::generate_catch_exception() { - StubGenStubId stub_id = StubGenStubId::catch_exception_id; + StubId stub_id = StubId::stubgen_catch_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -482,7 +482,7 @@ address StubGenerator::generate_catch_exception() { // NOTE: At entry of this stub, exception-pc must be on stack !! address StubGenerator::generate_forward_exception() { - StubGenStubId stub_id = StubGenStubId::forward_exception_id; + StubId stub_id = StubId::stubgen_forward_exception_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -546,7 +546,7 @@ address StubGenerator::generate_forward_exception() { // // Result: address StubGenerator::generate_orderaccess_fence() { - StubGenStubId stub_id = StubGenStubId::fence_id; + StubId stub_id = StubId::stubgen_fence_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -562,7 +562,7 @@ address StubGenerator::generate_orderaccess_fence() { // This routine is used to find the previous stack pointer for the // caller. address StubGenerator::generate_get_previous_sp() { - StubGenStubId stub_id = StubGenStubId::get_previous_sp_id; + StubId stub_id = StubId::stubgen_get_previous_sp_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -581,7 +581,7 @@ address StubGenerator::generate_get_previous_sp() { // MXCSR register to our expected state. address StubGenerator::generate_verify_mxcsr() { - StubGenStubId stub_id = StubGenStubId::verify_mxcsr_id; + StubId stub_id = StubId::stubgen_verify_mxcsr_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -610,7 +610,7 @@ address StubGenerator::generate_verify_mxcsr() { } address StubGenerator::generate_f2i_fixup() { - StubGenStubId stub_id = StubGenStubId::f2i_fixup_id; + StubId stub_id = StubId::stubgen_f2i_fixup_id; StubCodeMark mark(this, stub_id); Address inout(rsp, 5 * wordSize); // return address + 4 saves @@ -649,7 +649,7 @@ address StubGenerator::generate_f2i_fixup() { } address StubGenerator::generate_f2l_fixup() { - StubGenStubId stub_id = StubGenStubId::f2l_fixup_id; + StubId stub_id = StubId::stubgen_f2l_fixup_id; StubCodeMark mark(this, stub_id); Address inout(rsp, 5 * wordSize); // return address + 4 saves address start = __ pc(); @@ -687,7 +687,7 @@ address StubGenerator::generate_f2l_fixup() { } address StubGenerator::generate_d2i_fixup() { - StubGenStubId stub_id = StubGenStubId::d2i_fixup_id; + StubId stub_id = StubId::stubgen_d2i_fixup_id; StubCodeMark mark(this, stub_id); Address inout(rsp, 6 * wordSize); // return address + 5 saves @@ -735,7 +735,7 @@ address StubGenerator::generate_d2i_fixup() { } address StubGenerator::generate_d2l_fixup() { - StubGenStubId stub_id = StubGenStubId::d2l_fixup_id; + StubId stub_id = StubId::stubgen_d2l_fixup_id; StubCodeMark mark(this, stub_id); Address inout(rsp, 6 * wordSize); // return address + 5 saves @@ -784,7 +784,7 @@ address StubGenerator::generate_d2l_fixup() { address StubGenerator::generate_count_leading_zeros_lut() { __ align64(); - StubGenStubId stub_id = StubGenStubId::vector_count_leading_zeros_lut_id; + StubId stub_id = StubId::stubgen_vector_count_leading_zeros_lut_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -802,7 +802,7 @@ address StubGenerator::generate_count_leading_zeros_lut() { address StubGenerator::generate_popcount_avx_lut() { __ align64(); - StubGenStubId stub_id = StubGenStubId::vector_popcount_lut_id; + StubId stub_id = StubId::stubgen_vector_popcount_lut_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -820,7 +820,7 @@ address StubGenerator::generate_popcount_avx_lut() { address StubGenerator::generate_iota_indices() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_iota_indices_id; + StubId stub_id = StubId::stubgen_vector_iota_indices_id; StubCodeMark mark(this, stub_id); address start = __ pc(); // B @@ -882,7 +882,7 @@ address StubGenerator::generate_iota_indices() { address StubGenerator::generate_vector_reverse_bit_lut() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_reverse_bit_lut_id; + StubId stub_id = StubId::stubgen_vector_reverse_bit_lut_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -900,7 +900,7 @@ address StubGenerator::generate_vector_reverse_bit_lut() { address StubGenerator::generate_vector_reverse_byte_perm_mask_long() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_reverse_byte_perm_mask_long_id; + StubId stub_id = StubId::stubgen_vector_reverse_byte_perm_mask_long_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -918,7 +918,7 @@ address StubGenerator::generate_vector_reverse_byte_perm_mask_long() { address StubGenerator::generate_vector_reverse_byte_perm_mask_int() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_reverse_byte_perm_mask_int_id; + StubId stub_id = StubId::stubgen_vector_reverse_byte_perm_mask_int_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -936,7 +936,7 @@ address StubGenerator::generate_vector_reverse_byte_perm_mask_int() { address StubGenerator::generate_vector_reverse_byte_perm_mask_short() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_reverse_byte_perm_mask_short_id; + StubId stub_id = StubId::stubgen_vector_reverse_byte_perm_mask_short_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -954,7 +954,7 @@ address StubGenerator::generate_vector_reverse_byte_perm_mask_short() { address StubGenerator::generate_vector_byte_shuffle_mask() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_byte_shuffle_mask_id; + StubId stub_id = StubId::stubgen_vector_byte_shuffle_mask_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -966,7 +966,7 @@ address StubGenerator::generate_vector_byte_shuffle_mask() { return start; } -address StubGenerator::generate_fp_mask(StubGenStubId stub_id, int64_t mask) { +address StubGenerator::generate_fp_mask(StubId stub_id, int64_t mask) { __ align(CodeEntryAlignment); StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -977,13 +977,13 @@ address StubGenerator::generate_fp_mask(StubGenStubId stub_id, int64_t mask) { return start; } -address StubGenerator::generate_compress_perm_table(StubGenStubId stub_id) { +address StubGenerator::generate_compress_perm_table(StubId stub_id) { int esize; switch (stub_id) { - case compress_perm_table32_id: + case StubId::stubgen_compress_perm_table32_id: esize = 32; break; - case compress_perm_table64_id: + case StubId::stubgen_compress_perm_table64_id: esize = 64; break; default: @@ -1032,13 +1032,13 @@ address StubGenerator::generate_compress_perm_table(StubGenStubId stub_id) { return start; } -address StubGenerator::generate_expand_perm_table(StubGenStubId stub_id) { +address StubGenerator::generate_expand_perm_table(StubId stub_id) { int esize; switch (stub_id) { - case expand_perm_table32_id: + case StubId::stubgen_expand_perm_table32_id: esize = 32; break; - case expand_perm_table64_id: + case StubId::stubgen_expand_perm_table64_id: esize = 64; break; default: @@ -1085,7 +1085,7 @@ address StubGenerator::generate_expand_perm_table(StubGenStubId stub_id) { return start; } -address StubGenerator::generate_vector_mask(StubGenStubId stub_id, int64_t mask) { +address StubGenerator::generate_vector_mask(StubId stub_id, int64_t mask) { __ align(CodeEntryAlignment); StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1104,7 +1104,7 @@ address StubGenerator::generate_vector_mask(StubGenStubId stub_id, int64_t mask) address StubGenerator::generate_vector_byte_perm_mask() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vector_byte_perm_mask_id; + StubId stub_id = StubId::stubgen_vector_byte_perm_mask_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1120,7 +1120,7 @@ address StubGenerator::generate_vector_byte_perm_mask() { return start; } -address StubGenerator::generate_vector_fp_mask(StubGenStubId stub_id, int64_t mask) { +address StubGenerator::generate_vector_fp_mask(StubId stub_id, int64_t mask) { __ align(CodeEntryAlignment); StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1137,7 +1137,7 @@ address StubGenerator::generate_vector_fp_mask(StubGenStubId stub_id, int64_t ma return start; } -address StubGenerator::generate_vector_custom_i32(StubGenStubId stub_id, Assembler::AvxVectorLen len, +address StubGenerator::generate_vector_custom_i32(StubId stub_id, Assembler::AvxVectorLen len, int32_t val0, int32_t val1, int32_t val2, int32_t val3, int32_t val4, int32_t val5, int32_t val6, int32_t val7, int32_t val8, int32_t val9, int32_t val10, int32_t val11, @@ -1187,7 +1187,7 @@ address StubGenerator::generate_vector_custom_i32(StubGenStubId stub_id, Assembl // * [tos + 8]: saved r10 (rscratch1) - saved by caller // * = popped on exit address StubGenerator::generate_verify_oop() { - StubGenStubId stub_id = StubGenStubId::verify_oop_id; + StubId stub_id = StubId::stubgen_verify_oop_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1385,7 +1385,7 @@ address StubGenerator::generate_data_cache_writeback() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1403,7 +1403,7 @@ address StubGenerator::generate_data_cache_writeback_sync() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::data_cache_writeback_sync_id; + StubId stub_id = StubId::stubgen_data_cache_writeback_sync_id; StubCodeMark mark(this, stub_id); // pre wbsync is a no-op @@ -1425,13 +1425,13 @@ address StubGenerator::generate_data_cache_writeback_sync() { // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.MD5.implCompress(byte[] b, int ofs) -address StubGenerator::generate_md5_implCompress(StubGenStubId stub_id) { +address StubGenerator::generate_md5_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case md5_implCompress_id: + case StubId::stubgen_md5_implCompress_id: multi_block = false; break; - case md5_implCompressMB_id: + case StubId::stubgen_md5_implCompressMB_id: multi_block = true; break; default: @@ -1474,7 +1474,7 @@ address StubGenerator::generate_md5_implCompress(StubGenStubId stub_id) { address StubGenerator::generate_upper_word_mask() { __ align64(); - StubGenStubId stub_id = StubGenStubId::upper_word_mask_id; + StubId stub_id = StubId::stubgen_upper_word_mask_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1486,7 +1486,7 @@ address StubGenerator::generate_upper_word_mask() { address StubGenerator::generate_shuffle_byte_flip_mask() { __ align64(); - StubGenStubId stub_id = StubGenStubId::shuffle_byte_flip_mask_id; + StubId stub_id = StubId::stubgen_shuffle_byte_flip_mask_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1498,13 +1498,13 @@ address StubGenerator::generate_shuffle_byte_flip_mask() { // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) -address StubGenerator::generate_sha1_implCompress(StubGenStubId stub_id) { +address StubGenerator::generate_sha1_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha1_implCompress_id: + case StubId::stubgen_sha1_implCompress_id: multi_block = false; break; - case sha1_implCompressMB_id: + case StubId::stubgen_sha1_implCompressMB_id: multi_block = true; break; default: @@ -1546,7 +1546,7 @@ address StubGenerator::generate_sha1_implCompress(StubGenStubId stub_id) { address StubGenerator::generate_pshuffle_byte_flip_mask() { __ align64(); - StubGenStubId stub_id = StubGenStubId::pshuffle_byte_flip_mask_id; + StubId stub_id = StubId::stubgen_pshuffle_byte_flip_mask_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1574,7 +1574,7 @@ address StubGenerator::generate_pshuffle_byte_flip_mask() { //Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb. address StubGenerator::generate_pshuffle_byte_flip_mask_sha512() { __ align32(); - StubGenStubId stub_id = StubGenStubId::pshuffle_byte_flip_mask_sha512_id; + StubId stub_id = StubId::stubgen_pshuffle_byte_flip_mask_sha512_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1594,13 +1594,13 @@ address StubGenerator::generate_pshuffle_byte_flip_mask_sha512() { // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) -address StubGenerator::generate_sha256_implCompress(StubGenStubId stub_id) { +address StubGenerator::generate_sha256_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha256_implCompress_id: + case StubId::stubgen_sha256_implCompress_id: multi_block = false; break; - case sha256_implCompressMB_id: + case StubId::stubgen_sha256_implCompressMB_id: multi_block = true; break; default: @@ -1647,13 +1647,13 @@ address StubGenerator::generate_sha256_implCompress(StubGenStubId stub_id) { return start; } -address StubGenerator::generate_sha512_implCompress(StubGenStubId stub_id) { +address StubGenerator::generate_sha512_implCompress(StubId stub_id) { bool multi_block; switch (stub_id) { - case sha512_implCompress_id: + case StubId::stubgen_sha512_implCompress_id: multi_block = false; break; - case sha512_implCompressMB_id: + case StubId::stubgen_sha512_implCompressMB_id: multi_block = true; break; default: @@ -1697,7 +1697,7 @@ address StubGenerator::generate_sha512_implCompress(StubGenStubId stub_id) { address StubGenerator::base64_shuffle_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::shuffle_base64_id; + StubId stub_id = StubId::stubgen_shuffle_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1717,7 +1717,7 @@ address StubGenerator::base64_shuffle_addr() { address StubGenerator::base64_avx2_shuffle_addr() { __ align32(); - StubGenStubId stub_id = StubGenStubId::avx2_shuffle_base64_id; + StubId stub_id = StubId::stubgen_avx2_shuffle_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1731,7 +1731,7 @@ address StubGenerator::base64_avx2_shuffle_addr() { address StubGenerator::base64_avx2_input_mask_addr() { __ align32(); - StubGenStubId stub_id = StubGenStubId::avx2_input_mask_base64_id; + StubId stub_id = StubId::stubgen_avx2_input_mask_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1745,7 +1745,7 @@ address StubGenerator::base64_avx2_input_mask_addr() { address StubGenerator::base64_avx2_lut_addr() { __ align32(); - StubGenStubId stub_id = StubGenStubId::avx2_lut_base64_id; + StubId stub_id = StubId::stubgen_avx2_lut_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1765,7 +1765,7 @@ address StubGenerator::base64_avx2_lut_addr() { address StubGenerator::base64_encoding_table_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::encoding_table_base64_id; + StubId stub_id = StubId::stubgen_encoding_table_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1799,7 +1799,7 @@ address StubGenerator::base64_encoding_table_addr() { address StubGenerator::generate_base64_encodeBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_encodeBlock_id; + StubId stub_id = StubId::stubgen_base64_encodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2182,7 +2182,7 @@ address StubGenerator::generate_base64_encodeBlock() // base64 AVX512vbmi tables address StubGenerator::base64_vbmi_lookup_lo_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::lookup_lo_base64_id; + StubId stub_id = StubId::stubgen_lookup_lo_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2202,7 +2202,7 @@ address StubGenerator::base64_vbmi_lookup_lo_addr() { address StubGenerator::base64_vbmi_lookup_hi_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::lookup_hi_base64_id; + StubId stub_id = StubId::stubgen_lookup_hi_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2221,7 +2221,7 @@ address StubGenerator::base64_vbmi_lookup_hi_addr() { } address StubGenerator::base64_vbmi_lookup_lo_url_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::lookup_lo_base64url_id; + StubId stub_id = StubId::stubgen_lookup_lo_base64url_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2241,7 +2241,7 @@ address StubGenerator::base64_vbmi_lookup_lo_url_addr() { address StubGenerator::base64_vbmi_lookup_hi_url_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::lookup_hi_base64url_id; + StubId stub_id = StubId::stubgen_lookup_hi_base64url_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2261,7 +2261,7 @@ address StubGenerator::base64_vbmi_lookup_hi_url_addr() { address StubGenerator::base64_vbmi_pack_vec_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::pack_vec_base64_id; + StubId stub_id = StubId::stubgen_pack_vec_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2281,7 +2281,7 @@ address StubGenerator::base64_vbmi_pack_vec_addr() { address StubGenerator::base64_vbmi_join_0_1_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::join_0_1_base64_id; + StubId stub_id = StubId::stubgen_join_0_1_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2301,7 +2301,7 @@ address StubGenerator::base64_vbmi_join_0_1_addr() { address StubGenerator::base64_vbmi_join_1_2_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::join_1_2_base64_id; + StubId stub_id = StubId::stubgen_join_1_2_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2321,7 +2321,7 @@ address StubGenerator::base64_vbmi_join_1_2_addr() { address StubGenerator::base64_vbmi_join_2_3_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::join_2_3_base64_id; + StubId stub_id = StubId::stubgen_join_2_3_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2341,7 +2341,7 @@ address StubGenerator::base64_vbmi_join_2_3_addr() { address StubGenerator::base64_AVX2_decode_tables_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::avx2_decode_tables_base64_id; + StubId stub_id = StubId::stubgen_avx2_decode_tables_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2376,7 +2376,7 @@ address StubGenerator::base64_AVX2_decode_tables_addr() { address StubGenerator::base64_AVX2_decode_LUT_tables_addr() { __ align64(); - StubGenStubId stub_id = StubGenStubId::avx2_decode_lut_tables_base64_id; + StubId stub_id = StubId::stubgen_avx2_decode_lut_tables_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2416,7 +2416,7 @@ address StubGenerator::base64_AVX2_decode_LUT_tables_addr() { } address StubGenerator::base64_decoding_table_addr() { - StubGenStubId stub_id = StubGenStubId::decoding_table_base64_id; + StubId stub_id = StubId::stubgen_decoding_table_base64_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2499,7 +2499,7 @@ address StubGenerator::base64_decoding_table_addr() { // private void decodeBlock(byte[] src, int sp, int sl, byte[] dst, int dp, boolean isURL, isMIME) { address StubGenerator::generate_base64_decodeBlock() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::base64_decodeBlock_id; + StubId stub_id = StubId::stubgen_base64_decodeBlock_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3033,7 +3033,7 @@ address StubGenerator::generate_updateBytesCRC32() { assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3090,7 +3090,7 @@ address StubGenerator::generate_updateBytesCRC32() { address StubGenerator::generate_updateBytesCRC32C(bool is_pclmulqdq_supported) { assert(UseCRC32CIntrinsics, "need SSE4_2"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32C_id; + StubId stub_id = StubId::stubgen_updateBytesCRC32C_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3171,7 +3171,7 @@ address StubGenerator::generate_updateBytesCRC32C(bool is_pclmulqdq_supported) { */ address StubGenerator::generate_multiplyToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::multiplyToLen_id; + StubId stub_id = StubId::stubgen_multiplyToLen_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3228,7 +3228,7 @@ address StubGenerator::generate_multiplyToLen() { */ address StubGenerator::generate_vectorizedMismatch() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::vectorizedMismatch_id; + StubId stub_id = StubId::stubgen_vectorizedMismatch_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3280,7 +3280,7 @@ address StubGenerator::generate_vectorizedMismatch() { address StubGenerator::generate_squareToLen() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::squareToLen_id; + StubId stub_id = StubId::stubgen_squareToLen_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3316,7 +3316,7 @@ address StubGenerator::generate_squareToLen() { address StubGenerator::generate_method_entry_barrier() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::method_entry_barrier_id; + StubId stub_id = StubId::stubgen_method_entry_barrier_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3406,7 +3406,7 @@ address StubGenerator::generate_method_entry_barrier() { */ address StubGenerator::generate_mulAdd() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::mulAdd_id; + StubId stub_id = StubId::stubgen_mulAdd_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3448,7 +3448,7 @@ address StubGenerator::generate_mulAdd() { address StubGenerator::generate_bigIntegerRightShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerRightShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerRightShiftWorker_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3584,7 +3584,7 @@ address StubGenerator::generate_bigIntegerRightShift() { */ address StubGenerator::generate_bigIntegerLeftShift() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::bigIntegerLeftShiftWorker_id; + StubId stub_id = StubId::stubgen_bigIntegerLeftShiftWorker_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3736,7 +3736,7 @@ void StubGenerator::generate_libm_stubs() { * xmm0 - float */ address StubGenerator::generate_float16ToFloat() { - StubGenStubId stub_id = StubGenStubId::hf2f_id; + StubId stub_id = StubId::stubgen_hf2f_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3762,7 +3762,7 @@ address StubGenerator::generate_float16ToFloat() { * rax - float16 jshort */ address StubGenerator::generate_floatToFloat16() { - StubGenStubId stub_id = StubGenStubId::f2hf_id; + StubId stub_id = StubId::stubgen_f2hf_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3778,7 +3778,68 @@ address StubGenerator::generate_floatToFloat16() { return start; } -address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { +static void save_return_registers(MacroAssembler* masm) { + masm->push(rax); + if (InlineTypeReturnedAsFields) { + masm->push(rdi); + masm->push(rsi); + masm->push(rdx); + masm->push(rcx); + masm->push(r8); + masm->push(r9); + } + masm->push_d(xmm0); + if (InlineTypeReturnedAsFields) { + masm->push_d(xmm1); + masm->push_d(xmm2); + masm->push_d(xmm3); + masm->push_d(xmm4); + masm->push_d(xmm5); + masm->push_d(xmm6); + masm->push_d(xmm7); + } +#ifdef ASSERT + masm->movq(rax, 0xBADC0FFE); + masm->movq(rdi, rax); + masm->movq(rsi, rax); + masm->movq(rdx, rax); + masm->movq(rcx, rax); + masm->movq(r8, rax); + masm->movq(r9, rax); + masm->movq(xmm0, rax); + masm->movq(xmm1, rax); + masm->movq(xmm2, rax); + masm->movq(xmm3, rax); + masm->movq(xmm4, rax); + masm->movq(xmm5, rax); + masm->movq(xmm6, rax); + masm->movq(xmm7, rax); +#endif +} + +static void restore_return_registers(MacroAssembler* masm) { + if (InlineTypeReturnedAsFields) { + masm->pop_d(xmm7); + masm->pop_d(xmm6); + masm->pop_d(xmm5); + masm->pop_d(xmm4); + masm->pop_d(xmm3); + masm->pop_d(xmm2); + masm->pop_d(xmm1); + } + masm->pop_d(xmm0); + if (InlineTypeReturnedAsFields) { + masm->pop(r9); + masm->pop(r8); + masm->pop(rcx); + masm->pop(rdx); + masm->pop(rsi); + masm->pop(rdi); + } + masm->pop(rax); +} + +address StubGenerator::generate_cont_thaw(StubId stub_id) { if (!Continuations::enabled()) return nullptr; bool return_barrier; @@ -3786,17 +3847,17 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { Continuation::thaw_kind kind; switch (stub_id) { - case cont_thaw_id: + case StubId::stubgen_cont_thaw_id: return_barrier = false; return_barrier_exception = false; kind = Continuation::thaw_top; break; - case cont_returnBarrier_id: + case StubId::stubgen_cont_returnBarrier_id: return_barrier = true; return_barrier_exception = false; kind = Continuation::thaw_return_barrier; break; - case cont_returnBarrierExc_id: + case StubId::stubgen_cont_returnBarrierExc_id: return_barrier = true; return_barrier_exception = true; kind = Continuation::thaw_return_barrier_exception; @@ -3829,8 +3890,7 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { if (return_barrier) { // Preserve possible return value from a method returning to the return barrier. - __ push(rax); - __ push_d(xmm0); + save_return_registers(_masm); } __ movptr(c_rarg0, r15_thread); @@ -3841,8 +3901,7 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { if (return_barrier) { // Restore return value from a method returning to the return barrier. // No safepoint in the call to thaw, so even an oop return value should be OK. - __ pop_d(xmm0); - __ pop(rax); + restore_return_registers(_masm); } #ifdef ASSERT @@ -3868,8 +3927,7 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { if (return_barrier) { // Preserve possible return value from a method returning to the return barrier. (Again.) - __ push(rax); - __ push_d(xmm0); + save_return_registers(_masm); } // If we want, we can templatize thaw by kind, and have three different entries. @@ -3881,8 +3939,7 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { if (return_barrier) { // Restore return value from a method returning to the return barrier. (Again.) // No safepoint in the call to thaw, so even an oop return value should be OK. - __ pop_d(xmm0); - __ pop(rax); + restore_return_registers(_masm); } else { // Return 0 (success) from doYield. __ xorptr(rax, rax); @@ -3922,22 +3979,22 @@ address StubGenerator::generate_cont_thaw(StubGenStubId stub_id) { } address StubGenerator::generate_cont_thaw() { - return generate_cont_thaw(StubGenStubId::cont_thaw_id); + return generate_cont_thaw(StubId::stubgen_cont_thaw_id); } // TODO: will probably need multiple return barriers depending on return type address StubGenerator::generate_cont_returnBarrier() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrier_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrier_id); } address StubGenerator::generate_cont_returnBarrier_exception() { - return generate_cont_thaw(StubGenStubId::cont_returnBarrierExc_id); + return generate_cont_thaw(StubId::stubgen_cont_returnBarrierExc_id); } address StubGenerator::generate_cont_preempt_stub() { if (!Continuations::enabled()) return nullptr; - StubGenStubId stub_id = StubGenStubId::cont_preempt_id; + StubId stub_id = StubId::stubgen_cont_preempt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3968,7 +4025,7 @@ address StubGenerator::generate_cont_preempt_stub() { // exception handler for upcall stubs address StubGenerator::generate_upcall_stub_exception_handler() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_exception_handler_id; + StubId stub_id = StubId::stubgen_upcall_stub_exception_handler_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -3989,7 +4046,7 @@ address StubGenerator::generate_upcall_stub_exception_handler() { // j_rarg0 = jobject receiver // rbx = result address StubGenerator::generate_upcall_stub_load_target() { - StubGenStubId stub_id = StubGenStubId::upcall_stub_load_target_id; + StubId stub_id = StubId::stubgen_upcall_stub_load_target_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4009,7 +4066,7 @@ address StubGenerator::generate_upcall_stub_load_target() { } void StubGenerator::generate_lookup_secondary_supers_table_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_id; StubCodeMark mark(this, stub_id); const Register @@ -4029,7 +4086,7 @@ void StubGenerator::generate_lookup_secondary_supers_table_stub() { // Slow path implementation for UseSecondarySupersTable. address StubGenerator::generate_lookup_secondary_supers_table_slow_path_stub() { - StubGenStubId stub_id = StubGenStubId::lookup_secondary_supers_table_slow_path_id; + StubId stub_id = StubId::stubgen_lookup_secondary_supers_table_slow_path_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -4115,10 +4172,10 @@ void StubGenerator::generate_initial_stubs() { StubRoutines::x86::_d2i_fixup = generate_d2i_fixup(); StubRoutines::x86::_d2l_fixup = generate_d2l_fixup(); - StubRoutines::x86::_float_sign_mask = generate_fp_mask(StubGenStubId::float_sign_mask_id, 0x7FFFFFFF7FFFFFFF); - StubRoutines::x86::_float_sign_flip = generate_fp_mask(StubGenStubId::float_sign_flip_id, 0x8000000080000000); - StubRoutines::x86::_double_sign_mask = generate_fp_mask(StubGenStubId::double_sign_mask_id, 0x7FFFFFFFFFFFFFFF); - StubRoutines::x86::_double_sign_flip = generate_fp_mask(StubGenStubId::double_sign_flip_id, 0x8000000000000000); + StubRoutines::x86::_float_sign_mask = generate_fp_mask(StubId::stubgen_float_sign_mask_id, 0x7FFFFFFF7FFFFFFF); + StubRoutines::x86::_float_sign_flip = generate_fp_mask(StubId::stubgen_float_sign_flip_id, 0x8000000080000000); + StubRoutines::x86::_double_sign_mask = generate_fp_mask(StubId::stubgen_double_sign_mask_id, 0x7FFFFFFFFFFFFFFF); + StubRoutines::x86::_double_sign_flip = generate_fp_mask(StubId::stubgen_double_sign_flip_id, 0x8000000000000000); if (UseCRC32Intrinsics) { // set table address before stub generation which use it @@ -4335,25 +4392,25 @@ void StubGenerator::generate_compiler_stubs() { // Entry points that are C2 compiler specific. - StubRoutines::x86::_vector_float_sign_mask = generate_vector_mask(StubGenStubId::vector_float_sign_mask_id, 0x7FFFFFFF7FFFFFFF); - StubRoutines::x86::_vector_float_sign_flip = generate_vector_mask(StubGenStubId::vector_float_sign_flip_id, 0x8000000080000000); - StubRoutines::x86::_vector_double_sign_mask = generate_vector_mask(StubGenStubId::vector_double_sign_mask_id, 0x7FFFFFFFFFFFFFFF); - StubRoutines::x86::_vector_double_sign_flip = generate_vector_mask(StubGenStubId::vector_double_sign_flip_id, 0x8000000000000000); - StubRoutines::x86::_vector_all_bits_set = generate_vector_mask(StubGenStubId::vector_all_bits_set_id, 0xFFFFFFFFFFFFFFFF); - StubRoutines::x86::_vector_int_mask_cmp_bits = generate_vector_mask(StubGenStubId::vector_int_mask_cmp_bits_id, 0x0000000100000001); - StubRoutines::x86::_vector_short_to_byte_mask = generate_vector_mask(StubGenStubId::vector_short_to_byte_mask_id, 0x00ff00ff00ff00ff); + StubRoutines::x86::_vector_float_sign_mask = generate_vector_mask(StubId::stubgen_vector_float_sign_mask_id, 0x7FFFFFFF7FFFFFFF); + StubRoutines::x86::_vector_float_sign_flip = generate_vector_mask(StubId::stubgen_vector_float_sign_flip_id, 0x8000000080000000); + StubRoutines::x86::_vector_double_sign_mask = generate_vector_mask(StubId::stubgen_vector_double_sign_mask_id, 0x7FFFFFFFFFFFFFFF); + StubRoutines::x86::_vector_double_sign_flip = generate_vector_mask(StubId::stubgen_vector_double_sign_flip_id, 0x8000000000000000); + StubRoutines::x86::_vector_all_bits_set = generate_vector_mask(StubId::stubgen_vector_all_bits_set_id, 0xFFFFFFFFFFFFFFFF); + StubRoutines::x86::_vector_int_mask_cmp_bits = generate_vector_mask(StubId::stubgen_vector_int_mask_cmp_bits_id, 0x0000000100000001); + StubRoutines::x86::_vector_short_to_byte_mask = generate_vector_mask(StubId::stubgen_vector_short_to_byte_mask_id, 0x00ff00ff00ff00ff); StubRoutines::x86::_vector_byte_perm_mask = generate_vector_byte_perm_mask(); - StubRoutines::x86::_vector_int_to_byte_mask = generate_vector_mask(StubGenStubId::vector_int_to_byte_mask_id, 0x000000ff000000ff); - StubRoutines::x86::_vector_int_to_short_mask = generate_vector_mask(StubGenStubId::vector_int_to_short_mask_id, 0x0000ffff0000ffff); - StubRoutines::x86::_vector_32_bit_mask = generate_vector_custom_i32(StubGenStubId::vector_32_bit_mask_id, Assembler::AVX_512bit, + StubRoutines::x86::_vector_int_to_byte_mask = generate_vector_mask(StubId::stubgen_vector_int_to_byte_mask_id, 0x000000ff000000ff); + StubRoutines::x86::_vector_int_to_short_mask = generate_vector_mask(StubId::stubgen_vector_int_to_short_mask_id, 0x0000ffff0000ffff); + StubRoutines::x86::_vector_32_bit_mask = generate_vector_custom_i32(StubId::stubgen_vector_32_bit_mask_id, Assembler::AVX_512bit, 0xFFFFFFFF, 0, 0, 0); - StubRoutines::x86::_vector_64_bit_mask = generate_vector_custom_i32(StubGenStubId::vector_64_bit_mask_id, Assembler::AVX_512bit, + StubRoutines::x86::_vector_64_bit_mask = generate_vector_custom_i32(StubId::stubgen_vector_64_bit_mask_id, Assembler::AVX_512bit, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0); - StubRoutines::x86::_vector_int_shuffle_mask = generate_vector_mask(StubGenStubId::vector_int_shuffle_mask_id, 0x0302010003020100); + StubRoutines::x86::_vector_int_shuffle_mask = generate_vector_mask(StubId::stubgen_vector_int_shuffle_mask_id, 0x0302010003020100); StubRoutines::x86::_vector_byte_shuffle_mask = generate_vector_byte_shuffle_mask(); - StubRoutines::x86::_vector_short_shuffle_mask = generate_vector_mask(StubGenStubId::vector_short_shuffle_mask_id, 0x0100010001000100); - StubRoutines::x86::_vector_long_shuffle_mask = generate_vector_mask(StubGenStubId::vector_long_shuffle_mask_id, 0x0000000100000000); - StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask(StubGenStubId::vector_long_sign_mask_id, 0x8000000000000000); + StubRoutines::x86::_vector_short_shuffle_mask = generate_vector_mask(StubId::stubgen_vector_short_shuffle_mask_id, 0x0100010001000100); + StubRoutines::x86::_vector_long_shuffle_mask = generate_vector_mask(StubId::stubgen_vector_long_shuffle_mask_id, 0x0000000100000000); + StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask(StubId::stubgen_vector_long_sign_mask_id, 0x8000000000000000); StubRoutines::x86::_vector_iota_indices = generate_iota_indices(); StubRoutines::x86::_vector_count_leading_zeros_lut = generate_count_leading_zeros_lut(); StubRoutines::x86::_vector_reverse_bit_lut = generate_vector_reverse_bit_lut(); @@ -4362,10 +4419,10 @@ void StubGenerator::generate_compiler_stubs() { StubRoutines::x86::_vector_reverse_byte_perm_mask_short = generate_vector_reverse_byte_perm_mask_short(); if (VM_Version::supports_avx2() && !VM_Version::supports_avx512vl()) { - StubRoutines::x86::_compress_perm_table32 = generate_compress_perm_table(StubGenStubId::compress_perm_table32_id); - StubRoutines::x86::_compress_perm_table64 = generate_compress_perm_table(StubGenStubId::compress_perm_table64_id); - StubRoutines::x86::_expand_perm_table32 = generate_expand_perm_table(StubGenStubId::expand_perm_table32_id); - StubRoutines::x86::_expand_perm_table64 = generate_expand_perm_table(StubGenStubId::expand_perm_table64_id); + StubRoutines::x86::_compress_perm_table32 = generate_compress_perm_table(StubId::stubgen_compress_perm_table32_id); + StubRoutines::x86::_compress_perm_table64 = generate_compress_perm_table(StubId::stubgen_compress_perm_table64_id); + StubRoutines::x86::_expand_perm_table32 = generate_expand_perm_table(StubId::stubgen_expand_perm_table32_id); + StubRoutines::x86::_expand_perm_table64 = generate_expand_perm_table(StubId::stubgen_expand_perm_table64_id); } if (VM_Version::supports_avx2() && !VM_Version::supports_avx512_vpopcntdq()) { @@ -4409,15 +4466,15 @@ void StubGenerator::generate_compiler_stubs() { } if (UseMD5Intrinsics) { - StubRoutines::_md5_implCompress = generate_md5_implCompress(StubGenStubId::md5_implCompress_id); - StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubGenStubId::md5_implCompressMB_id); + StubRoutines::_md5_implCompress = generate_md5_implCompress(StubId::stubgen_md5_implCompress_id); + StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubId::stubgen_md5_implCompressMB_id); } if (UseSHA1Intrinsics) { StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask(); StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask(); - StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubGenStubId::sha1_implCompress_id); - StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubGenStubId::sha1_implCompressMB_id); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(StubId::stubgen_sha1_implCompress_id); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(StubId::stubgen_sha1_implCompressMB_id); } if (UseSHA256Intrinsics) { @@ -4430,15 +4487,15 @@ void StubGenerator::generate_compiler_stubs() { } StubRoutines::x86::_k256_W_adr = (address)StubRoutines::x86::_k256_W; StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask(); - StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubGenStubId::sha256_implCompress_id); - StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubGenStubId::sha256_implCompressMB_id); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(StubId::stubgen_sha256_implCompressMB_id); } if (UseSHA512Intrinsics) { StubRoutines::x86::_k512_W_addr = (address)StubRoutines::x86::_k512_W; StubRoutines::x86::_pshuffle_byte_flip_mask_addr_sha512 = generate_pshuffle_byte_flip_mask_sha512(); - StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubGenStubId::sha512_implCompress_id); - StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubGenStubId::sha512_implCompressMB_id); + StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubId::stubgen_sha512_implCompress_id); + StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubId::stubgen_sha512_implCompressMB_id); } if (UseBASE64Intrinsics) { @@ -4514,30 +4571,30 @@ void StubGenerator::generate_compiler_stubs() { #endif // COMPILER2_OR_JVMCI } -StubGenerator::StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { +StubGenerator::StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: generate_compiler_stubs(); break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index f521e70f312..12ab13e7fbd 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -98,19 +98,19 @@ class StubGenerator: public StubCodeGenerator { address generate_vector_reverse_byte_perm_mask_short(); address generate_vector_byte_shuffle_mask(); - address generate_fp_mask(StubGenStubId stub_id, int64_t mask); + address generate_fp_mask(StubId stub_id, int64_t mask); - address generate_compress_perm_table(StubGenStubId stub_id); + address generate_compress_perm_table(StubId stub_id); - address generate_expand_perm_table(StubGenStubId stub_id); + address generate_expand_perm_table(StubId stub_id); - address generate_vector_mask(StubGenStubId stub_id, int64_t mask); + address generate_vector_mask(StubId stub_id, int64_t mask); address generate_vector_byte_perm_mask(); - address generate_vector_fp_mask(StubGenStubId stub_id, int64_t mask); + address generate_vector_fp_mask(StubId stub_id, int64_t mask); - address generate_vector_custom_i32(StubGenStubId stub_id, Assembler::AvxVectorLen len, + address generate_vector_custom_i32(StubId stub_id, Assembler::AvxVectorLen len, int32_t val0, int32_t val1, int32_t val2, int32_t val3, int32_t val4 = 0, int32_t val5 = 0, int32_t val6 = 0, int32_t val7 = 0, int32_t val8 = 0, int32_t val9 = 0, int32_t val10 = 0, int32_t val11 = 0, @@ -180,9 +180,9 @@ class StubGenerator: public StubCodeGenerator { // - If user sets AVX3Threshold=0, then special cases for small blocks sizes operate over // 64 byte vector registers (ZMMs). - address generate_disjoint_copy_avx3_masked(StubGenStubId stub_id, address* entry); + address generate_disjoint_copy_avx3_masked(StubId stub_id, address* entry); - address generate_conjoint_copy_avx3_masked(StubGenStubId stub_id, address* entry, + address generate_conjoint_copy_avx3_masked(StubId stub_id, address* entry, address nooverlap_target); void arraycopy_avx3_special_cases(XMMRegister xmm, KRegister mask, Register from, @@ -230,14 +230,14 @@ class StubGenerator: public StubCodeGenerator { address generate_disjoint_short_copy(address *entry); - address generate_fill(StubGenStubId stub_id); + address generate_fill(StubId stub_id); address generate_conjoint_short_copy(address nooverlap_target, address *entry); - address generate_disjoint_int_oop_copy(StubGenStubId stub_id, address* entry); - address generate_conjoint_int_oop_copy(StubGenStubId stub_id, address nooverlap_target, + address generate_disjoint_int_oop_copy(StubId stub_id, address* entry); + address generate_conjoint_int_oop_copy(StubId stub_id, address nooverlap_target, address *entry); - address generate_disjoint_long_oop_copy(StubGenStubId stub_id, address* entry); - address generate_conjoint_long_oop_copy(StubGenStubId stub_id, address nooverlap_target, + address generate_disjoint_long_oop_copy(StubId stub_id, address* entry); + address generate_conjoint_long_oop_copy(StubId stub_id, address nooverlap_target, address *entry); // Helper for generating a dynamic type check. @@ -248,7 +248,7 @@ class StubGenerator: public StubCodeGenerator { Label& L_success); // Generate checkcasting array copy stub - address generate_checkcast_copy(StubGenStubId stub_id, address *entry); + address generate_checkcast_copy(StubId stub_id, address *entry); // Generate 'unsafe' array copy stub // Though just as safe as the other stubs, it takes an unscaled @@ -294,19 +294,19 @@ class StubGenerator: public StubCodeGenerator { // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.MD5.implCompress(byte[] b, int ofs) - address generate_md5_implCompress(StubGenStubId stub_id); + address generate_md5_implCompress(StubId stub_id); // SHA stubs // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) - address generate_sha1_implCompress(StubGenStubId stub_id); + address generate_sha1_implCompress(StubId stub_id); // ofs and limit are use for multi-block byte array. // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) - address generate_sha256_implCompress(StubGenStubId stub_id); - address generate_sha512_implCompress(StubGenStubId stub_id); + address generate_sha256_implCompress(StubId stub_id); + address generate_sha512_implCompress(StubId stub_id); // Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb. address generate_pshuffle_byte_flip_mask_sha512(); @@ -590,7 +590,7 @@ class StubGenerator: public StubCodeGenerator { void generate_string_indexof(address *fnptrs); #endif - address generate_cont_thaw(StubGenStubId stub_id); + address generate_cont_thaw(StubId stub_id); address generate_cont_thaw(); // TODO: will probably need multiple return barriers depending on return type @@ -644,7 +644,7 @@ class StubGenerator: public StubCodeGenerator { void generate_final_stubs(); public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id); + StubGenerator(CodeBuffer* code, BlobId blob_id); }; #endif // CPU_X86_STUBGENERATOR_X86_64_HPP diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_adler.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_adler.cpp index 8a2aeaa5887..2799997a761 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_adler.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_adler.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2021, 2025, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -66,7 +66,7 @@ address StubGenerator::generate_updateBytesAdler32() { assert(UseAdler32Intrinsics, ""); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesAdler32_id; + StubId stub_id = StubId::stubgen_updateBytesAdler32_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp index 26bf3f7d725..2cd1ed24fcd 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2019, 2025, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -249,7 +249,7 @@ void StubGenerator::generate_aes_stubs() { // rax - number of processed bytes address StubGenerator::generate_galoisCounterMode_AESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::galoisCounterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_galoisCounterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -336,7 +336,7 @@ address StubGenerator::generate_galoisCounterMode_AESCrypt() { // rax - number of processed bytes address StubGenerator::generate_avx2_galoisCounterMode_AESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::galoisCounterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_galoisCounterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -408,7 +408,7 @@ address StubGenerator::generate_avx2_galoisCounterMode_AESCrypt() { // Vector AES Counter implementation address StubGenerator::generate_counterMode_VectorAESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::counterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_counterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -497,7 +497,7 @@ address StubGenerator::generate_counterMode_VectorAESCrypt() { address StubGenerator::generate_counterMode_AESCrypt_Parallel() { assert(UseAES, "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::counterMode_AESCrypt_id; + StubId stub_id = StubId::stubgen_counterMode_AESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -785,7 +785,7 @@ address StubGenerator::generate_counterMode_AESCrypt_Parallel() { address StubGenerator::generate_cipherBlockChaining_decryptVectorAESCrypt() { assert(VM_Version::supports_avx512_vaes(), "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1068,7 +1068,7 @@ address StubGenerator::generate_cipherBlockChaining_decryptVectorAESCrypt() { address StubGenerator::generate_aescrypt_encryptBlock() { assert(UseAES, "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_encryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_encryptBlock_id; StubCodeMark mark(this, stub_id); Label L_doLast; address start = __ pc(); @@ -1163,7 +1163,7 @@ address StubGenerator::generate_aescrypt_encryptBlock() { address StubGenerator::generate_aescrypt_decryptBlock() { assert(UseAES, "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::aescrypt_decryptBlock_id; + StubId stub_id = StubId::stubgen_aescrypt_decryptBlock_id; StubCodeMark mark(this, stub_id); Label L_doLast; address start = __ pc(); @@ -1265,7 +1265,7 @@ address StubGenerator::generate_aescrypt_decryptBlock() { address StubGenerator::generate_cipherBlockChaining_encryptAESCrypt() { assert(UseAES, "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_encryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1417,7 +1417,7 @@ address StubGenerator::generate_cipherBlockChaining_encryptAESCrypt() { address StubGenerator::generate_cipherBlockChaining_decryptAESCrypt_Parallel() { assert(UseAES, "need AES instructions and misaligned SSE support"); __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::cipherBlockChaining_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1660,7 +1660,7 @@ __ opc(xmm_result3, src_reg); \ address StubGenerator::generate_electronicCodeBook_encryptAESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::electronicCodeBook_encryptAESCrypt_id; + StubId stub_id = StubId::stubgen_electronicCodeBook_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -1681,7 +1681,7 @@ address StubGenerator::generate_electronicCodeBook_encryptAESCrypt() { address StubGenerator::generate_electronicCodeBook_decryptAESCrypt() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::electronicCodeBook_decryptAESCrypt_id; + StubId stub_id = StubId::stubgen_electronicCodeBook_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp index 03b4b3ab2a8..36641be776b 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp @@ -90,25 +90,25 @@ void StubGenerator::generate_arraycopy_stubs() { StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(&entry); StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(entry, &entry_jshort_arraycopy); - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(StubGenStubId::jint_disjoint_arraycopy_id, &entry); - StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(StubGenStubId::jint_arraycopy_id, entry, &entry_jint_arraycopy); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(StubId::stubgen_jint_disjoint_arraycopy_id, &entry); + StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(StubId::stubgen_jint_arraycopy_id, entry, &entry_jint_arraycopy); - StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(StubGenStubId::jlong_disjoint_arraycopy_id, &entry); - StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(StubGenStubId::jlong_arraycopy_id, entry, &entry_jlong_arraycopy); + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(StubId::stubgen_jlong_disjoint_arraycopy_id, &entry); + StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(StubId::stubgen_jlong_arraycopy_id, entry, &entry_jlong_arraycopy); if (UseCompressedOops) { - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(StubGenStubId::oop_disjoint_arraycopy_id, &entry); - StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(StubGenStubId::oop_arraycopy_id, entry, &entry_oop_arraycopy); - StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_int_oop_copy(StubGenStubId::oop_disjoint_arraycopy_uninit_id, &entry); - StubRoutines::_oop_arraycopy_uninit = generate_conjoint_int_oop_copy(StubGenStubId::oop_arraycopy_uninit_id, entry, nullptr); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_id, &entry); + StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(StubId::stubgen_oop_arraycopy_id, entry, &entry_oop_arraycopy); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_int_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_uninit_id, &entry); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_int_oop_copy(StubId::stubgen_oop_arraycopy_uninit_id, entry, nullptr); } else { - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(StubGenStubId::oop_disjoint_arraycopy_id, &entry); - StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(StubGenStubId::oop_arraycopy_id, entry, &entry_oop_arraycopy); - StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_long_oop_copy(StubGenStubId::oop_disjoint_arraycopy_uninit_id, &entry); - StubRoutines::_oop_arraycopy_uninit = generate_conjoint_long_oop_copy(StubGenStubId::oop_arraycopy_uninit_id, entry, nullptr); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_id, &entry); + StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(StubId::stubgen_oop_arraycopy_id, entry, &entry_oop_arraycopy); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_long_oop_copy(StubId::stubgen_oop_disjoint_arraycopy_uninit_id, &entry); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_long_oop_copy(StubId::stubgen_oop_arraycopy_uninit_id, entry, nullptr); } - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_id, &entry_checkcast_arraycopy); - StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubGenStubId::checkcast_arraycopy_uninit_id, nullptr); + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id, nullptr); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(entry_jbyte_arraycopy, entry_jshort_arraycopy, @@ -121,12 +121,12 @@ void StubGenerator::generate_arraycopy_stubs() { entry_jlong_arraycopy, entry_checkcast_arraycopy); - StubRoutines::_jbyte_fill = generate_fill(StubGenStubId::jbyte_fill_id); - StubRoutines::_jshort_fill = generate_fill(StubGenStubId::jshort_fill_id); - StubRoutines::_jint_fill = generate_fill(StubGenStubId::jint_fill_id); - StubRoutines::_arrayof_jbyte_fill = generate_fill(StubGenStubId::arrayof_jbyte_fill_id); - StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); - StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); + StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id); + StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id); + StubRoutines::_jint_fill = generate_fill(StubId::stubgen_jint_fill_id); + StubRoutines::_arrayof_jbyte_fill = generate_fill(StubId::stubgen_arrayof_jbyte_fill_id); + StubRoutines::_arrayof_jshort_fill = generate_fill(StubId::stubgen_arrayof_jshort_fill_id); + StubRoutines::_arrayof_jint_fill = generate_fill(StubId::stubgen_arrayof_jint_fill_id); StubRoutines::_unsafe_setmemory = generate_unsafe_setmemory(StubRoutines::_jbyte_fill); @@ -484,7 +484,7 @@ void StubGenerator::copy_bytes_backward(Register from, Register dest, // disjoint_copy_avx3_masked is set to the no-overlap entry point // used by generate_conjoint_[byte/int/short/long]_copy(). // -address StubGenerator::generate_disjoint_copy_avx3_masked(StubGenStubId stub_id, address* entry) { +address StubGenerator::generate_disjoint_copy_avx3_masked(StubId stub_id, address* entry) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; int shift; @@ -492,32 +492,32 @@ address StubGenerator::generate_disjoint_copy_avx3_masked(StubGenStubId stub_id, bool dest_uninitialized; switch (stub_id) { - case jbyte_disjoint_arraycopy_id: + case StubId::stubgen_jbyte_disjoint_arraycopy_id: shift = 0; is_oop = false; dest_uninitialized = false; break; - case jshort_disjoint_arraycopy_id: + case StubId::stubgen_jshort_disjoint_arraycopy_id: shift = 1; is_oop = false; dest_uninitialized = false; break; - case jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: shift = 2; is_oop = false; dest_uninitialized = false; break; - case jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: shift = 3; is_oop = false; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: shift = (UseCompressedOops ? 2 : 3); is_oop = true; dest_uninitialized = false; break; - case oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: shift = (UseCompressedOops ? 2 : 3); is_oop = true; dest_uninitialized = true; @@ -822,7 +822,7 @@ void StubGenerator::arraycopy_avx3_large(Register to, Register from, Register te // c_rarg2 - element count, treated as ssize_t, can be zero // // -address StubGenerator::generate_conjoint_copy_avx3_masked(StubGenStubId stub_id, address* entry, address nooverlap_target) { +address StubGenerator::generate_conjoint_copy_avx3_masked(StubId stub_id, address* entry, address nooverlap_target) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; int shift; @@ -830,32 +830,32 @@ address StubGenerator::generate_conjoint_copy_avx3_masked(StubGenStubId stub_id, bool dest_uninitialized; switch (stub_id) { - case jbyte_arraycopy_id: + case StubId::stubgen_jbyte_arraycopy_id: shift = 0; is_oop = false; dest_uninitialized = false; break; - case jshort_arraycopy_id: + case StubId::stubgen_jshort_arraycopy_id: shift = 1; is_oop = false; dest_uninitialized = false; break; - case jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: shift = 2; is_oop = false; dest_uninitialized = false; break; - case jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: shift = 3; is_oop = false; dest_uninitialized = false; break; - case oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: shift = (UseCompressedOops ? 2 : 3); is_oop = true; dest_uninitialized = false; break; - case oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: shift = (UseCompressedOops ? 2 : 3); is_oop = true; dest_uninitialized = true; @@ -1334,7 +1334,7 @@ void StubGenerator::copy64_avx(Register dst, Register src, Register index, XMMRe // used by generate_conjoint_byte_copy(). // address StubGenerator::generate_disjoint_byte_copy(address* entry) { - StubGenStubId stub_id = StubGenStubId::jbyte_disjoint_arraycopy_id; + StubId stub_id = StubId::stubgen_jbyte_disjoint_arraycopy_id; // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; #if COMPILER2_OR_JVMCI @@ -1452,7 +1452,7 @@ __ BIND(L_exit); // and stored atomically. // address StubGenerator::generate_conjoint_byte_copy(address nooverlap_target, address* entry) { - StubGenStubId stub_id = StubGenStubId::jbyte_arraycopy_id; + StubId stub_id = StubId::stubgen_jbyte_arraycopy_id; // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; #if COMPILER2_OR_JVMCI @@ -1565,7 +1565,7 @@ address StubGenerator::generate_conjoint_byte_copy(address nooverlap_target, add // used by generate_conjoint_short_copy(). // address StubGenerator::generate_disjoint_short_copy(address *entry) { - StubGenStubId stub_id = StubGenStubId::jshort_disjoint_arraycopy_id; + StubId stub_id = StubId::stubgen_jshort_disjoint_arraycopy_id; // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; #if COMPILER2_OR_JVMCI @@ -1662,32 +1662,32 @@ __ BIND(L_exit); } -address StubGenerator::generate_fill(StubGenStubId stub_id) { +address StubGenerator::generate_fill(StubId stub_id) { BasicType t; bool aligned; switch (stub_id) { - case jbyte_fill_id: + case StubId::stubgen_jbyte_fill_id: t = T_BYTE; aligned = false; break; - case jshort_fill_id: + case StubId::stubgen_jshort_fill_id: t = T_SHORT; aligned = false; break; - case jint_fill_id: + case StubId::stubgen_jint_fill_id: t = T_INT; aligned = false; break; - case arrayof_jbyte_fill_id: + case StubId::stubgen_arrayof_jbyte_fill_id: t = T_BYTE; aligned = true; break; - case arrayof_jshort_fill_id: + case StubId::stubgen_arrayof_jshort_fill_id: t = T_SHORT; aligned = true; break; - case arrayof_jint_fill_id: + case StubId::stubgen_arrayof_jint_fill_id: t = T_INT; aligned = true; break; @@ -1737,7 +1737,7 @@ address StubGenerator::generate_fill(StubGenStubId stub_id) { // and stored atomically. // address StubGenerator::generate_conjoint_short_copy(address nooverlap_target, address *entry) { - StubGenStubId stub_id = StubGenStubId::jshort_arraycopy_id; + StubId stub_id = StubId::stubgen_jshort_arraycopy_id; // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; #if COMPILER2_OR_JVMCI @@ -1843,22 +1843,22 @@ address StubGenerator::generate_conjoint_short_copy(address nooverlap_target, ad // disjoint_int_copy_entry is set to the no-overlap entry point // used by generate_conjoint_int_oop_copy(). // -address StubGenerator::generate_disjoint_int_oop_copy(StubGenStubId stub_id, address* entry) { +address StubGenerator::generate_disjoint_int_oop_copy(StubId stub_id, address* entry) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; bool is_oop; bool dest_uninitialized; switch (stub_id) { - case StubGenStubId::jint_disjoint_arraycopy_id: + case StubId::stubgen_jint_disjoint_arraycopy_id: is_oop = false; dest_uninitialized = false; break; - case StubGenStubId::oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: assert(UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = false; break; - case StubGenStubId::oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: assert(UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = true; @@ -1974,22 +1974,22 @@ __ BIND(L_exit); // the hardware handle it. The two dwords within qwords that span // cache line boundaries will still be loaded and stored atomically. // -address StubGenerator::generate_conjoint_int_oop_copy(StubGenStubId stub_id, address nooverlap_target, address *entry) { +address StubGenerator::generate_conjoint_int_oop_copy(StubId stub_id, address nooverlap_target, address *entry) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; bool is_oop; bool dest_uninitialized; switch (stub_id) { - case StubGenStubId::jint_arraycopy_id: + case StubId::stubgen_jint_arraycopy_id: is_oop = false; dest_uninitialized = false; break; - case StubGenStubId::oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: assert(UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = false; break; - case StubGenStubId::oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: assert(UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = true; @@ -2107,22 +2107,22 @@ __ BIND(L_exit); // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the // no-overlap entry point used by generate_conjoint_long_oop_copy(). // -address StubGenerator::generate_disjoint_long_oop_copy(StubGenStubId stub_id, address *entry) { +address StubGenerator::generate_disjoint_long_oop_copy(StubId stub_id, address *entry) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; bool is_oop; bool dest_uninitialized; switch (stub_id) { - case StubGenStubId::jlong_disjoint_arraycopy_id: + case StubId::stubgen_jlong_disjoint_arraycopy_id: is_oop = false; dest_uninitialized = false; break; - case StubGenStubId::oop_disjoint_arraycopy_id: + case StubId::stubgen_oop_disjoint_arraycopy_id: assert(!UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = false; break; - case StubGenStubId::oop_disjoint_arraycopy_uninit_id: + case StubId::stubgen_oop_disjoint_arraycopy_uninit_id: assert(!UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = true; @@ -2240,22 +2240,22 @@ address StubGenerator::generate_disjoint_long_oop_copy(StubGenStubId stub_id, ad // c_rarg1 - destination array address // c_rarg2 - element count, treated as ssize_t, can be zero // -address StubGenerator::generate_conjoint_long_oop_copy(StubGenStubId stub_id, address nooverlap_target, address *entry) { +address StubGenerator::generate_conjoint_long_oop_copy(StubId stub_id, address nooverlap_target, address *entry) { // aligned is always false -- x86_64 always uses the unaligned code const bool aligned = false; bool is_oop; bool dest_uninitialized; switch (stub_id) { - case StubGenStubId::jlong_arraycopy_id: + case StubId::stubgen_jlong_arraycopy_id: is_oop = false; dest_uninitialized = false; break; - case StubGenStubId::oop_arraycopy_id: + case StubId::stubgen_oop_arraycopy_id: assert(!UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = false; break; - case StubGenStubId::oop_arraycopy_uninit_id: + case StubId::stubgen_oop_arraycopy_uninit_id: assert(!UseCompressedOops, "inconsistent oop copy size!"); is_oop = true; dest_uninitialized = true; @@ -2391,14 +2391,14 @@ void StubGenerator::generate_type_check(Register sub_klass, // rax == 0 - success // rax == -1^K - failure, where K is partial transfer count // -address StubGenerator::generate_checkcast_copy(StubGenStubId stub_id, address *entry) { +address StubGenerator::generate_checkcast_copy(StubId stub_id, address *entry) { bool dest_uninitialized; switch (stub_id) { - case StubGenStubId::checkcast_arraycopy_id: + case StubId::stubgen_checkcast_arraycopy_id: dest_uninitialized = false; break; - case StubGenStubId::checkcast_arraycopy_uninit_id: + case StubId::stubgen_checkcast_arraycopy_uninit_id: dest_uninitialized = true; break; default: @@ -2623,7 +2623,7 @@ address StubGenerator::generate_unsafe_copy(address byte_copy_entry, address sho const Register bits = rax; // test copy of low bits __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_arraycopy_id; + StubId stub_id = StubId::stubgen_unsafe_arraycopy_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -2759,7 +2759,7 @@ static void do_setmemory_atomic_loop(USM_TYPE type, Register dest, // address StubGenerator::generate_unsafe_setmemory(address unsafe_byte_fill) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::unsafe_setmemory_id; + StubId stub_id = StubId::stubgen_unsafe_setmemory_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); // required for proper stackwalking of RuntimeStub frame @@ -2929,7 +2929,7 @@ address StubGenerator::generate_generic_copy(address byte_copy_entry, address sh if (advance < 0) advance += modulus; if (advance > 0) __ nop(advance); } - StubGenStubId stub_id = StubGenStubId::generic_arraycopy_id; + StubId stub_id = StubId::stubgen_generic_arraycopy_id; StubCodeMark mark(this, stub_id); // Short-hop target to L_failed. Makes for denser prologue code. diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp index da60a9be276..c35f1b9f65e 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp @@ -46,6 +46,12 @@ // /******************************************************************************/ +/* Represents 0x7FFFFFFFFFFFFFFF double precision in lower 64 bits*/ +ATTRIBUTE_ALIGNED(16) static const juint _ABS_MASK[] = +{ + 4294967295, 2147483647, 0, 0 +}; + ATTRIBUTE_ALIGNED(4) static const juint _SIG_MASK[] = { 0, 1032192 @@ -184,14 +190,14 @@ ATTRIBUTE_ALIGNED(4) static const juint _D_table[] = #define __ _masm-> address StubGenerator::generate_libmCbrt() { - StubGenStubId stub_id = StubGenStubId::dcbrt_id; + StubId stub_id = StubId::stubgen_dcbrt_id; StubCodeMark mark(this, stub_id); address start = __ pc(); - Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1, L_2TAG_PACKET_3_0_1; - Label L_2TAG_PACKET_4_0_1, L_2TAG_PACKET_5_0_1, L_2TAG_PACKET_6_0_1; + Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1; Label B1_1, B1_2, B1_4; + address ABS_MASK = (address)_ABS_MASK; address SIG_MASK = (address)_SIG_MASK; address EXP_MASK = (address)_EXP_MASK; address EXP_MSK2 = (address)_EXP_MSK2; @@ -208,8 +214,12 @@ address StubGenerator::generate_libmCbrt() { __ enter(); // required for proper stackwalking of RuntimeStub frame __ bind(B1_1); - __ subq(rsp, 24); - __ movsd(Address(rsp), xmm0); + __ ucomisd(xmm0, ExternalAddress(ZERON), r11 /*rscratch*/); + __ jcc(Assembler::equal, L_2TAG_PACKET_1_0_1); // Branch only if x is +/- zero or NaN + __ movq(xmm1, xmm0); + __ andpd(xmm1, ExternalAddress(ABS_MASK), r11 /*rscratch*/); + __ ucomisd(xmm1, ExternalAddress(INF), r11 /*rscratch*/); + __ jcc(Assembler::equal, B1_4); // Branch only if x is +/- INF __ bind(B1_2); __ movq(xmm7, xmm0); @@ -228,8 +238,6 @@ address StubGenerator::generate_libmCbrt() { __ andl(rdx, rax); __ cmpl(rdx, 0); __ jcc(Assembler::equal, L_2TAG_PACKET_0_0_1); // Branch only if |x| is denormalized - __ cmpl(rdx, 524032); - __ jcc(Assembler::equal, L_2TAG_PACKET_1_0_1); // Branch only if |x| is INF or NaN __ shrl(rdx, 8); __ shrq(r9, 8); __ andpd(xmm2, xmm0); @@ -297,8 +305,6 @@ address StubGenerator::generate_libmCbrt() { __ andl(rdx, rax); __ shrl(rdx, 8); __ shrq(r9, 8); - __ cmpl(rdx, 0); - __ jcc(Assembler::equal, L_2TAG_PACKET_3_0_1); // Branch only if |x| is zero __ andpd(xmm2, xmm0); __ andpd(xmm0, xmm5); __ orpd(xmm3, xmm2); @@ -322,41 +328,10 @@ address StubGenerator::generate_libmCbrt() { __ psllq(xmm7, 52); __ jmp(L_2TAG_PACKET_2_0_1); - __ bind(L_2TAG_PACKET_3_0_1); - __ cmpq(r9, 0); - __ jcc(Assembler::notEqual, L_2TAG_PACKET_4_0_1); // Branch only if x is negative zero - __ xorpd(xmm0, xmm0); - __ jmp(B1_4); - - __ bind(L_2TAG_PACKET_4_0_1); - __ movsd(xmm0, ExternalAddress(ZERON), r11 /*rscratch*/); - __ jmp(B1_4); - __ bind(L_2TAG_PACKET_1_0_1); - __ movl(rax, Address(rsp, 4)); - __ movl(rdx, Address(rsp)); - __ movl(rcx, rax); - __ andl(rcx, 2147483647); - __ cmpl(rcx, 2146435072); - __ jcc(Assembler::above, L_2TAG_PACKET_5_0_1); // Branch only if |x| is NaN - __ cmpl(rdx, 0); - __ jcc(Assembler::notEqual, L_2TAG_PACKET_5_0_1); // Branch only if |x| is NaN - __ cmpl(rax, 2146435072); - __ jcc(Assembler::notEqual, L_2TAG_PACKET_6_0_1); // Branch only if x is negative INF - __ movsd(xmm0, ExternalAddress(INF), r11 /*rscratch*/); - __ jmp(B1_4); - - __ bind(L_2TAG_PACKET_6_0_1); - __ movsd(xmm0, ExternalAddress(NEG_INF), r11 /*rscratch*/); - __ jmp(B1_4); - - __ bind(L_2TAG_PACKET_5_0_1); - __ movsd(xmm0, Address(rsp)); __ addsd(xmm0, xmm0); - __ movq(Address(rsp, 8), xmm0); __ bind(B1_4); - __ addq(rsp, 24); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_chacha.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_chacha.cpp index f7fb4024077..7afaf34e031 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_chacha.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_chacha.cpp @@ -112,7 +112,7 @@ void StubGenerator::generate_chacha_stubs() { /* The 2-block AVX/AVX2-enabled ChaCha20 block function implementation */ address StubGenerator::generate_chacha20Block_avx() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::chacha20Block_id; + StubId stub_id = StubId::stubgen_chacha20Block_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -301,7 +301,7 @@ address StubGenerator::generate_chacha20Block_avx() { /* The 4-block AVX512-enabled ChaCha20 block function implementation */ address StubGenerator::generate_chacha20Block_avx512() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::chacha20Block_id; + StubId stub_id = StubId::stubgen_chacha20Block_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_cos.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_cos.cpp index 3f037a919d7..67017e7559a 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_cos.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_cos.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -173,7 +173,7 @@ #define __ _masm-> address StubGenerator::generate_libmCos() { - StubGenStubId stub_id = StubGenStubId::dcos_id; + StubId stub_id = StubId::stubgen_dcos_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp index 7121db2ab91..9555d60c8a4 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp @@ -274,7 +274,7 @@ static address generate_dilithiumAlmostNtt_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = dilithiumAlmostNtt_id; + StubId stub_id = StubId::stubgen_dilithiumAlmostNtt_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -464,7 +464,7 @@ static address generate_dilithiumAlmostInverseNtt_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = dilithiumAlmostInverseNtt_id; + StubId stub_id = StubId::stubgen_dilithiumAlmostInverseNtt_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -645,7 +645,7 @@ static address generate_dilithiumNttMult_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = dilithiumNttMult_id; + StubId stub_id = StubId::stubgen_dilithiumNttMult_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -709,7 +709,7 @@ static address generate_dilithiumMontMulByConstant_avx512(StubGenerator *stubgen MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = dilithiumMontMulByConstant_id; + StubId stub_id = StubId::stubgen_dilithiumMontMulByConstant_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -773,7 +773,7 @@ static address generate_dilithiumDecomposePoly_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = dilithiumDecomposePoly_id; + StubId stub_id = StubId::stubgen_dilithiumDecomposePoly_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp index b48ed80788b..299a37b88fd 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_exp.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * Intel Math Library (LIBM) Source Code * @@ -165,7 +165,7 @@ ATTRIBUTE_ALIGNED(4) static const juint _INF[] = #define __ _masm-> address StubGenerator::generate_libmExp() { - StubGenStubId stub_id = StubGenStubId::dexp_id; + StubId stub_id = StubId::stubgen_dexp_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_fmod.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_fmod.cpp index 958f65c883a..b1eaa4b8031 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_fmod.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_fmod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2023, 2025, Intel Corporation. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -73,7 +73,7 @@ ATTRIBUTE_ALIGNED(32) static const uint64_t CONST_e307[] = { address StubGenerator::generate_libmFmod() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::fmod_id; + StubId stub_id = StubId::stubgen_fmod_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); // required for proper stackwalking of RuntimeStub frame diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_ghash.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_ghash.cpp index 6d1f9fbd5a1..37485bac1d1 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_ghash.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_ghash.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2019, 2025, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -82,7 +82,7 @@ void StubGenerator::generate_ghash_stubs() { address StubGenerator::generate_ghash_processBlocks() { __ align(CodeEntryAlignment); Label L_ghash_loop, L_exit; - StubGenStubId stub_id = StubGenStubId::ghash_processBlocks_id; + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -219,7 +219,7 @@ address StubGenerator::generate_ghash_processBlocks() { address StubGenerator::generate_avx_ghash_processBlocks() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::ghash_processBlocks_id; + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_kyber.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_kyber.cpp index 91c005e92de..6e0af2563fa 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_kyber.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_kyber.cpp @@ -368,7 +368,7 @@ static int xmm29_29[] = {29, 29, 29, 29}; address generate_kyberNtt_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberNtt_id; + StubId stub_id = StubId::stubgen_kyberNtt_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -465,7 +465,7 @@ address generate_kyberInverseNtt_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberInverseNtt_id; + StubId stub_id = StubId::stubgen_kyberInverseNtt_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -590,7 +590,7 @@ address generate_kyberNttMult_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberNttMult_id; + StubId stub_id = StubId::stubgen_kyberNttMult_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -710,7 +710,7 @@ address generate_kyberAddPoly_2_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberAddPoly_2_id; + StubId stub_id = StubId::stubgen_kyberAddPoly_2_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -756,7 +756,7 @@ address generate_kyberAddPoly_3_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberAddPoly_3_id; + StubId stub_id = StubId::stubgen_kyberAddPoly_3_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -810,7 +810,7 @@ address generate_kyber12To16_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyber12To16_id; + StubId stub_id = StubId::stubgen_kyber12To16_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); @@ -907,7 +907,7 @@ address generate_kyberBarrettReduce_avx512(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = kyberBarrettReduce_id; + StubId stub_id = StubId::stubgen_kyberBarrettReduce_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); __ enter(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp index 6aacfaaea03..8665aec5903 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_log.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * Intel Math Library (LIBM) Source Code * @@ -176,7 +176,7 @@ ATTRIBUTE_ALIGNED(16) static const juint _coeff[] = #define __ _masm-> address StubGenerator::generate_libmLog() { - StubGenStubId stub_id = StubGenStubId::dlog_id; + StubId stub_id = StubId::stubgen_dlog_id; StubCodeMark mark(this, stub_id); address start = __ pc(); @@ -515,7 +515,7 @@ ATTRIBUTE_ALIGNED(16) static const juint _coeff_log10[] = }; address StubGenerator::generate_libmLog10() { - StubGenStubId stub_id = StubGenStubId::dlog10_id; + StubId stub_id = StubId::stubgen_dlog10_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly1305.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly1305.cpp index dfd4ca21dbd..461422b8afd 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly1305.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly1305.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2022, 2025, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -910,7 +910,7 @@ void StubGenerator::poly1305_process_blocks_avx512( // and accumulator will point to the current accumulator value address StubGenerator::generate_poly1305_processBlocks() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::poly1305_processBlocks_id; + StubId stub_id = StubId::stubgen_poly1305_processBlocks_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp index d142414be5e..d0ac050dbf9 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp @@ -559,7 +559,7 @@ void montgomeryMultiplyAVX2(const Register aLimbs, const Register bLimbs, const address StubGenerator::generate_intpoly_montgomeryMult_P256() { __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::intpoly_montgomeryMult_P256_id; + StubId stub_id = StubId::stubgen_intpoly_montgomeryMult_P256_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); @@ -681,7 +681,7 @@ address StubGenerator::generate_intpoly_assign() { // Special Cases 5, 10, 14, 16, 19 __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::intpoly_assign_id; + StubId stub_id = StubId::stubgen_intpoly_assign_id; StubCodeMark mark(this, stub_id); address start = __ pc(); __ enter(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp index 4029e53d1b1..22ac8059458 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_pow.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * Intel Math Library (LIBM) Source Code * @@ -759,7 +759,7 @@ ATTRIBUTE_ALIGNED(8) static const juint _DOUBLE0DOT5[] = { #define __ _masm-> address StubGenerator::generate_libmPow() { - StubGenStubId stub_id = StubGenStubId::dpow_id; + StubId stub_id = StubId::stubgen_dpow_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp index 9f13233f1d2..1e245952118 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp @@ -90,15 +90,15 @@ static address permsAndRotsAddr() { // c_rarg3 - int offset // c_rarg4 - int limit // -static address generate_sha3_implCompress(StubGenStubId stub_id, +static address generate_sha3_implCompress(StubId stub_id, StubGenerator *stubgen, MacroAssembler *_masm) { bool multiBlock; switch(stub_id) { - case sha3_implCompress_id: + case StubId::stubgen_sha3_implCompress_id: multiBlock = false; break; - case sha3_implCompressMB_id: + case StubId::stubgen_sha3_implCompressMB_id: multiBlock = true; break; default: @@ -327,7 +327,7 @@ static address generate_sha3_implCompress(StubGenStubId stub_id, // two computations are executed interleaved. static address generate_double_keccak(StubGenerator *stubgen, MacroAssembler *_masm) { __ align(CodeEntryAlignment); - StubGenStubId stub_id = double_keccak_id; + StubId stub_id = StubId::stubgen_double_keccak_id; StubCodeMark mark(stubgen, stub_id); address start = __ pc(); @@ -501,10 +501,10 @@ static address generate_double_keccak(StubGenerator *stubgen, MacroAssembler *_m void StubGenerator::generate_sha3_stubs() { if (UseSHA3Intrinsics) { StubRoutines::_sha3_implCompress = - generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id, this, _masm); + generate_sha3_implCompress(StubId::stubgen_sha3_implCompress_id, this, _masm); StubRoutines::_double_keccak = generate_double_keccak(this, _masm); StubRoutines::_sha3_implCompressMB = - generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id, this, _masm); + generate_sha3_implCompress(StubId::stubgen_sha3_implCompressMB_id, this, _masm); } } diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_sin.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_sin.cpp index 362eeb95e41..67ac2fa6b87 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_sin.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_sin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. + * Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -180,7 +180,7 @@ ATTRIBUTE_ALIGNED(8) static const juint _ALL_ONES[] = #define __ _masm-> address StubGenerator::generate_libmSin() { - StubGenStubId stub_id = StubGenStubId::dsin_id; + StubId stub_id = StubId::stubgen_dsin_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_tan.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_tan.cpp index 46cb0801a81..f73885b18c2 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_tan.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_tan.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, 2024, Intel Corporation. All rights reserved. +* Copyright (c) 2016, 2025, Intel Corporation. All rights reserved. * Intel Math Library (LIBM) Source Code * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -455,7 +455,7 @@ ATTRIBUTE_ALIGNED(8) static const juint _QQ_2_tan[] = #define __ _masm-> address StubGenerator::generate_libmTan() { - StubGenStubId stub_id = StubGenStubId::dtan_id; + StubId stub_id = StubId::stubgen_dtan_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp index 52ce2731b1f..372c4898f37 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp @@ -302,7 +302,7 @@ ATTRIBUTE_ALIGNED(16) static const juint _T2_neg_f[] = #define __ _masm-> address StubGenerator::generate_libmTanh() { - StubGenStubId stub_id = StubGenStubId::dtanh_id; + StubId stub_id = StubId::stubgen_dtanh_id; StubCodeMark mark(this, stub_id); address start = __ pc(); diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 778d61868cf..bb7dc038d30 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -2678,25 +2678,11 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr } else { if (is_static) { __ load_heap_oop(rax, field); - Label is_null_free_inline_type, uninitialized; - // Issue below if the static field has not been initialized yet - __ test_field_is_null_free_inline_type(flags, rscratch1, is_null_free_inline_type); - // field is not a null free inline type - __ push(atos); - __ jmp(Done); - // field is a null free inline type, must not return null even if uninitialized - __ bind(is_null_free_inline_type); - __ testptr(rax, rax); - __ jcc(Assembler::zero, uninitialized); - __ push(atos); - __ jmp(Done); - __ bind(uninitialized); - __ jump(RuntimeAddress(Interpreter::_throw_NPE_UninitializedField_entry)); + __ push(atos); + __ jmp(Done); } else { - Label is_flat, nonnull, is_null_free_inline_type, rewrite_inline, has_null_marker; - __ test_field_is_null_free_inline_type(flags, rscratch1, is_null_free_inline_type); - __ test_field_has_null_marker(flags, rscratch1, has_null_marker); - // field is not a null free inline type + Label is_flat, rewrite_inline; + __ test_field_is_flat(flags, rscratch1, is_flat); pop_and_check_object(obj); __ load_heap_oop(rax, field); __ push(atos); @@ -2704,35 +2690,17 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); } __ jmp(Done); - __ bind(is_null_free_inline_type); - __ test_field_is_flat(flags, rscratch1, is_flat); - // field is not flat - pop_and_check_object(obj); - __ load_heap_oop(rax, field); - __ testptr(rax, rax); - __ jcc(Assembler::notZero, nonnull); - __ jump(RuntimeAddress(Interpreter::_throw_NPE_UninitializedField_entry)); - __ bind(nonnull); - __ verify_oop(rax); - __ push(atos); - __ jmp(rewrite_inline); - __ bind(is_flat); - pop_and_check_object(rax); - __ read_flat_field(rcx, rdx, rbx, rax); - __ verify_oop(rax); - __ push(atos); - __ jmp(rewrite_inline); - __ bind(has_null_marker); - pop_and_check_object(rax); - __ load_field_entry(rcx, rbx); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), rax, rcx); - __ get_vm_result_oop(rax); - __ push(atos); + __ bind(is_flat); + // field is flat (null-free or nullable with a null-marker) + pop_and_check_object(rax); + __ read_flat_field(rcx, rdx, rbx, rax); + __ verify_oop(rax); + __ push(atos); __ bind(rewrite_inline); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_vgetfield, bc, rbx); } - __ jmp(Done); + __ jmp(Done); } } @@ -2989,51 +2957,32 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri } else { __ pop(atos); if (is_static) { - Label is_inline_type; - __ test_field_is_not_null_free_inline_type(flags, rscratch1, is_inline_type); - __ null_check(rax); - __ bind(is_inline_type); + Label is_nullable; + __ test_field_is_not_null_free_inline_type(flags, rscratch1, is_nullable); + __ null_check(rax); // FIXME JDK-8341120 + __ bind(is_nullable); do_oop_store(_masm, field, rax); __ jmp(Done); } else { - Label is_null_free_inline_type, is_flat, has_null_marker, - write_null, rewrite_not_inline, rewrite_inline; - __ test_field_is_null_free_inline_type(flags, rscratch1, is_null_free_inline_type); - __ test_field_has_null_marker(flags, rscratch1, has_null_marker); - // Not an inline type - pop_and_check_object(obj); - // Store into the field - do_oop_store(_masm, field, rax); - __ bind(rewrite_not_inline); - if (rc == may_rewrite) { - patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no); - } - __ jmp(Done); - // Implementation of the inline type semantic - __ bind(is_null_free_inline_type); - __ null_check(rax); - __ test_field_is_flat(flags, rscratch1, is_flat); - // field is not flat - pop_and_check_object(obj); - // Store into the field - do_oop_store(_masm, field, rax); - __ jmp(rewrite_inline); - __ bind(is_flat); - // field is flat - __ load_unsigned_short(rdx, Address(rcx, in_bytes(ResolvedFieldEntry::field_index_offset()))); - __ movptr(r9, Address(rcx, in_bytes(ResolvedFieldEntry::field_holder_offset()))); - pop_and_check_object(obj); // obj = rcx - __ load_klass(r8, rax, rscratch1); - __ payload_addr(rax, rax, r8); - __ addptr(obj, off); - __ inline_layout_info(r9, rdx, rbx); - // because we use InlineLayoutInfo, we need special value access code specialized for fields (arrays will need a different API) - __ flat_field_copy(IN_HEAP, rax, obj, rbx); - __ jmp(rewrite_inline); - __ bind(has_null_marker); // has null marker means the field is flat with a null marker - pop_and_check_object(rbx); - __ load_field_entry(rcx, rdx); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), rbx, rax, rcx); + Label is_flat, null_free_reference, rewrite_inline; + __ test_field_is_flat(flags, rscratch1, is_flat); + __ test_field_is_null_free_inline_type(flags, rscratch1, null_free_reference); + pop_and_check_object(obj); + // Store into the field + do_oop_store(_masm, field, rax); + if (rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + __ bind(null_free_reference); + __ null_check(rax); // FIXME JDK-8341120 + pop_and_check_object(obj); + // Store into the field + do_oop_store(_masm, field, rax); + __ jmp(rewrite_inline); + __ bind(is_flat); + pop_and_check_object(rscratch2); + __ write_flat_field(rcx, r8, rscratch1, rscratch2, rbx, rax); __ bind(rewrite_inline); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_vputfield, bc, rbx, true, byte_no); @@ -3261,28 +3210,16 @@ void TemplateTable::fast_storefield_helper(Address field, Register rax, Register switch (bytecode()) { case Bytecodes::_fast_vputfield: { - Label is_flat, has_null_marker, write_null, done; - __ test_field_has_null_marker(flags, rscratch1, has_null_marker); - // Null free field cases: flat or not flat - __ null_check(rax); + // Field is either flat (nullable or not) or non-flat and null-free + Label is_flat, done; __ test_field_is_flat(flags, rscratch1, is_flat); - // field is not flat - do_oop_store(_masm, field, rax); - __ jmp(done); + __ null_check(rax); // FIXME JDK-8341120 + do_oop_store(_masm, field, rax); + __ jmp(done); __ bind(is_flat); - __ load_field_entry(r8, r9); - __ load_unsigned_short(r9, Address(r8, in_bytes(ResolvedFieldEntry::field_index_offset()))); - __ movptr(r8, Address(r8, in_bytes(ResolvedFieldEntry::field_holder_offset()))); - __ inline_layout_info(r8, r9, r8); - __ load_klass(rdx, rax, rscratch1); - __ payload_addr(rax, rax, rdx); - __ lea(rcx, field); - __ flat_field_copy(IN_HEAP, rax, rcx, r8); - __ jmp(done); - __ bind(has_null_marker); // has null marker means the field is flat with a null marker - __ movptr(rbx, rcx); - __ load_field_entry(rcx, rdx); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), rbx, rax, rcx); + __ load_field_entry(r8, r9); + __ movptr(rscratch2, rcx); // re-shuffle registers because of VM call calling convention + __ write_flat_field(r8, rscratch1, r9, rscratch2, rbx, rax); __ bind(done); } break; @@ -3355,30 +3292,8 @@ void TemplateTable::fast_accessfield(TosState state) { // access field switch (bytecode()) { case Bytecodes::_fast_vgetfield: - { - Label is_flat, nonnull, Done, has_null_marker; - __ load_unsigned_byte(rscratch1, Address(rcx, in_bytes(ResolvedFieldEntry::flags_offset()))); - __ test_field_has_null_marker(rscratch1, rscratch2, has_null_marker); - __ test_field_is_flat(rscratch1, rscratch2, is_flat); - // field is not flat - __ load_heap_oop(rax, field); - __ testptr(rax, rax); - __ jcc(Assembler::notZero, nonnull); - __ jump(RuntimeAddress(Interpreter::_throw_NPE_UninitializedField_entry)); - __ bind(nonnull); - __ verify_oop(rax); - __ jmp(Done); - __ bind(is_flat); - // field is flat - __ read_flat_field(rcx, rdx, rbx, rax); - __ jmp(Done); - __ bind(has_null_marker); - // rax = instance, rcx = resolved entry - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), rax, rcx); - __ get_vm_result_oop(rax); - __ bind(Done); - __ verify_oop(rax); - } + __ read_flat_field(rcx, rdx, rbx, rax); + __ verify_oop(rax); break; case Bytecodes::_fast_agetfield: do_oop_load(_masm, field, rax); diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index ab1fcdf03a5..0276e7560b4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -440,7 +440,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits apx_f __ jcc(Assembler::equal, vector_save_restore); -#ifndef PRODUCT bool save_apx = UseAPX; VM_Version::set_apx_cpuFeatures(); UseAPX = true; @@ -457,7 +456,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movq(Address(rsi, 8), r31); UseAPX = save_apx; -#endif __ bind(vector_save_restore); // // Check if OS has enabled XGETBV instruction to access XCR0 @@ -1022,8 +1020,6 @@ void VM_Version::get_processor_features() { if (UseAPX && !apx_supported) { warning("UseAPX is not supported on this CPU, setting it to false"); FLAG_SET_DEFAULT(UseAPX, false); - } else if (FLAG_IS_DEFAULT(UseAPX)) { - FLAG_SET_DEFAULT(UseAPX, apx_supported ? true : false); } if (!UseAPX) { @@ -1481,16 +1477,6 @@ void VM_Version::get_processor_features() { UseUnalignedLoadStores = true; // use movdqu on newest ZX cpus } } - if (supports_sse4_2()) { - if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { - FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); - } - } else { - if (UseSSE42Intrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) { - warning("SSE4.2 intrinsics require SSE4.2 instructions or higher. Intrinsics will be disabled."); - } - FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); - } } if (FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) { @@ -1535,16 +1521,6 @@ void VM_Version::get_processor_features() { UseXmmI2D = false; } } - if (supports_sse4_2()) { - if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { - FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); - } - } else { - if (UseSSE42Intrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) { - warning("SSE4.2 intrinsics require SSE4.2 instructions or higher. Intrinsics will be disabled."); - } - FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); - } // some defaults for AMD family 15h if (cpu_family() == 0x15) { @@ -1633,16 +1609,6 @@ void VM_Version::get_processor_features() { UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus } } - if (supports_sse4_2()) { - if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { - FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); - } - } else { - if (UseSSE42Intrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) { - warning("SSE4.2 intrinsics require SSE4.2 instructions or higher. Intrinsics will be disabled."); - } - FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); - } } if (is_atom_family() || is_knights_family()) { #ifdef COMPILER2 @@ -1703,7 +1669,16 @@ void VM_Version::get_processor_features() { } } #endif - + if (supports_sse4_2()) { + if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { + FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); + } + } else { + if (UseSSE42Intrinsics && !FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { + warning("SSE4.2 intrinsics require SSE4.2 instructions or higher. Intrinsics will be disabled."); + } + FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); + } if (UseSSE42Intrinsics) { if (FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) { UseVectorizedMismatchIntrinsic = true; @@ -3151,17 +3126,11 @@ bool VM_Version::os_supports_apx_egprs() { if (!supports_apx_f()) { return false; } - // Enable APX support for product builds after - // completion of planned features listed in JDK-8329030. -#if !defined(PRODUCT) if (_cpuid_info.apx_save[0] != egpr_test_value() || _cpuid_info.apx_save[1] != egpr_test_value()) { return false; } return true; -#else - return false; -#endif } uint VM_Version::cores_per_cpu() { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index e9f3c06f4c9..81e92a9889b 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2024,7 +2024,7 @@ bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType if (is_subword_type(bt) && !VM_Version::supports_avx512bw()) { return false; // Implementation limitation } - if (is_floating_point_type(bt)) { + if (is_floating_point_type(bt) && !VM_Version::supports_avx10_2()) { return false; // Implementation limitation } return true; @@ -4056,24 +4056,24 @@ instruct evgather_masked(vec dst, memory mem, vec idx, kReg mask, kReg ktmp, rRe ins_pipe( pipe_slow ); %} -instruct vgather_subwordLE8B(vec dst, memory mem, rRegP idx_base, immI_0 offset, rRegP tmp, rRegI rtmp) %{ +instruct vgather_subwordLE8B(vec dst, memory mem, rRegP idx_base, rRegP tmp, rRegI rtmp) %{ predicate(is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGather mem (Binary idx_base offset))); + match(Set dst (LoadVectorGather mem idx_base)); effect(TEMP tmp, TEMP rtmp); format %{ "vector_gatherLE8 $dst, $mem, $idx_base\t! using $tmp and $rtmp as TEMP" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); BasicType elem_bt = Matcher::vector_element_basic_type(this); __ lea($tmp$$Register, $mem$$Address); - __ vgather8b_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, noreg, $rtmp$$Register, vlen_enc); + __ vgather8b(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $rtmp$$Register, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vgather_subwordGT8B(vec dst, memory mem, rRegP idx_base, immI_0 offset, rRegP tmp, rRegP idx_base_temp, +instruct vgather_subwordGT8B(vec dst, memory mem, rRegP idx_base, rRegP tmp, rRegP idx_base_temp, vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegI length, rFlagsReg cr) %{ predicate(is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGather mem (Binary idx_base offset))); + match(Set dst (LoadVectorGather mem idx_base)); effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP length, KILL cr); format %{ "vector_gatherGT8 $dst, $mem, $idx_base\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp and $length as TEMP" %} ins_encode %{ @@ -4082,49 +4082,15 @@ instruct vgather_subwordGT8B(vec dst, memory mem, rRegP idx_base, immI_0 offset, BasicType elem_bt = Matcher::vector_element_basic_type(this); __ lea($tmp$$Register, $mem$$Address); __ movptr($idx_base_temp$$Register, $idx_base$$Register); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, noreg, noreg, $xtmp1$$XMMRegister, + __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, noreg, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, noreg, $length$$Register, vector_len, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vgather_subwordLE8B_off(vec dst, memory mem, rRegP idx_base, rRegI offset, rRegP tmp, rRegI rtmp, rFlagsReg cr) %{ - predicate(is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGather mem (Binary idx_base offset))); - effect(TEMP tmp, TEMP rtmp, KILL cr); - format %{ "vector_gatherLE8_off $dst, $mem, $idx_base, $offset\t! using $tmp and $rtmp as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ lea($tmp$$Register, $mem$$Address); - __ vgather8b_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $offset$$Register, $rtmp$$Register, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - - -instruct vgather_subwordGT8B_off(vec dst, memory mem, rRegP idx_base, rRegI offset, rRegP tmp, rRegP idx_base_temp, - vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegI length, rFlagsReg cr) %{ - predicate(is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGather mem (Binary idx_base offset))); - effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP length, KILL cr); - format %{ "vector_gatherGT8_off $dst, $mem, $idx_base, $offset\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp and $length as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - int vector_len = Matcher::vector_length(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ lea($tmp$$Register, $mem$$Address); - __ movptr($idx_base_temp$$Register, $idx_base$$Register); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, $offset$$Register, noreg, $xtmp1$$XMMRegister, - $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, noreg, $length$$Register, vector_len, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - - -instruct vgather_masked_subwordLE8B_avx3(vec dst, memory mem, rRegP idx_base, immI_0 offset, kReg mask, rRegL mask_idx, rRegP tmp, rRegI rtmp, rRegL rtmp2, rFlagsReg cr) %{ +instruct vgather_masked_subwordLE8B_avx3(vec dst, memory mem, rRegP idx_base, kReg mask, rRegL mask_idx, rRegP tmp, rRegI rtmp, rRegL rtmp2, rFlagsReg cr) %{ predicate(VM_Version::supports_avx512bw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); + match(Set dst (LoadVectorGatherMasked mem (Binary idx_base mask))); effect(TEMP mask_idx, TEMP tmp, TEMP rtmp, TEMP rtmp2, KILL cr); format %{ "vector_masked_gatherLE8 $dst, $mem, $idx_base, $mask\t! using $mask_idx, $tmp, $rtmp and $rtmp2 as TEMP" %} ins_encode %{ @@ -4133,15 +4099,15 @@ instruct vgather_masked_subwordLE8B_avx3(vec dst, memory mem, rRegP idx_base, im __ xorq($mask_idx$$Register, $mask_idx$$Register); __ lea($tmp$$Register, $mem$$Address); __ kmovql($rtmp2$$Register, $mask$$KRegister); - __ vgather8b_masked_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, noreg, $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); + __ vgather8b_masked(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vgather_masked_subwordGT8B_avx3(vec dst, memory mem, rRegP idx_base, immI_0 offset, kReg mask, rRegP tmp, rRegP idx_base_temp, +instruct vgather_masked_subwordGT8B_avx3(vec dst, memory mem, rRegP idx_base, kReg mask, rRegP tmp, rRegP idx_base_temp, vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegL rtmp2, rRegL mask_idx, rRegI length, rFlagsReg cr) %{ predicate(VM_Version::supports_avx512bw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); + match(Set dst (LoadVectorGatherMasked mem (Binary idx_base mask))); effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP rtmp2, TEMP mask_idx, TEMP length, KILL cr); format %{ "vector_gatherGT8_masked $dst, $mem, $idx_base, $mask\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp, $rtmp2, $mask_idx and $length as TEMP" %} ins_encode %{ @@ -4152,52 +4118,15 @@ instruct vgather_masked_subwordGT8B_avx3(vec dst, memory mem, rRegP idx_base, im __ lea($tmp$$Register, $mem$$Address); __ movptr($idx_base_temp$$Register, $idx_base$$Register); __ kmovql($rtmp2$$Register, $mask$$KRegister); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, noreg, $rtmp2$$Register, $xtmp1$$XMMRegister, - $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, $mask_idx$$Register, $length$$Register, vector_len, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - -instruct vgather_masked_subwordLE8B_off_avx3(vec dst, memory mem, rRegP idx_base, rRegI offset, kReg mask, rRegL mask_idx, rRegP tmp, rRegI rtmp, rRegL rtmp2, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); - effect(TEMP mask_idx, TEMP tmp, TEMP rtmp, TEMP rtmp2, KILL cr); - format %{ "vector_masked_gatherLE8_off $dst, $mem, $idx_base, $offset, $mask\t! using $mask_idx, $tmp, $rtmp and $rtmp2 as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ xorq($mask_idx$$Register, $mask_idx$$Register); - __ lea($tmp$$Register, $mem$$Address); - __ kmovql($rtmp2$$Register, $mask$$KRegister); - __ vgather8b_masked_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $offset$$Register, - $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - -instruct vgather_masked_subwordGT8B_off_avx3(vec dst, memory mem, rRegP idx_base, rRegI offset, kReg mask, rRegP tmp, rRegP idx_base_temp, - vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegL rtmp2, rRegL mask_idx, rRegI length, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); - effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP rtmp2, TEMP mask_idx, TEMP length, KILL cr); - format %{ "vector_gatherGT8_masked_off $dst, $mem, $idx_base, $offset, $mask\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp, $rtmp2, $mask_idx and $length as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - int vector_len = Matcher::vector_length(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ xorq($mask_idx$$Register, $mask_idx$$Register); - __ lea($tmp$$Register, $mem$$Address); - __ movptr($idx_base_temp$$Register, $idx_base$$Register); - __ kmovql($rtmp2$$Register, $mask$$KRegister); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, $offset$$Register, $rtmp2$$Register, $xtmp1$$XMMRegister, + __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, $rtmp2$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, $mask_idx$$Register, $length$$Register, vector_len, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vgather_masked_subwordLE8B_avx2(vec dst, memory mem, rRegP idx_base, immI_0 offset, vec mask, rRegI mask_idx, rRegP tmp, rRegI rtmp, rRegI rtmp2, rFlagsReg cr) %{ +instruct vgather_masked_subwordLE8B_avx2(vec dst, memory mem, rRegP idx_base, vec mask, rRegI mask_idx, rRegP tmp, rRegI rtmp, rRegI rtmp2, rFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vlbw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); + match(Set dst (LoadVectorGatherMasked mem (Binary idx_base mask))); effect(TEMP mask_idx, TEMP tmp, TEMP rtmp, TEMP rtmp2, KILL cr); format %{ "vector_masked_gatherLE8 $dst, $mem, $idx_base, $mask\t! using $mask_idx, $tmp, $rtmp and $rtmp2 as TEMP" %} ins_encode %{ @@ -4210,15 +4139,15 @@ instruct vgather_masked_subwordLE8B_avx2(vec dst, memory mem, rRegP idx_base, im __ pextl($rtmp2$$Register, $rtmp2$$Register, $mask_idx$$Register); } __ xorl($mask_idx$$Register, $mask_idx$$Register); - __ vgather8b_masked_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, noreg, $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); + __ vgather8b_masked(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vgather_masked_subwordGT8B_avx2(vec dst, memory mem, rRegP idx_base, immI_0 offset, vec mask, rRegP tmp, rRegP idx_base_temp, +instruct vgather_masked_subwordGT8B_avx2(vec dst, memory mem, rRegP idx_base, vec mask, rRegP tmp, rRegP idx_base_temp, vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegI rtmp2, rRegI mask_idx, rRegI length, rFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vlbw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); + match(Set dst (LoadVectorGatherMasked mem (Binary idx_base mask))); effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP rtmp2, TEMP mask_idx, TEMP length, KILL cr); format %{ "vector_gatherGT8_masked $dst, $mem, $idx_base, $mask\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp, $rtmp2, $mask_idx and $length as TEMP" %} ins_encode %{ @@ -4233,53 +4162,7 @@ instruct vgather_masked_subwordGT8B_avx2(vec dst, memory mem, rRegP idx_base, im __ pextl($rtmp2$$Register, $rtmp2$$Register, $mask_idx$$Register); } __ xorl($mask_idx$$Register, $mask_idx$$Register); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, noreg, $rtmp2$$Register, $xtmp1$$XMMRegister, - $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, $mask_idx$$Register, $length$$Register, vector_len, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - -instruct vgather_masked_subwordLE8B_off_avx2(vec dst, memory mem, rRegP idx_base, rRegI offset, vec mask, rRegI mask_idx, rRegP tmp, rRegI rtmp, rRegI rtmp2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512vlbw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); - effect(TEMP mask_idx, TEMP tmp, TEMP rtmp, TEMP rtmp2, KILL cr); - format %{ "vector_masked_gatherLE8_off $dst, $mem, $idx_base, $offset, $mask\t! using $mask_idx, $tmp, $rtmp and $rtmp2 as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ lea($tmp$$Register, $mem$$Address); - __ vpmovmskb($rtmp2$$Register, $mask$$XMMRegister, vlen_enc); - if (elem_bt == T_SHORT) { - __ movl($mask_idx$$Register, 0x55555555); - __ pextl($rtmp2$$Register, $rtmp2$$Register, $mask_idx$$Register); - } - __ xorl($mask_idx$$Register, $mask_idx$$Register); - __ vgather8b_masked_offset(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base$$Register, $offset$$Register, - $rtmp2$$Register, $mask_idx$$Register, $rtmp$$Register, vlen_enc); - %} - ins_pipe( pipe_slow ); -%} - -instruct vgather_masked_subwordGT8B_off_avx2(vec dst, memory mem, rRegP idx_base, rRegI offset, vec mask, rRegP tmp, rRegP idx_base_temp, - vec xtmp1, vec xtmp2, vec xtmp3, rRegI rtmp, rRegI rtmp2, rRegI mask_idx, rRegI length, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512vlbw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) > 8); - match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); - effect(TEMP_DEF dst, TEMP tmp, TEMP idx_base_temp, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, TEMP rtmp2, TEMP mask_idx, TEMP length, KILL cr); - format %{ "vector_gatherGT8_masked_off $dst, $mem, $idx_base, $offset, $mask\t! using $tmp, $idx_base_temp, $xtmp1, $xtmp2, $xtmp3, $rtmp, $rtmp2, $mask_idx and $length as TEMP" %} - ins_encode %{ - int vlen_enc = vector_length_encoding(this); - int vector_len = Matcher::vector_length(this); - BasicType elem_bt = Matcher::vector_element_basic_type(this); - __ xorl($mask_idx$$Register, $mask_idx$$Register); - __ lea($tmp$$Register, $mem$$Address); - __ movptr($idx_base_temp$$Register, $idx_base$$Register); - __ vpmovmskb($rtmp2$$Register, $mask$$XMMRegister, vlen_enc); - if (elem_bt == T_SHORT) { - __ movl($mask_idx$$Register, 0x55555555); - __ pextl($rtmp2$$Register, $rtmp2$$Register, $mask_idx$$Register); - } - __ xorl($mask_idx$$Register, $mask_idx$$Register); - __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, $offset$$Register, $rtmp2$$Register, $xtmp1$$XMMRegister, + __ vgather_subword(elem_bt, $dst$$XMMRegister, $tmp$$Register, $idx_base_temp$$Register, $rtmp2$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, $mask_idx$$Register, $length$$Register, vector_len, vlen_enc); %} ins_pipe( pipe_slow ); @@ -5326,9 +5209,9 @@ instruct mul_reduction64B(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legV //--------------------Min/Max Float Reduction -------------------- // Float Min Reduction -instruct minmax_reduction2F(legRegF dst, immF src1, legVec src2, legVec tmp, - legVec atmp, legVec btmp, legVec xmm_1, rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && +instruct minmax_reduction2F(legRegF dst, immF src1, legVec src2, legVec tmp, legVec atmp, + legVec btmp, legVec xmm_1, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && Matcher::vector_length(n->in(2)) == 2); @@ -5349,7 +5232,7 @@ instruct minmax_reduction2F(legRegF dst, immF src1, legVec src2, legVec tmp, instruct minmax_reductionF(legRegF dst, immF src1, legVec src2, legVec tmp, legVec atmp, legVec btmp, legVec xmm_0, legVec xmm_1, rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && Matcher::vector_length(n->in(2)) >= 4); @@ -5368,9 +5251,9 @@ instruct minmax_reductionF(legRegF dst, immF src1, legVec src2, legVec tmp, legV ins_pipe( pipe_slow ); %} -instruct minmax_reduction2F_av(legRegF dst, legVec src, legVec tmp, - legVec atmp, legVec btmp, legVec xmm_1, rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && +instruct minmax_reduction2F_av(legRegF dst, legVec src, legVec tmp, legVec atmp, + legVec btmp, legVec xmm_1, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && Matcher::vector_length(n->in(2)) == 2); match(Set dst (MinReductionV dst src)); match(Set dst (MaxReductionV dst src)); @@ -5388,9 +5271,9 @@ instruct minmax_reduction2F_av(legRegF dst, legVec src, legVec tmp, %} -instruct minmax_reductionF_av(legRegF dst, legVec src, legVec tmp, - legVec atmp, legVec btmp, legVec xmm_0, legVec xmm_1, rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && +instruct minmax_reductionF_av(legRegF dst, legVec src, legVec tmp, legVec atmp, legVec btmp, + legVec xmm_0, legVec xmm_1, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && Matcher::vector_length(n->in(2)) >= 4); match(Set dst (MinReductionV dst src)); match(Set dst (MaxReductionV dst src)); @@ -5407,12 +5290,78 @@ instruct minmax_reductionF_av(legRegF dst, legVec src, legVec tmp, ins_pipe( pipe_slow ); %} +instruct minmax_reduction2F_avx10(regF dst, immF src1, vec src2, vec xtmp1) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && + ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || + (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && + Matcher::vector_length(n->in(2)) == 2); + match(Set dst (MinReductionV src1 src2)); + match(Set dst (MaxReductionV src1 src2)); + effect(TEMP dst, TEMP xtmp1); + format %{ "vector_minmax_reduction $dst, $src1, $src2 \t; using $xtmp1 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src2); + __ reduceFloatMinMax(opcode, vlen, false, $dst$$XMMRegister, $src2$$XMMRegister, + xnoreg, xnoreg, xnoreg, $xtmp1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct minmax_reductionF_avx10(regF dst, immF src1, vec src2, vec xtmp1, vec xtmp2) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && + ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || + (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && + Matcher::vector_length(n->in(2)) >= 4); + match(Set dst (MinReductionV src1 src2)); + match(Set dst (MaxReductionV src1 src2)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2); + format %{ "vector_minmax_reduction $dst, $src1, $src2 \t; using $xtmp1 and $xtmp2 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src2); + __ reduceFloatMinMax(opcode, vlen, false, $dst$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, + xnoreg, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct minmax_reduction2F_avx10_av(regF dst, vec src, vec xtmp1) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && + Matcher::vector_length(n->in(2)) == 2); + match(Set dst (MinReductionV dst src)); + match(Set dst (MaxReductionV dst src)); + effect(TEMP dst, TEMP xtmp1); + format %{ "vector_minmax2F_reduction $dst, $src \t; using $xtmp1 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src); + __ reduceFloatMinMax(opcode, vlen, true, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, + $xtmp1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct minmax_reductionF_avx10_av(regF dst, vec src, vec xtmp1, vec xtmp2) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && + Matcher::vector_length(n->in(2)) >= 4); + match(Set dst (MinReductionV dst src)); + match(Set dst (MaxReductionV dst src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2); + format %{ "vector_minmax2F_reduction $dst, $src \t; using $xtmp1 and $xtmp2 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src); + __ reduceFloatMinMax(opcode, vlen, true, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, + $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} //--------------------Min Double Reduction -------------------- -instruct minmax_reduction2D(legRegD dst, immD src1, legVec src2, - legVec tmp1, legVec tmp2, legVec tmp3, legVec tmp4, // TEMPs - rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && +instruct minmax_reduction2D(legRegD dst, immD src1, legVec src2, legVec tmp1, legVec tmp2, + legVec tmp3, legVec tmp4, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && Matcher::vector_length(n->in(2)) == 2); @@ -5431,10 +5380,9 @@ instruct minmax_reduction2D(legRegD dst, immD src1, legVec src2, ins_pipe( pipe_slow ); %} -instruct minmax_reductionD(legRegD dst, immD src1, legVec src2, - legVec tmp1, legVec tmp2, legVec tmp3, legVec tmp4, legVec tmp5, // TEMPs - rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && +instruct minmax_reductionD(legRegD dst, immD src1, legVec src2, legVec tmp1, legVec tmp2, + legVec tmp3, legVec tmp4, legVec tmp5, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && Matcher::vector_length(n->in(2)) >= 4); @@ -5454,10 +5402,9 @@ instruct minmax_reductionD(legRegD dst, immD src1, legVec src2, %} -instruct minmax_reduction2D_av(legRegD dst, legVec src, - legVec tmp1, legVec tmp2, legVec tmp3, legVec tmp4, // TEMPs - rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && +instruct minmax_reduction2D_av(legRegD dst, legVec src, legVec tmp1, legVec tmp2, + legVec tmp3, legVec tmp4, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && Matcher::vector_length(n->in(2)) == 2); match(Set dst (MinReductionV dst src)); match(Set dst (MaxReductionV dst src)); @@ -5474,10 +5421,9 @@ instruct minmax_reduction2D_av(legRegD dst, legVec src, ins_pipe( pipe_slow ); %} -instruct minmax_reductionD_av(legRegD dst, legVec src, - legVec tmp1, legVec tmp2, legVec tmp3, legVec tmp4, legVec tmp5, // TEMPs - rFlagsReg cr) %{ - predicate(Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && +instruct minmax_reductionD_av(legRegD dst, legVec src, legVec tmp1, legVec tmp2, legVec tmp3, + legVec tmp4, legVec tmp5, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && Matcher::vector_length(n->in(2)) >= 4); match(Set dst (MinReductionV dst src)); match(Set dst (MaxReductionV dst src)); @@ -5494,6 +5440,75 @@ instruct minmax_reductionD_av(legRegD dst, legVec src, ins_pipe( pipe_slow ); %} +instruct minmax_reduction2D_avx10(regD dst, immD src1, vec src2, vec xtmp1) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && + ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || + (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && + Matcher::vector_length(n->in(2)) == 2); + match(Set dst (MinReductionV src1 src2)); + match(Set dst (MaxReductionV src1 src2)); + effect(TEMP dst, TEMP xtmp1); + format %{ "vector_minmax2D_reduction $dst, $src1, $src2 ; using $xtmp1 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src2); + __ reduceDoubleMinMax(opcode, vlen, false, $dst$$XMMRegister, $src2$$XMMRegister, xnoreg, + xnoreg, xnoreg, $xtmp1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct minmax_reductionD_avx10(regD dst, immD src1, vec src2, vec xtmp1, vec xtmp2) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && + ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || + (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && + Matcher::vector_length(n->in(2)) >= 4); + match(Set dst (MinReductionV src1 src2)); + match(Set dst (MaxReductionV src1 src2)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2); + format %{ "vector_minmaxD_reduction $dst, $src1, $src2 ; using $xtmp1 and $xtmp2 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src2); + __ reduceDoubleMinMax(opcode, vlen, false, $dst$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, + xnoreg, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + + +instruct minmax_reduction2D_av_avx10(regD dst, vec src, vec xtmp1) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && + Matcher::vector_length(n->in(2)) == 2); + match(Set dst (MinReductionV dst src)); + match(Set dst (MaxReductionV dst src)); + effect(TEMP dst, TEMP xtmp1); + format %{ "vector_minmax2D_reduction $dst, $src ; using $xtmp1 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src); + __ reduceDoubleMinMax(opcode, vlen, true, $dst$$XMMRegister, $src$$XMMRegister, + xnoreg, xnoreg, xnoreg, $xtmp1$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct minmax_reductionD_av_avx10(regD dst, vec src, vec xtmp1, vec xtmp2) %{ + predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && + Matcher::vector_length(n->in(2)) >= 4); + match(Set dst (MinReductionV dst src)); + match(Set dst (MaxReductionV dst src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2); + format %{ "vector_minmaxD_reduction $dst, $src ; using $xtmp1 and $xtmp2 as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + int vlen = Matcher::vector_length(this, $src); + __ reduceDoubleMinMax(opcode, vlen, true, $dst$$XMMRegister, $src$$XMMRegister, + xnoreg, xnoreg, xnoreg, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + // ====================VECTOR ARITHMETIC======================================= // --------------------------------- ADD -------------------------------------- @@ -6380,9 +6395,25 @@ instruct vminmaxL_reg_evex(vec dst, vec src1, vec src2) %{ ins_pipe( pipe_slow ); %} +// Float/Double vector Min/Max +instruct minmaxFP_avx10_reg(vec dst, vec a, vec b) %{ + predicate(VM_Version::supports_avx10_2() && + is_floating_point_type(Matcher::vector_element_basic_type(n))); // T_FLOAT, T_DOUBLE + match(Set dst (MinV a b)); + match(Set dst (MaxV a b)); + format %{ "vector_minmaxFP $dst, $a, $b" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int opcode = this->ideal_Opcode(); + BasicType elem_bt = Matcher::vector_element_basic_type(this); + __ vminmax_fp(opcode, elem_bt, $dst$$XMMRegister, k0, $a$$XMMRegister, $b$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + // Float/Double vector Min/Max instruct minmaxFP_reg(legVec dst, legVec a, legVec b, legVec tmp, legVec atmp, legVec btmp) %{ - predicate(Matcher::vector_length_in_bytes(n) <= 32 && + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_length_in_bytes(n) <= 32 && is_floating_point_type(Matcher::vector_element_basic_type(n)) && // T_FLOAT, T_DOUBLE UseAVX > 0); match(Set dst (MinV a b)); @@ -6403,8 +6434,8 @@ instruct minmaxFP_reg(legVec dst, legVec a, legVec b, legVec tmp, legVec atmp, l ins_pipe( pipe_slow ); %} -instruct evminmaxFP_reg_eavx(vec dst, vec a, vec b, vec atmp, vec btmp, kReg ktmp) %{ - predicate(Matcher::vector_length_in_bytes(n) == 64 && +instruct evminmaxFP_reg_evex(vec dst, vec a, vec b, vec atmp, vec btmp, kReg ktmp) %{ + predicate(!VM_Version::supports_avx10_2() && Matcher::vector_length_in_bytes(n) == 64 && is_floating_point_type(Matcher::vector_element_basic_type(n))); // T_FLOAT, T_DOUBLE match(Set dst (MinV a b)); match(Set dst (MaxV a b)); @@ -10719,8 +10750,22 @@ instruct scalar_binOps_HF_reg(regF dst, regF src1, regF src2) ins_pipe(pipe_slow); %} +instruct scalar_minmax_HF_avx10_reg(regF dst, regF src1, regF src2) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MaxHF src1 src2)); + match(Set dst (MinHF src1 src2)); + format %{ "scalar_min_max_fp16 $dst, $src1, $src2" %} + ins_encode %{ + int function = this->ideal_Opcode() == Op_MinHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + __ eminmaxsh($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, function); + %} + ins_pipe( pipe_slow ); +%} + instruct scalar_minmax_HF_reg(regF dst, regF src1, regF src2, kReg ktmp, regF xtmp1, regF xtmp2) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (MaxHF src1 src2)); match(Set dst (MinHF src1 src2)); effect(TEMP_DEF dst, TEMP ktmp, TEMP xtmp1, TEMP xtmp2); @@ -10820,8 +10865,37 @@ instruct vector_fma_HF_mem(vec dst, memory src1, vec src2) ins_pipe( pipe_slow ); %} +instruct vector_minmax_HF_avx10_mem(vec dst, vec src1, memory src2) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MinVHF src1 (VectorReinterpret (LoadVector src2)))); + match(Set dst (MaxVHF src1 (VectorReinterpret (LoadVector src2)))); + format %{ "vector_min_max_fp16_mem $dst, $src1, $src2" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$Address, true, function, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vector_minmax_HF_avx10_reg(vec dst, vec src1, vec src2) +%{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MinVHF src1 src2)); + match(Set dst (MaxVHF src1 src2)); + format %{ "vector_min_max_fp16 $dst, $src1, $src2" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$XMMRegister, true, function, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct vector_minmax_HF_reg(vec dst, vec src1, vec src2, kReg ktmp, vec xtmp1, vec xtmp2) %{ + predicate(!VM_Version::supports_avx10_2()); match(Set dst (MinVHF src1 src2)); match(Set dst (MaxVHF src1 src2)); effect(TEMP_DEF dst, TEMP ktmp, TEMP xtmp1, TEMP xtmp2); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 48f7d64613b..d2d658c92e2 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -4475,9 +4475,20 @@ instruct loadD(regD dst, memory mem) ins_pipe(pipe_slow); // XXX %} +// max = java.lang.Math.max(float a, float b) +instruct maxF_avx10_reg(regF dst, regF a, regF b) %{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MaxF a b)); + format %{ "maxF $dst, $a, $b" %} + ins_encode %{ + __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN); + %} + ins_pipe( pipe_slow ); +%} + // max = java.lang.Math.max(float a, float b) instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{ - predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); match(Set dst (MaxF a b)); effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); format %{ "maxF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} @@ -4488,7 +4499,7 @@ instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, %} instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{ - predicate(UseAVX > 0 && VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); match(Set dst (MaxF a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); @@ -4500,9 +4511,20 @@ instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRe ins_pipe( pipe_slow ); %} +// max = java.lang.Math.max(double a, double b) +instruct maxD_avx10_reg(regD dst, regD a, regD b) %{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MaxD a b)); + format %{ "maxD $dst, $a, $b" %} + ins_encode %{ + __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN); + %} + ins_pipe( pipe_slow ); +%} + // max = java.lang.Math.max(double a, double b) instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{ - predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); match(Set dst (MaxD a b)); effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp); format %{ "maxD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} @@ -4513,7 +4535,7 @@ instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, %} instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{ - predicate(UseAVX > 0 && VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); match(Set dst (MaxD a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); @@ -4525,9 +4547,20 @@ instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRe ins_pipe( pipe_slow ); %} +// max = java.lang.Math.min(float a, float b) +instruct minF_avx10_reg(regF dst, regF a, regF b) %{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MinF a b)); + format %{ "minF $dst, $a, $b" %} + ins_encode %{ + __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN); + %} + ins_pipe( pipe_slow ); +%} + // min = java.lang.Math.min(float a, float b) instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{ - predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); match(Set dst (MinF a b)); effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); format %{ "minF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} @@ -4538,7 +4571,7 @@ instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, %} instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{ - predicate(UseAVX > 0 && VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); match(Set dst (MinF a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); @@ -4550,9 +4583,20 @@ instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRe ins_pipe( pipe_slow ); %} +// max = java.lang.Math.min(double a, double b) +instruct minD_avx10_reg(regD dst, regD a, regD b) %{ + predicate(VM_Version::supports_avx10_2()); + match(Set dst (MinD a b)); + format %{ "minD $dst, $a, $b" %} + ins_encode %{ + __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN); + %} + ins_pipe( pipe_slow ); +%} + // min = java.lang.Math.min(double a, double b) instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{ - predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n)); match(Set dst (MinD a b)); effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp); format %{ "minD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %} @@ -4563,7 +4607,7 @@ instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, %} instruct minD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{ - predicate(UseAVX > 0 && VLoopReductions::is_reduction(n)); + predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n)); match(Set dst (MinD a b)); effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr); @@ -6430,7 +6474,7 @@ instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI sr ins_pipe(pipe_cmov_mem); %} -instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2) +instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2) %{ predicate(UseAPX); match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2)))); @@ -6813,7 +6857,7 @@ instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{ %} %} -instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2) +instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2) %{ predicate(UseAPX); match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2))); @@ -6920,7 +6964,7 @@ instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL sr ins_pipe(pipe_cmov_mem); %} -instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2) +instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2) %{ predicate(UseAPX); match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2)))); diff --git a/src/hotspot/cpu/zero/continuationHelper_zero.inline.hpp b/src/hotspot/cpu/zero/continuationHelper_zero.inline.hpp index a1f782623b2..a20417904f0 100644 --- a/src/hotspot/cpu/zero/continuationHelper_zero.inline.hpp +++ b/src/hotspot/cpu/zero/continuationHelper_zero.inline.hpp @@ -105,7 +105,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) { return nullptr; } -inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) { +inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) { Unimplemented(); } diff --git a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp index 4931ad79e67..ad92e5551e5 100644 --- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp +++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp @@ -131,15 +131,15 @@ void SharedRuntime::generate_deopt_blob() { _deopt_blob = generate_empty_deopt_blob(); } -SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) { +SafepointBlob* SharedRuntime::generate_handler_blob(StubId id, address call_ptr) { return generate_empty_safepoint_blob(); } -RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address destination) { +RuntimeStub* SharedRuntime::generate_resolve_blob(StubId id, address destination) { return generate_empty_runtime_stub(); } -RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address runtime_entry) { +RuntimeStub* SharedRuntime::generate_throw_exception(StubId id, address runtime_entry) { return generate_empty_runtime_stub(); } diff --git a/src/hotspot/cpu/zero/stubGenerator_zero.cpp b/src/hotspot/cpu/zero/stubGenerator_zero.cpp index 65fe33dcba4..08cb173b507 100644 --- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp +++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp @@ -180,6 +180,10 @@ class StubGenerator: public StubCodeGenerator { void generate_preuniverse_stubs() { StubRoutines::_fence_entry = ShouldNotCallThisStub(); + StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub(); + StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); + StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); + StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); } void generate_initial_stubs() { @@ -192,12 +196,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_forward_exception_entry = ShouldNotCallThisStub(); StubRoutines::_call_stub_entry = (address) call_stub; StubRoutines::_catch_exception_entry = ShouldNotCallThisStub(); - - // atomic calls - StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); } void generate_continuation_stubs() { @@ -215,31 +213,31 @@ class StubGenerator: public StubCodeGenerator { } public: - StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { + StubGenerator(CodeBuffer* code, BlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { - case preuniverse_id: + case BlobId::stubgen_preuniverse_id: generate_preuniverse_stubs(); break; - case initial_id: + case BlobId::stubgen_initial_id: generate_initial_stubs(); break; - case continuation_id: + case BlobId::stubgen_continuation_id: generate_continuation_stubs(); break; - case compiler_id: + case BlobId::stubgen_compiler_id: // do nothing break; - case final_id: + case BlobId::stubgen_final_id: generate_final_stubs(); break; default: - fatal("unexpected blob id: %d", blob_id); + fatal("unexpected blob id: %s", StubInfo::name(blob_id)); break; }; } }; -void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id) { +void StubGenerator_generate(CodeBuffer* code, BlobId blob_id) { StubGenerator g(code, blob_id); } diff --git a/src/hotspot/os/aix/decoder_aix.hpp b/src/hotspot/os/aix/decoder_aix.hpp index 0d87ba87b94..2ba3e1c5a3a 100644 --- a/src/hotspot/os/aix/decoder_aix.hpp +++ b/src/hotspot/os/aix/decoder_aix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -23,6 +23,9 @@ * */ +#ifndef OS_AIX_DECODER_AIX_HPP +#define OS_AIX_DECODER_AIX_HPP + #include "utilities/decoder.hpp" #include "porting_aix.hpp" @@ -44,3 +47,4 @@ class AIXDecoder: public AbstractDecoder { }; +#endif // OS_AIX_DECODER_AIX_HPP diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 9c6218aee16..17186fb9f3d 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -879,17 +879,6 @@ void os::free_thread(OSThread* osthread) { //////////////////////////////////////////////////////////////////////////////// // time support -double os::elapsedVTime() { - struct rusage usage; - int retval = getrusage(RUSAGE_THREAD, &usage); - if (retval == 0) { - return usage.ru_utime.tv_sec + usage.ru_stime.tv_sec + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) / (1000.0 * 1000); - } else { - // better than nothing, but not much - return elapsedTime(); - } -} - // We use mread_real_time here. // On AIX: If the CPU has a time register, the result will be RTC_POWER and // it has to be converted to real time. AIX documentations suggests to do @@ -2441,7 +2430,7 @@ static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* dummy, &dummy_size) == 0) { tid = pinfo.__pi_tid; } else { - tty->print_cr("pthread_getthrds_np failed."); + tty->print_cr("pthread_getthrds_np failed, errno: %d.", errno); error = true; } @@ -2452,7 +2441,7 @@ static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* sys_time = thrdentry.ti_ru.ru_stime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_stime.tv_usec * 1000LL; user_time = thrdentry.ti_ru.ru_utime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_utime.tv_usec * 1000LL; } else { - tty->print_cr("pthread_getthrds_np failed."); + tty->print_cr("getthrds64 failed, errno: %d.", errno); error = true; } } diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 6f7d9a6de37..4b74e7c00f3 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -782,10 +782,6 @@ void os::free_thread(OSThread* osthread) { //////////////////////////////////////////////////////////////////////////////// // time support -double os::elapsedVTime() { - // better than nothing, but not much - return elapsedTime(); -} #ifdef __APPLE__ void os::Bsd::clock_init() { diff --git a/src/hotspot/os/bsd/semaphore_bsd.cpp b/src/hotspot/os/bsd/semaphore_bsd.cpp index 771756ea5e0..827c955677e 100644 --- a/src/hotspot/os/bsd/semaphore_bsd.cpp +++ b/src/hotspot/os/bsd/semaphore_bsd.cpp @@ -31,18 +31,23 @@ #ifdef __APPLE__ // OS X doesn't support unnamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. -static const char* sem_init_strerror(kern_return_t value) { +static const char* sem_strerror(kern_return_t value) { switch (value) { - case KERN_INVALID_ARGUMENT: return "Invalid argument"; - case KERN_RESOURCE_SHORTAGE: return "Resource shortage"; - default: return "Unknown"; + case KERN_INVALID_ARGUMENT: return "Invalid argument"; + case KERN_RESOURCE_SHORTAGE: return "Resource shortage"; + case KERN_TERMINATED: return "Resource has been destroyed"; + case KERN_ABORTED: return "Operation was aborted"; + case KERN_INVALID_VALUE: return "Invalid time specified"; + case KERN_OPERATION_TIMED_OUT: return "Operation timed-out"; + default: return "Unknown"; } } OSXSemaphore::OSXSemaphore(uint value) { kern_return_t ret = semaphore_create(mach_task_self(), &_semaphore, SYNC_POLICY_FIFO, value); - guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret)); + guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s (0x%x)", + sem_strerror(ret), (uint)ret); } OSXSemaphore::~OSXSemaphore() { @@ -53,7 +58,8 @@ void OSXSemaphore::signal(uint count) { for (uint i = 0; i < count; i++) { kern_return_t ret = semaphore_signal(_semaphore); - assert(ret == KERN_SUCCESS, "Failed to signal semaphore"); + assert(ret == KERN_SUCCESS, "Failed to signal semaphore: %s (0x%x)", + sem_strerror(ret), (uint)ret); } } @@ -62,7 +68,8 @@ void OSXSemaphore::wait() { while ((ret = semaphore_wait(_semaphore)) == KERN_ABORTED) { // Semaphore was interrupted. Retry. } - assert(ret == KERN_SUCCESS, "Failed to wait on semaphore"); + assert(ret == KERN_SUCCESS, "Failed to wait on semaphore: %s (0x%x)", + sem_strerror(ret), (uint)ret); } bool OSXSemaphore::trywait() { @@ -100,6 +107,10 @@ bool OSXSemaphore::timedwait(int64_t millis) { kr = semaphore_timedwait(_semaphore, waitspec); } + assert(kr == KERN_SUCCESS || kr == KERN_OPERATION_TIMED_OUT, + "Failed to timed-wait on semaphore: %s (0x%x)", + sem_strerror(kr), (uint)kr); + return kr == KERN_SUCCESS; } #endif // __APPLE__ diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 1a23c956f35..b747fe4d88f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1487,16 +1487,6 @@ void os::Linux::capture_initial_stack(size_t max_size) { //////////////////////////////////////////////////////////////////////////////// // time support -double os::elapsedVTime() { - struct rusage usage; - int retval = getrusage(RUSAGE_THREAD, &usage); - if (retval == 0) { - return (double) (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) + (double) (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) / (1000 * 1000); - } else { - // better than nothing, but not much - return elapsedTime(); - } -} void os::Linux::fast_thread_clock_init() { clockid_t clockid; diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 303e44eadcb..d417f384a18 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -1599,7 +1600,16 @@ jlong os::elapsed_frequency() { return NANOSECS_PER_SEC; // nanosecond resolution } -bool os::supports_vtime() { return true; } +double os::elapsed_process_cpu_time() { + struct rusage usage; + int retval = getrusage(RUSAGE_SELF, &usage); + if (retval == 0) { + return usage.ru_utime.tv_sec + usage.ru_stime.tv_sec + + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) / (1000.0 * 1000.0); + } else { + return -1; + } +} // Return the real, user, and system times in seconds from an // arbitrary fixed point in the past. diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 24969683a1f..d1624b51ef3 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1194,19 +1194,36 @@ FILETIME java_to_windows_time(jlong l) { return result; } -bool os::supports_vtime() { return true; } - -double os::elapsedVTime() { - FILETIME created; - FILETIME exited; +double os::elapsed_process_cpu_time() { + FILETIME create; + FILETIME exit; FILETIME kernel; FILETIME user; - if (GetThreadTimes(GetCurrentThread(), &created, &exited, &kernel, &user) != 0) { - // the resolution of windows_to_java_time() should be sufficient (ms) - return (double) (windows_to_java_time(kernel) + windows_to_java_time(user)) / MILLIUNITS; - } else { - return elapsedTime(); + + if (GetProcessTimes(GetCurrentProcess(), &create, &exit, &kernel, &user) == 0) { + return -1; + } + + SYSTEMTIME user_total; + if (FileTimeToSystemTime(&user, &user_total) == 0) { + return -1; } + + SYSTEMTIME kernel_total; + if (FileTimeToSystemTime(&kernel, &kernel_total) == 0) { + return -1; + } + + double user_seconds = + double(user_total.wHour) * 3600.0 + double(user_total.wMinute) * 60.0 + + double(user_total.wSecond) + double(user_total.wMilliseconds) / 1000.0; + + double kernel_seconds = double(kernel_total.wHour) * 3600.0 + + double(kernel_total.wMinute) * 60.0 + + double(kernel_total.wSecond) + + double(kernel_total.wMilliseconds) / 1000.0; + + return user_seconds + kernel_seconds; } jlong os::javaTimeMillis() { @@ -2623,7 +2640,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr()); } -#if !defined(PRODUCT) if ((exception_code == EXCEPTION_ACCESS_VIOLATION) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) { // Verify that OS save/restore APX registers. @@ -2631,7 +2647,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr_apx()); } #endif -#endif #ifdef CAN_SHOW_REGISTERS_ON_ASSERT if (VMError::was_assert_poison_crash(exception_record)) { diff --git a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp index 5424b58da6d..b55c1cd27c8 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp @@ -92,6 +92,9 @@ void VM_Version::get_os_cpu_info() { cpu_has("hw.optional.armv8_2_sha3")) { _features |= CPU_SHA3; } + if (cpu_has("hw.optional.arm.FEAT_SB")) { + _features |= CPU_SB; + } int cache_line_size; int hw_conf_cache_line[] = { CTL_HW, HW_CACHELINE }; diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 1a7063198e3..ecc2e5a7f00 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -429,13 +429,11 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, stub = VM_Version::cpuinfo_cont_addr(); } -#if !defined(PRODUCT) && defined(_LP64) if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) { // Verify that OS save/restore APX registers. stub = VM_Version::cpuinfo_cont_addr_apx(); VM_Version::clear_apx_test_state(); } -#endif // We test if stub is already set (by the stack overflow code // above) so it is not overwritten by the code that follows. This diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 9725c6cd6c0..a8edeefc885 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -71,6 +71,10 @@ #define HWCAP_SVE (1 << 22) #endif +#ifndef HWCAP_SB +#define HWCAP_SB (1 << 29) +#endif + #ifndef HWCAP_PACA #define HWCAP_PACA (1 << 30) #endif @@ -143,6 +147,7 @@ void VM_Version::get_os_cpu_info() { HWCAP_SHA3 | HWCAP_SHA512 | HWCAP_SVE | + HWCAP_SB | HWCAP_PACA | HWCAP_FPHP | HWCAP_ASIMDHP); diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 9c648f78118..ff7fce234c4 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -255,13 +255,11 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, stub = VM_Version::cpuinfo_cont_addr(); } -#if !defined(PRODUCT) && defined(_LP64) if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) { // Verify that OS save/restore APX registers. stub = VM_Version::cpuinfo_cont_addr_apx(); VM_Version::clear_apx_test_state(); } -#endif if (thread->thread_state() == _thread_in_Java) { // Java thread running in Java code => find exception handler if any diff --git a/src/hotspot/share/c1/c1_CodeStubs.hpp b/src/hotspot/share/c1/c1_CodeStubs.hpp index c7bf745f496..fc4e2024e4c 100644 --- a/src/hotspot/share/c1/c1_CodeStubs.hpp +++ b/src/hotspot/share/c1/c1_CodeStubs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -341,10 +341,10 @@ class NewInstanceStub: public CodeStub { LIR_Opr _klass_reg; LIR_Opr _result; CodeEmitInfo* _info; - C1StubId _stub_id; + StubId _stub_id; public: - NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id); + NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id); virtual void emit_code(LIR_Assembler* e); virtual CodeEmitInfo* info() const { return _info; } virtual void visit(LIR_OpVisitState* visitor) { @@ -603,11 +603,11 @@ class DeoptimizeStub : public CodeStub { class SimpleExceptionStub: public CodeStub { private: LIR_Opr _obj; - C1StubId _stub; + StubId _stub; CodeEmitInfo* _info; public: - SimpleExceptionStub(C1StubId stub, LIR_Opr obj, CodeEmitInfo* info): + SimpleExceptionStub(StubId stub, LIR_Opr obj, CodeEmitInfo* info): _obj(obj), _stub(stub), _info(info) { FrameMap* f = Compilation::current()->frame_map(); f->update_reserved_argument_area_size(2 * BytesPerWord); @@ -634,7 +634,7 @@ class SimpleExceptionStub: public CodeStub { class ArrayStoreExceptionStub: public SimpleExceptionStub { public: - ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(C1StubId::throw_array_store_exception_id, obj, info) {} + ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(StubId::c1_throw_array_store_exception_id, obj, info) {} #ifndef PRODUCT virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); } #endif // PRODUCT diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index 64a2e6456d8..82dea9b0141 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -237,7 +237,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_getObjectSize: -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV64) || defined(PPC64) case vmIntrinsics::_clone: #endif break; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index d4fe0c041eb..60e69fd0f34 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -384,7 +384,7 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_ , _tmp(tmp) , _expected_type(expected_type) , _flags(flags) { -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV64) || defined(PPC64) if (expected_type != nullptr && flags == 0) { _stub = nullptr; } else { diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 0c9d0c9570b..02f176528ec 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -629,7 +629,6 @@ void LIRGenerator::logic_op (Bytecodes::Code code, LIR_Opr result_op, LIR_Opr le void LIRGenerator::monitor_enter(LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no, CodeEmitInfo* info_for_exception, CodeEmitInfo* info, CodeStub* throw_ie_stub) { - if (!GenerateSynchronizationCode) return; // for slow path, use debug info for state after successful locking CodeStub* slow_path = new MonitorEnterStub(object, lock, info, throw_ie_stub, scratch); __ load_stack_address_monitor(monitor_no, lock); @@ -639,7 +638,6 @@ void LIRGenerator::monitor_enter(LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_ void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, LIR_Opr scratch, int monitor_no) { - if (!GenerateSynchronizationCode) return; // setup registers LIR_Opr hdr = lock; lock = new_hdr; @@ -669,7 +667,7 @@ void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, bool is_unr if (UseFastNewInstance && klass->is_loaded() && (allow_inline || !klass->is_inlinetype()) && !Klass::layout_helper_needs_slow_path(klass->layout_helper())) { - C1StubId stub_id = klass->is_initialized() ? C1StubId::fast_new_instance_id : C1StubId::fast_new_instance_init_check_id; + StubId stub_id = klass->is_initialized() ? StubId::c1_fast_new_instance_id : StubId::c1_fast_new_instance_init_check_id; CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, stub_id); @@ -680,7 +678,7 @@ void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, bool is_unr __ allocate_object(dst, scratch1, scratch2, scratch3, scratch4, oopDesc::header_size(), instance_size, klass_reg, !klass->is_initialized(), slow_path); } else { - CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, C1StubId::new_instance_id); + CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, StubId::c1_new_instance_id); __ jump(slow_path); __ branch_destination(slow_path->continuation()); } @@ -1423,7 +1421,7 @@ void LIRGenerator::do_RegisterFinalizer(Intrinsic* x) { args->append(receiver.result()); CodeEmitInfo* info = state_for(x, x->state()); call_runtime(&signature, args, - CAST_FROM_FN_PTR(address, Runtime1::entry_for(C1StubId::register_finalizer_id)), + CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_register_finalizer_id)), voidType, info); set_no_result(x); @@ -3040,7 +3038,7 @@ void LIRGenerator::do_Base(Base* x) { } assert(obj->is_valid(), "must be valid"); - if (method()->is_synchronized() && GenerateSynchronizationCode) { + if (method()->is_synchronized()) { LIR_Opr lock = syncLockOpr(); __ load_stack_address_monitor(0, lock); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index 386bcc0d248..b09f061b735 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -43,7 +43,7 @@ static LinearScanTimers _total_timer; // helper macro for short definition of timer - #define TIME_LINEAR_SCAN(timer_name) TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan || TimeEachLinearScan, Verbose); + #define TIME_LINEAR_SCAN(timer_name) TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan, Verbose); #else #define TIME_LINEAR_SCAN(timer_name) @@ -3016,8 +3016,6 @@ void LinearScan::assign_reg_num() { void LinearScan::do_linear_scan() { - NOT_PRODUCT(_total_timer.begin_method()); - number_instructions(); NOT_PRODUCT(print_lir(1, "Before Register Allocation")); @@ -3072,7 +3070,6 @@ void LinearScan::do_linear_scan() { NOT_PRODUCT(print_lir(1, "Before Code Generation", false)); NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final)); - NOT_PRODUCT(_total_timer.end_method(this)); } @@ -6727,45 +6724,6 @@ const char* LinearScanTimers::timer_name(int idx) { } } -void LinearScanTimers::begin_method() { - if (TimeEachLinearScan) { - // reset all timers to measure only current method - for (int i = 0; i < number_of_timers; i++) { - timer(i)->reset(); - } - } -} - -void LinearScanTimers::end_method(LinearScan* allocator) { - if (TimeEachLinearScan) { - - double c = timer(timer_do_nothing)->seconds(); - double total = 0; - for (int i = 1; i < number_of_timers; i++) { - total += timer(i)->seconds() - c; - } - - if (total >= 0.0005) { - // print all information in one line for automatic processing - tty->print("@"); allocator->compilation()->method()->print_name(); - - tty->print("@ %d ", allocator->compilation()->method()->code_size()); - tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2); - tty->print("@ %d ", allocator->block_count()); - tty->print("@ %d ", allocator->num_virtual_regs()); - tty->print("@ %d ", allocator->interval_count()); - tty->print("@ %d ", allocator->_num_calls); - tty->print("@ %d ", allocator->num_loops()); - - tty->print("@ %6.6f ", total); - for (int i = 1; i < number_of_timers; i++) { - tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100); - } - tty->cr(); - } - } -} - void LinearScanTimers::print(double total_time) { if (TimeLinearScan) { // correction value: sum of dummy-timer that only measures the time that diff --git a/src/hotspot/share/c1/c1_LinearScan.hpp b/src/hotspot/share/c1/c1_LinearScan.hpp index 36d84a4fad9..2088352d336 100644 --- a/src/hotspot/share/c1/c1_LinearScan.hpp +++ b/src/hotspot/share/c1/c1_LinearScan.hpp @@ -948,11 +948,7 @@ class LinearScanTimers : public StackObj { public: LinearScanTimers(); - - void begin_method(); // called for each method when register allocation starts - void end_method(LinearScan* allocator); // called for each method when register allocation completed void print(double total_time); // called before termination of VM to print global summary - elapsedTimer* timer(int idx) { return &(_timers[idx]); } }; diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 04ace2d0485..fec2269298e 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -64,6 +64,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stackWatermarkSet.hpp" +#include "runtime/stubInfo.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/vframe.inline.hpp" #include "runtime/vframeArray.hpp" @@ -105,14 +106,7 @@ void StubAssembler::set_num_rt_args(int args) { } // Implementation of Runtime1 - -CodeBlob* Runtime1::_blobs[(int)C1StubId::NUM_STUBIDS]; - -#define C1_BLOB_NAME_DEFINE(name) "C1 Runtime " # name "_blob", -const char *Runtime1::_blob_names[] = { - C1_STUBS_DO(C1_BLOB_NAME_DEFINE) -}; -#undef C1_STUB_NAME_DEFINE +CodeBlob* Runtime1::_blobs[StubInfo::C1_STUB_COUNT]; #ifndef PRODUCT // statistics @@ -198,19 +192,21 @@ static void deopt_caller(JavaThread* current) { } } -class C1StubIdStubAssemblerCodeGenClosure: public StubAssemblerCodeGenClosure { +class C1StubAssemblerCodeGenClosure: public StubAssemblerCodeGenClosure { private: - C1StubId _id; + StubId _id; public: - C1StubIdStubAssemblerCodeGenClosure(C1StubId id) : _id(id) {} + C1StubAssemblerCodeGenClosure(StubId id) : _id(id) { + assert(StubInfo::is_c1(_id), "not a c1 stub id %s", StubInfo::name(_id)); + } virtual OopMapSet* generate_code(StubAssembler* sasm) { return Runtime1::generate_code_for(_id, sasm); } }; -CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, C1StubId id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure* cl) { - if ((int)id >= 0) { - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C1Blob, (uint)id, name, 0, nullptr); +CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, StubId id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure* cl) { + if (id != StubId::NO_STUBID) { + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C1Blob, StubInfo::blob(id)); if (blob != nullptr) { return blob; } @@ -250,61 +246,63 @@ CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, C1StubId id, const ch must_gc_arguments, false /* alloc_fail_is_fatal */ ); if (blob != nullptr && (int)id >= 0) { - AOTCodeCache::store_code_blob(*blob, AOTCodeEntry::C1Blob, (uint)id, name, 0, nullptr); + AOTCodeCache::store_code_blob(*blob, AOTCodeEntry::C1Blob, StubInfo::blob(id)); } return blob; } -bool Runtime1::generate_blob_for(BufferBlob* buffer_blob, C1StubId id) { - assert(C1StubId::NO_STUBID < id && id < C1StubId::NUM_STUBIDS, "illegal stub id"); +bool Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubId id) { + assert(StubInfo::is_c1(id), "not a c1 stub %s", StubInfo::name(id)); bool expect_oop_map = true; #ifdef ASSERT // Make sure that stubs that need oopmaps have them switch (id) { // These stubs don't need to have an oopmap - case C1StubId::dtrace_object_alloc_id: - case C1StubId::slow_subtype_check_id: - case C1StubId::fpu2long_stub_id: - case C1StubId::unwind_exception_id: - case C1StubId::counter_overflow_id: - case C1StubId::is_instance_of_id: + case StubId::c1_dtrace_object_alloc_id: + case StubId::c1_slow_subtype_check_id: + case StubId::c1_fpu2long_stub_id: + case StubId::c1_unwind_exception_id: + case StubId::c1_counter_overflow_id: + case StubId::c1_is_instance_of_id: expect_oop_map = false; break; default: break; } #endif - C1StubIdStubAssemblerCodeGenClosure cl(id); + C1StubAssemblerCodeGenClosure cl(id); CodeBlob* blob = generate_blob(buffer_blob, id, name_for(id), expect_oop_map, &cl); // install blob - _blobs[(int)id] = blob; + int idx = StubInfo::c1_offset(id); // will assert on non-c1 id + _blobs[idx] = blob; return blob != nullptr; } bool Runtime1::initialize(BufferBlob* blob) { // platform-dependent initialization initialize_pd(); - // generate stubs - int limit = (int)C1StubId::NUM_STUBIDS; - for (int id = 0; id <= (int)C1StubId::forward_exception_id; id++) { - if (!generate_blob_for(blob, (C1StubId) id)) { + // iterate blobs in C1 group and generate a single stub per blob + StubId id = StubInfo::stub_base(StubGroup::C1); + StubId limit = StubInfo::next(StubInfo::stub_max(StubGroup::C1)); + for (; id != limit; id = StubInfo::next(id)) { + if (!generate_blob_for(blob, id)) { return false; } - } - AOTCodeCache::init_early_c1_table(); - for (int id = (int)C1StubId::forward_exception_id+1; id < limit; id++) { - if (!generate_blob_for(blob, (C1StubId) id)) { - return false; + if (id == StubId::c1_forward_exception_id) { + // publish early c1 stubs at this point so later stubs can refer to them + AOTCodeCache::init_early_c1_table(); } } // printing #ifndef PRODUCT if (PrintSimpleStubs) { ResourceMark rm; - for (int id = 0; id < limit; id++) { - _blobs[id]->print(); - if (_blobs[id]->oop_maps() != nullptr) { - _blobs[id]->oop_maps()->print(); + id = StubInfo::stub_base(StubGroup::C1); + for (; id != limit; id = StubInfo::next(id)) { + CodeBlob* blob = blob_for(id); + blob->print(); + if (blob->oop_maps() != nullptr) { + blob->oop_maps()->print(); } } } @@ -313,22 +311,22 @@ bool Runtime1::initialize(BufferBlob* blob) { return bs->generate_c1_runtime_stubs(blob); } -CodeBlob* Runtime1::blob_for(C1StubId id) { - assert(C1StubId::NO_STUBID < id && id < C1StubId::NUM_STUBIDS, "illegal stub id"); - return _blobs[(int)id]; +CodeBlob* Runtime1::blob_for(StubId id) { + int idx = StubInfo::c1_offset(id); // will assert on non-c1 id + return _blobs[idx]; } -const char* Runtime1::name_for(C1StubId id) { - assert(C1StubId::NO_STUBID < id && id < C1StubId::NUM_STUBIDS, "illegal stub id"); - return _blob_names[(int)id]; +const char* Runtime1::name_for(StubId id) { + return StubInfo::name(id); } const char* Runtime1::name_for_address(address entry) { - int limit = (int)C1StubId::NUM_STUBIDS; - for (int i = 0; i < limit; i++) { - C1StubId id = (C1StubId)i; - if (entry == entry_for(id)) return name_for(id); + // iterate stubs starting from C1 group base + StubId id = StubInfo::stub_base(StubGroup::C1); + StubId limit = StubInfo::next(StubInfo::stub_max(StubGroup::C1)); + for (; id != limit; id = StubInfo::next(id)) { + if (entry == entry_for(id)) return StubInfo::name(id); } #define FUNCTION_CASE(a, f) \ @@ -582,7 +580,7 @@ JRT_ENTRY(void, Runtime1::buffer_inline_args_no_receiver(JavaThread* current, Me buffer_inline_args_impl(current, method, false); JRT_END -JRT_ENTRY(void, Runtime1::unimplemented_entry(JavaThread* current, C1StubId id)) +JRT_ENTRY(void, Runtime1::unimplemented_entry(JavaThread* current, StubId id)) tty->print_cr("Runtime1::entry_for(%d) returned unimplemented entry point", (int)id); JRT_END @@ -682,8 +680,8 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c // This function is called when we are about to throw an exception. Therefore, // we have to poll the stack watermark barrier to make sure that not yet safe // stack frames are made safe before returning into them. - if (current->last_frame().cb() == Runtime1::blob_for(C1StubId::handle_exception_from_callee_id)) { - // The C1StubId::handle_exception_from_callee_id handler is invoked after the + if (current->last_frame().cb() == Runtime1::blob_for(StubId::c1_handle_exception_from_callee_id)) { + // The StubId::c1_handle_exception_from_callee_id handler is invoked after the // frame has been unwound. It instead builds its own stub frame, to call the // runtime. But the throwing frame has already been unwound here. StackWatermarkSet::after_unwind(current); @@ -1092,7 +1090,7 @@ static Klass* resolve_field_return_klass(const methodHandle& caller, int bci, TR // Therefore, if there is any chance of a race condition, we try to // patch only naturally aligned words, as single, full-word writes. -JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) +JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, StubId stub_id )) #ifndef PRODUCT if (PrintC1Statistics) { _patch_code_slowcase_cnt++; @@ -1132,9 +1130,9 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) Handle mirror(current, nullptr); // oop needed by load_mirror_patching code Handle appendix(current, nullptr); // oop needed by appendix_patching code bool load_klass_or_mirror_patch_id = - (stub_id == C1StubId::load_klass_patching_id || stub_id == C1StubId::load_mirror_patching_id); + (stub_id == StubId::c1_load_klass_patching_id || stub_id == StubId::c1_load_mirror_patching_id); - if (stub_id == C1StubId::access_field_patching_id) { + if (stub_id == StubId::c1_access_field_patching_id) { Bytecode_field field_access(caller_method, bci); fieldDescriptor result; // initialize class if needed @@ -1236,7 +1234,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) default: fatal("unexpected bytecode for load_klass_or_mirror_patch_id"); } load_klass = k; - } else if (stub_id == C1StubId::load_appendix_patching_id) { + } else if (stub_id == StubId::c1_load_appendix_patching_id) { Bytecode_invoke bytecode(caller_method, bci); Bytecodes::Code bc = bytecode.invoke_code(); @@ -1333,7 +1331,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) if (TracePatching) { ttyLocker ttyl; tty->print_cr(" Patching %s at bci %d at address " INTPTR_FORMAT " (%s)", Bytecodes::name(code), bci, - p2i(instr_pc), (stub_id == C1StubId::access_field_patching_id) ? "field" : "klass"); + p2i(instr_pc), (stub_id == StubId::c1_access_field_patching_id) ? "field" : "klass"); nmethod* caller_code = CodeCache::find_nmethod(caller_frame.pc()); assert(caller_code != nullptr, "nmethod not found"); @@ -1349,7 +1347,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) } // depending on the code below, do_patch says whether to copy the patch body back into the nmethod bool do_patch = true; - if (stub_id == C1StubId::access_field_patching_id) { + if (stub_id == StubId::c1_access_field_patching_id) { // The offset may not be correct if the class was not loaded at code generation time. // Set it now. NativeMovRegMem* n_move = nativeMovRegMem_at(copy_buff); @@ -1375,7 +1373,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) assert(n_copy->data() == 0 || n_copy->data() == (intptr_t)Universe::non_oop_word(), "illegal init value"); - if (stub_id == C1StubId::load_klass_patching_id) { + if (stub_id == StubId::c1_load_klass_patching_id) { assert(load_klass != nullptr, "klass not set"); n_copy->set_data((intx) (load_klass)); } else { @@ -1387,7 +1385,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); } } - } else if (stub_id == C1StubId::load_appendix_patching_id) { + } else if (stub_id == StubId::c1_load_appendix_patching_id) { NativeMovConstReg* n_copy = nativeMovConstReg_at(copy_buff); assert(n_copy->data() == 0 || n_copy->data() == (intptr_t)Universe::non_oop_word(), @@ -1406,7 +1404,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) // first replace the tail, then the call #ifdef ARM if((load_klass_or_mirror_patch_id || - stub_id == C1StubId::load_appendix_patching_id) && + stub_id == StubId::c1_load_appendix_patching_id) && nativeMovConstReg_at(copy_buff)->is_pc_relative()) { nmethod* nm = CodeCache::find_nmethod(instr_pc); address addr = nullptr; @@ -1414,13 +1412,13 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) RelocIterator mds(nm, copy_buff, copy_buff + 1); while (mds.next()) { if (mds.type() == relocInfo::oop_type) { - assert(stub_id == C1StubId::load_mirror_patching_id || - stub_id == C1StubId::load_appendix_patching_id, "wrong stub id"); + assert(stub_id == StubId::c1_load_mirror_patching_id || + stub_id == StubId::c1_load_appendix_patching_id, "wrong stub id"); oop_Relocation* r = mds.oop_reloc(); addr = (address)r->oop_addr(); break; } else if (mds.type() == relocInfo::metadata_type) { - assert(stub_id == C1StubId::load_klass_patching_id, "wrong stub id"); + assert(stub_id == StubId::c1_load_klass_patching_id, "wrong stub id"); metadata_Relocation* r = mds.metadata_reloc(); addr = (address)r->metadata_addr(); break; @@ -1443,9 +1441,9 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) NativeGeneralJump::replace_mt_safe(instr_pc, copy_buff); if (load_klass_or_mirror_patch_id || - stub_id == C1StubId::load_appendix_patching_id) { + stub_id == StubId::c1_load_appendix_patching_id) { relocInfo::relocType rtype = - (stub_id == C1StubId::load_klass_patching_id) ? + (stub_id == StubId::c1_load_klass_patching_id) ? relocInfo::metadata_type : relocInfo::oop_type; // update relocInfo to metadata @@ -1479,9 +1477,9 @@ JRT_END #else // DEOPTIMIZE_WHEN_PATCHING -static bool is_patching_needed(JavaThread* current, C1StubId stub_id) { - if (stub_id == C1StubId::load_klass_patching_id || - stub_id == C1StubId::load_mirror_patching_id) { +static bool is_patching_needed(JavaThread* current, StubId stub_id) { + if (stub_id == StubId::c1_load_klass_patching_id || + stub_id == StubId::c1_load_mirror_patching_id) { // last java frame on stack vframeStream vfst(current, true); assert(!vfst.at_end(), "Java frame must exist"); @@ -1510,7 +1508,7 @@ static bool is_patching_needed(JavaThread* current, C1StubId stub_id) { return true; } -void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) { +void Runtime1::patch_code(JavaThread* current, StubId stub_id) { #ifndef PRODUCT if (PrintC1Statistics) { _patch_code_slowcase_cnt++; @@ -1565,7 +1563,7 @@ int Runtime1::move_klass_patching(JavaThread* current) { { // Enter VM mode ResetNoHandleMark rnhm; - patch_code(current, C1StubId::load_klass_patching_id); + patch_code(current, StubId::c1_load_klass_patching_id); } // Back in JAVA, use no oops DON'T safepoint @@ -1582,7 +1580,7 @@ int Runtime1::move_mirror_patching(JavaThread* current) { { // Enter VM mode ResetNoHandleMark rnhm; - patch_code(current, C1StubId::load_mirror_patching_id); + patch_code(current, StubId::c1_load_mirror_patching_id); } // Back in JAVA, use no oops DON'T safepoint @@ -1599,7 +1597,7 @@ int Runtime1::move_appendix_patching(JavaThread* current) { { // Enter VM mode ResetNoHandleMark rnhm; - patch_code(current, C1StubId::load_appendix_patching_id); + patch_code(current, StubId::c1_load_appendix_patching_id); } // Back in JAVA, use no oops DON'T safepoint @@ -1626,7 +1624,7 @@ int Runtime1::access_field_patching(JavaThread* current) { { // Enter VM mode ResetNoHandleMark rnhm; - patch_code(current, C1StubId::access_field_patching_id); + patch_code(current, StubId::c1_access_field_patching_id); } // Back in JAVA, use no oops DON'T safepoint diff --git a/src/hotspot/share/c1/c1_Runtime1.hpp b/src/hotspot/share/c1/c1_Runtime1.hpp index e154d664a6b..e77e4a1a8a0 100644 --- a/src/hotspot/share/c1/c1_Runtime1.hpp +++ b/src/hotspot/share/c1/c1_Runtime1.hpp @@ -30,6 +30,7 @@ #include "interpreter/interpreter.hpp" #include "memory/allStatic.hpp" #include "runtime/stubDeclarations.hpp" +#include "runtime/stubInfo.hpp" class StubAssembler; @@ -42,16 +43,6 @@ class StubAssemblerCodeGenClosure: public Closure { virtual OopMapSet* generate_code(StubAssembler* sasm) = 0; }; -// define C1StubId enum tags: unwind_exception_id etc - -#define C1_STUB_ID_ENUM_DECLARE(name) STUB_ID_NAME(name), -enum class C1StubId :int { - NO_STUBID = -1, - C1_STUBS_DO(C1_STUB_ID_ENUM_DECLARE) - NUM_STUBIDS -}; -#undef C1_STUB_ID_ENUM_DECLARE - class Runtime1: public AllStatic { friend class ArrayCopyStub; friend class AOTCodeAddressTable; @@ -88,18 +79,17 @@ class Runtime1: public AllStatic { #endif private: - static CodeBlob* _blobs[(int)C1StubId::NUM_STUBIDS]; - static const char* _blob_names[]; + static CodeBlob* _blobs[(int)StubInfo::C1_STUB_COUNT]; static void buffer_inline_args_impl(JavaThread* current, Method* m, bool allocate_receiver); // stub generation public: - static CodeBlob* generate_blob(BufferBlob* buffer_blob, C1StubId id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure *cl); - static bool generate_blob_for(BufferBlob* blob, C1StubId id); - static OopMapSet* generate_code_for(C1StubId id, StubAssembler* sasm); + static CodeBlob* generate_blob(BufferBlob* buffer_blob, StubId id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure *cl); + static bool generate_blob_for(BufferBlob* blob, StubId id); + static OopMapSet* generate_code_for(StubId id, StubAssembler* sasm); private: static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument); - static OopMapSet* generate_handle_exception(C1StubId id, StubAssembler* sasm); + static OopMapSet* generate_handle_exception(StubId id, StubAssembler* sasm); static void generate_unwind_exception(StubAssembler *sasm); static OopMapSet* generate_patching(StubAssembler* sasm, address target); @@ -121,7 +111,7 @@ class Runtime1: public AllStatic { static address counter_overflow(JavaThread* current, int bci, Method* method); - static void unimplemented_entry(JavaThread* current, C1StubId id); + static void unimplemented_entry(JavaThread* current, StubId id); static address exception_handler_for_pc(JavaThread* current); @@ -145,7 +135,7 @@ class Runtime1: public AllStatic { static int move_mirror_patching(JavaThread* current); static int move_appendix_patching(JavaThread* current); - static void patch_code(JavaThread* current, C1StubId stub_id); + static void patch_code(JavaThread* current, StubId stub_id); public: // initialization @@ -156,9 +146,9 @@ class Runtime1: public AllStatic { static uint runtime_blob_current_thread_offset(frame f); // stubs - static CodeBlob* blob_for (C1StubId id); - static address entry_for(C1StubId id) { return blob_for(id)->code_begin(); } - static const char* name_for (C1StubId id); + static CodeBlob* blob_for (StubId id); + static address entry_for(StubId id) { return blob_for(id)->code_begin(); } + static const char* name_for (StubId id); static const char* name_for_address(address entry); // platform might add runtime names. diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index 9326b26412c..186fff1d30f 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -212,9 +212,6 @@ develop(bool, TimeLinearScan, false, \ "detailed timing of LinearScan phases") \ \ - develop(bool, TimeEachLinearScan, false, \ - "print detailed timing of each LinearScan run") \ - \ develop(bool, CountLinearScan, false, \ "collect statistic counters during LinearScan") \ \ diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index d8999774a53..adcc4bfb50a 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -30,6 +30,7 @@ #include "cds/dumpTimeClassInfo.inline.hpp" #include "cds/heapShared.hpp" #include "cds/lambdaProxyClassDictionary.hpp" +#include "cds/regeneratedClasses.hpp" #include "classfile/systemDictionaryShared.hpp" #include "logging/log.hpp" #include "memory/metaspaceClosure.hpp" @@ -188,7 +189,11 @@ void AOTArtifactFinder::end_scanning_for_oops() { void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { if (CDSConfig::is_initing_classes_at_dump_time()) { - assert(ik->is_initialized(), "must be"); + if (RegeneratedClasses::is_regenerated_object(ik)) { + precond(RegeneratedClasses::get_original_object(ik)->is_initialized()); + } else { + precond(ik->is_initialized()); + } add_cached_instance_class(ik); bool created; @@ -243,6 +248,11 @@ void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { add_cached_instance_class(intf); } + InstanceKlass* nest_host = ik->nest_host_or_null(); + if (nest_host != nullptr) { + add_cached_instance_class(nest_host); + } + if (CDSConfig::is_dumping_final_static_archive() && ik->defined_by_other_loaders()) { // The following are not appliable to unregistered classes return; diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp index 46a118c42e9..db18a8ee1b5 100644 --- a/src/hotspot/share/cds/aotClassInitializer.cpp +++ b/src/hotspot/share/cds/aotClassInitializer.cpp @@ -26,6 +26,7 @@ #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" #include "cds/heapShared.hpp" +#include "cds/regeneratedClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmSymbols.hpp" @@ -103,6 +104,10 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { return false; } + if (RegeneratedClasses::is_regenerated_object(ik)) { + ik = RegeneratedClasses::get_original_object(ik); + } + if (!ik->is_initialized() && !ik->is_being_initialized()) { return false; } diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 6b5b491a0bf..bd9e5977eea 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -38,7 +38,6 @@ #include "cds/regeneratedClasses.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderDataShared.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -575,6 +574,9 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref if (ref->msotype() == MetaspaceObj::ClassType) { Klass* klass = (Klass*)ref->obj(); assert(klass->is_klass(), "must be"); + if (RegeneratedClasses::has_been_regenerated(klass)) { + klass = RegeneratedClasses::get_regenerated_object(klass); + } if (is_excluded(klass)) { ResourceMark rm; log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name()); @@ -847,7 +849,7 @@ void ArchiveBuilder::make_klasses_shareable() { address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start const int narrow_klass_shift = precomputed_narrow_klass_shift(); narrowKlass nk = CompressedKlassPointers::encode_not_null_without_asserts(requested_k, narrow_klass_base, narrow_klass_shift); - k->set_prototype_header(markWord::prototype().set_narrow_klass(nk)); + k->set_prototype_header_klass(nk); } #endif //_LP64 if (k->is_flatArray_klass()) { diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp index aaec179059e..ce79105bba7 100644 --- a/src/hotspot/share/cds/archiveHeapWriter.cpp +++ b/src/hotspot/share/cds/archiveHeapWriter.cpp @@ -27,6 +27,7 @@ #include "cds/cdsConfig.hpp" #include "cds/filemap.hpp" #include "cds/heapShared.hpp" +#include "cds/regeneratedClasses.hpp" #include "classfile/javaClasses.hpp" #include "classfile/modules.hpp" #include "classfile/systemDictionary.hpp" @@ -191,6 +192,7 @@ objArrayOop ArchiveHeapWriter::allocate_root_segment(size_t offset, int element_ if (UseCompactObjectHeaders) { oopDesc::release_set_mark(mem, Universe::objectArrayKlass()->prototype_header()); } else { + assert(!EnableValhalla || Universe::objectArrayKlass()->prototype_header() == markWord::prototype(), "should be the same"); oopDesc::set_mark(mem, markWord::prototype()); oopDesc::release_set_klass(mem, Universe::objectArrayKlass()); } @@ -543,6 +545,10 @@ template void ArchiveHeapWriter::relocate_field_in_buffer(T* field_ oop source_referent = load_source_oop_from_buffer(field_addr_in_buffer); if (source_referent != nullptr) { if (java_lang_Class::is_instance(source_referent)) { + Klass* k = java_lang_Class::as_Klass(source_referent); + if (RegeneratedClasses::has_been_regenerated(k)) { + source_referent = RegeneratedClasses::get_regenerated_object(k)->java_mirror(); + } // When the source object points to a "real" mirror, the buffered object should point // to the "scratch" mirror, which has all unarchivable fields scrubbed (to be reinstated // at run time). @@ -756,6 +762,11 @@ void ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) { Metadata** buffered_field_addr = requested_addr_to_buffered_addr(requested_field_addr); Metadata* native_ptr = *buffered_field_addr; guarantee(native_ptr != nullptr, "sanity"); + + if (RegeneratedClasses::has_been_regenerated(native_ptr)) { + native_ptr = RegeneratedClasses::get_regenerated_object(native_ptr); + } + guarantee(ArchiveBuilder::current()->has_been_buffered((address)native_ptr), "Metadata %p should have been archived", native_ptr); diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index b465ff256d5..066857dbd11 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -838,9 +838,6 @@ bool CDSConfig::is_dumping_regenerated_lambdaform_invokers() { // that point to the lambda form invokers in the base archive. Such pointers will // be invalid if lambda form invokers are regenerated in the dynamic archive. return false; - } else if (CDSConfig::is_dumping_method_handles()) { - // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated. - return false; } else { return is_dumping_archive(); } diff --git a/src/hotspot/share/cds/cdsProtectionDomain.cpp b/src/hotspot/share/cds/cdsProtectionDomain.cpp index d761db989c8..f44680b136b 100644 --- a/src/hotspot/share/cds/cdsProtectionDomain.cpp +++ b/src/hotspot/share/cds/cdsProtectionDomain.cpp @@ -27,7 +27,6 @@ #include "cds/cdsProtectionDomain.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/systemDictionaryShared.hpp" diff --git a/src/hotspot/share/cds/cds_globals.hpp b/src/hotspot/share/cds/cds_globals.hpp index e51dd26ff06..730902207f0 100644 --- a/src/hotspot/share/cds/cds_globals.hpp +++ b/src/hotspot/share/cds/cds_globals.hpp @@ -147,7 +147,7 @@ product(bool, AOTVerifyTrainingData, trueInDebug, DIAGNOSTIC, \ "Verify archived training data") \ \ - product(bool, AOTCompileEagerly, false, DIAGNOSTIC, \ + product(bool, AOTCompileEagerly, false, EXPERIMENTAL, \ "Compile methods as soon as possible") \ \ /* AOT Code flags */ \ diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 6c8165088a6..e5d843d0c81 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -30,7 +30,7 @@ #include "cds/lambdaProxyClassDictionary.hpp" #include "cds/metaspaceShared.hpp" #include "cds/unregisteredClasses.hpp" -#include "classfile/classLoaderExt.hpp" +#include "classfile/classLoader.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 1bb61892a1e..7b4cc2edaf7 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -39,7 +39,6 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoader.inline.hpp" #include "classfile/classLoaderData.inline.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" @@ -479,7 +478,7 @@ class FileHeaderHelper { assert(_archive_name != nullptr, "Archive name is null"); _fd = os::open(_archive_name, O_RDONLY | O_BINARY, 0); if (_fd < 0) { - aot_log_info(aot)("Specified %s not found (%s)", CDSConfig::type_of_archive_being_loaded(), _archive_name); + MetaspaceShared::report_loading_error("Specified %s not found (%s)", CDSConfig::type_of_archive_being_loaded(), _archive_name); return false; } return initialize(_fd); @@ -1292,8 +1291,8 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba // can't mmap into a ReservedSpace, so we just ::read() the data. We're going to patch all the // regions anyway, so there's no benefit for mmap anyway. if (!read_region(i, requested_addr, size, /* do_commit = */ true)) { - aot_log_info(aot)("Failed to read %s shared space into reserved space at " INTPTR_FORMAT, - shared_region_name[i], p2i(requested_addr)); + MetaspaceShared::report_loading_error("Failed to read %s shared space into reserved space at " INTPTR_FORMAT, + shared_region_name[i], p2i(requested_addr)); return MAP_ARCHIVE_OTHER_FAILURE; // oom or I/O error. } else { assert(r->mapped_base() != nullptr, "must be initialized"); @@ -1306,8 +1305,8 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba requested_addr, size, r->read_only(), r->allow_exec(), mtClassShared); if (base != requested_addr) { - aot_log_info(aot)("Unable to map %s shared space at " INTPTR_FORMAT, - shared_region_name[i], p2i(requested_addr)); + MetaspaceShared::report_loading_error("Unable to map %s shared space at " INTPTR_FORMAT, + shared_region_name[i], p2i(requested_addr)); _memory_mapping_failed = true; return MAP_ARCHIVE_MMAP_FAILURE; } @@ -1372,8 +1371,8 @@ bool FileMapInfo::map_aot_code_region(ReservedSpace rs) { char* mapped_base; if (MetaspaceShared::use_windows_memory_mapping()) { if (!read_region(MetaspaceShared::ac, requested_base, r->used_aligned(), /* do_commit = */ true)) { - aot_log_info(aot)("Failed to read aot code shared space into reserved space at " INTPTR_FORMAT, - p2i(requested_base)); + MetaspaceShared::report_loading_error("Failed to read aot code shared space into reserved space at " INTPTR_FORMAT, + p2i(requested_base)); return false; } mapped_base = requested_base; @@ -1385,7 +1384,7 @@ bool FileMapInfo::map_aot_code_region(ReservedSpace rs) { requested_base, r->used_aligned(), read_only, allow_exec, mtClassShared); } if (mapped_base == nullptr) { - aot_log_info(aot)("failed to map aot code region"); + MetaspaceShared::report_loading_error("failed to map aot code region"); return false; } else { assert(mapped_base == requested_base, "must be"); @@ -1761,9 +1760,9 @@ bool FileMapInfo::map_heap_region_impl() { r->allow_exec(), mtJavaHeap); if (base == nullptr || base != addr) { dealloc_heap_region(); - aot_log_info(aot)("UseSharedSpaces: Unable to map at required address in java heap. " - INTPTR_FORMAT ", size = %zu bytes", - p2i(addr), _mapped_heap_memregion.byte_size()); + MetaspaceShared::report_loading_error("UseSharedSpaces: Unable to map at required address in java heap. " + INTPTR_FORMAT ", size = %zu bytes", + p2i(addr), _mapped_heap_memregion.byte_size()); return false; } @@ -1999,16 +1998,16 @@ int FileMapHeader::compute_crc() { bool FileMapHeader::validate() { const char* file_type = CDSConfig::type_of_archive_being_loaded(); if (_obj_alignment != ObjectAlignmentInBytes) { - aot_log_info(aot)("The %s's ObjectAlignmentInBytes of %d" - " does not equal the current ObjectAlignmentInBytes of %d.", - file_type, _obj_alignment, ObjectAlignmentInBytes); + MetaspaceShared::report_loading_error("The %s's ObjectAlignmentInBytes of %d" + " does not equal the current ObjectAlignmentInBytes of %d.", + file_type, _obj_alignment, ObjectAlignmentInBytes); return false; } if (_compact_strings != CompactStrings) { - aot_log_info(aot)("The %s's CompactStrings setting (%s)" - " does not equal the current CompactStrings setting (%s).", file_type, - _compact_strings ? "enabled" : "disabled", - CompactStrings ? "enabled" : "disabled"); + MetaspaceShared::report_loading_error("The %s's CompactStrings setting (%s)" + " does not equal the current CompactStrings setting (%s).", file_type, + _compact_strings ? "enabled" : "disabled", + CompactStrings ? "enabled" : "disabled"); return false; } bool jvmci_compiler_is_enabled = CompilerConfig::is_jvmci_compiler_enabled(); @@ -2092,8 +2091,9 @@ bool FileMapHeader::validate() { const char* prop = Arguments::get_property("java.system.class.loader"); if (prop != nullptr) { if (has_aot_linked_classes()) { - aot_log_error(aot)("%s has aot-linked classes. It cannot be used when the " - "java.system.class.loader property is specified.", CDSConfig::type_of_archive_being_loaded()); + MetaspaceShared::report_loading_error("%s has aot-linked classes. It cannot be used when the " + "java.system.class.loader property is specified.", + CDSConfig::type_of_archive_being_loaded()); return false; } aot_log_warning(aot)("Archived non-system classes are disabled because the " @@ -2105,10 +2105,10 @@ bool FileMapHeader::validate() { if (!_verify_local && BytecodeVerificationLocal) { // we cannot load boot classes, so there's no point of using the CDS archive - aot_log_info(aot)("The %s's BytecodeVerificationLocal setting (%s)" - " does not equal the current BytecodeVerificationLocal setting (%s).", file_type, - _verify_local ? "enabled" : "disabled", - BytecodeVerificationLocal ? "enabled" : "disabled"); + MetaspaceShared::report_loading_error("The %s's BytecodeVerificationLocal setting (%s)" + " does not equal the current BytecodeVerificationLocal setting (%s).", file_type, + _verify_local ? "enabled" : "disabled", + BytecodeVerificationLocal ? "enabled" : "disabled"); return false; } @@ -2129,8 +2129,8 @@ bool FileMapHeader::validate() { // Note: _allow_archiving_with_java_agent is set in the shared archive during dump time // while AllowArchivingWithJavaAgent is set during the current run. if (_allow_archiving_with_java_agent && !AllowArchivingWithJavaAgent) { - aot_log_warning(aot)("The setting of the AllowArchivingWithJavaAgent is different " - "from the setting in the %s.", file_type); + MetaspaceShared::report_loading_error("The setting of the AllowArchivingWithJavaAgent is different " + "from the setting in the %s.", file_type); return false; } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index b53d19b79f4..a627891208f 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -36,8 +36,8 @@ #include "cds/cdsHeapVerifier.hpp" #include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" +#include "cds/regeneratedClasses.hpp" #include "classfile/classLoaderData.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/modules.hpp" #include "classfile/stringTable.hpp" @@ -337,6 +337,9 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra } else if (java_lang_invoke_ResolvedMethodName::is_instance(obj)) { Method* m = java_lang_invoke_ResolvedMethodName::vmtarget(obj); if (m != nullptr) { + if (RegeneratedClasses::has_been_regenerated(m)) { + m = RegeneratedClasses::get_regenerated_object(m); + } InstanceKlass* method_holder = m->method_holder(); AOTArtifactFinder::add_cached_class(method_holder); } @@ -506,10 +509,17 @@ void HeapShared::copy_and_rescan_aot_inited_mirror(InstanceKlass* ik) { ik->set_is_runtime_setup_required(); } - oop orig_mirror = ik->java_mirror(); - oop m = scratch_java_mirror(ik); - assert(ik->is_initialized(), "must be"); + oop orig_mirror; + if (RegeneratedClasses::is_regenerated_object(ik)) { + InstanceKlass* orig_ik = RegeneratedClasses::get_original_object(ik); + precond(orig_ik->is_initialized()); + orig_mirror = orig_ik->java_mirror(); + } else { + precond(ik->is_initialized()); + orig_mirror = ik->java_mirror(); + } + oop m = scratch_java_mirror(ik); int nfields = 0; for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { @@ -587,6 +597,7 @@ static void copy_java_mirror_hashcode(oop orig_mirror, oop scratch_m) { narrowKlass nk = CompressedKlassPointers::encode(orig_mirror->klass()); scratch_m->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash)); } else { + // For valhalla, the prototype header is the same as markWord::prototype(); scratch_m->set_mark(markWord::prototype().copy_set_hash(src_hash)); } assert(scratch_m->mark().is_unlocked(), "sanity"); @@ -1524,6 +1535,13 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap p2i(scratch_java_mirror(orig_obj))); } + if (java_lang_Class::is_instance(orig_obj)) { + Klass* k = java_lang_Class::as_Klass(orig_obj); + if (RegeneratedClasses::has_been_regenerated(k)) { + orig_obj = RegeneratedClasses::get_regenerated_object(k)->java_mirror(); + } + } + if (CDSConfig::is_initing_classes_at_dump_time()) { if (java_lang_Class::is_instance(orig_obj)) { orig_obj = scratch_java_mirror(orig_obj); diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index d6a51c87513..ab91e76e923 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -224,6 +224,7 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, result->set_is_generated_shared_class(); if (!klass->is_shared()) { + log_info(aot, lambda)("regenerate_class excluding klass %s %s", class_name, klass->name()->as_C_string()); SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); // exclude the existing class from dump } log_info(aot, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index d2ea0b487e5..2883027256c 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -49,7 +49,6 @@ #include "cds/metaspaceShared.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/classLoaderDataShared.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/modules.hpp" @@ -839,11 +838,10 @@ void MetaspaceShared::preload_and_dump(TRAPS) { struct stat st; if (os::stat(AOTCache, &st) != 0) { tty->print_cr("AOTCache creation failed: %s", AOTCache); - vm_exit(0); } else { tty->print_cr("AOTCache creation is complete: %s " INT64_FORMAT " bytes", AOTCache, (int64_t)(st.st_size)); - vm_exit(0); } + vm_direct_exit(0); } } } diff --git a/src/hotspot/share/cds/regeneratedClasses.cpp b/src/hotspot/share/cds/regeneratedClasses.cpp index 38bf1a11952..b36f360b82a 100644 --- a/src/hotspot/share/cds/regeneratedClasses.cpp +++ b/src/hotspot/share/cds/regeneratedClasses.cpp @@ -24,6 +24,7 @@ #include "cds/archiveBuilder.hpp" #include "cds/regeneratedClasses.hpp" +#include "classfile/vmSymbols.hpp" #include "memory/universe.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" @@ -34,7 +35,8 @@ #include "utilities/resourceHash.hpp" using RegeneratedObjTable = ResourceHashtable; -static RegeneratedObjTable* _renegerated_objs = nullptr; // InstanceKlass* and Method* +static RegeneratedObjTable* _regenerated_objs = nullptr; // InstanceKlass* and Method* orig_obj -> regen_obj +static RegeneratedObjTable* _original_objs = nullptr; // InstanceKlass* and Method* regen_obj -> orig_obj static GrowableArrayCHeap* _regenerated_mirrors = nullptr; // The regenerated Klass is not added to any class loader, so we need @@ -46,40 +48,71 @@ void RegeneratedClasses::add_class(InstanceKlass* orig_klass, InstanceKlass* reg } _regenerated_mirrors->append(OopHandle(Universe::vm_global(), regen_klass->java_mirror())); - if (_renegerated_objs == nullptr) { - _renegerated_objs = new (mtClass)RegeneratedObjTable(); + if (_regenerated_objs == nullptr) { + _regenerated_objs = new (mtClass)RegeneratedObjTable(); + } + if (_original_objs == nullptr) { + _original_objs = new (mtClass)RegeneratedObjTable(); } - _renegerated_objs->put((address)orig_klass, (address)regen_klass); + _regenerated_objs->put((address)orig_klass, (address)regen_klass); + _original_objs->put((address)regen_klass, (address)orig_klass); Array* methods = orig_klass->methods(); for (int i = 0; i < methods->length(); i++) { Method* orig_m = methods->at(i); Method* regen_m = regen_klass->find_method(orig_m->name(), orig_m->signature()); if (regen_m == nullptr) { ResourceMark rm; - log_warning(aot)("Method in original class is missing from regenerated class: " INTPTR_FORMAT " %s", - p2i(orig_m), orig_m->external_name()); + if (orig_m->name() != vmSymbols::object_initializer_name()) { + // JLI Holder classes are never instantiated, they don't need to have constructors. + // Not printing the warning if the method is a constructor. + log_warning(aot)("Method in original class is missing from regenerated class: " INTPTR_FORMAT " %s", + p2i(orig_m), orig_m->external_name()); + } } else { - _renegerated_objs->put((address)orig_m, (address)regen_m); + _regenerated_objs->put((address)orig_m, (address)regen_m); + _original_objs->put((address)regen_m, (address)orig_m); } } } bool RegeneratedClasses::has_been_regenerated(address orig_obj) { - if (_renegerated_objs == nullptr) { + if (_regenerated_objs == nullptr) { + return false; + } else { + return _regenerated_objs->get(orig_obj) != nullptr; + } +} + +address RegeneratedClasses::get_regenerated_object(address orig_obj) { + assert(_regenerated_objs != nullptr, "must be"); + address* p =_regenerated_objs->get(orig_obj); + assert(p != nullptr, "must be"); + return *p; +} + +bool RegeneratedClasses::is_regenerated_object(address regen_obj) { + if (_original_objs == nullptr) { return false; } else { - return _renegerated_objs->get(orig_obj) != nullptr; + return _original_objs->get(regen_obj) != nullptr; } } +address RegeneratedClasses::get_original_object(address regen_obj) { + assert(_original_objs != nullptr, "must be"); + address* p =_original_objs->get(regen_obj); + assert(p != nullptr, "must be"); + return *p; +} + void RegeneratedClasses::record_regenerated_objects() { assert_locked_or_safepoint(DumpTimeTable_lock); - if (_renegerated_objs != nullptr) { + if (_regenerated_objs != nullptr) { auto doit = [&] (address orig_obj, address regen_obj) { ArchiveBuilder::current()->record_regenerated_object(orig_obj, regen_obj); }; - _renegerated_objs->iterate_all(doit); + _regenerated_objs->iterate_all(doit); } } @@ -92,7 +125,7 @@ void RegeneratedClasses::cleanup() { delete _regenerated_mirrors; _regenerated_mirrors = nullptr; } - if (_renegerated_objs != nullptr) { - delete _renegerated_objs; + if (_regenerated_objs != nullptr) { + delete _regenerated_objs; } } diff --git a/src/hotspot/share/cds/regeneratedClasses.hpp b/src/hotspot/share/cds/regeneratedClasses.hpp index a1edaffe529..080d84a2154 100644 --- a/src/hotspot/share/cds/regeneratedClasses.hpp +++ b/src/hotspot/share/cds/regeneratedClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -43,7 +43,26 @@ class RegeneratedClasses : public AllStatic { static void add_class(InstanceKlass* orig_klass, InstanceKlass* regen_klass); static void cleanup(); static bool has_been_regenerated(address orig_obj); + static address get_regenerated_object(address orig_obj); // orig_obj -> regen_obj static void record_regenerated_objects(); + + // Handy functions to avoid type casts + template static bool has_been_regenerated(T orig_obj) { + return has_been_regenerated((address)orig_obj); + } + template static T get_regenerated_object(T orig_obj) { + return (T)get_regenerated_object((address)orig_obj); + } + + static bool is_regenerated_object(address regen_obj); + static address get_original_object(address regen_obj); // regen_obj -> orig_obj + + template static bool is_regenerated_object(T regen_obj) { + return is_regenerated_object((address)regen_obj); + } + template static T get_original_object(T regen_obj) { + return (T)get_original_object((address)regen_obj); + } }; #endif // SHARE_CDS_REGENERATEDCLASSES_HPP diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 81ec57f33b8..c390e91ca58 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -3063,15 +3063,15 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea "Class is both outer and inner class in class file %s", CHECK_0); } - u2 recognized_modifiers = RECOGNIZED_INNER_CLASS_MODIFIERS; + // Access flags + u2 flags; // JVM_ACC_MODULE is defined in JDK-9 and later. if (_major_version >= JAVA_9_VERSION) { - recognized_modifiers |= JVM_ACC_MODULE; + flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS | JVM_ACC_MODULE); + } else { + flags = cfs->get_u2_fast() & RECOGNIZED_INNER_CLASS_MODIFIERS; } - // Access flags - u2 flags = cfs->get_u2_fast() & recognized_modifiers; - if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) { // Set abstract bit for old class files for backward compatibility flags |= JVM_ACC_ABSTRACT; @@ -3085,8 +3085,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea } } - const char* name = inner_name_index == 0 ? "unnamed" : cp->symbol_at(inner_name_index)->as_utf8(); - verify_legal_class_modifiers(flags, name, false, CHECK_0); + verify_legal_class_modifiers(flags, CHECK_0); AccessFlags inner_access_flags(flags); inner_classes->at_put(index++, inner_class_info_index); @@ -4427,9 +4426,8 @@ static void check_illegal_static_method(const InstanceKlass* this_klass, TRAPS) // utility methods for format checking -void ClassFileParser::verify_legal_class_modifiers(jint flags, const char* name, bool is_Object, TRAPS) const { +void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const { const bool is_module = (flags & JVM_ACC_MODULE) != 0; - const bool is_inner_class = name != nullptr; assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set"); if (is_module) { ResourceMark rm(THREAD); @@ -4464,24 +4462,13 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, const char* name, if (!valid_value_class) { class_note = " (a value class must be final or else abstract)"; } - if (name == nullptr) { // Not an inner class - Exceptions::fthrow( - THREAD_AND_LOCATION, - vmSymbols::java_lang_ClassFormatError(), - "Illegal class modifiers in class %s%s: 0x%X", - _class_name->as_C_string(), class_note, flags - ); - return; - } else { - // Names are all known to be < 64k so we know this formatted message is not excessively large. - Exceptions::fthrow( - THREAD_AND_LOCATION, - vmSymbols::java_lang_ClassFormatError(), - "Illegal class modifiers in declaration of inner class %s%s of class %s: 0x%X", - name, class_note, _class_name->as_C_string(), flags - ); - return; - } + Exceptions::fthrow( + THREAD_AND_LOCATION, + vmSymbols::java_lang_ClassFormatError(), + "Illegal class modifiers in class %s%s: 0x%X", + _class_name->as_C_string(), class_note, flags + ); + return; } } @@ -5444,7 +5431,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, assert(module_entry != nullptr, "module_entry should always be set"); // Obtain java.lang.Module - Handle module_handle(THREAD, module_entry->module()); + Handle module_handle(THREAD, module_entry->module_oop()); // Allocate mirror and initialize static fields java_lang_Class::create_mirror(ik, @@ -5793,15 +5780,15 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, // ACCESS FLAGS stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len - u2 recognized_modifiers = JVM_RECOGNIZED_CLASS_MODIFIERS; + // Access flags + u2 flags; // JVM_ACC_MODULE is defined in JDK-9 and later. if (_major_version >= JAVA_9_VERSION) { - recognized_modifiers |= JVM_ACC_MODULE; + flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE); + } else { + flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS; } - // Access flags - u2 flags = stream->get_u2_fast() & recognized_modifiers; - if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) { // Set abstract bit for old class files for backward compatibility flags |= JVM_ACC_ABSTRACT; @@ -5816,6 +5803,17 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, } } + verify_legal_class_modifiers(flags, CHECK); + + short bad_constant = class_bad_constant_seen(); + if (bad_constant != 0) { + // Do not throw CFE until after the access_flags are checked because if + // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. + classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD); + return; + } + + _access_flags.set_flags(flags); // This class and superclass _this_class_index = stream->get_u2_fast(); @@ -5828,20 +5826,6 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != nullptr, "class_name can't be null"); - bool is_java_lang_Object = class_name_in_cp == vmSymbols::java_lang_Object(); - - verify_legal_class_modifiers(flags, nullptr, is_java_lang_Object, CHECK); - - _access_flags.set_flags(flags); - - short bad_constant = class_bad_constant_seen(); - if (bad_constant != 0) { - // Do not throw CFE until after the access_flags are checked because if - // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. - classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD); - return; - } - // Don't need to check whether this class name is legal or not. // It has been checked when constant pool is parsed. // However, make sure it is not an array type. @@ -6034,7 +6018,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st _super_klass = vmClasses::Object_klass(); } else { _super_klass = (const InstanceKlass*) - SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, + SystemDictionary::resolve_super_or_fail(_class_name, super_class_name, loader, true, @@ -6106,7 +6090,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st "Bad interface name in class file %s", CHECK); // Call resolve on the interface class name with class circularity checking - interf = SystemDictionary::resolve_with_circularity_detection_or_fail( + interf = SystemDictionary::resolve_super_or_fail( _class_name, unresolved_klass, Handle(THREAD, _loader_data->class_loader()), @@ -6185,10 +6169,10 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st log_info(class, preload)("Preloading of class %s during loading of class %s. " "Cause: a null-free non-static field is declared with this type", s->as_C_string(), _class_name->as_C_string()); - InstanceKlass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, s, - Handle(THREAD, - _loader_data->class_loader()), - false, THREAD); + InstanceKlass* klass = SystemDictionary::resolve_with_circularity_detection(_class_name, s, + Handle(THREAD, + _loader_data->class_loader()), + false, THREAD); if (HAS_PENDING_EXCEPTION) { log_warning(class, preload)("Preloading of class %s during loading of class %s " "(cause: null-free non-static field) failed: %s", @@ -6212,9 +6196,9 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st "Cause: field type in LoadableDescriptors attribute", name->as_C_string(), _class_name->as_C_string()); oop loader = loader_data()->class_loader(); - Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, name, - Handle(THREAD, loader), - false, THREAD); + Klass* klass = SystemDictionary::resolve_super_or_fail(_class_name, name, + Handle(THREAD, loader), + false, THREAD); if (klass != nullptr) { if (klass->is_inline_klass()) { _inline_layout_info_array->adr_at(fieldinfo.index())->set_klass(InlineKlass::cast(klass)); diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 1a855971965..91f586c330f 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -464,7 +464,7 @@ class ClassFileParser { void verify_class_version(u2 major, u2 minor, Symbol* class_name, TRAPS); - void verify_legal_class_modifiers(jint flags, const char* name, bool is_Object, TRAPS) const; + void verify_legal_class_modifiers(jint flags, TRAPS) const; void verify_legal_field_modifiers(jint flags, AccessFlags class_access_flags, TRAPS) const; diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 6f3d10a346e..2872b492631 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -25,11 +25,11 @@ #include "cds/aotClassLocation.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" +#include "cds/dynamicArchive.hpp" #include "cds/heapShared.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoader.inline.hpp" #include "classfile/classLoaderData.inline.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/classLoadInfo.hpp" #include "classfile/javaClasses.hpp" #include "classfile/klassFactory.hpp" @@ -96,9 +96,18 @@ static JImageClose_t JImageClose = nullptr; static JImageFindResource_t JImageFindResource = nullptr; static JImageGetResource_t JImageGetResource = nullptr; -// JimageFile pointer, or null if exploded JDK build. +// JImageFile pointer, or null if exploded JDK build. static JImageFile* JImage_file = nullptr; +// JImageMode status to control preview behaviour. JImage_file is unusable +// for normal lookup until (JImage_mode != JIMAGE_MODE_UNINITIALIZED). +enum JImageMode { + JIMAGE_MODE_UNINITIALIZED = 0, + JIMAGE_MODE_DEFAULT = 1, + JIMAGE_MODE_ENABLE_PREVIEW = 2 +}; +static JImageMode JImage_mode = JIMAGE_MODE_UNINITIALIZED; + // Globals PerfCounter* ClassLoader::_perf_accumulated_time = nullptr; @@ -153,7 +162,7 @@ void ClassLoader::print_counters(outputStream *st) { GrowableArray* ClassLoader::_patch_mod_entries = nullptr; GrowableArray* ClassLoader::_exploded_entries = nullptr; -ClassPathEntry* ClassLoader::_jrt_entry = nullptr; +ClassPathImageEntry* ClassLoader::_jrt_entry = nullptr; ClassPathEntry* volatile ClassLoader::_first_append_entry_list = nullptr; ClassPathEntry* volatile ClassLoader::_last_append_entry = nullptr; @@ -170,15 +179,6 @@ static bool string_starts_with(const char* str, const char* str_to_find) { } #endif -static const char* get_jimage_version_string() { - static char version_string[10] = ""; - if (version_string[0] == '\0') { - jio_snprintf(version_string, sizeof(version_string), "%d.%d", - VM_Version::vm_major_version(), VM_Version::vm_minor_version()); - } - return (const char*)version_string; -} - bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) { size_t str_len = strlen(str); size_t str_to_find_len = strlen(str_to_find); @@ -233,6 +233,73 @@ Symbol* ClassLoader::package_from_class_name(const Symbol* name, bool* bad_class return SymbolTable::new_symbol(name, pointer_delta_as_int(start, base), pointer_delta_as_int(end, base)); } +// -------------------------------- +// The following jimage_xxx static functions encapsulate all JImage_file and JImage_mode access. +// This is done to make it easy to reason about the JImage file state (exists vs initialized etc.). + +// Opens the named JImage file and sets the JImage file reference. +// Returns true if opening the JImage file was successful (see also jimage_exists()). +static bool jimage_open(const char* modules_path) { + // Currently 'error' is not set to anything useful, so ignore it here. + jint error; + JImage_file = (*JImageOpen)(modules_path, &error); + return JImage_file != nullptr; +} + +// Closes and clears the JImage file reference (this will only be called during shutdown). +static void jimage_close() { + if (JImage_file != nullptr) { + (*JImageClose)(JImage_file); + JImage_file = nullptr; + } +} + +// Returns whether a JImage file was opened (but NOT whether it was initialized yet). +static bool jimage_exists() { + return JImage_file != nullptr; +} + +// Returns the JImage file reference (which may or may not be initialized). +static JImageFile* jimage_non_null() { + assert(jimage_exists(), "should have been opened by ClassLoader::lookup_vm_options " + "and remained throughout normal JVM lifetime"); + return JImage_file; +} + +// Called once to set the access mode for resource (i.e. preview or non-preview) before +// general resource lookup can occur. +static void jimage_init(bool enable_preview) { + assert(JImage_mode == JIMAGE_MODE_UNINITIALIZED, "jimage_init must not be called twice"); + JImage_mode = enable_preview ? JIMAGE_MODE_ENABLE_PREVIEW : JIMAGE_MODE_DEFAULT; +} + +// Returns true if jimage_init() has been called. Once the JImage file is initialized, +// jimage_is_preview_enabled() can be called to correctly determine the access mode. +static bool jimage_is_initialized() { + return jimage_exists() && JImage_mode != JIMAGE_MODE_UNINITIALIZED; +} + +// Returns the access mode for an initialized JImage file (reflects --enable-preview). +static bool jimage_is_preview_enabled() { + assert(jimage_is_initialized(), "jimage is not initialized"); + return JImage_mode == JIMAGE_MODE_ENABLE_PREVIEW; +} + +// Looks up the location of a named JImage resource. This "raw" lookup function allows +// the preview mode to be manually specified, so must not be accessible outside this +// class. ClassPathImageEntry manages all calls for resources after startup is complete. +static JImageLocationRef jimage_find_resource(const char* module_name, + const char* file_name, + bool is_preview, + jlong *size) { + return ((*JImageFindResource)(jimage_non_null(), + module_name, + file_name, + is_preview, + size)); +} +// -------------------------------- + // Given a fully qualified package name, find its defining package in the class loader's // package entry table. PackageEntry* ClassLoader::get_package_entry(Symbol* pkg_name, ClassLoaderData* loader_data) { @@ -371,28 +438,15 @@ ClassFileStream* ClassPathZipEntry::open_stream(JavaThread* current, const char* DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = nullptr;) -JImageFile* ClassPathImageEntry::jimage() const { - return JImage_file; -} - -JImageFile* ClassPathImageEntry::jimage_non_null() const { - assert(ClassLoader::has_jrt_entry(), "must be"); - assert(jimage() != nullptr, "should have been opened by ClassLoader::lookup_vm_options " - "and remained throughout normal JVM lifetime"); - return jimage(); -} - void ClassPathImageEntry::close_jimage() { - if (jimage() != nullptr) { - (*JImageClose)(jimage()); - JImage_file = nullptr; - } + jimage_close(); } -ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) : +ClassPathImageEntry::ClassPathImageEntry(const char* name) : ClassPathEntry() { - guarantee(jimage != nullptr, "jimage file is null"); + guarantee(jimage_is_initialized(), "jimage is not initialized"); guarantee(name != nullptr, "jimage file name is null"); + assert(_singleton == nullptr, "VM supports only one jimage"); DEBUG_ONLY(_singleton = this); size_t len = strlen(name) + 1; @@ -411,8 +465,10 @@ ClassFileStream* ClassPathImageEntry::open_stream(JavaThread* current, const cha // 2. A package is in at most one module in the jimage file. // ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current, const char* name, ClassLoaderData* loader_data) { + bool is_preview = jimage_is_preview_enabled(); + jlong size; - JImageLocationRef location = (*JImageFindResource)(jimage_non_null(), "", get_jimage_version_string(), name, &size); + JImageLocationRef location = jimage_find_resource("", name, is_preview, &size); if (location == 0) { TempNewSymbol class_name = SymbolTable::new_symbol(name); @@ -420,7 +476,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current if (pkg_name != nullptr) { if (!Universe::is_module_initialized()) { - location = (*JImageFindResource)(jimage_non_null(), JAVA_BASE_NAME, get_jimage_version_string(), name, &size); + location = jimage_find_resource(JAVA_BASE_NAME, name, is_preview, &size); } else { PackageEntry* package_entry = ClassLoader::get_package_entry(pkg_name, loader_data); if (package_entry != nullptr) { @@ -431,7 +487,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current assert(module->is_named(), "Boot classLoader package is in unnamed module"); const char* module_name = module->name()->as_C_string(); if (module_name != nullptr) { - location = (*JImageFindResource)(jimage_non_null(), module_name, get_jimage_version_string(), name, &size); + location = jimage_find_resource(module_name, name, is_preview, &size); } } } @@ -444,7 +500,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current char* data = NEW_RESOURCE_ARRAY(char, size); (*JImageGetResource)(jimage_non_null(), location, data, size); // Resource allocated - assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be"); + assert(this == ClassLoader::get_jrt_entry(), "must be"); return new ClassFileStream((u1*)data, checked_cast(size), _name, @@ -454,16 +510,9 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current return nullptr; } -JImageLocationRef ClassLoader::jimage_find_resource(JImageFile* jf, - const char* module_name, - const char* file_name, - jlong &size) { - return ((*JImageFindResource)(jf, module_name, get_jimage_version_string(), file_name, &size)); -} - bool ClassPathImageEntry::is_modules_image() const { assert(this == _singleton, "VM supports a single jimage"); - assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be used for jrt entry"); + assert(this == ClassLoader::get_jrt_entry(), "must be used for jrt entry"); return true; } @@ -618,14 +667,15 @@ void ClassLoader::setup_bootstrap_search_path_impl(JavaThread* current, const ch struct stat st; if (os::stat(path, &st) == 0) { // Directory found - if (JImage_file != nullptr) { + if (jimage_exists()) { assert(Arguments::has_jimage(), "sanity check"); const char* canonical_path = get_canonical_path(path, current); assert(canonical_path != nullptr, "canonical_path issue"); - _jrt_entry = new ClassPathImageEntry(JImage_file, canonical_path); + // Hand over lifecycle control of the JImage file to the _jrt_entry singleton + // (see ClassPathImageEntry::close_jimage). The image must be initialized by now. + _jrt_entry = new ClassPathImageEntry(canonical_path); assert(_jrt_entry != nullptr && _jrt_entry->is_modules_image(), "No java runtime image present"); - assert(_jrt_entry->jimage() != nullptr, "No java runtime image"); } // else it's an exploded build. } else { // If path does not exist, exit @@ -1305,7 +1355,47 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, const char* const file_name = file_name_for_class_name(class_name, ik->name()->utf8_length()); assert(file_name != nullptr, "invariant"); - ClassLoaderExt::record_result_for_builtin_loader(checked_cast(classpath_index), ik, redefined); + record_result_for_builtin_loader(checked_cast(classpath_index), ik, redefined); +} + +void ClassLoader::record_result_for_builtin_loader(s2 classpath_index, InstanceKlass* result, bool redefined) { + assert(CDSConfig::is_dumping_archive(), "sanity"); + + oop loader = result->class_loader(); + if (SystemDictionary::is_system_class_loader(loader)) { + AOTClassLocationConfig::dumptime_set_has_app_classes(); + } else if (SystemDictionary::is_platform_class_loader(loader)) { + AOTClassLocationConfig::dumptime_set_has_platform_classes(); + } else { + precond(loader == nullptr); + } + + if (CDSConfig::is_dumping_preimage_static_archive() || CDSConfig::is_dumping_dynamic_archive()) { + if (!AOTClassLocationConfig::dumptime()->is_valid_classpath_index(classpath_index, result)) { + classpath_index = -1; + } + } + + AOTClassLocationConfig::dumptime_update_max_used_index(classpath_index); + result->set_shared_classpath_index(classpath_index); + +#if INCLUDE_CDS_JAVA_HEAP + if (CDSConfig::is_dumping_heap() && AllowArchivingWithJavaAgent && result->defined_by_boot_loader() && + classpath_index < 0 && redefined) { + // When dumping the heap (which happens only during static dump), classes for the built-in + // loaders are always loaded from known locations (jimage, classpath or modulepath), + // so classpath_index should always be >= 0. + // The only exception is when a java agent is used during dump time (for testing + // purposes only). If a class is transformed by the agent, the AOTClassLocation of + // this class may point to an unknown location. This may break heap object archiving, + // which requires all the boot classes to be from known locations. This is an + // uncommon scenario (even in test cases). Let's simply disable heap object archiving. + ResourceMark rm; + log_warning(aot)("heap objects cannot be written because class %s maybe modified by ClassFileLoadHook.", + result->external_name()); + CDSConfig::disable_heap_dumping(); + } +#endif // INCLUDE_CDS_JAVA_HEAP } void ClassLoader::record_hidden_class(InstanceKlass* ik) { @@ -1330,6 +1420,17 @@ void ClassLoader::record_hidden_class(InstanceKlass* ik) { } } } + +void ClassLoader::append_boot_classpath(ClassPathEntry* new_entry) { + if (CDSConfig::is_using_archive()) { + warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended"); + FileMapInfo::current_info()->set_has_platform_or_app_classes(false); + if (DynamicArchive::is_mapped()) { + FileMapInfo::dynamic_info()->set_has_platform_or_app_classes(false); + } + } + add_to_boot_append_entries(new_entry); +} #endif // INCLUDE_CDS // Initialize the class loader's access to methods in libzip. Parse and @@ -1388,20 +1489,8 @@ void ClassLoader::initialize(TRAPS) { setup_bootstrap_search_path(THREAD); } -static char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) { - jlong size; - JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", jimage_version, path, &size); - if (location == 0) - return nullptr; - char *val = NEW_C_HEAP_ARRAY(char, size+1, mtClass); - (*JImageGetResource)(jimage, location, val, size); - val[size] = '\0'; - return val; -} - // Lookup VM options embedded in the modules jimage file char* ClassLoader::lookup_vm_options() { - jint error; char modules_path[JVM_MAXPATHLEN]; const char* fileSep = os::file_separator(); @@ -1409,28 +1498,42 @@ char* ClassLoader::lookup_vm_options() { load_jimage_library(); jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep); - JImage_file =(*JImageOpen)(modules_path, &error); - if (JImage_file == nullptr) { - return nullptr; + if (jimage_open(modules_path)) { + // Special case where we lookup the options string *before* calling jimage_init(). + // Since VM arguments have not been parsed, and the ClassPathImageEntry singleton + // has not been created yet, we access the JImage file directly in non-preview mode. + jlong size; + JImageLocationRef location = + jimage_find_resource(JAVA_BASE_NAME, "jdk/internal/vm/options", /* is_preview */ false, &size); + if (location != 0) { + char *options = NEW_C_HEAP_ARRAY(char, size+1, mtClass); + (*JImageGetResource)(jimage_non_null(), location, options, size); + options[size] = '\0'; + return options; + } } + return nullptr; +} - const char *jimage_version = get_jimage_version_string(); - char *options = lookup_vm_resource(JImage_file, jimage_version, "jdk/internal/vm/options"); - return options; +// Finishes initializing the JImageFile (if present) by setting the access mode. +void ClassLoader::init_jimage(bool enable_preview) { + if (jimage_exists()) { + jimage_init(enable_preview); + } } bool ClassLoader::is_module_observable(const char* module_name) { assert(JImageOpen != nullptr, "jimage library should have been opened"); - if (JImage_file == nullptr) { + if (!jimage_exists()) { struct stat st; const char *path = get_exploded_module_path(module_name, true); bool res = os::stat(path, &st) == 0; FREE_C_HEAP_ARRAY(char, path); return res; } + // We don't expect preview mode (i.e. --enable-preview) to affect module visibility. jlong size; - const char *jimage_version = get_jimage_version_string(); - return (*JImageFindResource)(JImage_file, module_name, jimage_version, "module-info.class", &size) != 0; + return jimage_find_resource(module_name, "module-info.class", /* is_preview */ false, &size) != 0; } jlong ClassLoader::classloader_time_ms() { diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index d762e6caca7..574dd3ccd07 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -99,7 +99,8 @@ class ClassPathZipEntry: public ClassPathEntry { }; -// For java image files +// A singleton path entry which takes ownership of the initialized JImageFile +// reference. Not used for exploded builds. class ClassPathImageEntry: public ClassPathEntry { private: const char* _name; @@ -107,11 +108,12 @@ class ClassPathImageEntry: public ClassPathEntry { public: bool is_modules_image() const; const char* name() const { return _name == nullptr ? "" : _name; } - JImageFile* jimage() const; - JImageFile* jimage_non_null() const; + // Called to close the JImage during os::abort (normally not called). void close_jimage(); - ClassPathImageEntry(JImageFile* jimage, const char* name); + // Takes effective ownership of the static JImageFile pointer. + ClassPathImageEntry(const char* name); virtual ~ClassPathImageEntry() { ShouldNotReachHere(); } + ClassFileStream* open_stream(JavaThread* current, const char* name); ClassFileStream* open_stream_for_loader(JavaThread* current, const char* name, ClassLoaderData* loader_data); }; @@ -200,10 +202,10 @@ class ClassLoader: AllStatic { static GrowableArray* _patch_mod_entries; // 2. the base piece - // Contains the ClassPathEntry of the modular java runtime image. + // Contains the ClassPathImageEntry of the modular java runtime image. // If no java runtime image is present, this indicates a // build with exploded modules is being used instead. - static ClassPathEntry* _jrt_entry; + static ClassPathImageEntry* _jrt_entry; static GrowableArray* _exploded_entries; enum { EXPLODED_ENTRY_SIZE = 80 }; // Initial number of exploded modules @@ -345,18 +347,25 @@ class ClassLoader: AllStatic { static char* uri_to_path(const char* uri); static void record_result(JavaThread* current, InstanceKlass* ik, const ClassFileStream* stream, bool redefined); + static void record_result_for_builtin_loader(s2 classpath_index, InstanceKlass* result, bool redefined); static void record_hidden_class(InstanceKlass* ik); + static void append_boot_classpath(ClassPathEntry* new_entry); #endif + // Retrieves additional VM options prior to flags processing. Options held + // in the JImage file are retrieved without fully initializing it. (this is + // the only JImage lookup which can succeed before init_jimage() is called). static char* lookup_vm_options(); + // Called once, after all flags are processed, to finish initializing the + // JImage file. Until this is called, jimage_find_resource(), and any other + // JImage resource lookups or access will fail. + static void init_jimage(bool enable_preview); + // Determines if the named module is present in the // modules jimage file or in the exploded modules directory. static bool is_module_observable(const char* module_name); - static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name, - const char* file_name, jlong &size); - static void trace_class_path(const char* msg, const char* name = nullptr); // VM monitoring and management support diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index 8e14051cb72..d71f73e51e9 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -66,6 +66,7 @@ #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/inlineKlass.inline.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" @@ -589,6 +590,33 @@ void ClassLoaderData::remove_class(Klass* scratch_class) { ShouldNotReachHere(); // should have found this class!! } +void ClassLoaderData::add_jmethod_id(jmethodID mid) { + MutexLocker m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); + if (_jmethod_ids == nullptr) { + _jmethod_ids = new (mtClass) GrowableArray(32, mtClass); + } + _jmethod_ids->push(mid); +} + +// Method::remove_jmethod_ids removes jmethodID entries from the table which +// releases memory. +// Because native code (e.g., JVMTI agent) holding jmethod_ids may access them +// after the associated classes and class loader are unloaded, subsequent lookups +// for these ids will return null since they are no longer found in the table. +// The Java Native Interface Specification says "method ID +// does not prevent the VM from unloading the class from which the ID has +// been derived. After the class is unloaded, the method or field ID becomes +// invalid". +void ClassLoaderData::remove_jmethod_ids() { + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + for (int i = 0; i < _jmethod_ids->length(); i++) { + jmethodID mid = _jmethod_ids->at(i); + JmethodIDTable::remove(mid); + } + delete _jmethod_ids; + _jmethod_ids = nullptr; +} + void ClassLoaderData::unload() { _unloading = true; @@ -612,19 +640,8 @@ void ClassLoaderData::unload() { // after erroneous classes are released. classes_do(InstanceKlass::unload_class); - // Method::clear_jmethod_ids only sets the jmethod_ids to null without - // releasing the memory for related JNIMethodBlocks and JNIMethodBlockNodes. - // This is done intentionally because native code (e.g. JVMTI agent) holding - // jmethod_ids may access them after the associated classes and class loader - // are unloaded. The Java Native Interface Specification says "method ID - // does not prevent the VM from unloading the class from which the ID has - // been derived. After the class is unloaded, the method or field ID becomes - // invalid". In real world usages, the native code may rely on jmethod_ids - // being null after class unloading. Hence, it is unsafe to free the memory - // from the VM side without knowing when native code is going to stop using - // them. if (_jmethod_ids != nullptr) { - Method::clear_jmethod_ids(this); + remove_jmethod_ids(); } } @@ -1054,9 +1071,7 @@ void ClassLoaderData::print_on(outputStream* out) const { out->print_cr(" - dictionary " INTPTR_FORMAT, p2i(_dictionary)); } if (_jmethod_ids != nullptr) { - out->print (" - jmethod count "); - Method::print_jmethod_ids_count(this, out); - out->print_cr(""); + out->print_cr(" - jmethod count %d", _jmethod_ids->length()); } out->print_cr(" - deallocate list " INTPTR_FORMAT, p2i(_deallocate_list)); out->print_cr(" - next CLD " INTPTR_FORMAT, p2i(_next)); diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp index 4372830a6b9..09cfbc3577a 100644 --- a/src/hotspot/share/classfile/classLoaderData.hpp +++ b/src/hotspot/share/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -53,7 +53,6 @@ // and provides iterators for root tracing and other GC operations. class ClassLoaderDataGraph; -class JNIMethodBlock; class ModuleEntry; class PackageEntry; class ModuleEntryTable; @@ -98,11 +97,7 @@ class ClassLoaderData : public CHeapObj { }; friend class ClassLoaderDataGraph; - template - friend class ClassLoaderDataGraphIteratorBase; friend class ClassLoaderDataGraphKlassIteratorAtomic; - friend class ClassLoaderDataGraphKlassIteratorStatic; - friend class ClassLoaderDataGraphMetaspaceIterator; friend class Klass; friend class MetaDataFactory; friend class Method; @@ -143,10 +138,9 @@ class ClassLoaderData : public CHeapObj { ModuleEntry* _unnamed_module; // This class loader's unnamed module. Dictionary* _dictionary; // The loaded InstanceKlasses, including initiated by this class loader - // These method IDs are created for the class loader and set to null when the - // class loader is unloaded. They are rarely freed, only for redefine classes - // and if they lose a data race in InstanceKlass. - JNIMethodBlock* _jmethod_ids; + // These method IDs are created for the class loader and removed when the + // class loader is unloaded. + GrowableArray* _jmethod_ids; // Metadata to be deallocated when it's safe at class unloading, when // this class loader isn't unloaded itself. @@ -317,8 +311,9 @@ class ClassLoaderData : public CHeapObj { void classes_do(KlassClosure* klass_closure); Klass* klasses() { return _klasses; } - JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } - void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } + void add_jmethod_id(jmethodID id); + void remove_jmethod_ids(); + GrowableArray* jmethod_ids() const { return _jmethod_ids; } void print() const; void print_on(outputStream* out) const PRODUCT_RETURN; diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp index 49f15e8af33..1dcca4d1069 100644 --- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp +++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp @@ -34,9 +34,7 @@ class ClassLoaderDataGraph : public AllStatic { friend class ClassLoaderData; - friend class ClassLoaderDataGraphMetaspaceIterator; friend class ClassLoaderDataGraphKlassIteratorAtomic; - friend class ClassLoaderDataGraphKlassIteratorStatic; friend class VMStructs; private: class ClassLoaderDataGraphIterator; diff --git a/src/hotspot/share/classfile/classLoaderDataShared.cpp b/src/hotspot/share/classfile/classLoaderDataShared.cpp index 94ded38f5da..ac84a24267f 100644 --- a/src/hotspot/share/classfile/classLoaderDataShared.cpp +++ b/src/hotspot/share/classfile/classLoaderDataShared.cpp @@ -208,7 +208,7 @@ void ClassLoaderDataShared::clear_archived_oops() { oop ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data() { assert(CDSConfig::is_using_full_module_graph(), "must be"); _archived_boot_loader_data.restore(null_class_loader_data(), false, true); - return _archived_javabase_moduleEntry->module(); + return _archived_javabase_moduleEntry->module_oop(); } void ClassLoaderDataShared::restore_java_platform_loader_from_archive(ClassLoaderData* loader_data) { diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp deleted file mode 100644 index cd57f4e5e25..00000000000 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2015, 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. - * - * 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 "cds/aotClassLocation.hpp" -#include "cds/cds_globals.hpp" -#include "cds/cdsConfig.hpp" -#include "cds/dynamicArchive.hpp" -#include "cds/filemap.hpp" -#include "cds/heapShared.hpp" -#include "classfile/classFileParser.hpp" -#include "classfile/classLoader.inline.hpp" -#include "classfile/classLoaderExt.hpp" -#include "classfile/classLoaderData.inline.hpp" -#include "classfile/classLoadInfo.hpp" -#include "classfile/klassFactory.hpp" -#include "classfile/modules.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/vmSymbols.hpp" -#include "gc/shared/collectedHeap.hpp" -#include "logging/log.hpp" -#include "memory/allocation.inline.hpp" -#include "memory/resourceArea.hpp" -#include "oops/instanceKlass.hpp" -#include "oops/klass.inline.hpp" -#include "oops/oop.inline.hpp" -#include "oops/symbol.hpp" -#include "runtime/arguments.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/java.hpp" -#include "runtime/os.hpp" -#include "utilities/checkedCast.hpp" -#include "utilities/stringUtils.hpp" - -void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) { - if (CDSConfig::is_using_archive()) { - warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended"); - FileMapInfo::current_info()->set_has_platform_or_app_classes(false); - if (DynamicArchive::is_mapped()) { - FileMapInfo::dynamic_info()->set_has_platform_or_app_classes(false); - } - } - ClassLoader::add_to_boot_append_entries(new_entry); -} - -int ClassLoaderExt::compare_module_names(const char** p1, const char** p2) { - return strcmp(*p1, *p2); -} - -void ClassLoaderExt::record_result_for_builtin_loader(s2 classpath_index, InstanceKlass* result, bool redefined) { - assert(CDSConfig::is_dumping_archive(), "sanity"); - - oop loader = result->class_loader(); - if (SystemDictionary::is_system_class_loader(loader)) { - AOTClassLocationConfig::dumptime_set_has_app_classes(); - } else if (SystemDictionary::is_platform_class_loader(loader)) { - AOTClassLocationConfig::dumptime_set_has_platform_classes(); - } else { - precond(loader == nullptr); - } - - if (CDSConfig::is_dumping_preimage_static_archive() || CDSConfig::is_dumping_dynamic_archive()) { - if (!AOTClassLocationConfig::dumptime()->is_valid_classpath_index(classpath_index, result)) { - classpath_index = -1; - } - } - - AOTClassLocationConfig::dumptime_update_max_used_index(classpath_index); - result->set_shared_classpath_index(classpath_index); - -#if INCLUDE_CDS_JAVA_HEAP - if (CDSConfig::is_dumping_heap() && AllowArchivingWithJavaAgent && result->defined_by_boot_loader() && - classpath_index < 0 && redefined) { - // When dumping the heap (which happens only during static dump), classes for the built-in - // loaders are always loaded from known locations (jimage, classpath or modulepath), - // so classpath_index should always be >= 0. - // The only exception is when a java agent is used during dump time (for testing - // purposes only). If a class is transformed by the agent, the AOTClassLocation of - // this class may point to an unknown location. This may break heap object archiving, - // which requires all the boot classes to be from known locations. This is an - // uncommon scenario (even in test cases). Let's simply disable heap object archiving. - ResourceMark rm; - log_warning(aot)("heap objects cannot be written because class %s maybe modified by ClassFileLoadHook.", - result->external_name()); - CDSConfig::disable_heap_dumping(); - } -#endif // INCLUDE_CDS_JAVA_HEAP -} diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp deleted file mode 100644 index ee6b59bde14..00000000000 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2014, 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. - * - * 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. - * - */ - -#ifndef SHARE_CLASSFILE_CLASSLOADEREXT_HPP -#define SHARE_CLASSFILE_CLASSLOADEREXT_HPP - -#include "classfile/classLoader.hpp" -#include "classfile/moduleEntry.hpp" -#include "utilities/macros.hpp" - -class ClassListParser; - -class ClassLoaderExt: public ClassLoader { // AllStatic -public: -#if INCLUDE_CDS -public: - // Called by JVMTI code to add boot classpath - - static void append_boot_classpath(ClassPathEntry* new_entry); - - static int compare_module_names(const char** p1, const char** p2); - static void record_result_for_builtin_loader(s2 classpath_index, InstanceKlass* result, bool redefined); -#endif // INCLUDE_CDS -}; - -#endif // SHARE_CLASSFILE_CLASSLOADEREXT_HPP diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 75290526530..051fee6ced5 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1038,15 +1038,15 @@ void java_lang_Class::set_mirror_module_field(JavaThread* current, Klass* k, Han // If java.base was already defined then patch this particular class with java.base. if (javabase_was_defined) { ModuleEntry *javabase_entry = ModuleEntryTable::javabase_moduleEntry(); - assert(javabase_entry != nullptr && javabase_entry->module() != nullptr, + assert(javabase_entry != nullptr && javabase_entry->module_oop() != nullptr, "Setting class module field, " JAVA_BASE_NAME " should be defined"); - Handle javabase_handle(current, javabase_entry->module()); + Handle javabase_handle(current, javabase_entry->module_oop()); set_module(mirror(), javabase_handle()); } } else { assert(Universe::is_module_initialized() || (ModuleEntryTable::javabase_defined() && - (module() == ModuleEntryTable::javabase_moduleEntry()->module())), + (module() == ModuleEntryTable::javabase_moduleEntry()->module_oop())), "Incorrect java.lang.Module specification while creating mirror"); set_module(mirror(), module()); } @@ -1927,7 +1927,7 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) { return nullptr; } - class GetStackTraceClosure : public HandshakeClosure { + class GetStackTraceHandshakeClosure : public HandshakeClosure { public: const Handle _java_thread; int _depth; @@ -1935,11 +1935,11 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) { GrowableArray* _methods; GrowableArray* _bcis; - GetStackTraceClosure(Handle java_thread) : - HandshakeClosure("GetStackTraceClosure"), _java_thread(java_thread), _depth(0), _retry_handshake(false), + GetStackTraceHandshakeClosure(Handle java_thread) : + HandshakeClosure("GetStackTraceHandshakeClosure"), _java_thread(java_thread), _depth(0), _retry_handshake(false), _methods(nullptr), _bcis(nullptr) { } - ~GetStackTraceClosure() { + ~GetStackTraceHandshakeClosure() { delete _methods; delete _bcis; } @@ -2005,13 +2005,13 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) { // Handshake with target ResourceMark rm(THREAD); HandleMark hm(THREAD); - GetStackTraceClosure gstc(Handle(THREAD, java_thread)); + GetStackTraceHandshakeClosure gsthc(Handle(THREAD, java_thread)); do { - Handshake::execute(&gstc, &tlh, thread); - } while (gstc.read_reset_retry()); + Handshake::execute(&gsthc, &tlh, thread); + } while (gsthc.read_reset_retry()); // Stop if no stack trace is found. - if (gstc._depth == 0) { + if (gsthc._depth == 0) { return nullptr; } @@ -2021,12 +2021,12 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) { if (k->should_be_initialized()) { k->initialize(CHECK_NULL); } - objArrayHandle trace = oopFactory::new_objArray_handle(k, gstc._depth, CHECK_NULL); + objArrayHandle trace = oopFactory::new_objArray_handle(k, gsthc._depth, CHECK_NULL); - for (int i = 0; i < gstc._depth; i++) { - methodHandle method(THREAD, gstc._methods->at(i)); + for (int i = 0; i < gsthc._depth; i++) { + methodHandle method(THREAD, gsthc._methods->at(i)); oop element = java_lang_StackTraceElement::create(method, - gstc._bcis->at(i), + gsthc._bcis->at(i), CHECK_NULL); trace->obj_at_put(i, element); } diff --git a/src/hotspot/share/classfile/moduleEntry.cpp b/src/hotspot/share/classfile/moduleEntry.cpp index 208c4efe035..65d7183dbea 100644 --- a/src/hotspot/share/classfile/moduleEntry.cpp +++ b/src/hotspot/share/classfile/moduleEntry.cpp @@ -49,7 +49,7 @@ ModuleEntry* ModuleEntryTable::_javabase_module = nullptr; -oop ModuleEntry::module() const { return _module.resolve(); } +oop ModuleEntry::module_oop() const { return _module_handle.resolve(); } void ModuleEntry::set_location(Symbol* location) { // _location symbol's refcounts are managed by ModuleEntry, @@ -284,7 +284,7 @@ ModuleEntry::ModuleEntry(Handle module_handle, } if (!module_handle.is_null()) { - _module = loader_data->add_handle(module_handle); + _module_handle = loader_data->add_handle(module_handle); } set_version(version); @@ -401,7 +401,7 @@ ModuleEntry* ModuleEntry::allocate_archived_entry() const { memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); if (CDSConfig::is_dumping_full_module_graph()) { - archived_entry->_archived_module_index = HeapShared::append_root(module()); + archived_entry->_archived_module_index = HeapShared::append_root(module_oop()); } else { archived_entry->_archived_module_index = -1; } @@ -422,7 +422,7 @@ ModuleEntry* ModuleEntry::allocate_archived_entry() const { // Clear handles and restore at run time. Handles cannot be archived. OopHandle null_handle; - archived_entry->_module = null_handle; + archived_entry->_module_handle = null_handle; // For verify_archived_module_entries() DEBUG_ONLY(_num_inited_module_entries++); @@ -526,7 +526,7 @@ void ModuleEntry::restore_archived_oops(ClassLoaderData* loader_data) { assert(CDSConfig::is_using_archive(), "runtime only"); Handle module_handle(Thread::current(), HeapShared::get_root(_archived_module_index, /*clear=*/true)); assert(module_handle.not_null(), "huh"); - set_module(loader_data->add_handle(module_handle)); + set_module_handle(loader_data->add_handle(module_handle)); // This was cleared to zero during dump time -- we didn't save the value // because it may be affected by archive relocation. @@ -662,7 +662,7 @@ void ModuleEntryTable::finalize_javabase(Handle module_handle, Symbol* version, jb_module->set_location(location); // Once java.base's ModuleEntry _module field is set with the known // java.lang.Module, java.base is considered "defined" to the VM. - jb_module->set_module(boot_loader_data->add_handle(module_handle)); + jb_module->set_module_handle(boot_loader_data->add_handle(module_handle)); // Store pointer to the ModuleEntry for java.base in the java.lang.Module object. java_lang_Module::set_module_entry(module_handle(), jb_module); @@ -700,7 +700,7 @@ void ModuleEntryTable::patch_javabase_entries(JavaThread* current, Handle module // We allow -XX:ArchiveHeapTestClass to archive additional classes // into the CDS heap, but these must be in the unnamed module. ModuleEntry* unnamed_module = ClassLoaderData::the_null_class_loader_data()->unnamed_module(); - Handle unnamed_module_handle(current, unnamed_module->module()); + Handle unnamed_module_handle(current, unnamed_module->module_oop()); java_lang_Class::fixup_module_field(k, unnamed_module_handle); } else #endif @@ -745,7 +745,7 @@ void ModuleEntry::print(outputStream* st) { st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s", p2i(this), name_as_C_string(), - p2i(module()), + p2i(module_oop()), loader_data()->loader_name_and_id(), version() != nullptr ? version()->as_C_string() : "nullptr", location() != nullptr ? location()->as_C_string() : "nullptr", diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index c2d07a78512..e66999c3cd9 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -53,7 +53,7 @@ class ModuleClosure; // A ModuleEntry describes a module that has been defined by a call to JVM_DefineModule. // It contains: // - Symbol* containing the module's name. -// - pointer to the java.lang.Module for this module. +// - pointer to the java.lang.Module: the representation of this module as a Java object // - pointer to the java.security.ProtectionDomain shared by classes defined to this module. // - ClassLoaderData*, class loader of this module. // - a growable array containing other module entries that this module can read. @@ -63,7 +63,7 @@ class ModuleClosure; // data structure. This lock must be taken on all accesses to either table. class ModuleEntry : public CHeapObj { private: - OopHandle _module; // java.lang.Module + OopHandle _module_handle; // java.lang.Module OopHandle _shared_pd; // java.security.ProtectionDomain, cached // for shared classes from this module Symbol* _name; // name of this module @@ -96,9 +96,9 @@ class ModuleEntry : public CHeapObj { ~ModuleEntry(); Symbol* name() const { return _name; } - oop module() const; - OopHandle module_handle() const { return _module; } - void set_module(OopHandle j) { _module = j; } + oop module_oop() const; + OopHandle module_handle() const { return _module_handle; } + void set_module_handle(OopHandle j) { _module_handle = j; } // The shared ProtectionDomain reference is set once the VM loads a shared class // originated from the current Module. The referenced ProtectionDomain object is @@ -262,7 +262,7 @@ class ModuleEntryTable : public CHeapObj { } static bool javabase_defined() { return ((_javabase_module != nullptr) && - (_javabase_module->module() != nullptr)); } + (_javabase_module->module_oop() != nullptr)); } static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location); static void patch_javabase_entries(JavaThread* current, Handle module_handle); diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index 4b146abc06b..72e56b03a58 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -30,7 +30,6 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataShared.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/javaAssertions.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaClasses.inline.hpp" @@ -625,6 +624,11 @@ void Modules::ArchivedProperty::runtime_check() const { } } + +static int compare_module_names(const char** p1, const char** p2) { + return strcmp(*p1, *p2); +} + // Caller needs ResourceMark const char* Modules::ArchivedProperty::get_numbered_property_as_sorted_string() const { assert(_numbered, "sanity"); @@ -665,7 +669,7 @@ const char* Modules::ArchivedProperty::get_numbered_property_as_sorted_string() // list[2] = "java.base" // list[3] = "" // list[4] = "" - list.sort(ClassLoaderExt::compare_module_names); + list.sort(compare_module_names); const char* prefix = ""; stringStream st; @@ -773,7 +777,7 @@ void Modules::set_bootloader_unnamed_module(Handle module, TRAPS) { ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data(); ModuleEntry* unnamed_module = boot_loader_data->unnamed_module(); assert(unnamed_module != nullptr, "boot loader's unnamed ModuleEntry not defined"); - unnamed_module->set_module(boot_loader_data->add_handle(module)); + unnamed_module->set_module_handle(boot_loader_data->add_handle(module)); // Store pointer to the ModuleEntry in the unnamed module's java.lang.Module object. java_lang_Module::set_module_entry(module(), unnamed_module); } @@ -954,8 +958,8 @@ oop Modules::get_named_module(Handle h_loader, const char* package_name) { get_package_entry_by_name(package_sym, h_loader); const ModuleEntry* const module_entry = (pkg_entry != nullptr ? pkg_entry->module() : nullptr); - if (module_entry != nullptr && module_entry->module() != nullptr && module_entry->is_named()) { - return module_entry->module(); + if (module_entry != nullptr && module_entry->module_oop() != nullptr && module_entry->is_named()) { + return module_entry->module_oop(); } return nullptr; } diff --git a/src/hotspot/share/classfile/placeholders.cpp b/src/hotspot/share/classfile/placeholders.cpp index 7404c498e12..f6b8fb5484f 100644 --- a/src/hotspot/share/classfile/placeholders.cpp +++ b/src/hotspot/share/classfile/placeholders.cpp @@ -61,8 +61,8 @@ static InternalPlaceholderTable* _placeholders; // For DEFINE_CLASS, the head of the queue owns the // define token and the rest of the threads wait to return the // result the first thread gets. -// For INLINE_FIELD, set when loading inline type fields for -// class circularity checking. +// For DETECT_CIRCULARITY, set when loading super class, interfaces, or inline type +// fields for class circularity checking. class SeenThread: public CHeapObj { private: JavaThread* _thread; diff --git a/src/hotspot/share/classfile/placeholders.hpp b/src/hotspot/share/classfile/placeholders.hpp index bcccfe859f5..1bace6f1bbc 100644 --- a/src/hotspot/share/classfile/placeholders.hpp +++ b/src/hotspot/share/classfile/placeholders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -47,7 +47,6 @@ class PlaceholderTable : public AllStatic { // on a class/classloader basis // so the head of that queue owns the token // and the rest of the threads return the result the first thread gets - // VALUE_OBJECT_FIELD: needed to check for inline type fields circularity enum classloadAction { LOAD_INSTANCE = 1, // calling load_instance_class DETECT_CIRCULARITY = 2, // loading while detecting class circularity diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 193ce95d321..8363a918d91 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -32,6 +32,7 @@ #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/vmClasses.hpp" +#include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "gc/shared/oopStorageSet.hpp" @@ -115,6 +116,7 @@ OopStorage* StringTable::_oop_storage; static size_t _current_size = 0; static volatile size_t _items_count = 0; +DEBUG_ONLY(static bool _disable_interning_during_cds_dump = false); volatile bool _alt_hash = false; @@ -346,6 +348,10 @@ bool StringTable::has_work() { return Atomic::load_acquire(&_has_work); } +size_t StringTable::items_count_acquire() { + return Atomic::load_acquire(&_items_count); +} + void StringTable::trigger_concurrent_work() { // Avoid churn on ServiceThread if (!has_work()) { @@ -504,6 +510,9 @@ oop StringTable::intern(const char* utf8_string, TRAPS) { } oop StringTable::intern(const StringWrapper& name, TRAPS) { + assert(!Atomic::load_acquire(&_disable_interning_during_cds_dump), + "All threads that may intern strings should have been stopped before CDS starts copying the interned string table"); + // shared table always uses java_lang_String::hash_code unsigned int hash = hash_wrapped_string(name); oop found_string = lookup_shared(name, hash); @@ -793,7 +802,7 @@ void StringTable::verify() { } // Verification and comp -class VerifyCompStrings : StackObj { +class StringTable::VerifyCompStrings : StackObj { static unsigned string_hash(oop const& str) { return java_lang_String::hash_code_noupdate(str); } @@ -805,7 +814,7 @@ class VerifyCompStrings : StackObj { string_hash, string_equals> _table; public: size_t _errors; - VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {} + VerifyCompStrings() : _table(unsigned(items_count_acquire() / 8) + 1, 0 /* do not resize */), _errors(0) {} bool operator()(WeakHandle* val) { oop s = val->resolve(); if (s == nullptr) { @@ -939,20 +948,31 @@ oop StringTable::lookup_shared(const jchar* name, int len) { return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0); } -// This is called BEFORE we enter the CDS safepoint. We can allocate heap objects. -// This should be called when we know no more strings will be added (which will be easy -// to guarantee because CDS runs with a single Java thread. See JDK-8253495.) +// This is called BEFORE we enter the CDS safepoint. We can still allocate Java object arrays to +// be used by the shared strings table. void StringTable::allocate_shared_strings_array(TRAPS) { if (!CDSConfig::is_dumping_heap()) { return; } - assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added"); - if (_items_count > (size_t)max_jint) { - fatal("Too many strings to be archived: %zu", _items_count); + CompileBroker::wait_for_no_active_tasks(); + + precond(CDSConfig::allow_only_single_java_thread()); + + // At this point, no more strings will be added: + // - There's only a single Java thread (this thread). It no longer executes Java bytecodes + // so JIT compilation will eventually stop. + // - CompileBroker has no more active tasks, so all JIT requests have been processed. + + // This flag will be cleared after intern table dumping has completed, so we can run the + // compiler again (for future AOT method compilation, etc). + DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, true)); + + if (items_count_acquire() > (size_t)max_jint) { + fatal("Too many strings to be archived: %zu", items_count_acquire()); } - int total = (int)_items_count; + int total = (int)items_count_acquire(); size_t single_array_size = refArrayOopDesc::object_size(total); log_info(aot)("allocated string table for %d strings", total); @@ -972,7 +992,7 @@ void StringTable::allocate_shared_strings_array(TRAPS) { // This can only happen if you have an extremely large number of classes that // refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern // but bail out for safety. - log_error(aot)("Too many strings to be archived: %zu", _items_count); + log_error(aot)("Too many strings to be archived: %zu", items_count_acquire()); MetaspaceShared::unrecoverable_writing_error(); } @@ -1070,7 +1090,7 @@ oop StringTable::init_shared_strings_array() { void StringTable::write_shared_table() { _shared_table.reset(); - CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats()); + CompactHashtableWriter writer((int)items_count_acquire(), ArchiveBuilder::string_stats()); int index = 0; auto copy_into_shared_table = [&] (WeakHandle* val) { @@ -1084,6 +1104,8 @@ void StringTable::write_shared_table() { }; _local_table->do_safepoint_scan(copy_into_shared_table); writer.dump(&_shared_table, "string"); + + DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, false)); } void StringTable::set_shared_strings_array_index(int root_index) { diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index bf7bb9e2cd9..9194d0b8002 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -40,7 +40,7 @@ class StringTableConfig; class StringTable : AllStatic { friend class StringTableConfig; - + class VerifyCompStrings; static volatile bool _has_work; // Set if one bucket is out of balance due to hash algorithm deficiency @@ -74,6 +74,7 @@ class StringTable : AllStatic { static void item_added(); static void item_removed(); + static size_t items_count_acquire(); static oop intern(const StringWrapper& name, TRAPS); static oop do_intern(const StringWrapper& name, uintx hash, TRAPS); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 16d9b83dc4f..e8be9ecd00e 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -30,7 +30,6 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/classLoadInfo.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.inline.hpp" @@ -374,7 +373,7 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader assert(class_name != nullptr && !Signature::is_array(class_name), "must be"); if (Signature::has_envelope(class_name)) { ResourceMark rm(THREAD); - // Ignore wrapping L and ; (and Q and ; for value types). + // Ignore wrapping L and ;. TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1, class_name->utf8_length() - 2); return resolve_instance_class_or_null(name, class_loader, THREAD); @@ -422,7 +421,8 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe) } // Must be called for any superclass or superinterface resolution -// during class definition to allow class circularity checking +// during class definition, or may be called for inline field layout processing +// to detect class circularity errors. // superinterface callers: // parse_interfaces - from defineClass // superclass callers: @@ -435,10 +435,12 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe) // If another thread is trying to resolve the class, it must do // superclass checks on its own thread to catch class circularity and // to avoid deadlock. +// inline field layout callers: +// The field's class must be loaded to determine layout. // // resolve_with_circularity_detection adds a DETECT_CIRCULARITY placeholder to the placeholder table before calling // resolve_instance_class_or_null. ClassCircularityError is detected when a DETECT_CIRCULARITY or LOAD_INSTANCE -// placeholder for the same thread, class, classloader is found. +// placeholder for the same thread, class, and classloader is found. // This can be seen with logging option: -Xlog:class+load+placeholders=debug. // InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* class_name, @@ -473,7 +475,7 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas { MutexLocker mu(THREAD, SystemDictionary_lock); - // Must check ClassCircularity before resolving next_name (superclass or interface). + // Must check ClassCircularity before resolving next_name (superclass, interface, field types or speculatively preloaded argument types). PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data); if (probe != nullptr && probe->check_seen_thread(THREAD, PlaceholderTable::DETECT_CIRCULARITY)) { log_circularity_error(class_name, probe); @@ -497,7 +499,7 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string()); } - // Resolve the superclass or superinterface, check results on return + // Resolve the superclass, superinterface, field type or speculatively preloaded argument types and check results on return. InstanceKlass* superk = SystemDictionary::resolve_instance_class_or_null(next_name, class_loader, @@ -1104,7 +1106,7 @@ bool SystemDictionary::preload_from_null_free_field(InstanceKlass* ik, Handle cl log_info(class, preload)("Preloading of class %s during loading of shared class %s. " "Cause: a null-free non-static field is declared with this type", name->as_C_string(), ik->name()->as_C_string()); - InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name, + InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection(ik->name(), name, class_loader, false, CHECK_false); if (HAS_PENDING_EXCEPTION) { log_warning(class, preload)("Preloading of class %s during loading of class %s " @@ -1142,7 +1144,7 @@ void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, log_info(class, preload)("Preloading of class %s during loading of shared class %s. " "Cause: field type in LoadableDescriptors attribute", name->as_C_string(), ik->name()->as_C_string()); - InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name, + InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection(ik->name(), name, class_loader, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 326d8e32c2e..c5047c1e832 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -68,7 +68,6 @@ class BootstrapInfo; class ClassFileStream; class ClassLoadInfo; class Dictionary; -class AllFieldStream; class PackageEntry; class GCTimer; class EventClassLoad; @@ -113,8 +112,7 @@ class SystemDictionary : AllStatic { // Resolve a superclass or superinterface. Called from ClassFileParser, // parse_interfaces, resolve_instance_class_or_null, load_shared_class // "class_name" is the class whose super class or interface is being resolved. - static InstanceKlass* resolve_with_circularity_detection_or_fail(Symbol* class_name, - Symbol* super_name, + static InstanceKlass* resolve_super_or_fail(Symbol* class_name, Symbol* super_name, Handle class_loader, bool is_superclass, TRAPS) { return resolve_with_circularity_detection(class_name, super_name, class_loader, is_superclass, THREAD); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 8bd09a0d947..f863347c152 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -44,7 +44,6 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.hpp" -#include "classfile/classLoaderExt.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaClasses.inline.hpp" @@ -348,6 +347,13 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) { } } + InstanceKlass* nest_host = k->nest_host_or_null(); + if (nest_host != nullptr && nest_host != k && check_for_exclusion(nest_host, nullptr)) { + ResourceMark rm; + aot_log_warning(aot)("Skipping %s: nest_host class %s is excluded", k->name()->as_C_string(), nest_host->name()->as_C_string()); + return true; + } + return false; // false == k should NOT be excluded } diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 90da15eee9b..eea1ddc3c0c 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -1648,12 +1648,12 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + object_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ifnull : case Bytecodes::_ifnonnull : current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + object_type(), CHECK_VERIFY(this)); target = bcs.dest(); stackmap_table.check_jump_target (¤t_frame, target, CHECK_VERIFY(this)); diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index ac1a6e59f2d..a136c9efcd0 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -1292,9 +1292,13 @@ class methodHandle; "Ljava/lang/Class;" \ "I" \ "Ljava/lang/Class;" \ + "I" \ "Ljava/lang/Object;" \ "J" \ "Ljdk/internal/vm/vector/VectorSupport$Vector;" \ + "Ljdk/internal/vm/vector/VectorSupport$Vector;" \ + "Ljdk/internal/vm/vector/VectorSupport$Vector;" \ + "Ljdk/internal/vm/vector/VectorSupport$Vector;" \ "Ljdk/internal/vm/vector/VectorSupport$VectorMask;" \ "Ljava/lang/Object;" \ "I[II" \ @@ -1309,6 +1313,7 @@ class methodHandle; "Ljava/lang/Class;" \ "I" \ "Ljava/lang/Class;" \ + "I" \ "Ljava/lang/Object;" \ "J" \ "Ljdk/internal/vm/vector/VectorSupport$Vector;" \ diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index ea3b7a43f6c..705ec72f28a 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -42,6 +42,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/os.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubInfo.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/copy.hpp" #ifdef COMPILER1 @@ -147,12 +148,15 @@ static uint32_t encode_id(AOTCodeEntry::Kind kind, int id) { if (kind == AOTCodeEntry::Adapter) { return id; } else if (kind == AOTCodeEntry::SharedBlob) { + assert(StubInfo::is_shared(static_cast(id)), "not a shared blob id %d", id); return id; } else if (kind == AOTCodeEntry::C1Blob) { - return (int)SharedStubId::NUM_STUBIDS + id; + assert(StubInfo::is_c1(static_cast(id)), "not a c1 blob id %d", id); + return id; } else { // kind must be AOTCodeEntry::C2Blob - return (int)SharedStubId::NUM_STUBIDS + COMPILER1_PRESENT((int)C1StubId::NUM_STUBIDS) + id; + assert(StubInfo::is_c2(static_cast(id)), "not a c2 blob id %d", id); + return id; } } @@ -899,6 +903,12 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind return true; } +bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind, BlobId id, int entry_offset_count, int* entry_offsets) { + assert(AOTCodeEntry::is_blob(entry_kind), + "wrong entry kind for blob id %s", StubInfo::name(id)); + return store_code_blob(blob, entry_kind, (uint)id, StubInfo::name(id), entry_offset_count, entry_offsets); +} + CodeBlob* AOTCodeCache::load_code_blob(AOTCodeEntry::Kind entry_kind, uint id, const char* name, int entry_offset_count, int* entry_offsets) { AOTCodeCache* cache = open_for_use(); if (cache == nullptr) { @@ -926,6 +936,12 @@ CodeBlob* AOTCodeCache::load_code_blob(AOTCodeEntry::Kind entry_kind, uint id, c return blob; } +CodeBlob* AOTCodeCache::load_code_blob(AOTCodeEntry::Kind entry_kind, BlobId id, int entry_offset_count, int* entry_offsets) { + assert(AOTCodeEntry::is_blob(entry_kind), + "wrong entry kind for blob id %s", StubInfo::name(id)); + return load_code_blob(entry_kind, (uint)id, StubInfo::name(id), entry_offset_count, entry_offsets); +} + CodeBlob* AOTCodeReader::compile_code_blob(const char* name, int entry_offset_count, int* entry_offsets) { uint entry_position = _entry->offset(); @@ -1299,6 +1315,7 @@ void AOTCodeAddressTable::init_extrs() { SET_ADDRESS(_extrs, SharedRuntime::resolve_opt_virtual_call_C); SET_ADDRESS(_extrs, SharedRuntime::resolve_virtual_call_C); SET_ADDRESS(_extrs, SharedRuntime::resolve_static_call_C); + SET_ADDRESS(_extrs, SharedRuntime::throw_StackOverflowError); SET_ADDRESS(_extrs, SharedRuntime::throw_delayed_StackOverflowError); SET_ADDRESS(_extrs, SharedRuntime::throw_AbstractMethodError); SET_ADDRESS(_extrs, SharedRuntime::throw_IncompatibleClassChangeError); @@ -1474,8 +1491,10 @@ void AOTCodeAddressTable::init_shared_blobs() { void AOTCodeAddressTable::init_early_c1() { #ifdef COMPILER1 // Runtime1 Blobs - for (int i = 0; i <= (int)C1StubId::forward_exception_id; i++) { - C1StubId id = (C1StubId)i; + StubId id = StubInfo::stub_base(StubGroup::C1); + // include forward_exception in range we publish + StubId limit = StubInfo::next(StubId::c1_forward_exception_id); + for (; id != limit; id = StubInfo::next(id)) { if (Runtime1::blob_for(id) == nullptr) { log_info(aot, codecache, init)("C1 blob %s is missing", Runtime1::name_for(id)); continue; @@ -1498,6 +1517,9 @@ AOTCodeAddressTable::~AOTCodeAddressTable() { if (_extrs_addr != nullptr) { FREE_C_HEAP_ARRAY(address, _extrs_addr); } + if (_stubs_addr != nullptr) { + FREE_C_HEAP_ARRAY(address, _stubs_addr); + } if (_shared_blobs_addr != nullptr) { FREE_C_HEAP_ARRAY(address, _shared_blobs_addr); } diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index 1595f19e905..702ce2565df 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -25,6 +25,8 @@ #ifndef SHARE_CODE_AOTCODECACHE_HPP #define SHARE_CODE_AOTCODECACHE_HPP +#include "runtime/stubInfo.hpp" + /* * AOT Code Cache collects code from Code Cache and corresponding metadata * during application training run. @@ -136,6 +138,7 @@ class AOTCodeAddressTable : public CHeapObj { public: AOTCodeAddressTable() : _extrs_addr(nullptr), + _stubs_addr(nullptr), _shared_blobs_addr(nullptr), _C1_blobs_addr(nullptr), _extrs_length(0), @@ -326,6 +329,7 @@ class AOTCodeCache : public CHeapObj { bool write_dbg_strings(CodeBlob& cb); #endif // PRODUCT + // save and restore API for non-enumerable code blobs static bool store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind, uint id, const char* name, @@ -337,6 +341,18 @@ class AOTCodeCache : public CHeapObj { int entry_offset_count = 0, int* entry_offsets = nullptr) NOT_CDS_RETURN_(nullptr); + // save and restore API for enumerable code blobs + static bool store_code_blob(CodeBlob& blob, + AOTCodeEntry::Kind entry_kind, + BlobId id, + int entry_offset_count = 0, + int* entry_offsets = nullptr) NOT_CDS_RETURN_(false); + + static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind, + BlobId id, + int entry_offset_count = 0, + int* entry_offsets = nullptr) NOT_CDS_RETURN_(nullptr); + static uint store_entries_cnt() { if (is_on_for_dump()) { return cache()->_store_entries_cnt; diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index e54f0548051..c03bb01da16 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -162,7 +162,7 @@ CodeBlob::CodeBlob(const char* name, CodeBlobKind kind, CodeBuffer* cb, int size } } else { // We need unique and valid not null address - assert(_mutable_data = blob_end(), "sanity"); + assert(_mutable_data == blob_end(), "sanity"); } set_oop_maps(oop_maps); @@ -179,6 +179,7 @@ CodeBlob::CodeBlob(const char* name, CodeBlobKind kind, int size, uint16_t heade _code_offset(_content_offset), _data_offset(size), _frame_size(0), + _mutable_data_size(0), S390_ONLY(_ctable_offset(0) COMMA) _header_size(header_size), _frame_complete_offset(CodeOffsets::frame_never_safe), @@ -187,7 +188,7 @@ CodeBlob::CodeBlob(const char* name, CodeBlobKind kind, int size, uint16_t heade { assert(is_aligned(size, oopSize), "unaligned size"); assert(is_aligned(header_size, oopSize), "unaligned size"); - assert(_mutable_data = blob_end(), "sanity"); + assert(_mutable_data == blob_end(), "sanity"); } void CodeBlob::restore_mutable_data(address reloc_data) { @@ -197,8 +198,11 @@ void CodeBlob::restore_mutable_data(address reloc_data) { if (_mutable_data == nullptr) { vm_exit_out_of_memory(_mutable_data_size, OOM_MALLOC_ERROR, "codebuffer: no space for mutable data"); } + } else { + _mutable_data = blob_end(); // default value } if (_relocation_size > 0) { + assert(_mutable_data_size > 0, "relocation is part of mutable data section"); memcpy((address)relocation_begin(), reloc_data, relocation_size()); } } @@ -208,6 +212,8 @@ void CodeBlob::purge() { if (_mutable_data != blob_end()) { os::free(_mutable_data); _mutable_data = blob_end(); // Valid not null address + _mutable_data_size = 0; + _relocation_size = 0; } if (_oop_maps != nullptr) { delete _oop_maps; diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index c871687207d..629ded66945 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -250,7 +250,7 @@ class CodeBlob { // Sizes int size() const { return _size; } int header_size() const { return _header_size; } - int relocation_size() const { return pointer_delta_as_int((address) relocation_end(), (address) relocation_begin()); } + int relocation_size() const { return _relocation_size; } int content_size() const { return pointer_delta_as_int(content_end(), content_begin()); } int code_size() const { return pointer_delta_as_int(code_end(), code_begin()); } @@ -487,6 +487,7 @@ class RuntimeStub: public RuntimeBlob { void* operator new(size_t s, unsigned size) throw(); public: + static const int ENTRY_COUNT = 1; // Creation static RuntimeStub* new_runtime_stub( const char* stub_name, @@ -589,6 +590,7 @@ class DeoptimizationBlob: public SingletonBlob { ); public: + static const int ENTRY_COUNT = 4 JVMTI_ONLY(+ 2); // Creation static DeoptimizationBlob* create( CodeBuffer* cb, @@ -719,6 +721,7 @@ class SafepointBlob: public SingletonBlob { ); public: + static const int ENTRY_COUNT = 1; // Creation static SafepointBlob* create( CodeBuffer* cb, diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 6a5cc0f4a40..f7c86ce58fa 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -882,6 +882,7 @@ void CodeCache::do_unloading(bool unloading_occurred) { void CodeCache::verify_clean_inline_caches() { #ifdef ASSERT + if (!VerifyInlineCaches) return; NMethodIterator iter(NMethodIterator::not_unloading); while(iter.next()) { nmethod* nm = iter.method(); diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp index d92f98f96a1..3308cbf2cb8 100644 --- a/src/hotspot/share/code/compiledIC.hpp +++ b/src/hotspot/share/code/compiledIC.hpp @@ -192,13 +192,13 @@ class CompiledDirectCall : public ResourceObj { static inline CompiledDirectCall* before(address return_addr) { CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr)); - st->verify(); + if (VerifyInlineCaches) st->verify(); return st; } static inline CompiledDirectCall* at(address native_call) { CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call)); - st->verify(); + if (VerifyInlineCaches) st->verify(); return st; } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 0c27cdada91..cee3219778a 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1954,6 +1954,11 @@ bool nmethod::is_maybe_on_stack() { void nmethod::inc_decompile_count() { if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return; // Could be gated by ProfileTraps, but do not bother... +#if INCLUDE_JVMCI + if (jvmci_skip_profile_deopt()) { + return; + } +#endif Method* m = method(); if (m == nullptr) return; MethodData* mdo = m->method_data(); @@ -2175,6 +2180,7 @@ void nmethod::purge(bool unregister_nmethod) { } CodeCache::unregister_old_nmethod(this); + JVMCI_ONLY( _metadata_size = 0; ) CodeBlob::purge(); } @@ -3482,6 +3488,9 @@ void nmethod::decode2(outputStream* ost) const { if (use_compressed_format && ! compressed_with_comments) { const_cast(this)->print_constant_pool(st); + st->bol(); + st->cr(); + st->print_cr("Loading hsdis library failed, undisassembled code is shown in MachCode section"); //---< Open the output (Marker for post-mortem disassembler) >--- st->print_cr("[MachCode]"); const char* header = nullptr; @@ -3516,6 +3525,9 @@ void nmethod::decode2(outputStream* ost) const { if (compressed_with_comments) { const_cast(this)->print_constant_pool(st); + st->bol(); + st->cr(); + st->print_cr("Loading hsdis library failed, undisassembled code is shown in MachCode section"); //---< Open the output (Marker for post-mortem disassembler) >--- st->print_cr("[MachCode]"); while ((p < end) && (p != nullptr)) { @@ -4111,4 +4123,8 @@ const char* nmethod::jvmci_name() { } return nullptr; } + +bool nmethod::jvmci_skip_profile_deopt() const { + return jvmci_nmethod_data() != nullptr && !jvmci_nmethod_data()->profile_deopt(); +} #endif diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 01d7b837d52..43ee4c8e6cf 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -931,6 +931,10 @@ class nmethod : public CodeBlob { JVMCINMethodData* jvmci_nmethod_data() const { return jvmci_data_size() == 0 ? nullptr : (JVMCINMethodData*) jvmci_data_begin(); } + + // Returns true if the runtime should NOT collect deoptimization profile for a JVMCI + // compiled method + bool jvmci_skip_profile_deopt() const; #endif void oops_do(OopClosure* f) { oops_do(f, false); } diff --git a/src/hotspot/share/compiler/abstractDisassembler.cpp b/src/hotspot/share/compiler/abstractDisassembler.cpp index 32f37e7b513..df7781e93d5 100644 --- a/src/hotspot/share/compiler/abstractDisassembler.cpp +++ b/src/hotspot/share/compiler/abstractDisassembler.cpp @@ -350,6 +350,9 @@ void AbstractDisassembler::decode_abstract(address start, address end, outputStr outputStream* st = (ost == nullptr) ? tty : ost; + st->bol(); + st->cr(); + st->print_cr("Loading hsdis library failed, undisassembled code is shown in MachCode section"); //---< Open the output (Marker for post-mortem disassembler) >--- st->bol(); st->print_cr("[MachCode]"); diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 61158fe838a..068811ce108 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -236,7 +236,7 @@ CompileTaskWrapper::~CompileTaskWrapper() { #if INCLUDE_JVMCI if (CompileBroker::compiler(task->comp_level())->is_jvmci()) { if (!task->has_waiter()) { - // The waiting thread timed out and thus did not free the task. + // The waiting thread timed out and thus did not delete the task. free_task = true; } task->set_blocking_jvmci_compile_state(nullptr); @@ -249,15 +249,15 @@ CompileTaskWrapper::~CompileTaskWrapper() { } } if (free_task) { - // The task can only be freed once the task lock is released. - CompileTask::free(task); + // The task can only be deleted once the task lock is released. + delete task; } } else { task->mark_complete(); - // By convention, the compiling thread is responsible for - // recycling a non-blocking CompileTask. - CompileTask::free(task); + // By convention, the compiling thread is responsible for deleting + // a non-blocking CompileTask. + delete task; } } @@ -360,12 +360,12 @@ void CompileQueue::add(CompileTask* task) { } /** - * Empties compilation queue by putting all compilation tasks onto - * a freelist. Furthermore, the method wakes up all threads that are - * waiting on a compilation task to finish. This can happen if background + * Empties compilation queue by deleting all compilation tasks. + * Furthermore, the method wakes up all threads that are waiting + * on a compilation task to finish. This can happen if background * compilation is disabled. */ -void CompileQueue::free_all() { +void CompileQueue::delete_all() { MutexLocker mu(MethodCompileQueue_lock); CompileTask* next = _first; @@ -385,11 +385,10 @@ void CompileQueue::free_all() { } } if (!found_waiter) { - // If no one was waiting for this task, we need to free it ourselves. In this case, the task - // is also certainly unlocked, because, again, there is no waiter. - // Otherwise, by convention, it's the waiters responsibility to free the task. - // Put the task back on the freelist. - CompileTask::free(current); + // If no one was waiting for this task, we need to delete it ourselves. + // In this case, the task is also certainly unlocked, because, again, there is no waiter. + // Otherwise, by convention, it's the waiters responsibility to delete the task. + delete current; } } _first = nullptr; @@ -1627,10 +1626,8 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue, int hot_count, CompileTask::CompileReason compile_reason, bool blocking) { - CompileTask* new_task = CompileTask::allocate(); - new_task->initialize(compile_id, method, osr_bci, comp_level, - hot_count, compile_reason, - blocking); + CompileTask* new_task = new CompileTask(compile_id, method, osr_bci, comp_level, + hot_count, compile_reason, blocking); queue->add(new_task); return new_task; } @@ -1651,7 +1648,7 @@ static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 10; * JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE * * JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS. * - * @return true if this thread needs to free/recycle the task + * @return true if this thread needs to delete the task */ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* task, JavaThread* thread) { assert(UseJVMCICompiler, "sanity"); @@ -1734,22 +1731,26 @@ void CompileBroker::wait_for_completion(CompileTask* task) { if (free_task) { if (is_compilation_disabled_forever()) { - CompileTask::free(task); + delete task; return; } // It is harmless to check this status without the lock, because - // completion is a stable property (until the task object is recycled). + // completion is a stable property (until the task object is deleted). assert(task->is_complete(), "Compilation should have completed"); - // By convention, the waiter is responsible for recycling a + // By convention, the waiter is responsible for deleting a // blocking CompileTask. Since there is only one waiter ever // waiting on a CompileTask, we know that no one else will - // be using this CompileTask; we can free it. - CompileTask::free(task); + // be using this CompileTask; we can delete it. + delete task; } } +void CompileBroker::wait_for_no_active_tasks() { + CompileTask::wait_for_no_active_tasks(); +} + /** * Initialize compiler thread(s) + compiler object(s). The postcondition * of this function is that the compiler runtimes are initialized and that @@ -1823,11 +1824,11 @@ void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerTh // Delete all queued compilation tasks to make compiler threads exit faster. if (_c1_compile_queue != nullptr) { - _c1_compile_queue->free_all(); + _c1_compile_queue->delete_all(); } if (_c2_compile_queue != nullptr) { - _c2_compile_queue->free_all(); + _c2_compile_queue->delete_all(); } // Set flags so that we continue execution with using interpreter only. diff --git a/src/hotspot/share/compiler/compileBroker.hpp b/src/hotspot/share/compiler/compileBroker.hpp index 9a0e77ce4ba..046b2fa5197 100644 --- a/src/hotspot/share/compiler/compileBroker.hpp +++ b/src/hotspot/share/compiler/compileBroker.hpp @@ -140,7 +140,7 @@ class CompileQueue : public CHeapObj { // Redefine Classes support void mark_on_stack(); - void free_all(); + void delete_all(); void print_tty(); void print(outputStream* st = tty); @@ -383,6 +383,9 @@ class CompileBroker: AllStatic { static bool is_compilation_disabled_forever() { return _should_compile_new_jobs == shutdown_compilation; } + + static void wait_for_no_active_tasks(); + static void handle_full_code_cache(CodeBlobType code_blob_type); // Ensures that warning is only printed once. static bool should_print_compiler_warning() { diff --git a/src/hotspot/share/compiler/compileLog.cpp b/src/hotspot/share/compiler/compileLog.cpp index 85b8cbdf592..9641e99c33a 100644 --- a/src/hotspot/share/compiler/compileLog.cpp +++ b/src/hotspot/share/compiler/compileLog.cpp @@ -28,10 +28,11 @@ #include "jvm.h" #include "memory/allocation.inline.hpp" #include "oops/method.hpp" +#include "runtime/atomic.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" -CompileLog* CompileLog::_first = nullptr; +CompileLog* volatile CompileLog::_list_head = nullptr; // ------------------------------------------------------------------ // CompileLog::CompileLog @@ -49,9 +50,12 @@ CompileLog::CompileLog(const char* file_name, FILE* fp, intx thread_id) strcpy((char*)_file, file_name); // link into the global list - { MutexLocker locker(CompileTaskAlloc_lock); - _next = _first; - _first = this; + while (true) { + CompileLog* head = Atomic::load_acquire(&_list_head); + _next = head; + if (Atomic::cmpxchg(&_list_head, head, this) == head) { + break; + } } } @@ -202,7 +206,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) if (called_exit) return; called_exit = true; - CompileLog* log = _first; + CompileLog* log = Atomic::load_acquire(&_list_head); while (log != nullptr) { log->flush(); const char* partial_file = log->file(); @@ -290,7 +294,7 @@ void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) delete log; // Removes partial file log = next_log; } - _first = nullptr; + Atomic::store(&_list_head, (CompileLog*)nullptr); } // ------------------------------------------------------------------ diff --git a/src/hotspot/share/compiler/compileLog.hpp b/src/hotspot/share/compiler/compileLog.hpp index d91819104a5..10698b3c13b 100644 --- a/src/hotspot/share/compiler/compileLog.hpp +++ b/src/hotspot/share/compiler/compileLog.hpp @@ -53,7 +53,7 @@ class CompileLog : public xmlStream { CompileLog* _next; // static chain of all logs - static CompileLog* _first; // head of static chain + static CompileLog* volatile _list_head; // head of static chain void va_tag(bool push, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0); diff --git a/src/hotspot/share/compiler/compileTask.cpp b/src/hotspot/share/compiler/compileTask.cpp index b955a250fae..9c06688d348 100644 --- a/src/hotspot/share/compiler/compileTask.cpp +++ b/src/hotspot/share/compiler/compileTask.cpp @@ -36,59 +36,15 @@ #include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" -CompileTask* CompileTask::_task_free_list = nullptr; - -/** - * Allocate a CompileTask, from the free list if possible. - */ -CompileTask* CompileTask::allocate() { - MutexLocker locker(CompileTaskAlloc_lock); - CompileTask* task = nullptr; - - if (_task_free_list != nullptr) { - task = _task_free_list; - _task_free_list = task->next(); - task->set_next(nullptr); - } else { - task = new CompileTask(); - task->set_next(nullptr); - task->set_is_free(true); - } - assert(task->is_free(), "Task must be free."); - task->set_is_free(false); - return task; -} - -/** -* Add a task to the free list. -*/ -void CompileTask::free(CompileTask* task) { - MutexLocker locker(CompileTaskAlloc_lock); - if (!task->is_free()) { - if ((task->_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_method_holder))) { - JNIHandles::destroy_weak_global(task->_method_holder); - } else { - JNIHandles::destroy_global(task->_method_holder); - } - if (task->_failure_reason_on_C_heap && task->_failure_reason != nullptr) { - os::free((void*) task->_failure_reason); - } - task->_failure_reason = nullptr; - task->_failure_reason_on_C_heap = false; - - task->set_is_free(true); - task->set_next(_task_free_list); - _task_free_list = task; - } -} - -void CompileTask::initialize(int compile_id, - const methodHandle& method, - int osr_bci, - int comp_level, - int hot_count, - CompileTask::CompileReason compile_reason, - bool is_blocking) { +int CompileTask::_active_tasks = 0; + +CompileTask::CompileTask(int compile_id, + const methodHandle& method, + int osr_bci, + int comp_level, + int hot_count, + CompileReason compile_reason, + bool is_blocking) { Thread* thread = Thread::current(); _compile_id = compile_id; _method = method(); @@ -120,6 +76,33 @@ void CompileTask::initialize(int compile_id, _arena_bytes = 0; _next = nullptr; + + Atomic::add(&_active_tasks, 1, memory_order_relaxed); +} + +CompileTask::~CompileTask() { + if (_method_holder != nullptr && JNIHandles::is_weak_global_handle(_method_holder)) { + JNIHandles::destroy_weak_global(_method_holder); + } else { + JNIHandles::destroy_global(_method_holder); + } + if (_failure_reason_on_C_heap && _failure_reason != nullptr) { + os::free((void*) _failure_reason); + _failure_reason = nullptr; + _failure_reason_on_C_heap = false; + } + + if (Atomic::sub(&_active_tasks, 1, memory_order_relaxed) == 0) { + MonitorLocker wait_ml(CompileTaskWait_lock); + wait_ml.notify_all(); + } +} + +void CompileTask::wait_for_no_active_tasks() { + MonitorLocker locker(CompileTaskWait_lock); + while (Atomic::load(&_active_tasks) > 0) { + locker.wait(); + } } /** diff --git a/src/hotspot/share/compiler/compileTask.hpp b/src/hotspot/share/compiler/compileTask.hpp index 166f6497f2b..1a3ecbde566 100644 --- a/src/hotspot/share/compiler/compileTask.hpp +++ b/src/hotspot/share/compiler/compileTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -82,7 +82,7 @@ class CompileTask : public CHeapObj { } private: - static CompileTask* _task_free_list; + static int _active_tasks; int _compile_id; Method* _method; jobject _method_holder; @@ -103,7 +103,6 @@ class CompileTask : public CHeapObj { int _comp_level; int _num_inlined_bytecodes; CompileTask* _next, *_prev; - bool _is_free; // Fields used for logging why the compilation was initiated: jlong _time_queued; // time when task was enqueued jlong _time_started; // time when compilation started @@ -116,13 +115,10 @@ class CompileTask : public CHeapObj { size_t _arena_bytes; // peak size of temporary memory during compilation (e.g. node arenas) public: - CompileTask() : _failure_reason(nullptr), _failure_reason_on_C_heap(false) {} - void initialize(int compile_id, const methodHandle& method, int osr_bci, int comp_level, - int hot_count, - CompileTask::CompileReason compile_reason, bool is_blocking); - - static CompileTask* allocate(); - static void free(CompileTask* task); + CompileTask(int compile_id, const methodHandle& method, int osr_bci, int comp_level, + int hot_count, CompileReason compile_reason, bool is_blocking); + ~CompileTask(); + static void wait_for_no_active_tasks(); int compile_id() const { return _compile_id; } Method* method() const { return _method; } @@ -204,8 +200,6 @@ class CompileTask : public CHeapObj { void set_next(CompileTask* next) { _next = next; } CompileTask* prev() const { return _prev; } void set_prev(CompileTask* prev) { _prev = prev; } - bool is_free() const { return _is_free; } - void set_is_free(bool val) { _is_free = val; } bool is_unloaded() const; CompileTrainingData* training_data() const { return _training_data; } diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp index 0022d50cbb9..24b43fe3541 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp @@ -49,6 +49,9 @@ class EpsilonHeap : public CollectedHeap { volatile size_t _last_counter_update; volatile size_t _last_heap_print; + void print_tracing_info() const override; + void stop() override {}; + public: static EpsilonHeap* heap(); @@ -128,7 +131,6 @@ class EpsilonHeap : public CollectedHeap { void print_heap_on(outputStream* st) const override; void print_gc_on(outputStream* st) const override {} - void print_tracing_info() const override; bool print_location(outputStream* st, void* addr) const override; private: diff --git a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp index c4791311e9b..425be474602 100644 --- a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp +++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp @@ -218,9 +218,9 @@ class C1G1PostBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { bool G1BarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) { C1G1PreBarrierCodeGenClosure pre_code_gen_cl; C1G1PostBarrierCodeGenClosure post_code_gen_cl; - _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, "g1_pre_barrier_slow", + _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "g1_pre_barrier_slow", false, &pre_code_gen_cl); - _post_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, "g1_post_barrier_slow", + _post_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "g1_post_barrier_slow", false, &post_code_gen_cl); return _pre_barrier_c1_runtime_code_blob != nullptr && _post_barrier_c1_runtime_code_blob != nullptr; } diff --git a/src/hotspot/share/gc/g1/g1Analytics.hpp b/src/hotspot/share/gc/g1/g1Analytics.hpp index d4c6463b486..2fd3c78df27 100644 --- a/src/hotspot/share/gc/g1/g1Analytics.hpp +++ b/src/hotspot/share/gc/g1/g1Analytics.hpp @@ -110,7 +110,7 @@ class G1Analytics: public CHeapObj { return _short_term_pause_time_ratio; } - uint number_of_recorded_pause_times() const { + static constexpr uint max_num_of_recorded_pause_times() { return NumPrevPausesForHeuristics; } diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index bd156a69fe6..ee91c327337 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -196,8 +196,8 @@ void G1Arguments::initialize() { if (FLAG_IS_DEFAULT(GCTimeRatio) || GCTimeRatio == 0) { // In G1, we want the default GC overhead goal to be higher than // it is for PS, or the heap might be expanded too aggressively. - // We set it here to ~8%. - FLAG_SET_DEFAULT(GCTimeRatio, 12); + // We set it here to 4%. + FLAG_SET_DEFAULT(GCTimeRatio, 24); } // Below, we might need to calculate the pause time interval based on diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index b6c18420b82..040f258e6a8 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -795,8 +795,7 @@ void G1CollectedHeap::prepare_for_mutator_after_full_collection(size_t allocatio assert(num_free_regions() == 0, "we should not have added any free regions"); rebuild_region_sets(false /* free_list_only */); abort_refinement(); - resize_heap_if_necessary(allocation_word_size); - uncommit_regions_if_necessary(); + resize_heap_after_full_collection(allocation_word_size); // Rebuild the code root lists for each region rebuild_code_roots(); @@ -879,19 +878,39 @@ void G1CollectedHeap::upgrade_to_full_collection() { size_t(0) /* allocation_word_size */); } -void G1CollectedHeap::resize_heap_if_necessary(size_t allocation_word_size) { + +void G1CollectedHeap::resize_heap(size_t resize_bytes, bool should_expand) { + if (should_expand) { + expand(resize_bytes, _workers); + } else { + shrink(resize_bytes); + uncommit_regions_if_necessary(); + } +} + +void G1CollectedHeap::resize_heap_after_full_collection(size_t allocation_word_size) { assert_at_safepoint_on_vm_thread(); bool should_expand; - size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand, allocation_word_size); + size_t resize_bytes = _heap_sizing_policy->full_collection_resize_amount(should_expand, allocation_word_size); - if (resize_amount == 0) { - return; - } else if (should_expand) { - expand(resize_amount, _workers); - } else { - shrink(resize_amount); + if (resize_bytes != 0) { + resize_heap(resize_bytes, should_expand); + } +} + +void G1CollectedHeap::resize_heap_after_young_collection(size_t allocation_word_size) { + Ticks start = Ticks::now(); + + bool should_expand; + + size_t resize_bytes = _heap_sizing_policy->young_collection_resize_amount(should_expand, allocation_word_size); + + if (resize_bytes != 0) { + resize_heap(resize_bytes, should_expand); } + + phase_times()->record_resize_heap_time((Ticks::now() - start).seconds() * 1000.0); } HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size, @@ -1002,22 +1021,22 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) { } bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_workers) { + assert(expand_bytes > 0, "precondition"); + size_t aligned_expand_bytes = os::align_up_vm_page_size(expand_bytes); aligned_expand_bytes = align_up(aligned_expand_bytes, G1HeapRegion::GrainBytes); - log_debug(gc, ergo, heap)("Expand the heap. requested expansion amount: %zuB expansion amount: %zuB", - expand_bytes, aligned_expand_bytes); + uint num_regions_to_expand = (uint)(aligned_expand_bytes / G1HeapRegion::GrainBytes); + + log_debug(gc, ergo, heap)("Heap resize. Requested expansion amount: %zuB aligned expansion amount: %zuB (%u regions)", + expand_bytes, aligned_expand_bytes, num_regions_to_expand); if (num_inactive_regions() == 0) { - log_debug(gc, ergo, heap)("Did not expand the heap (heap already fully expanded)"); + log_debug(gc, ergo, heap)("Heap resize. Did not expand the heap (heap already fully expanded)"); return false; } - uint regions_to_expand = (uint)(aligned_expand_bytes / G1HeapRegion::GrainBytes); - assert(regions_to_expand > 0, "Must expand by at least one region"); - - uint expanded_by = _hrm.expand_by(regions_to_expand, pretouch_workers); - assert(expanded_by > 0, "must have failed during commit."); + uint expanded_by = _hrm.expand_by(num_regions_to_expand, pretouch_workers); size_t actual_expand_bytes = expanded_by * G1HeapRegion::GrainBytes; assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition"); @@ -1040,24 +1059,45 @@ bool G1CollectedHeap::expand_single_region(uint node_index) { } void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { - size_t aligned_shrink_bytes = os::align_down_vm_page_size(shrink_bytes); - aligned_shrink_bytes = align_down(aligned_shrink_bytes, G1HeapRegion::GrainBytes); + assert(shrink_bytes > 0, "must be"); + assert(is_aligned(shrink_bytes, G1HeapRegion::GrainBytes), + "Shrink request for %zuB not aligned to heap region size %zuB", + shrink_bytes, G1HeapRegion::GrainBytes); + uint num_regions_to_remove = (uint)(shrink_bytes / G1HeapRegion::GrainBytes); uint num_regions_removed = _hrm.shrink_by(num_regions_to_remove); size_t shrunk_bytes = num_regions_removed * G1HeapRegion::GrainBytes; - log_debug(gc, ergo, heap)("Shrink the heap. requested shrinking amount: %zuB aligned shrinking amount: %zuB actual amount shrunk: %zuB", - shrink_bytes, aligned_shrink_bytes, shrunk_bytes); + log_debug(gc, ergo, heap)("Heap resize. Requested shrinking amount: %zuB actual shrinking amount: %zuB (%u regions)", + shrink_bytes, shrunk_bytes, num_regions_removed); if (num_regions_removed > 0) { - log_debug(gc, heap)("Uncommittable regions after shrink: %u", num_regions_removed); policy()->record_new_heap_size(num_committed_regions()); } else { - log_debug(gc, ergo, heap)("Did not shrink the heap (heap shrinking operation failed)"); + log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (heap shrinking operation failed)"); } } void G1CollectedHeap::shrink(size_t shrink_bytes) { + if (capacity() == min_capacity()) { + log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (heap already at minimum)"); + return; + } + + size_t aligned_shrink_bytes = os::align_down_vm_page_size(shrink_bytes); + aligned_shrink_bytes = align_down(aligned_shrink_bytes, G1HeapRegion::GrainBytes); + + aligned_shrink_bytes = capacity() - MAX2(capacity() - aligned_shrink_bytes, min_capacity()); + assert(is_aligned(aligned_shrink_bytes, G1HeapRegion::GrainBytes), "Bytes to shrink %zuB not aligned", aligned_shrink_bytes); + + log_debug(gc, ergo, heap)("Heap resize. Requested shrink amount: %zuB aligned shrink amount: %zuB", + shrink_bytes, aligned_shrink_bytes); + + if (aligned_shrink_bytes == 0) { + log_debug(gc, ergo, heap)("Heap resize. Did not shrink the heap (shrink request too small)"); + return; + } + _verifier->verify_region_sets_optional(); // We should only reach here at the end of a Full GC or during Remark which @@ -1069,7 +1109,7 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) { // could instead use the remove_all_pending() method on free_list to // remove only the ones that we need to remove. _hrm.remove_all_free_regions(); - shrink_helper(shrink_bytes); + shrink_helper(aligned_shrink_bytes); rebuild_region_sets(true /* free_list_only */); _hrm.verify_optional(); @@ -1269,6 +1309,9 @@ jint G1CollectedHeap::initialize_service_thread() { jint G1CollectedHeap::initialize() { + if (!os::is_thread_cpu_time_supported()) { + vm_exit_during_initialization("G1 requires cpu time gathering support"); + } // Necessary to satisfy locking discipline assertions. MutexLocker x(Heap_lock); @@ -1335,7 +1378,7 @@ jint G1CollectedHeap::initialize() { } os::trace_page_sizes("Heap", - MinHeapSize, + min_capacity(), reserved_byte_size, heap_rs.base(), heap_rs.size(), @@ -2021,7 +2064,7 @@ bool G1CollectedHeap::block_is_obj(const HeapWord* addr) const { } size_t G1CollectedHeap::tlab_capacity(Thread* ignored) const { - return (_policy->young_list_target_length() - _survivor.length()) * G1HeapRegion::GrainBytes; + return eden_target_length() * G1HeapRegion::GrainBytes; } size_t G1CollectedHeap::tlab_used(Thread* ignored) const { @@ -2042,6 +2085,10 @@ size_t G1CollectedHeap::max_capacity() const { return max_num_regions() * G1HeapRegion::GrainBytes; } +size_t G1CollectedHeap::min_capacity() const { + return MinHeapSize; +} + void G1CollectedHeap::prepare_for_verify() { _verifier->prepare_for_verify(); } @@ -2234,7 +2281,7 @@ void G1CollectedHeap::gc_epilogue(bool full) { _free_arena_memory_task->notify_new_stats(&_young_gen_card_set_stats, &_collection_set_candidates_card_set_stats); - update_parallel_gc_threads_cpu_time(); + update_perf_counter_cpu_time(); } uint G1CollectedHeap::uncommit_regions(uint region_limit) { @@ -2318,10 +2365,10 @@ void G1CollectedHeap::verify_region_attr_remset_is_tracked() { } #endif -void G1CollectedHeap::update_parallel_gc_threads_cpu_time() { +void G1CollectedHeap::update_perf_counter_cpu_time() { assert(Thread::current()->is_VM_thread(), "Must be called from VM thread to avoid races"); - if (!UsePerfData || !os::is_thread_cpu_time_supported()) { + if (!UsePerfData) { return; } @@ -2387,24 +2434,11 @@ void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType phase_times()->record_verify_after_time_ms((Ticks::now() - start).seconds() * MILLIUNITS); } -void G1CollectedHeap::expand_heap_after_young_collection(){ - size_t expand_bytes = _heap_sizing_policy->young_collection_expansion_amount(); - if (expand_bytes > 0) { - // No need for an ergo logging here, - // expansion_amount() does this when it returns a value > 0. - Ticks expand_start = Ticks::now(); - if (expand(expand_bytes, _workers)) { - double expand_ms = (Ticks::now() - expand_start).seconds() * MILLIUNITS; - phase_times()->record_expand_heap_time(expand_ms); - } - } -} - -void G1CollectedHeap::do_collection_pause_at_safepoint() { +void G1CollectedHeap::do_collection_pause_at_safepoint(size_t allocation_word_size) { assert_at_safepoint_on_vm_thread(); guarantee(!is_stw_gc_active(), "collection is not reentrant"); - do_collection_pause_at_safepoint_helper(); + do_collection_pause_at_safepoint_helper(allocation_word_size); } G1HeapPrinterMark::G1HeapPrinterMark(G1CollectedHeap* g1h) : _g1h(g1h), _heap_transition(g1h) { @@ -2468,7 +2502,7 @@ void G1CollectedHeap::flush_region_pin_cache() { } } -void G1CollectedHeap::do_collection_pause_at_safepoint_helper() { +void G1CollectedHeap::do_collection_pause_at_safepoint_helper(size_t allocation_word_size) { ResourceMark rm; IsSTWGCActiveMark active_gc_mark; @@ -2486,7 +2520,7 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper() { bool should_start_concurrent_mark_operation = collector_state()->in_concurrent_start_gc(); // Perform the collection. - G1YoungCollector collector(gc_cause()); + G1YoungCollector collector(gc_cause(), allocation_word_size); collector.collect(); // It should now be safe to tell the concurrent mark thread to start @@ -2608,6 +2642,13 @@ void G1CollectedHeap::set_young_gen_card_set_stats(const G1MonotonicArenaMemoryS void G1CollectedHeap::record_obj_copy_mem_stats() { size_t total_old_allocated = _old_evac_stats.allocated() + _old_evac_stats.direct_allocated(); + uint total_allocated = _survivor_evac_stats.regions_filled() + _old_evac_stats.regions_filled(); + + log_debug(gc)("Allocated %u survivor %u old percent total %1.2f%% (%u%%)", + _survivor_evac_stats.regions_filled(), _old_evac_stats.regions_filled(), + percent_of(total_allocated, num_committed_regions() - total_allocated), + G1ReservePercent); + policy()->old_gen_alloc_tracker()-> add_allocated_bytes_since_last_gc(total_old_allocated * HeapWordSize); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index ad440577f2d..1cbd3dfd525 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -262,7 +262,7 @@ class G1CollectedHeap : public CollectedHeap { void set_collection_set_candidates_stats(G1MonotonicArenaMemoryStats& stats); void set_young_gen_card_set_stats(const G1MonotonicArenaMemoryStats& stats); - void update_parallel_gc_threads_cpu_time(); + void update_perf_counter_cpu_time(); private: // Return true if an explicit GC should start a concurrent cycle instead @@ -473,6 +473,8 @@ class G1CollectedHeap : public CollectedHeap { void retire_gc_alloc_region(G1HeapRegion* alloc_region, size_t allocated_bytes, G1HeapRegionAttr dest); + void resize_heap(size_t resize_bytes, bool should_expand); + // - if clear_all_soft_refs is true, all soft references should be // cleared during the GC. // - if do_maximal_compaction is true, full gc will do a maximally @@ -558,7 +560,8 @@ class G1CollectedHeap : public CollectedHeap { void pin_object(JavaThread* thread, oop obj) override; void unpin_object(JavaThread* thread, oop obj) override; - void resize_heap_if_necessary(size_t allocation_word_size); + void resize_heap_after_young_collection(size_t allocation_word_size); + void resize_heap_after_full_collection(size_t allocation_word_size); // Check if there is memory to uncommit and if so schedule a task to do it. void uncommit_regions_if_necessary(); @@ -743,11 +746,11 @@ class G1CollectedHeap : public CollectedHeap { // followed by a by-policy upgrade to a full collection. // precondition: at safepoint on VM thread // precondition: !is_stw_gc_active() - void do_collection_pause_at_safepoint(); + void do_collection_pause_at_safepoint(size_t allocation_word_size = 0); // Helper for do_collection_pause_at_safepoint, containing the guts // of the incremental collection pause, executed by the vm thread. - void do_collection_pause_at_safepoint_helper(); + void do_collection_pause_at_safepoint_helper(size_t allocation_word_size); void verify_before_young_collection(G1HeapVerifier::G1VerifyType type); void verify_after_young_collection(G1HeapVerifier::G1VerifyType type); @@ -764,8 +767,6 @@ class G1CollectedHeap : public CollectedHeap { // Must be called before any decision based on pin counts. void flush_region_pin_cache(); - void expand_heap_after_young_collection(); - // Update object copying statistics. void record_obj_copy_mem_stats(); private: @@ -882,6 +883,10 @@ class G1CollectedHeap : public CollectedHeap { private: jint initialize_concurrent_refinement(); jint initialize_service_thread(); + + void print_tracing_info() const override; + void stop() override; + public: // Initialize the G1CollectedHeap to have the initial and // maximum sizes and remembered and barrier sets @@ -891,7 +896,6 @@ class G1CollectedHeap : public CollectedHeap { // Returns whether concurrent mark threads (and the VM) are about to terminate. bool concurrent_mark_is_terminating() const; - void stop() override; void safepoint_synchronize_begin() override; void safepoint_synchronize_end() override; @@ -1022,6 +1026,8 @@ class G1CollectedHeap : public CollectedHeap { void start_concurrent_gc_for_metadata_allocation(GCCause::Cause gc_cause); + bool last_gc_was_periodic() { return _gc_lastcause == GCCause::_g1_periodic_collection; } + void remove_from_old_gen_sets(const uint old_regions_removed, const uint humongous_regions_removed); void prepend_to_freelist(G1FreeRegionList* list); @@ -1190,6 +1196,7 @@ class G1CollectedHeap : public CollectedHeap { // Print the maximum heap capacity. size_t max_capacity() const override; + size_t min_capacity() const; Tickspan time_since_last_collection() const { return Ticks::now() - _collection_pause_end; } @@ -1204,6 +1211,7 @@ class G1CollectedHeap : public CollectedHeap { G1SurvivorRegions* survivor() { return &_survivor; } + inline uint eden_target_length() const; uint eden_regions_count() const { return _eden.length(); } uint eden_regions_count(uint node_index) const { return _eden.regions_on_node(node_index); } uint survivor_regions_count() const { return _survivor.length(); } @@ -1309,9 +1317,6 @@ class G1CollectedHeap : public CollectedHeap { void gc_threads_do(ThreadClosure* tc) const override; - // Override - void print_tracing_info() const override; - // Used to print information about locations in the hs_err file. bool print_location(outputStream* st, void* addr) const override; }; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index 943c68b74c7..553be04d285 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -316,4 +316,8 @@ inline bool G1CollectedHeap::is_collection_set_candidate(const G1HeapRegion* r) return candidates->contains(r); } +inline uint G1CollectedHeap::eden_target_length() const { + return _policy->young_list_target_length() - survivor_regions_count(); +} + #endif // SHARE_GC_G1_G1COLLECTEDHEAP_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1CollectorState.hpp b/src/hotspot/share/gc/g1/g1CollectorState.hpp index f9f1839c7be..8f01227206b 100644 --- a/src/hotspot/share/gc/g1/g1CollectorState.hpp +++ b/src/hotspot/share/gc/g1/g1CollectorState.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -65,7 +65,7 @@ class G1CollectorState { bool _mark_or_rebuild_in_progress; // The marking bitmap is currently being cleared or about to be cleared. - bool _clearing_bitmap; + bool _clear_bitmap_in_progress; // Set during a full gc pause. bool _in_full_gc; @@ -79,7 +79,7 @@ class G1CollectorState { _initiate_conc_mark_if_possible(false), _mark_or_rebuild_in_progress(false), - _clearing_bitmap(false), + _clear_bitmap_in_progress(false), _in_full_gc(false) { } // Phase setters @@ -93,7 +93,7 @@ class G1CollectorState { void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; } void set_mark_or_rebuild_in_progress(bool v) { _mark_or_rebuild_in_progress = v; } - void set_clearing_bitmap(bool v) { _clearing_bitmap = v; } + void set_clear_bitmap_in_progress(bool v) { _clear_bitmap_in_progress = v; } // Phase getters bool in_young_only_phase() const { return _in_young_only_phase && !_in_full_gc; } @@ -107,7 +107,7 @@ class G1CollectorState { bool initiate_conc_mark_if_possible() const { return _initiate_conc_mark_if_possible; } bool mark_or_rebuild_in_progress() const { return _mark_or_rebuild_in_progress; } - bool clearing_bitmap() const { return _clearing_bitmap; } + bool clear_bitmap_in_progress() const { return _clear_bitmap_in_progress; } // Calculate GC Pause Type from internal state. G1GCPauseType young_gc_pause_type(bool concurrent_operation_is_full_mark) const; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 25a9b80093c..673c723af4c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -71,6 +71,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/threads.hpp" #include "utilities/align.hpp" @@ -507,8 +508,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _remark_weak_ref_times(), _cleanup_times(), - _accum_task_vtime(nullptr), - _concurrent_workers(nullptr), _num_concurrent_workers(0), _max_concurrent_workers(0), @@ -542,7 +541,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, } _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_num_tasks, mtGC); - _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_num_tasks, mtGC); // so that the assertion in MarkingTaskQueue::task_queue doesn't fail _num_active_tasks = _max_num_tasks; @@ -552,8 +550,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, _task_queues->register_queue(i, task_queue); _tasks[i] = new G1CMTask(i, this, task_queue, _region_mark_stats); - - _accum_task_vtime[i] = 0.0; } reset_at_marking_complete(); @@ -980,30 +976,23 @@ class G1CMConcurrentMarkingTask : public WorkerTask { void work(uint worker_id) { ResourceMark rm; - double start_vtime = os::elapsedVTime(); - - { - SuspendibleThreadSetJoiner sts_join; + SuspendibleThreadSetJoiner sts_join; - assert(worker_id < _cm->active_tasks(), "invariant"); + assert(worker_id < _cm->active_tasks(), "invariant"); - G1CMTask* task = _cm->task(worker_id); - task->record_start_time(); - if (!_cm->has_aborted()) { - do { - task->do_marking_step(G1ConcMarkStepDurationMillis, - true /* do_termination */, - false /* is_serial*/); + G1CMTask* task = _cm->task(worker_id); + task->record_start_time(); + if (!_cm->has_aborted()) { + do { + task->do_marking_step(G1ConcMarkStepDurationMillis, + true /* do_termination */, + false /* is_serial*/); - _cm->do_yield_check(); - } while (!_cm->has_aborted() && task->has_aborted()); - } - task->record_end_time(); - guarantee(!task->has_aborted() || _cm->has_aborted(), "invariant"); + _cm->do_yield_check(); + } while (!_cm->has_aborted() && task->has_aborted()); } - - double end_vtime = os::elapsedVTime(); - _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime); + task->record_end_time(); + guarantee(!task->has_aborted() || _cm->has_aborted(), "invariant"); } G1CMConcurrentMarkingTask(G1ConcurrentMark* cm) : @@ -1124,7 +1113,7 @@ uint G1ConcurrentMark::completed_mark_cycles() const { } void G1ConcurrentMark::concurrent_cycle_end(bool mark_cycle_completed) { - _g1h->collector_state()->set_clearing_bitmap(false); + _g1h->collector_state()->set_clear_bitmap_in_progress(false); _g1h->trace_heap_after_gc(_gc_tracer_cm); @@ -1461,8 +1450,13 @@ void G1ConcurrentMark::remark() { // GC pause. _g1h->increment_total_collections(); - _g1h->resize_heap_if_necessary(size_t(0) /* allocation_word_size */); - _g1h->uncommit_regions_if_necessary(); + // For Remark Pauses that may have been triggered by PeriodicGCs, we maintain + // resizing based on MinHeapFreeRatio or MaxHeapFreeRatio. If a PeriodicGC is + // triggered, it likely means there are very few regular GCs, making resizing + // based on gc heuristics less effective. + if (_g1h->last_gc_was_periodic()) { + _g1h->resize_heap_after_full_collection(0 /* allocation_word_size */); + } compute_new_sizes(); @@ -1496,7 +1490,7 @@ void G1ConcurrentMark::remark() { _remark_weak_ref_times.add((now - mark_work_end) * 1000.0); _remark_times.add((now - start) * 1000.0); - _g1h->update_parallel_gc_threads_cpu_time(); + _g1h->update_perf_counter_cpu_time(); policy->record_concurrent_mark_remark_end(); } @@ -1704,25 +1698,12 @@ void G1ConcurrentMark::weak_refs_work() { // Prefer to grow the stack until the max capacity. _global_mark_stack.set_should_grow(); - // We need at least one active thread. If reference processing - // is not multi-threaded we use the current (VMThread) thread, - // otherwise we use the workers from the G1CollectedHeap and - // we utilize all the worker threads we can. - uint active_workers = (ParallelRefProcEnabled ? _g1h->workers()->active_workers() : 1U); - active_workers = clamp(active_workers, 1u, _max_num_tasks); - - // Set the degree of MT processing here. If the discovery was done MT, - // the number of threads involved during discovery could differ from - // the number of active workers. This is OK as long as the discovered - // Reference lists are balanced (see balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); - // Parallel processing task executor. G1CMRefProcProxyTask task(rp->max_num_queues(), *_g1h, *this); ReferenceProcessorPhaseTimes pt(_gc_timer_cm, rp->max_num_queues()); // Process the weak references. - const ReferenceProcessorStats& stats = rp->process_discovered_references(task, pt); + const ReferenceProcessorStats& stats = rp->process_discovered_references(task, _g1h->workers(), pt); _gc_tracer_cm->report_gc_reference_stats(stats); pt.print_all_references(); @@ -1732,8 +1713,6 @@ void G1ConcurrentMark::weak_refs_work() { assert(has_overflown() || _global_mark_stack.is_empty(), "Mark stack should be empty (unless it has overflown)"); - - assert(rp->num_queues() == active_workers, "why not"); } if (has_overflown()) { @@ -2090,6 +2069,23 @@ void G1ConcurrentMark::abort_marking_threads() { _second_overflow_barrier_sync.abort(); } +double G1ConcurrentMark::worker_threads_cpu_time_s() { + class CountCpuTimeThreadClosure : public ThreadClosure { + public: + jlong _total_cpu_time; + + CountCpuTimeThreadClosure() : ThreadClosure(), _total_cpu_time(0) { } + + void do_thread(Thread* t) { + _total_cpu_time += os::thread_cpu_time(t); + } + } cl; + + threads_do(&cl); + + return (double)cl._total_cpu_time / NANOSECS_PER_SEC; +} + static void print_ms_time_info(const char* prefix, const char* name, NumberSeq& ns) { log_trace(gc, marking)("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).", @@ -2119,7 +2115,7 @@ void G1ConcurrentMark::print_summary_info() { log.trace(" Total stop_world time = %8.2f s.", (_remark_times.sum() + _cleanup_times.sum())/1000.0); log.trace(" Total concurrent time = %8.2f s (%8.2f s marking).", - cm_thread()->vtime_accum(), cm_thread()->vtime_mark_accum()); + cm_thread()->total_mark_cpu_time_s(), cm_thread()->worker_threads_cpu_time_s()); } void G1ConcurrentMark::threads_do(ThreadClosure* tc) const { @@ -2263,8 +2259,6 @@ bool G1CMTask::regular_clock_call() { return false; } - double curr_time_ms = os::elapsedVTime() * 1000.0; - // (4) We check whether we should yield. If we have to, then we abort. if (SuspendibleThreadSet::should_yield()) { // We should yield. To do this we abort the task. The caller is @@ -2274,7 +2268,7 @@ bool G1CMTask::regular_clock_call() { // (5) We check whether we've reached our time quota. If we have, // then we abort. - double elapsed_time_ms = curr_time_ms - _start_time_ms; + double elapsed_time_ms = (double)(os::current_thread_cpu_time() - _start_cpu_time_ns) / NANOSECS_PER_MILLISEC; if (elapsed_time_ms > _time_target_ms) { _has_timed_out = true; return false; @@ -2789,9 +2783,9 @@ void G1CMTask::handle_abort(bool is_serial, double elapsed_time_ms) { phase has visited reach a given limit. Additional invocations to the method clock have been planted in a few other strategic places too. The initial reason for the clock method was to avoid calling - vtime too regularly, as it is quite expensive. So, once it was in - place, it was natural to piggy-back all the other conditions on it - too and not constantly check them throughout the code. + cpu time gathering too regularly, as it is quite expensive. So, + once it was in place, it was natural to piggy-back all the other + conditions on it too and not constantly check them throughout the code. If do_termination is true then do_marking_step will enter its termination protocol. @@ -2814,7 +2808,7 @@ void G1CMTask::do_marking_step(double time_target_ms, bool is_serial) { assert(time_target_ms >= 1.0, "minimum granularity is 1ms"); - _start_time_ms = os::elapsedVTime() * 1000.0; + _start_cpu_time_ns = os::current_thread_cpu_time(); // If do_stealing is true then do_marking_step will attempt to // steal work from the other G1CMTasks. It only makes sense to @@ -2908,8 +2902,8 @@ void G1CMTask::do_marking_step(double time_target_ms, // closure which was statically allocated in this frame doesn't // escape it by accident. set_cm_oop_closure(nullptr); - double end_time_ms = os::elapsedVTime() * 1000.0; - double elapsed_time_ms = end_time_ms - _start_time_ms; + jlong end_cpu_time_ns = os::current_thread_cpu_time(); + double elapsed_time_ms = (double)(end_cpu_time_ns - _start_cpu_time_ns) / NANOSECS_PER_MILLISEC; // Update the step history. _step_times_ms.add(elapsed_time_ms); @@ -2932,7 +2926,7 @@ G1CMTask::G1CMTask(uint worker_id, _mark_stats_cache(mark_stats, G1RegionMarkStatsCache::RegionMarkStatsCacheSize), _calls(0), _time_target_ms(0.0), - _start_time_ms(0.0), + _start_cpu_time_ns(0), _cm_oop_closure(nullptr), _curr_region(nullptr), _finger(nullptr), diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index a4c2e94b2b1..3c3416ebcad 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -446,8 +446,6 @@ class G1ConcurrentMark : public CHeapObj { NumberSeq _remark_weak_ref_times; NumberSeq _cleanup_times; - double* _accum_task_vtime; // Accumulated task vtime - WorkerThreads* _concurrent_workers; uint _num_concurrent_workers; // The number of marking worker threads we're using uint _max_concurrent_workers; // Maximum number of marking worker threads @@ -612,16 +610,8 @@ class G1ConcurrentMark : public CHeapObj { // running. void abort_marking_threads(); - void update_accum_task_vtime(uint i, double vtime) { - _accum_task_vtime[i] += vtime; - } - - double all_task_accum_vtime() { - double ret = 0.0; - for (uint i = 0; i < _max_num_tasks; ++i) - ret += _accum_task_vtime[i]; - return ret; - } + // Total cpu time spent in mark worker threads in seconds. + double worker_threads_cpu_time_s(); // Attempts to steal an object from the task queues of other tasks bool try_stealing(uint worker_id, G1TaskQueueEntry& task_entry); @@ -753,8 +743,8 @@ class G1CMTask : public TerminatorTerminator { // When the virtual timer reaches this time, the marking step should exit double _time_target_ms; - // Start time of the current marking step - double _start_time_ms; + // Start cpu time of the current marking step + jlong _start_cpu_time_ns; // Oop closure used for iterations over oops G1CMOopClosure* _cm_oop_closure; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp index 83d547966ed..c05e7cc4be4 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp @@ -47,8 +47,6 @@ G1ConcurrentMarkThread::G1ConcurrentMarkThread(G1ConcurrentMark* cm) : ConcurrentGCThread(), - _vtime_start(0.0), - _vtime_accum(0.0), _cm(cm), _state(Idle) { @@ -113,8 +111,6 @@ class G1ConcPhaseTimer : public GCTraceConcTimeImplhas_aborted()); - _vtime_accum = (os::elapsedVTime() - _vtime_start); - - update_threads_cpu_time(); + update_perf_counter_cpu_time(); } _cm->root_regions()->cancel_scan(); } @@ -171,7 +165,7 @@ bool G1ConcurrentMarkThread::phase_clear_cld_claimed_marks() { bool G1ConcurrentMarkThread::phase_scan_root_regions() { G1ConcPhaseTimer p(_cm, "Concurrent Scan Root Regions"); _cm->scan_root_regions(); - update_threads_cpu_time(); + update_perf_counter_cpu_time(); return _cm->has_aborted(); } @@ -231,7 +225,7 @@ bool G1ConcurrentMarkThread::subphase_delay_to_keep_mmu_before_remark() { bool G1ConcurrentMarkThread::subphase_remark() { ConcurrentGCBreakpoints::at("BEFORE MARKING COMPLETED"); - update_threads_cpu_time(); + update_perf_counter_cpu_time(); VM_G1PauseRemark op; VMThread::execute(&op); return _cm->has_aborted(); @@ -241,7 +235,7 @@ bool G1ConcurrentMarkThread::phase_rebuild_and_scrub() { ConcurrentGCBreakpoints::at("AFTER REBUILD STARTED"); G1ConcPhaseTimer p(_cm, "Concurrent Rebuild Remembered Sets and Scrub Regions"); _cm->rebuild_and_scrub(); - update_threads_cpu_time(); + update_perf_counter_cpu_time(); return _cm->has_aborted(); } @@ -342,8 +336,8 @@ void G1ConcurrentMarkThread::concurrent_cycle_end(bool mark_cycle_completed) { ConcurrentGCBreakpoints::notify_active_to_idle(); } -void G1ConcurrentMarkThread::update_threads_cpu_time() { - if (!UsePerfData || !os::is_thread_cpu_time_supported()) { +void G1ConcurrentMarkThread::update_perf_counter_cpu_time() { + if (!UsePerfData) { return; } ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::gc_conc_mark); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp index 55655ac2c14..5f9ec4ef404 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -35,9 +35,6 @@ class G1Policy; class G1ConcurrentMarkThread: public ConcurrentGCThread { friend class VMStructs; - double _vtime_start; // Initial virtual time. - double _vtime_accum; // Accumulated virtual time. - G1ConcurrentMark* _cm; enum ServiceState : uint { @@ -88,10 +85,11 @@ class G1ConcurrentMarkThread: public ConcurrentGCThread { // Constructor G1ConcurrentMarkThread(G1ConcurrentMark* cm); - // Total virtual time so far for this thread and concurrent marking tasks. - double vtime_accum(); - // Marking virtual time so far this thread and concurrent marking tasks. - double vtime_mark_accum(); + // Total cpu time used by all marking related threads (i.e. this thread and the + // marking worker threads) in seconds. + double total_mark_cpu_time_s(); + // Cpu time used by all marking worker threads in seconds. + double worker_threads_cpu_time_s(); G1ConcurrentMark* cm() { return _cm; } @@ -110,7 +108,7 @@ class G1ConcurrentMarkThread: public ConcurrentGCThread { bool in_undo_mark() const; // Update the perf data counter for concurrent mark. - void update_threads_cpu_time(); + void update_perf_counter_cpu_time(); }; #endif // SHARE_GC_G1_G1CONCURRENTMARKTHREAD_HPP diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp index 52ebf1c6e37..254eaf62bb2 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -28,15 +28,16 @@ #include "gc/g1/g1ConcurrentMarkThread.hpp" #include "gc/g1/g1ConcurrentMark.hpp" +#include "runtime/os.hpp" // Total virtual time so far. -inline double G1ConcurrentMarkThread::vtime_accum() { - return _vtime_accum + _cm->all_task_accum_vtime(); +inline double G1ConcurrentMarkThread::total_mark_cpu_time_s() { + return os::thread_cpu_time(this) + worker_threads_cpu_time_s(); } // Marking virtual time so far -inline double G1ConcurrentMarkThread::vtime_mark_accum() { - return _cm->all_task_accum_vtime(); +inline double G1ConcurrentMarkThread::worker_threads_cpu_time_s() { + return _cm->worker_threads_cpu_time_s(); } inline void G1ConcurrentMarkThread::set_idle() { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp index da1f85eba73..2fa19d46093 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp @@ -40,8 +40,6 @@ G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) : ConcurrentGCThread(), - _vtime_start(0.0), - _vtime_accum(0.0), _notifier(Mutex::nosafepoint, FormatBuffer<>("G1 Refine#%d", worker_id), true), _requested_active(false), _refinement_stats(), @@ -53,8 +51,6 @@ G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint } void G1ConcurrentRefineThread::run_service() { - _vtime_start = os::elapsedVTime(); - while (wait_for_completed_buffers()) { SuspendibleThreadSetJoiner sts_join; G1ConcurrentRefineStats active_stats_start = _refinement_stats; @@ -74,7 +70,7 @@ void G1ConcurrentRefineThread::run_service() { } } report_inactive("Deactivated", _refinement_stats - active_stats_start); - track_usage(); + update_perf_counter_cpu_time(); } log_debug(gc, refine)("Stopping %d", _worker_id); @@ -128,12 +124,17 @@ void G1ConcurrentRefineThread::stop_service() { activate(); } +jlong G1ConcurrentRefineThread::cpu_time() { + return os::thread_cpu_time(this); +} + // The (single) primary thread drives the controller for the refinement threads. class G1PrimaryConcurrentRefineThread final : public G1ConcurrentRefineThread { bool wait_for_completed_buffers() override; bool maybe_deactivate() override; void do_refinement_step() override; - void track_usage() override; + // Updates jstat cpu usage for all refinement threads. + void update_perf_counter_cpu_time() override; public: G1PrimaryConcurrentRefineThread(G1ConcurrentRefine* cr) : @@ -179,10 +180,8 @@ void G1PrimaryConcurrentRefineThread::do_refinement_step() { } } -void G1PrimaryConcurrentRefineThread::track_usage() { - G1ConcurrentRefineThread::track_usage(); - // The primary thread is responsible for updating the CPU time for all workers. - if (UsePerfData && os::is_thread_cpu_time_supported()) { +void G1PrimaryConcurrentRefineThread::update_perf_counter_cpu_time() { + if (UsePerfData) { ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::gc_conc_refine); cr()->threads_do(&tttc); } @@ -191,6 +190,7 @@ void G1PrimaryConcurrentRefineThread::track_usage() { class G1SecondaryConcurrentRefineThread final : public G1ConcurrentRefineThread { bool wait_for_completed_buffers() override; void do_refinement_step() override; + void update_perf_counter_cpu_time() override { /* Nothing to do. The primary thread does all the work. */ } public: G1SecondaryConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) : diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp index 0711b61b194..b1e34e4b78d 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -39,9 +39,6 @@ class G1ConcurrentRefineThread: public ConcurrentGCThread { friend class VMStructs; friend class G1CollectedHeap; - double _vtime_start; // Initial virtual time. - double _vtime_accum; // Accumulated virtual time. - Monitor _notifier; bool _requested_active; @@ -71,15 +68,8 @@ class G1ConcurrentRefineThread: public ConcurrentGCThread { // precondition: this is the current thread. virtual void do_refinement_step() = 0; - // Update concurrent refine threads stats. - // If we are in Primary thread, we additionally update CPU time tracking. - virtual void track_usage() { - if (os::supports_vtime()) { - _vtime_accum = (os::elapsedVTime() - _vtime_start); - } else { - _vtime_accum = 0.0; - } - }; + // Update concurrent refine threads cpu time stats. + virtual void update_perf_counter_cpu_time() = 0; // Helper for do_refinement_step implementations. Try to perform some // refinement work, limited by stop_at. Returns true if any refinement work @@ -113,8 +103,8 @@ class G1ConcurrentRefineThread: public ConcurrentGCThread { return &_refinement_stats; } - // Total virtual time so far. - double vtime_accum() { return _vtime_accum; } + // Total cpu time spent in this thread so far. + jlong cpu_time(); }; #endif // SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index 637995c7e52..4992df8e214 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -299,18 +299,14 @@ void G1FullCollector::phase1_mark_live_objects() { } { - uint old_active_mt_degree = reference_processor()->num_queues(); - reference_processor()->set_active_mt_degree(workers()); GCTraceTime(Debug, gc, phases) debug("Phase 1: Reference Processing", scope()->timer()); // Process reference objects found during marking. ReferenceProcessorPhaseTimes pt(scope()->timer(), reference_processor()->max_num_queues()); G1FullGCRefProcProxyTask task(*this, reference_processor()->max_num_queues()); - const ReferenceProcessorStats& stats = reference_processor()->process_discovered_references(task, pt); + const ReferenceProcessorStats& stats = reference_processor()->process_discovered_references(task, _heap->workers(), pt); scope()->tracer()->report_gc_reference_stats(stats); pt.print_all_references(); assert(marker(0)->oop_stack()->is_empty(), "Should be no oops on the stack"); - - reference_processor()->set_active_mt_degree(old_active_mt_degree); } { diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index f7b0cb23b65..9171c8fd16d 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -178,7 +178,7 @@ void G1GCPhaseTimes::reset() { _cur_pre_evacuate_prepare_time_ms = 0.0; _cur_post_evacuate_cleanup_1_time_ms = 0.0; _cur_post_evacuate_cleanup_2_time_ms = 0.0; - _cur_expand_heap_time_ms = 0.0; + _cur_resize_heap_time_ms = 0.0; _cur_ref_proc_time_ms = 0.0; _cur_collection_start_sec = 0.0; _root_region_scan_wait_time_ms = 0.0; @@ -488,7 +488,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set(bool evacuation_failed _cur_post_evacuate_cleanup_2_time_ms + _recorded_total_rebuild_freelist_time_ms + _recorded_prepare_for_mutator_time_ms + - _cur_expand_heap_time_ms; + _cur_resize_heap_time_ms; info_time("Post Evacuate Collection Set", sum_ms); @@ -537,7 +537,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set(bool evacuation_failed trace_phase(_gc_par_phases[RebuildFreeList]); debug_time("Prepare For Mutator", _recorded_prepare_for_mutator_time_ms); - debug_time("Expand Heap After Collection", _cur_expand_heap_time_ms); + debug_time("Resize Heap After Collection", _cur_resize_heap_time_ms); return sum_ms; } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index ea868cd939e..a92f4f977ff 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -188,7 +188,7 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_post_evacuate_cleanup_1_time_ms; double _cur_post_evacuate_cleanup_2_time_ms; - double _cur_expand_heap_time_ms; + double _cur_resize_heap_time_ms; double _cur_ref_proc_time_ms; double _cur_collection_start_sec; @@ -283,8 +283,8 @@ class G1GCPhaseTimes : public CHeapObj { _cur_pre_evacuate_prepare_time_ms = ms; } - void record_expand_heap_time(double ms) { - _cur_expand_heap_time_ms = ms; + void record_resize_heap_time(double ms) { + _cur_resize_heap_time_ms = ms; } void record_initial_evac_time(double ms) { @@ -405,8 +405,8 @@ class G1GCPhaseTimes : public CHeapObj { _cur_collection_nmethod_list_cleanup_time_ms; } - double cur_expand_heap_time_ms() { - return _cur_expand_heap_time_ms; + double cur_resize_heap_time_ms() { + return _cur_resize_heap_time_ms; } double root_region_scan_wait_time_ms() { diff --git a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp index 71e25177166..6f82d7cc284 100644 --- a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp +++ b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp @@ -23,7 +23,7 @@ */ #include "gc/g1/g1Analytics.hpp" -#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/shared/gc_globals.hpp" #include "logging/log.hpp" @@ -38,162 +38,307 @@ G1HeapSizingPolicy* G1HeapSizingPolicy::create(const G1CollectedHeap* g1h, const G1HeapSizingPolicy::G1HeapSizingPolicy(const G1CollectedHeap* g1h, const G1Analytics* analytics) : _g1h(g1h), _analytics(analytics), - _num_prev_pauses_for_heuristics(analytics->number_of_recorded_pause_times()) { + // Bias for expansion at startup; the +1 is to counter the first sample always + // being 0.0, i.e. lower than any threshold. + _gc_cpu_usage_deviation_counter((G1CPUUsageExpandThreshold / 2) + 1), + _recent_cpu_usage_deltas(long_term_count_limit()), + _long_term_count(0) { +} - assert(MinOverThresholdForGrowth < _num_prev_pauses_for_heuristics, "Threshold must be less than %u", _num_prev_pauses_for_heuristics); - clear_ratio_check_data(); +void G1HeapSizingPolicy::reset_cpu_usage_tracking_data() { + _long_term_count = 0; + _gc_cpu_usage_deviation_counter = 0; + // Keep the recent GC CPU usage data. } -void G1HeapSizingPolicy::clear_ratio_check_data() { - _ratio_over_threshold_count = 0; - _ratio_over_threshold_sum = 0.0; - _pauses_since_start = 0; +void G1HeapSizingPolicy::decay_cpu_usage_tracking_data() { + _long_term_count = 0; + _gc_cpu_usage_deviation_counter /= 2; + // Keep the recent GC CPU usage data. } -double G1HeapSizingPolicy::scale_with_heap(double pause_time_threshold) { - double threshold = pause_time_threshold; +double G1HeapSizingPolicy::scale_with_heap(double gc_cpu_usage_target) { + double target = gc_cpu_usage_target; // If the heap is at less than half its maximum size, scale the threshold down, // to a limit of 1%. Thus the smaller the heap is, the more likely it is to expand, // though the scaling code will likely keep the increase small. if (_g1h->capacity() <= _g1h->max_capacity() / 2) { - threshold *= (double)_g1h->capacity() / (double)(_g1h->max_capacity() / 2); - threshold = MAX2(threshold, 0.01); + target *= (double)_g1h->capacity() / (double)(_g1h->max_capacity() / 2); + target = MAX2(target, 0.01); } - return threshold; + return target; } -static void log_expansion(double short_term_pause_time_ratio, - double long_term_pause_time_ratio, - double threshold, - double pause_time_ratio, - bool fully_expanded, - size_t resize_bytes) { - - log_debug(gc, ergo, heap)("Heap expansion: " - "short term pause time ratio %1.2f%% long term pause time ratio %1.2f%% " - "threshold %1.2f%% pause time ratio %1.2f%% fully expanded %s " - "resize by %zuB", - short_term_pause_time_ratio * 100.0, - long_term_pause_time_ratio * 100.0, - threshold * 100.0, - pause_time_ratio * 100.0, - BOOL_TO_STR(fully_expanded), - resize_bytes); +static void log_resize(double short_term_cpu_usage, + double long_term_cpu_usage, + double lower_threshold, + double upper_threshold, + double cpu_usage_target, + bool at_limit, + size_t resize_bytes, + bool expand) { + + log_debug(gc, ergo, heap)("Heap resize: " + "short term GC CPU usage %1.2f%% long term GC CPU usage %1.2f%% " + "lower threshold %1.2f%% upper threshold %1.2f%% GC CPU usage target %1.2f%% " + "at limit %s resize by %zuB expand %s", + short_term_cpu_usage * 100.0, + long_term_cpu_usage * 100.0, + lower_threshold * 100.0, + upper_threshold * 100.0, + cpu_usage_target * 100.0, + BOOL_TO_STR(at_limit), + resize_bytes, + BOOL_TO_STR(expand)); } -size_t G1HeapSizingPolicy::young_collection_expansion_amount() { - assert(GCTimeRatio > 0, "must be"); +// Logistic function, returns values in the range [0,1] +static double sigmoid_function(double value) { + // Sigmoid Parameters: + double inflection_point = 1.0; // Inflection point (midpoint of the sigmoid). + double steepness = 6.0; + return 1.0 / (1.0 + exp(-steepness * (value - inflection_point))); +} - double long_term_pause_time_ratio = _analytics->long_term_pause_time_ratio(); - double short_term_pause_time_ratio = _analytics->short_term_pause_time_ratio(); - const double pause_time_threshold = 1.0 / (1.0 + GCTimeRatio); - double threshold = scale_with_heap(pause_time_threshold); +// Computes a smooth scaling factor based on the relative deviation of actual gc_cpu_usage +// from the gc_cpu_usage_target, using a sigmoid function to transition between +// the specified minimum and maximum scaling factors. +// +// The input cpu_usage_delta represents the relative deviation of the current gc_cpu_usage to the +// gc_cpu_usage_target. This value is passed through a sigmoid function that produces a smooth +// output between 0 and 1, which is then scaled to the range [min_scale_factor, max_scale_factor]. +// +// The sigmoid's inflection point is set at cpu_usage_delta = 1.0 (a 100% deviation), where the scaling +// response increases most rapidly. +// +// The steepness parameter controls how sharply the scale factor changes near the inflection point. +// * Low steepness (1-3): gradual scaling over a wide range of deviations (more conservative). +// * High steepness (7-10): rapid scaling near the inflection point; small deviations result +// in very low scaling, but larger deviations ramp up scaling quickly. +// Steepness at 10 is nearly a step function. +// +// In this case, we choose a steepness of 6.0: +// - For small deviations, the sigmoid output is close to 0, resulting in scale factors near the +// lower bound, preventing excessive resizing. +// - As cpu_usage_delta grows toward 1.0, the steepness value makes the transition sharper, enabling +// more aggressive scaling for large deviations. +// +// This helps avoid overreacting to small gc_cpu_usage deviations but respond appropriately +// when necessary. +double G1HeapSizingPolicy::scale_cpu_usage_delta(double cpu_usage_delta, + double min_scale_factor, + double max_scale_factor) const { + double sigmoid = sigmoid_function(cpu_usage_delta); + + double scale_factor = min_scale_factor + (max_scale_factor - min_scale_factor) * sigmoid; + return scale_factor; +} - size_t expand_bytes = 0; +// Calculate the relative difference between a and b. +static double rel_diff(double a, double b) { + return (a - b) / b; +} - if (_g1h->capacity() == _g1h->max_capacity()) { - log_expansion(short_term_pause_time_ratio, long_term_pause_time_ratio, - threshold, pause_time_threshold, true, 0); - clear_ratio_check_data(); - return expand_bytes; +size_t G1HeapSizingPolicy::young_collection_expand_amount(double cpu_usage_delta) const { + assert(cpu_usage_delta >= 0.0, "must be"); + + size_t reserved_bytes = _g1h->max_capacity(); + size_t committed_bytes = _g1h->capacity(); + size_t uncommitted_bytes = reserved_bytes - committed_bytes; + size_t expand_bytes_via_pct = uncommitted_bytes * G1ExpandByPercentOfAvailable / 100; + size_t min_expand_bytes = MIN2(G1HeapRegion::GrainBytes, uncommitted_bytes); + + // Take the current size or G1ExpandByPercentOfAvailable % of + // the available expansion space, whichever is smaller, as the base + // expansion size. Then possibly scale this size according to how much the + // GC CPU usage (on average) has exceeded the target. + const double min_scale_factor = 0.2; + const double max_scale_factor = 2.0; + + double scale_factor = scale_cpu_usage_delta(cpu_usage_delta, + min_scale_factor, + max_scale_factor); + + size_t resize_bytes = MIN2(expand_bytes_via_pct, committed_bytes); + + resize_bytes = static_cast(resize_bytes * scale_factor); + + // Ensure the expansion size is at least the minimum growth amount + // and at most the remaining uncommitted byte size. + return clamp(resize_bytes, min_expand_bytes, uncommitted_bytes); +} + +size_t G1HeapSizingPolicy::young_collection_shrink_amount(double cpu_usage_delta, size_t allocation_word_size) const { + assert(cpu_usage_delta >= 0.0, "must be"); + + const double max_scale_factor = G1ShrinkByPercentOfAvailable / 100.0; + const double min_scale_factor = max_scale_factor / 10.0; + + double scale_factor = scale_cpu_usage_delta(cpu_usage_delta, + min_scale_factor, + max_scale_factor); + assert(scale_factor <= max_scale_factor, "must be"); + + // We are at the end of GC, so free regions are at maximum. Do not try to shrink + // to have less than the reserve or the number of regions we are most certainly + // going to use during this mutator phase. + uint target_regions_to_shrink = _g1h->num_free_regions(); + + uint needed_for_allocation = _g1h->eden_target_length(); + if (_g1h->is_humongous(allocation_word_size)) { + needed_for_allocation += (uint) _g1h->humongous_obj_size_in_regions(allocation_word_size); } - // If the last GC time ratio is over the threshold, increment the count of - // times it has been exceeded, and add this ratio to the sum of exceeded - // ratios. - if (short_term_pause_time_ratio > threshold) { - _ratio_over_threshold_count++; - _ratio_over_threshold_sum += short_term_pause_time_ratio; + if (target_regions_to_shrink >= needed_for_allocation) { + target_regions_to_shrink -= needed_for_allocation; + } else { + target_regions_to_shrink = 0; + } + + size_t resize_bytes = (double)G1HeapRegion::GrainBytes * target_regions_to_shrink * scale_factor; + + log_debug(gc, ergo, heap)("Shrink log: scale factor %1.2f%% " + "total free regions %u " + "needed for alloc %u " + "base targeted for shrinking %u " + "resize_bytes %zd ( %zu regions)", + scale_factor * 100.0, + _g1h->num_free_regions(), + needed_for_allocation, + target_regions_to_shrink, + resize_bytes, + (resize_bytes / G1HeapRegion::GrainBytes)); + + return resize_bytes; +} + +size_t G1HeapSizingPolicy::young_collection_resize_amount(bool& expand, size_t allocation_word_size) { + assert(GCTimeRatio > 0, "must be"); + expand = false; + + const double long_term_gc_cpu_usage = _analytics->long_term_pause_time_ratio(); + const double short_term_gc_cpu_usage = _analytics->short_term_pause_time_ratio(); + + double gc_cpu_usage_target = 1.0 / (1.0 + GCTimeRatio); + gc_cpu_usage_target = scale_with_heap(gc_cpu_usage_target); + + // Calculate gc_cpu_usage acceptable deviation thresholds: + // - upper_threshold, do not want to exceed this. + // - lower_threshold, we do not want to go below. + const double gc_cpu_usage_margin = G1CPUUsageDeviationPercent / 100.0; + const double upper_threshold = gc_cpu_usage_target * (1 + gc_cpu_usage_margin); + const double lower_threshold = gc_cpu_usage_target * (1 - gc_cpu_usage_margin); + + // Decide to expand/shrink based on how far the current GC CPU usage deviates + // from the target. This allows the policy to respond more quickly to GC pressure + // when the heap is small relative to the maximum heap. + const double long_term_delta = rel_diff(long_term_gc_cpu_usage, gc_cpu_usage_target); + const double short_term_delta = rel_diff(short_term_gc_cpu_usage, gc_cpu_usage_target); + + // If the short term GC CPU usage exceeds the upper threshold, increment the deviation + // counter. If it falls below the lower_threshold, decrement the deviation counter. + if (short_term_gc_cpu_usage > upper_threshold) { + _gc_cpu_usage_deviation_counter++; + } else if (short_term_gc_cpu_usage < lower_threshold) { + _gc_cpu_usage_deviation_counter--; + } + // Ignore very first sample as it is garbage. + if (_long_term_count != 0 || _recent_cpu_usage_deltas.num() != 0) { + _recent_cpu_usage_deltas.add(short_term_delta); + } + _long_term_count++; + + log_trace(gc, ergo, heap)("Heap resize triggers: long term count: %u " + "long term count limit: %u " + "short term delta: %1.2f " + "recent recorded short term deltas: %u" + "GC CPU usage deviation counter: %d", + _long_term_count, + long_term_count_limit(), + short_term_delta, + _recent_cpu_usage_deltas.num(), + _gc_cpu_usage_deviation_counter); + + // Check if there is a short- or long-term need for resizing, expansion first. + // + // Short-term resizing need is detected by exceeding the upper or lower thresholds + // multiple times, tracked in _gc_cpu_usage_deviation_counter. If it contains a large + // positive or negative (larger than the respective thresholds), we trigger + // resizing calculation. + // + // Slowly occurring long-term changes to the actual GC CPU usage are checked + // only every once in a while. + // + // The _gc_cpu_usage_deviation_counter value is reset after each resize, or slowly + // decayed if no resizing happens. + + size_t resize_bytes = 0; + + const bool use_long_term_delta = (_long_term_count == long_term_count_limit()); + const double avg_short_term_delta = _recent_cpu_usage_deltas.avg(); + + double delta; + if (use_long_term_delta) { + // For expansion, deltas are positive, and we want to expand aggressively. + // For shrinking, deltas are negative, so the MAX2 below selects the least + // aggressive one as we are using the absolute value for scaling. + delta = MAX2(avg_short_term_delta, long_term_delta); + } else { + delta = avg_short_term_delta; } + // Delta is negative when shrinking, but the calculation of the resize amount + // always expects an absolute value. Do that here unconditionally. + delta = fabsd(delta); + + int count_threshold_for_shrink = (int)G1CPUUsageShrinkThreshold; - log_trace(gc, ergo, heap)("Heap expansion triggers: pauses since start: %u " - "num prev pauses for heuristics: %u " - "ratio over threshold count: %u", - _pauses_since_start, - _num_prev_pauses_for_heuristics, - _ratio_over_threshold_count); - - // Check if we've had enough GC time ratio checks that were over the - // threshold to trigger an expansion. We'll also expand if we've - // reached the end of the history buffer and the average of all entries - // is still over the threshold. This indicates a smaller number of GCs were - // long enough to make the average exceed the threshold. - bool filled_history_buffer = _pauses_since_start == _num_prev_pauses_for_heuristics; - if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) || - (filled_history_buffer && (long_term_pause_time_ratio > threshold))) { - size_t min_expand_bytes = G1HeapRegion::GrainBytes; - size_t reserved_bytes = _g1h->max_capacity(); - size_t committed_bytes = _g1h->capacity(); - size_t uncommitted_bytes = reserved_bytes - committed_bytes; - size_t expand_bytes_via_pct = - uncommitted_bytes * G1ExpandByPercentOfAvailable / 100; - double scale_factor = 1.0; - - // If the current size is less than 1/4 of the Initial heap size, expand - // by half of the delta between the current and Initial sizes. IE, grow - // back quickly. - // - // Otherwise, take the current size, or G1ExpandByPercentOfAvailable % of - // the available expansion space, whichever is smaller, as the base - // expansion size. Then possibly scale this size according to how much the - // threshold has (on average) been exceeded by. If the delta is small - // (less than the StartScaleDownAt value), scale the size down linearly, but - // not by less than MinScaleDownFactor. If the delta is large (greater than - // the StartScaleUpAt value), scale up, but adding no more than MaxScaleUpFactor - // times the base size. The scaling will be linear in the range from - // StartScaleUpAt to (StartScaleUpAt + ScaleUpRange). In other words, - // ScaleUpRange sets the rate of scaling up. - if (committed_bytes < InitialHeapSize / 4) { - expand_bytes = (InitialHeapSize - committed_bytes) / 2; - } else { - double const MinScaleDownFactor = 0.2; - double const MaxScaleUpFactor = 2; - double const StartScaleDownAt = pause_time_threshold; - double const StartScaleUpAt = pause_time_threshold * 1.5; - double const ScaleUpRange = pause_time_threshold * 2.0; - - double ratio_delta; - if (filled_history_buffer) { - ratio_delta = long_term_pause_time_ratio - threshold; - } else { - ratio_delta = (_ratio_over_threshold_sum / _ratio_over_threshold_count) - threshold; - } - - expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes); - if (ratio_delta < StartScaleDownAt) { - scale_factor = ratio_delta / StartScaleDownAt; - scale_factor = MAX2(scale_factor, MinScaleDownFactor); - } else if (ratio_delta > StartScaleUpAt) { - scale_factor = 1 + ((ratio_delta - StartScaleUpAt) / ScaleUpRange); - scale_factor = MIN2(scale_factor, MaxScaleUpFactor); - } + if ((_gc_cpu_usage_deviation_counter >= (int)G1CPUUsageExpandThreshold) || + (use_long_term_delta && (long_term_gc_cpu_usage > upper_threshold))) { + expand = true; + + // Short-cut calculation if already at maximum capacity. + if (_g1h->capacity() == _g1h->max_capacity()) { + log_resize(short_term_gc_cpu_usage, long_term_gc_cpu_usage, + lower_threshold, upper_threshold, gc_cpu_usage_target, true, 0, expand); + reset_cpu_usage_tracking_data(); + return resize_bytes; } - expand_bytes = static_cast(expand_bytes * scale_factor); + log_trace(gc, ergo, heap)("expand deltas long %1.2f short %1.2f use long term %u delta %1.2f", + long_term_delta, avg_short_term_delta, use_long_term_delta, delta); - // Ensure the expansion size is at least the minimum growth amount - // and at most the remaining uncommitted byte size. - expand_bytes = clamp(expand_bytes, min_expand_bytes, uncommitted_bytes); + resize_bytes = young_collection_expand_amount(delta); - clear_ratio_check_data(); - } else { - // An expansion was not triggered. If we've started counting, increment - // the number of checks we've made in the current window. If we've - // reached the end of the window without resizing, clear the counters to - // start again the next time we see a ratio above the threshold. - if (_ratio_over_threshold_count > 0) { - _pauses_since_start++; - if (_pauses_since_start > _num_prev_pauses_for_heuristics) { - clear_ratio_check_data(); - } + reset_cpu_usage_tracking_data(); + } else if ((_gc_cpu_usage_deviation_counter <= -count_threshold_for_shrink) || + (use_long_term_delta && (long_term_gc_cpu_usage < lower_threshold))) { + expand = false; + // Short-cut calculation if already at minimum capacity. + if (_g1h->capacity() == _g1h->min_capacity()) { + log_resize(short_term_gc_cpu_usage, long_term_gc_cpu_usage, + lower_threshold, upper_threshold, gc_cpu_usage_target, true, 0, expand); + reset_cpu_usage_tracking_data(); + return resize_bytes; } + + log_trace(gc, ergo, heap)("expand deltas long %1.2f short %1.2f use long term %u delta %1.2f", + long_term_delta, avg_short_term_delta, use_long_term_delta, delta); + + resize_bytes = young_collection_shrink_amount(delta, allocation_word_size); + + reset_cpu_usage_tracking_data(); + } else if (use_long_term_delta) { + // A resize has not been triggered, but the long term counter overflowed. + decay_cpu_usage_tracking_data(); + expand = false; // Does not matter. } - log_expansion(short_term_pause_time_ratio, long_term_pause_time_ratio, - threshold, pause_time_threshold, false, expand_bytes); + log_resize(short_term_gc_cpu_usage, long_term_gc_cpu_usage, + lower_threshold, upper_threshold, gc_cpu_usage_target, + false, resize_bytes, expand); - return expand_bytes; + return resize_bytes; } static size_t target_heap_capacity(size_t used_bytes, uintx free_ratio) { @@ -257,17 +402,17 @@ size_t G1HeapSizingPolicy::full_collection_resize_amount(bool& expand, size_t al // Should not be greater than the heap max size. No need to adjust // it with respect to the heap min size as it's a lower bound (i.e., // we'll try to make the capacity larger than it, not smaller). - minimum_desired_capacity = MIN2(minimum_desired_capacity, MaxHeapSize); + minimum_desired_capacity = MIN2(minimum_desired_capacity, _g1h->max_capacity()); // Should not be less than the heap min size. No need to adjust it // with respect to the heap max size as it's an upper bound (i.e., // we'll try to make the capacity smaller than it, not greater). - maximum_desired_capacity = MAX2(maximum_desired_capacity, MinHeapSize); + maximum_desired_capacity = MAX2(maximum_desired_capacity, _g1h->min_capacity()); // Don't expand unless it's significant; prefer expansion to shrinking. if (capacity_after_gc < minimum_desired_capacity) { size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - log_debug(gc, ergo, heap)("Attempt heap expansion (capacity lower than min desired capacity). " + log_debug(gc, ergo, heap)("Heap resize. Attempt heap expansion (capacity lower than min desired capacity). " "Capacity: %zuB occupancy: %zuB live: %zuB " "min_desired_capacity: %zuB (%zu %%)", capacity_after_gc, used_after_gc, _g1h->used(), minimum_desired_capacity, MinHeapFreeRatio); @@ -279,7 +424,7 @@ size_t G1HeapSizingPolicy::full_collection_resize_amount(bool& expand, size_t al // Capacity too large, compute shrinking size size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; - log_debug(gc, ergo, heap)("Attempt heap shrinking (capacity higher than max desired capacity). " + log_debug(gc, ergo, heap)("Heap resize. Attempt heap shrinking (capacity higher than max desired capacity). " "Capacity: %zuB occupancy: %zuB live: %zuB " "maximum_desired_capacity: %zuB (%zu %%)", capacity_after_gc, used_after_gc, _g1h->used(), maximum_desired_capacity, MaxHeapFreeRatio); diff --git a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp index 4ee302403ed..32096f692b4 100644 --- a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp +++ b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp @@ -25,42 +25,87 @@ #ifndef SHARE_GC_G1_G1HEAPSIZINGPOLICY_HPP #define SHARE_GC_G1_G1HEAPSIZINGPOLICY_HPP +#include "gc/g1/g1Analytics.hpp" #include "memory/allocation.hpp" +#include "utilities/numberSeq.hpp" -class G1Analytics; class G1CollectedHeap; +// +// Contains heuristics to resize the heap, i.e. expand or shrink, during operation. +// +// For young collections, this heuristics is based on GC CPU usage, i.e. trying to +// change the heap so that the GC CPU usage stays approximately close to the target +// GC CPU usage set by the user. +// +// The heuristics track both short and long term GC behavior to affect heap resizing. +// +// Short term tracking is based on the short-term GC CPU usage i.e we count events +// for which short-term GC CPU usage is outside the range: +// gc_cpu_usage_target × [1 - d, 1 + d], where d = G1CPUUsageDeviationPercent / 100 +// If below that range, we decrement that counter, if above, we increment it. +// +// If that counter reaches the G1CPUUsageExpandThreshold we consider expansion, +// if that counter reaches -G1CPUUsageShrinkThreshold we consider shrinking the heap. +// +// While doing so, we accumulate the relative difference to the target GC CPU usage +// to guide the expansion/shrinking amount. +// +// Furthermore, if there is no short-term based resizing event for a "long" time, +// we decay that counter, i.e. drop it towards zero again to avoid that previous +// intermediate length short term behavior followed by a quiet time and a single +// short term event causes unnecessary resizes. +// +// Long term behavior is solely managed by regularly comparing actual long term +// GC CPU usage with the boundaries of acceptable deviation range. If the actual +// long term GC CPU usage is outside this range, expand or shrink accordingly. +// +// The mechanism is meant to filter out short term events because heap resizing +// has some overhead. +// +// For full collections, we base resize decisions only on Min/MaxHeapFreeRatio. +// class G1HeapSizingPolicy: public CHeapObj { - // MinOverThresholdForGrowth must be less than the number of recorded - // pause times in G1Analytics, representing the minimum number of pause - // time ratios that exceed GCTimeRatio before a heap expansion will be triggered. - const static uint MinOverThresholdForGrowth = 4; - const G1CollectedHeap* _g1h; const G1Analytics* _analytics; - const uint _num_prev_pauses_for_heuristics; - // Ratio check data for determining if heap growth is necessary. - uint _ratio_over_threshold_count; - double _ratio_over_threshold_sum; - uint _pauses_since_start; + // Number of times short-term GC CPU usage crossed the lower or upper threshold + // recently; every time the upper threshold is exceeded, it is incremented, and + // decremented if the lower threshold is exceeded. + int _gc_cpu_usage_deviation_counter; + // Recent GC CPU usage deviations relative to the gc_cpu_usage_target + TruncatedSeq _recent_cpu_usage_deltas; + uint _long_term_count; + + // Clear GC CPU usage tracking data used by young_collection_resize_amount(). + void reset_cpu_usage_tracking_data(); + // Decay (move towards "no changes") GC CPU usage tracking data. + void decay_cpu_usage_tracking_data(); - // Scale "full" gc pause time threshold with heap size as we want to resize more + // Scale the gc_cpu_usage_target with heap size as we want to resize more // eagerly at small heap sizes. - double scale_with_heap(double pause_time_threshold); + double scale_with_heap(double gc_cpu_usage_target); + + // Scale the cpu usage delta depending on the relative difference from the target gc_cpu_usage. + double scale_cpu_usage_delta(double cpu_usage_delta, double min_scale_factor, double max_scale_factor) const; + + size_t young_collection_expand_amount(double cpu_usage_delta) const; + size_t young_collection_shrink_amount(double cpu_usage_delta, size_t allocation_word_size) const; G1HeapSizingPolicy(const G1CollectedHeap* g1h, const G1Analytics* analytics); public: - // If an expansion would be appropriate, because recent GC overhead had - // exceeded the desired limit, return an amount to expand by. - size_t young_collection_expansion_amount(); + static constexpr uint long_term_count_limit() { + return G1Analytics::max_num_of_recorded_pause_times(); + } + // Return by how many bytes the heap should be changed based on recent GC CPU + // usage after young collection. If expand is set, the heap should be expanded, + // otherwise shrunk. + size_t young_collection_resize_amount(bool& expand, size_t allocation_word_size); // Returns the amount of bytes to resize the heap; if expand is set, the heap // should by expanded by that amount, shrunk otherwise. size_t full_collection_resize_amount(bool& expand, size_t allocation_word_size); - // Clear ratio tracking data used by expansion_amount(). - void clear_ratio_check_data(); static G1HeapSizingPolicy* create(const G1CollectedHeap* g1h, const G1Analytics* analytics); }; diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 92b56953067..cc7cffc0c38 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -594,7 +594,7 @@ void G1Policy::record_full_collection_end() { collector_state()->set_initiate_conc_mark_if_possible(need_to_start_conc_mark("end of Full GC")); collector_state()->set_in_concurrent_start_gc(false); collector_state()->set_mark_or_rebuild_in_progress(false); - collector_state()->set_clearing_bitmap(false); + collector_state()->set_clear_bitmap_in_progress(false); _eden_surv_rate_group->start_adding_regions(); // also call this on any additional surv rate groups @@ -1318,7 +1318,7 @@ void G1Policy::record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_se } collector_state()->set_in_young_gc_before_mixed(mixed_gc_pending); collector_state()->set_mark_or_rebuild_in_progress(false); - collector_state()->set_clearing_bitmap(true); + collector_state()->set_clear_bitmap_in_progress(true); double end_sec = os::elapsedTime(); double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0; diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index c0ee48b6bd3..4114f0e7ba5 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1138,7 +1138,7 @@ class G1MergeHeapRootsTask : public WorkerTask { // Mark phase midway, which might have also left stale marks in old generation regions. // There might actually have been scheduled multiple collections, but at that point we do // not care that much about performance and just do the work multiple times if needed. - return (_g1h->collector_state()->clearing_bitmap() || + return (_g1h->collector_state()->clear_bitmap_in_progress() || _g1h->concurrent_mark_is_terminating()) && hr->is_old(); } diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index 38f874d5359..ec876d020ec 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -44,7 +44,7 @@ void G1RemSetSummary::update() { CollectData(G1RemSetSummary * summary) : _summary(summary), _counter(0) {} virtual void do_thread(Thread* t) { G1ConcurrentRefineThread* crt = static_cast(t); - _summary->set_rs_thread_vtime(_counter, crt->vtime_accum()); + _summary->set_refine_thread_cpu_time(_counter, crt->cpu_time()); _counter++; } } collector(this); @@ -53,23 +53,23 @@ void G1RemSetSummary::update() { g1h->concurrent_refine()->threads_do(&collector); } -void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) { - assert(_rs_threads_vtimes != nullptr, "just checking"); - assert(thread < _num_vtimes, "just checking"); - _rs_threads_vtimes[thread] = value; +void G1RemSetSummary::set_refine_thread_cpu_time(uint thread, jlong value) { + assert(_refine_threads_cpu_times != nullptr, "just checking"); + assert(thread < _num_refine_threads, "just checking"); + _refine_threads_cpu_times[thread] = value; } -double G1RemSetSummary::rs_thread_vtime(uint thread) const { - assert(_rs_threads_vtimes != nullptr, "just checking"); - assert(thread < _num_vtimes, "just checking"); - return _rs_threads_vtimes[thread]; +jlong G1RemSetSummary::refine_thread_cpu_time(uint thread) const { + assert(_refine_threads_cpu_times != nullptr, "just checking"); + assert(thread < _num_refine_threads, "just checking"); + return _refine_threads_cpu_times[thread]; } G1RemSetSummary::G1RemSetSummary(bool should_update) : - _num_vtimes(G1ConcRefinementThreads), - _rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)) { + _num_refine_threads(G1ConcRefinementThreads), + _refine_threads_cpu_times(NEW_C_HEAP_ARRAY(jlong, _num_refine_threads, mtGC)) { - memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes); + memset(_refine_threads_cpu_times, 0, sizeof(jlong) * _num_refine_threads); if (should_update) { update(); @@ -77,26 +77,26 @@ G1RemSetSummary::G1RemSetSummary(bool should_update) : } G1RemSetSummary::~G1RemSetSummary() { - FREE_C_HEAP_ARRAY(double, _rs_threads_vtimes); + FREE_C_HEAP_ARRAY(jlong, _refine_threads_cpu_times); } void G1RemSetSummary::set(G1RemSetSummary* other) { assert(other != nullptr, "just checking"); - assert(_num_vtimes == other->_num_vtimes, "just checking"); + assert(_num_refine_threads == other->_num_refine_threads, "just checking"); - memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes); + memcpy(_refine_threads_cpu_times, other->_refine_threads_cpu_times, sizeof(jlong) * _num_refine_threads); } void G1RemSetSummary::subtract_from(G1RemSetSummary* other) { assert(other != nullptr, "just checking"); - assert(_num_vtimes == other->_num_vtimes, "just checking"); + assert(_num_refine_threads == other->_num_refine_threads, "just checking"); - for (uint i = 0; i < _num_vtimes; i++) { - set_rs_thread_vtime(i, other->rs_thread_vtime(i) - rs_thread_vtime(i)); + for (uint i = 0; i < _num_refine_threads; i++) { + set_refine_thread_cpu_time(i, other->refine_thread_cpu_time(i) - refine_thread_cpu_time(i)); } } -class RegionTypeCounter { +class G1PerRegionTypeRemSetCounters { private: const char* _name; @@ -130,7 +130,7 @@ class RegionTypeCounter { public: - RegionTypeCounter(const char* name) : _name(name), _rs_unused_mem_size(0), _rs_mem_size(0), _cards_occupied(0), + G1PerRegionTypeRemSetCounters(const char* name) : _name(name), _rs_unused_mem_size(0), _rs_mem_size(0), _cards_occupied(0), _amount(0), _amount_tracked(0), _code_root_mem_size(0), _code_root_elems(0) { } void add(size_t rs_unused_mem_size, size_t rs_mem_size, size_t cards_occupied, @@ -180,13 +180,12 @@ class RegionTypeCounter { }; -class HRRSStatsIter: public G1HeapRegionClosure { -private: - RegionTypeCounter _young; - RegionTypeCounter _humongous; - RegionTypeCounter _free; - RegionTypeCounter _old; - RegionTypeCounter _all; +class G1HeapRegionStatsClosure: public G1HeapRegionClosure { + G1PerRegionTypeRemSetCounters _young; + G1PerRegionTypeRemSetCounters _humongous; + G1PerRegionTypeRemSetCounters _free; + G1PerRegionTypeRemSetCounters _old; + G1PerRegionTypeRemSetCounters _all; size_t _max_rs_mem_sz; G1HeapRegion* _max_rs_mem_sz_region; @@ -214,7 +213,7 @@ class HRRSStatsIter: public G1HeapRegionClosure { G1HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; } public: - HRRSStatsIter() : _young("Young"), _humongous("Humongous"), + G1HeapRegionStatsClosure() : _young("Young"), _humongous("Humongous"), _free("Free"), _old("Old"), _all("All"), _max_rs_mem_sz(0), _max_rs_mem_sz_region(nullptr), _max_code_root_mem_sz(0), _max_code_root_mem_sz_region(nullptr), @@ -249,7 +248,7 @@ class HRRSStatsIter: public G1HeapRegionClosure { } size_t code_root_elems = hrrs->code_roots_list_length(); - RegionTypeCounter* current = nullptr; + G1PerRegionTypeRemSetCounters* current = nullptr; if (r->is_free()) { current = &_free; } else if (r->is_young()) { @@ -290,7 +289,7 @@ class HRRSStatsIter: public G1HeapRegionClosure { } - RegionTypeCounter* current = &_old; + G1PerRegionTypeRemSetCounters* current = &_old; for (G1CSetCandidateGroup* group : g1h->policy()->candidates()->from_marking_groups()) { if (group->length() > 1) { G1CardSet* group_card_set = group->card_set(); @@ -311,7 +310,7 @@ class HRRSStatsIter: public G1HeapRegionClosure { } void print_summary_on(outputStream* out) { - RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, nullptr }; + G1PerRegionTypeRemSetCounters* counters[] = { &_young, &_humongous, &_free, &_old, nullptr }; out->print_cr(" Current rem set statistics"); out->print_cr(" Total per region rem sets sizes = %zu" @@ -319,13 +318,13 @@ class HRRSStatsIter: public G1HeapRegionClosure { total_rs_mem_sz(), max_rs_mem_sz(), total_rs_unused_mem_sz()); - for (RegionTypeCounter** current = &counters[0]; *current != nullptr; current++) { + for (G1PerRegionTypeRemSetCounters** current = &counters[0]; *current != nullptr; current++) { (*current)->print_rs_mem_info_on(out, total_rs_mem_sz()); } out->print_cr(" %zu occupied cards represented.", total_cards_occupied()); - for (RegionTypeCounter** current = &counters[0]; *current != nullptr; current++) { + for (G1PerRegionTypeRemSetCounters** current = &counters[0]; *current != nullptr; current++) { (*current)->print_cards_occupied_info_on(out, total_cards_occupied()); } @@ -360,13 +359,13 @@ class HRRSStatsIter: public G1HeapRegionClosure { proper_unit_for_byte_size(total_code_root_mem_sz()), byte_size_in_proper_unit(max_code_root_rem_set->code_roots_mem_size()), proper_unit_for_byte_size(max_code_root_rem_set->code_roots_mem_size())); - for (RegionTypeCounter** current = &counters[0]; *current != nullptr; current++) { + for (G1PerRegionTypeRemSetCounters** current = &counters[0]; *current != nullptr; current++) { (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); } out->print_cr(" %zu code roots represented.", total_code_root_elems()); - for (RegionTypeCounter** current = &counters[0]; *current != nullptr; current++) { + for (G1PerRegionTypeRemSetCounters** current = &counters[0]; *current != nullptr; current++) { (*current)->print_code_root_elems_info_on(out, total_code_root_elems()); } @@ -383,12 +382,12 @@ void G1RemSetSummary::print_on(outputStream* out, bool show_thread_times) { if (show_thread_times) { out->print_cr(" Concurrent refinement threads times (s)"); out->print(" "); - for (uint i = 0; i < _num_vtimes; i++) { - out->print(" %5.2f", rs_thread_vtime(i)); + for (uint i = 0; i < _num_refine_threads; i++) { + out->print(" %5.2f", (double)refine_thread_cpu_time(i) / NANOSECS_PER_SEC); } out->cr(); } - HRRSStatsIter blk; + G1HeapRegionStatsClosure blk; G1CollectedHeap::heap()->heap_region_iterate(&blk); blk.do_cset_groups(); blk.print_summary_on(out); diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.hpp b/src/hotspot/share/gc/g1/g1RemSetSummary.hpp index f3bb7d3adcc..373f38952c8 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.hpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -31,15 +31,14 @@ class G1RemSet; -// A G1RemSetSummary manages statistical information about the G1RemSet - +// A G1RemSetSummary manages statistical information about the remembered set. class G1RemSetSummary { - size_t _num_vtimes; - double* _rs_threads_vtimes; + size_t _num_refine_threads; + jlong* _refine_threads_cpu_times; - void set_rs_thread_vtime(uint thread, double value); + void set_refine_thread_cpu_time(uint thread, jlong value); - // update this summary with current data from various places + // Update this summary with current data from various places. void update(); public: @@ -47,14 +46,14 @@ class G1RemSetSummary { ~G1RemSetSummary(); - // set the counters in this summary to the values of the others + // Set the counters in this summary to the values of the others. void set(G1RemSetSummary* other); - // subtract all counters from the other summary, and set them in the current + // Subtract all counters from the other summary, and set them in the current. void subtract_from(G1RemSetSummary* other); void print_on(outputStream* out, bool show_thread_times); - double rs_thread_vtime(uint thread) const; + jlong refine_thread_cpu_time(uint thread) const; }; #endif // SHARE_GC_G1_G1REMSETSUMMARY_HPP diff --git a/src/hotspot/share/gc/g1/g1ServiceThread.cpp b/src/hotspot/share/gc/g1/g1ServiceThread.cpp index 22675ec2a64..3c96123d14f 100644 --- a/src/hotspot/share/gc/g1/g1ServiceThread.cpp +++ b/src/hotspot/share/gc/g1/g1ServiceThread.cpp @@ -119,7 +119,7 @@ G1ServiceTask* G1ServiceThread::wait_for_task() { void G1ServiceThread::run_task(G1ServiceTask* task) { jlong start = os::elapsed_counter(); - double vstart = os::elapsedVTime(); + jlong start_cpu_time_ns = os::thread_cpu_time(this); assert(task->time() <= start, "task run early: " JLONG_FORMAT " > " JLONG_FORMAT, @@ -130,12 +130,12 @@ void G1ServiceThread::run_task(G1ServiceTask* task) { task->execute(); - update_thread_cpu_time(); + update_perf_counter_cpu_time(); log_debug(gc, task)("G1 Service Thread (%s) (run: %1.3fms) (cpu: %1.3fms)", task->name(), TimeHelper::counter_to_millis(os::elapsed_counter() - start), - (os::elapsedVTime() - vstart) * MILLIUNITS); + (double)(os::thread_cpu_time(this) - start_cpu_time_ns) / NANOSECS_PER_MILLISEC); } void G1ServiceThread::run_service() { @@ -153,8 +153,8 @@ void G1ServiceThread::stop_service() { ml.notify(); } -void G1ServiceThread::update_thread_cpu_time() { - if (UsePerfData && os::is_thread_cpu_time_supported()) { +void G1ServiceThread::update_perf_counter_cpu_time() { + if (UsePerfData) { ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::gc_service); tttc.do_thread(this); } diff --git a/src/hotspot/share/gc/g1/g1ServiceThread.hpp b/src/hotspot/share/gc/g1/g1ServiceThread.hpp index cfa7abb6552..4ed9c241562 100644 --- a/src/hotspot/share/gc/g1/g1ServiceThread.hpp +++ b/src/hotspot/share/gc/g1/g1ServiceThread.hpp @@ -121,7 +121,7 @@ class G1ServiceThread: public ConcurrentGCThread { void schedule(G1ServiceTask* task, jlong delay, bool notify); // Update the perf data counter for service thread. - void update_thread_cpu_time(); + void update_perf_counter_cpu_time(); public: G1ServiceThread(); diff --git a/src/hotspot/share/gc/g1/g1SharedClosures.hpp b/src/hotspot/share/gc/g1/g1SharedClosures.hpp index 5541d6274a3..a81f62ff308 100644 --- a/src/hotspot/share/gc/g1/g1SharedClosures.hpp +++ b/src/hotspot/share/gc/g1/g1SharedClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_GC_G1_G1SHAREDCLOSURES_HPP +#define SHARE_GC_G1_G1SHAREDCLOSURES_HPP + #include "gc/g1/g1NMethodClosure.hpp" #include "gc/g1/g1OopClosures.hpp" #include "memory/iterator.hpp" @@ -54,3 +57,5 @@ class G1SharedClosures { _clds(&_oops_in_cld, process_only_dirty), _nmethods(pss->worker_id(), &_oops_in_nmethod, should_mark) {} }; + +#endif // SHARE_GC_G1_G1SHAREDCLOSURES_HPP diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index b56d9991acb..458d6c3d008 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -971,12 +971,9 @@ void G1YoungCollector::process_discovered_references(G1ParScanThreadStateSet* pe ReferenceProcessor* rp = ref_processor_stw(); assert(rp->discovery_enabled(), "should have been enabled"); - uint no_of_gc_workers = workers()->active_workers(); - rp->set_active_mt_degree(no_of_gc_workers); - G1STWRefProcProxyTask task(rp->max_num_queues(), *_g1h, *per_thread_states, *task_queues()); ReferenceProcessorPhaseTimes& pt = *phase_times()->ref_phase_times(); - ReferenceProcessorStats stats = rp->process_discovered_references(task, pt); + ReferenceProcessorStats stats = rp->process_discovered_references(task, _g1h->workers(), pt); gc_tracer_stw()->report_gc_reference_stats(stats); @@ -1062,7 +1059,7 @@ void G1YoungCollector::post_evacuate_collection_set(G1EvacInfo* evacuation_info, _g1h->gc_epilogue(false); - _g1h->expand_heap_after_young_collection(); + _g1h->resize_heap_after_young_collection(_allocation_word_size); } bool G1YoungCollector::evacuation_failed() const { @@ -1077,9 +1074,11 @@ bool G1YoungCollector::evacuation_alloc_failed() const { return _evac_failure_regions.has_regions_alloc_failed(); } -G1YoungCollector::G1YoungCollector(GCCause::Cause gc_cause) : +G1YoungCollector::G1YoungCollector(GCCause::Cause gc_cause, + size_t allocation_word_size) : _g1h(G1CollectedHeap::heap()), _gc_cause(gc_cause), + _allocation_word_size(allocation_word_size), _concurrent_operation_is_full_mark(false), _evac_failure_regions() { diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.hpp b/src/hotspot/share/gc/g1/g1YoungCollector.hpp index d6835389801..2c4929958fe 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -79,6 +79,7 @@ class G1YoungCollector { G1YoungGCAllocationFailureInjector* allocation_failure_injector() const; GCCause::Cause _gc_cause; + size_t _allocation_word_size; bool _concurrent_operation_is_full_mark; @@ -137,7 +138,8 @@ class G1YoungCollector { bool evacuation_alloc_failed() const; public: - G1YoungCollector(GCCause::Cause gc_cause); + G1YoungCollector(GCCause::Cause gc_cause, + size_t allocation_word_size); void collect(); bool concurrent_operation_is_full_mark() const { return _concurrent_operation_is_full_mark; } diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 44d0d22257e..0a054c6efd4 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -144,7 +144,7 @@ \ product(size_t, G1SATBBufferSize, 1*K, \ "Number of entries in an SATB log buffer.") \ - constraint(G1SATBBufferSizeConstraintFunc, AtParse) \ + constraint(G1SATBBufferSizeConstraintFunc, AfterErgo) \ \ develop(uintx, G1SATBProcessCompletedThreshold, 20, \ "Number of completed buffers that triggers log processing.") \ @@ -158,12 +158,39 @@ range(0, 100) \ \ product(uint, G1ExpandByPercentOfAvailable, 20, EXPERIMENTAL, \ - "When expanding, % of uncommitted space to claim.") \ + "When expanding, % of uncommitted space to expand the heap by in "\ + "a single expand attempt.") \ range(0, 100) \ \ + product(uint, G1ShrinkByPercentOfAvailable, 50, DIAGNOSTIC, \ + "When shrinking, maximum % of free space to free for a single " \ + "shrink attempt.") \ + range(0, 100) \ + \ + product(uint, G1CPUUsageDeviationPercent, 25, DIAGNOSTIC, \ + "The acceptable deviation (in percent) from the target GC CPU " \ + "usage (based on GCTimeRatio). Creates a tolerance range " \ + "around the target to deal with short-term fluctuations without " \ + "triggering GC resizing mechanism prematurely.") \ + range(0, 100) \ + \ + product(uint, G1CPUUsageExpandThreshold, 4, DIAGNOSTIC, \ + "If the GC CPU usage deviation counter exceeds this threshold, " \ + "a heap expansion may be triggered. The counter is incremented " \ + "when short-term GC CPU usage exceeds the upper bound of the " \ + "acceptable deviation range.") \ + constraint(G1CPUUsageExpandConstraintFunc, AfterErgo) \ + \ + product(uint, G1CPUUsageShrinkThreshold, 8, DIAGNOSTIC, \ + "If the GC CPU usage deviation counter drops below the negative " \ + "of this threshold, a heap shrink may be triggered. The counter " \ + "is decremented when short-term GC CPU usage is below the lower " \ + "bound of acceptable deviation range.") \ + constraint(G1CPUUsageShrinkConstraintFunc, AfterErgo) \ + \ product(size_t, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ - constraint(G1UpdateBufferSizeConstraintFunc, AtParse) \ + constraint(G1UpdateBufferSizeConstraintFunc, AfterErgo) \ \ product(uint, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ diff --git a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp index 68da7400256..488a9c7aac9 100644 --- a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp +++ b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp @@ -23,6 +23,7 @@ */ #include "gc/g1/g1HeapRegionBounds.inline.hpp" +#include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/jvmFlagConstraintsG1.hpp" #include "gc/shared/bufferNode.hpp" #include "gc/shared/ptrQueue.hpp" @@ -210,3 +211,32 @@ JVMFlag::Error G1UpdateBufferSizeConstraintFunc(size_t value, bool verbose) { value, verbose); } + +JVMFlag::Error gc_cpu_usage_threshold_helper(JVMFlagsEnum flagid, + uint value, + bool verbose) { + if (UseG1GC) { + JVMFlag* flag = JVMFlag::flag_from_enum(flagid); + const uint min_count = 1; + const uint max_count = G1HeapSizingPolicy::long_term_count_limit(); + if (value < min_count || value > max_count) { + JVMFlag::printError(verbose, + "%s (%u) must be in range [%u, %u]\n", + flag->name(), value, min_count, max_count); + return JVMFlag::VIOLATES_CONSTRAINT; + } + } + return JVMFlag::SUCCESS; +} + +JVMFlag::Error G1CPUUsageExpandConstraintFunc(uint value, bool verbose) { + return gc_cpu_usage_threshold_helper(FLAG_MEMBER_ENUM(G1CPUUsageExpandThreshold), + value, + verbose); +} + +JVMFlag::Error G1CPUUsageShrinkConstraintFunc(uint value, bool verbose) { + return gc_cpu_usage_threshold_helper(FLAG_MEMBER_ENUM(G1CPUUsageShrinkThreshold), + value, + verbose); +} diff --git a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp index 8ba56351ed9..89f05d73dcc 100644 --- a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp +++ b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -48,6 +48,10 @@ /* G1 PtrQueue buffer size constraints */ \ f(size_t, G1SATBBufferSizeConstraintFunc) \ f(size_t, G1UpdateBufferSizeConstraintFunc) \ + \ + /* G1 GC deviation counter threshold constraints */ \ + f(uint, G1CPUUsageExpandConstraintFunc) \ + f(uint, G1CPUUsageShrinkConstraintFunc) \ /* */ G1_GC_CONSTRAINTS(DECLARE_CONSTRAINT) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 7ab515fffb4..d07a989c3a6 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -201,8 +201,6 @@ void MutableNUMASpace::bias_region(MemRegion mr, uint lgrp_id) { const size_t os_align = UseLargePages ? page_size() : os::vm_page_size(); os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); // Then we uncommit the pages in the range. - // The alignment_hint argument must be less than or equal to the small page - // size if not using large pages or else this function does nothing. os::disclaim_memory((char*)aligned_region.start(), aligned_region.byte_size()); // And make them local/first-touch biased. os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), checked_cast(lgrp_id)); @@ -414,8 +412,8 @@ void MutableNUMASpace::initialize(MemRegion mr, size_t chunk_byte_size = 0; if (i < lgrp_spaces()->length() - 1) { - if (!UseAdaptiveNUMAChunkSizing || - (UseAdaptiveNUMAChunkSizing && NUMAChunkResizeWeight == 0) || + if (!UseAdaptiveNUMAChunkSizing || + NUMAChunkResizeWeight == 0 || samples_count() < AdaptiveSizePolicyReadyThreshold) { // No adaptation. Divide the space equally. chunk_byte_size = default_chunk_size(); diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 2ce36a6f961..68900c8dbf2 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -111,6 +111,9 @@ class ParallelScavengeHeap : public CollectedHeap { void do_full_collection(bool clear_all_soft_refs) override; + void print_tracing_info() const override; + void stop() override {}; + public: ParallelScavengeHeap() : CollectedHeap(), @@ -212,7 +215,6 @@ class ParallelScavengeHeap : public CollectedHeap { void print_heap_on(outputStream* st) const override; void print_gc_on(outputStream* st) const override; void gc_threads_do(ThreadClosure* tc) const override; - void print_tracing_info() const override; WorkerThreads* safepoint_workers() override { return &_workers; } diff --git a/src/hotspot/share/gc/parallel/parallel_globals.hpp b/src/hotspot/share/gc/parallel/parallel_globals.hpp index e3b9660b069..83b378d5bbe 100644 --- a/src/hotspot/share/gc/parallel/parallel_globals.hpp +++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp @@ -41,7 +41,7 @@ "for a system GC") \ \ product(bool, PSChunkLargeArrays, true, \ - "Process large arrays in chunks") + "(Deprecated) Process large arrays in chunks") // end of GC_PARALLEL_FLAGS diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 81f2bf0b30c..9cc94f3f24c 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1311,9 +1311,8 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { ReferenceProcessorStats stats; ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->max_num_queues()); - ref_processor()->set_active_mt_degree(active_gc_threads); ParallelCompactRefProcProxyTask task(ref_processor()->max_num_queues()); - stats = ref_processor()->process_discovered_references(task, pt); + stats = ref_processor()->process_discovered_references(task, &ParallelScavengeHeap::heap()->workers(), pt); gc_tracer->report_gc_reference_stats(stats); pt.print_all_references(); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 7729b3e2006..9816655603c 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -294,7 +294,7 @@ class ScavengeRootsTask : public WorkerTask { } PSThreadRootsTaskClosure closure(worker_id); - Threads::possibly_parallel_threads_do(true /* is_par */, &closure); + Threads::possibly_parallel_threads_do(_active_workers > 1 /* is_par */, &closure); // Scavenge OopStorages { @@ -410,12 +410,11 @@ bool PSScavenge::invoke(bool clear_soft_refs) { { GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer); - reference_processor()->set_active_mt_degree(active_workers); ReferenceProcessorStats stats; ReferenceProcessorPhaseTimes pt(&_gc_timer, reference_processor()->max_num_queues()); ParallelScavengeRefProcProxyTask task(reference_processor()->max_num_queues()); - stats = reference_processor()->process_discovered_references(task, pt); + stats = reference_processor()->process_discovered_references(task, &ParallelScavengeHeap::heap()->workers(), pt); _gc_tracer.report_gc_reference_stats(stats); pt.print_all_references(); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index cb36207ff47..4f45821a889 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -631,7 +631,7 @@ bool DefNewGeneration::collect(bool clear_all_soft_refs) { ReferenceProcessor* rp = ref_processor(); ReferenceProcessorPhaseTimes pt(_gc_timer, rp->max_num_queues()); SerialGCRefProcProxyTask task(is_alive, keep_alive, evacuate_followers); - const ReferenceProcessorStats& stats = rp->process_discovered_references(task, pt); + const ReferenceProcessorStats& stats = rp->process_discovered_references(task, nullptr, pt); _gc_tracer->report_gc_reference_stats(stats); _gc_tracer->report_tenuring_threshold(tenuring_threshold()); pt.print_all_references(); diff --git a/src/hotspot/share/gc/serial/serialFullGC.cpp b/src/hotspot/share/gc/serial/serialFullGC.cpp index 75dc3710867..06c1cee9dcc 100644 --- a/src/hotspot/share/gc/serial/serialFullGC.cpp +++ b/src/hotspot/share/gc/serial/serialFullGC.cpp @@ -499,7 +499,7 @@ void SerialFullGC::phase1_mark(bool clear_all_softrefs) { ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->max_num_queues()); SerialGCRefProcProxyTask task(is_alive, keep_alive, follow_stack_closure); - const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references(task, pt); + const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references(task, nullptr, pt); pt.print_all_references(); gc_tracer()->report_gc_reference_stats(stats); } diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 34c79ac0a18..d93e895d209 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -118,6 +118,9 @@ class SerialHeap : public CollectedHeap { void gc_prologue(); void gc_epilogue(bool full); + void print_tracing_info() const override; + void stop() override {}; + public: // Returns JNI_OK on success jint initialize() override; @@ -209,7 +212,6 @@ class SerialHeap : public CollectedHeap { void print_heap_on(outputStream* st) const override; void print_gc_on(outputStream* st) const override; void gc_threads_do(ThreadClosure* tc) const override; - void print_tracing_info() const override; // Used to print information about locations in the hs_err file. bool print_location(outputStream* st, void* addr) const override; diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 2d23dce9488..b636e3890d3 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -38,6 +38,7 @@ #include "gc/shared/gcWhen.hpp" #include "gc/shared/memAllocator.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" +#include "gc/shared/stringdedup/stringDedupProcessor.hpp" #include "gc/shared/tlab_globals.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" @@ -200,6 +201,34 @@ void CollectedHeap::print_relative_to_gc(GCWhen::Type when) const { } } +class CPUTimeThreadClosure : public ThreadClosure { +private: + jlong _cpu_time = 0; + +public: + virtual void do_thread(Thread* thread) { + jlong cpu_time = os::thread_cpu_time(thread); + if (cpu_time != -1) { + _cpu_time += cpu_time; + } + } + jlong cpu_time() { return _cpu_time; }; +}; + +double CollectedHeap::elapsed_gc_cpu_time() const { + double string_dedup_cpu_time = UseStringDeduplication ? + os::thread_cpu_time((Thread*)StringDedup::_processor->_thread) : 0; + + if (string_dedup_cpu_time == -1) { + string_dedup_cpu_time = 0; + } + + CPUTimeThreadClosure cl; + gc_threads_do(&cl); + + return (double)(cl.cpu_time() + _vmthread_cpu_time + string_dedup_cpu_time) / NANOSECS_PER_SEC; +} + void CollectedHeap::print_before_gc() const { print_relative_to_gc(GCWhen::BeforeGC); } @@ -281,6 +310,7 @@ CollectedHeap::CollectedHeap() : _last_whole_heap_examined_time_ns(os::javaTimeNanos()), _total_collections(0), _total_full_collections(0), + _vmthread_cpu_time(0), _gc_cause(GCCause::_no_gc), _gc_lastcause(GCCause::_no_gc) { @@ -603,6 +633,40 @@ void CollectedHeap::post_initialize() { initialize_serviceability(); } +void CollectedHeap::log_gc_cpu_time() const { + LogTarget(Info, gc, cpu) out; + if (os::is_thread_cpu_time_supported() && out.is_enabled()) { + double process_cpu_time = os::elapsed_process_cpu_time(); + double gc_cpu_time = elapsed_gc_cpu_time(); + + if (process_cpu_time == -1 || gc_cpu_time == -1) { + log_warning(gc, cpu)("Could not sample CPU time"); + return; + } + + double usage; + if (gc_cpu_time > process_cpu_time || + process_cpu_time == 0 || gc_cpu_time == 0) { + // This can happen e.g. for short running processes with + // low CPU utilization + usage = 0; + } else { + usage = 100 * gc_cpu_time / process_cpu_time; + } + out.print("GC CPU usage: %.2f%% (Process: %.4fs GC: %.4fs)", usage, process_cpu_time, gc_cpu_time); + } +} + +void CollectedHeap::before_exit() { + print_tracing_info(); + + // Log GC CPU usage. + log_gc_cpu_time(); + + // Stop any on-going concurrent work and prepare for exit. + stop(); +} + #ifndef PRODUCT bool CollectedHeap::promotion_should_fail(volatile size_t* count) { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 958f3253f12..fe75a0e7875 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -132,6 +132,8 @@ class CollectedHeap : public CHeapObj { NOT_PRODUCT(volatile size_t _promotion_failure_alot_count;) NOT_PRODUCT(volatile size_t _promotion_failure_alot_gc_number;) + jlong _vmthread_cpu_time; + // Reason for current garbage collection. Should be set to // a value reflecting no collection between collections. GCCause::Cause _gc_cause; @@ -206,6 +208,13 @@ class CollectedHeap : public CHeapObj { return static_cast(heap); } + // Print any relevant tracing info that flags imply. + // Default implementation does nothing. + virtual void print_tracing_info() const = 0; + + // Stop any onging concurrent work and prepare for exit. + virtual void stop() = 0; + public: static inline size_t filler_array_max_size() { @@ -239,13 +248,14 @@ class CollectedHeap : public CHeapObj { // This is the correct place to place such initialization methods. virtual void post_initialize(); - // Stop any onging concurrent work and prepare for exit. - virtual void stop() {} + void before_exit(); // Stop and resume concurrent GC threads interfering with safepoint operations virtual void safepoint_synchronize_begin() {} virtual void safepoint_synchronize_end() {} + void add_vmthread_cpu_time(jlong time); + void initialize_reserved_region(const ReservedHeapSpace& rs); virtual size_t capacity() const = 0; @@ -420,6 +430,8 @@ class CollectedHeap : public CHeapObj { void print_relative_to_gc(GCWhen::Type when) const; + void log_gc_cpu_time() const; + public: void pre_full_gc_dump(GCTimer* timer); void post_full_gc_dump(GCTimer* timer); @@ -452,9 +464,7 @@ class CollectedHeap : public CHeapObj { // Iterator for all GC threads (other than VM thread) virtual void gc_threads_do(ThreadClosure* tc) const = 0; - // Print any relevant tracing info that flags imply. - // Default implementation does nothing. - virtual void print_tracing_info() const = 0; + double elapsed_gc_cpu_time() const; void print_before_gc() const; void print_after_gc() const; diff --git a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp index baad35a23f9..2410e1fe50e 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp @@ -52,4 +52,8 @@ inline oop CollectedHeap::class_allocate(Klass* klass, size_t size, TRAPS) { return allocator.allocate(); } +inline void CollectedHeap::add_vmthread_cpu_time(jlong time) { + _vmthread_cpu_time += time; +} + #endif // SHARE_GC_SHARED_COLLECTEDHEAP_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/parallelCleaning.cpp b/src/hotspot/share/gc/shared/parallelCleaning.cpp index 8cb09939f22..0334230eb4e 100644 --- a/src/hotspot/share/gc/shared/parallelCleaning.cpp +++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp @@ -95,7 +95,7 @@ void CodeCacheUnloadingTask::work(uint worker_id) { } KlassCleaningTask::KlassCleaningTask() : - _clean_klass_tree_claimed(0), + _clean_klass_tree_claimed(false), _klass_iterator() { } @@ -104,7 +104,7 @@ bool KlassCleaningTask::claim_clean_klass_tree_task() { return false; } - return Atomic::cmpxchg(&_clean_klass_tree_claimed, 0, 1) == 0; + return !Atomic::cmpxchg(&_clean_klass_tree_claimed, false, true); } InstanceKlass* KlassCleaningTask::claim_next_klass() { @@ -118,16 +118,14 @@ InstanceKlass* KlassCleaningTask::claim_next_klass() { } void KlassCleaningTask::work() { - ResourceMark rm; - // One worker will clean the subklass/sibling klass tree. if (claim_clean_klass_tree_task()) { - Klass::clean_subklass_tree(); + Klass::clean_weak_klass_links(true /* class_unloading_occurred */, false /* clean_alive_klasses */); } // All workers will help cleaning the classes, InstanceKlass* klass; while ((klass = claim_next_klass()) != nullptr) { - clean_klass(klass); + Klass::clean_weak_instanceklass_links(klass); } } diff --git a/src/hotspot/share/gc/shared/parallelCleaning.hpp b/src/hotspot/share/gc/shared/parallelCleaning.hpp index a15326f1b85..4a7c724fef5 100644 --- a/src/hotspot/share/gc/shared/parallelCleaning.hpp +++ b/src/hotspot/share/gc/shared/parallelCleaning.hpp @@ -52,23 +52,16 @@ class CodeCacheUnloadingTask { void work(uint worker_id); }; - +// Cleans out the Klass tree from stale data. class KlassCleaningTask : public StackObj { - volatile int _clean_klass_tree_claimed; + volatile bool _clean_klass_tree_claimed; ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator; -public: - KlassCleaningTask(); - -private: bool claim_clean_klass_tree_task(); InstanceKlass* claim_next_klass(); public: - - void clean_klass(InstanceKlass* ik) { - ik->clean_weak_instanceklass_links(); - } + KlassCleaningTask(); void work(); }; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 0ee4ac134c2..e5d1bd4bec1 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -179,6 +179,7 @@ void ReferenceProcessor::verify_total_count_zero(DiscoveredList lists[], const c #endif ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times) { double start_time = os::elapsedTime(); @@ -197,17 +198,17 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefPro { RefProcTotalPhaseTimesTracker tt(SoftWeakFinalRefsPhase, &phase_times); - process_soft_weak_final_refs(proxy_task, phase_times); + process_soft_weak_final_refs(proxy_task, workers, phase_times); } { RefProcTotalPhaseTimesTracker tt(KeepAliveFinalRefsPhase, &phase_times); - process_final_keep_alive(proxy_task, phase_times); + process_final_keep_alive(proxy_task, workers, phase_times); } { RefProcTotalPhaseTimesTracker tt(PhantomRefsPhase, &phase_times); - process_phantom_refs(proxy_task, phase_times); + process_phantom_refs(proxy_task, workers, phase_times); } phase_times.set_total_time_ms((os::elapsedTime() - start_time) * 1000); @@ -619,8 +620,7 @@ void ReferenceProcessor::maybe_balance_queues(DiscoveredList refs_lists[]) { // Move entries from all queues[0, 1, ..., _max_num_q-1] to // queues[0, 1, ..., _num_q-1] because only the first _num_q // corresponding to the active workers will be processed. -void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) -{ +void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) { // calculate total length size_t total_refs = 0; log_develop_trace(gc, ref)("Balance ref_lists "); @@ -633,60 +633,60 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) size_t avg_refs = total_refs / _num_queues + 1; uint to_idx = 0; for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) { - bool move_all = false; + size_t from_len = ref_lists[from_idx].length(); + + size_t remaining_to_move; if (from_idx >= _num_queues) { - move_all = ref_lists[from_idx].length() > 0; + // Move all + remaining_to_move = from_len; + } else { + // Move those above avg_refs + remaining_to_move = from_len > avg_refs + ? from_len - avg_refs + : 0; } - while ((ref_lists[from_idx].length() > avg_refs) || - move_all) { + + while (remaining_to_move > 0) { assert(to_idx < _num_queues, "Sanity Check!"); - if (ref_lists[to_idx].length() < avg_refs) { - // move superfluous refs - size_t refs_to_move; - // Move all the Ref's if the from queue will not be processed. - if (move_all) { - refs_to_move = MIN2(ref_lists[from_idx].length(), - avg_refs - ref_lists[to_idx].length()); - } else { - refs_to_move = MIN2(ref_lists[from_idx].length() - avg_refs, - avg_refs - ref_lists[to_idx].length()); - } - - assert(refs_to_move > 0, "otherwise the code below will fail"); - - oop move_head = ref_lists[from_idx].head(); - oop move_tail = move_head; - oop new_head = move_head; - // find an element to split the list on - for (size_t j = 0; j < refs_to_move; ++j) { - move_tail = new_head; - new_head = java_lang_ref_Reference::discovered(new_head); - } - - // Add the chain to the to list. - if (ref_lists[to_idx].head() == nullptr) { - // to list is empty. Make a loop at the end. - java_lang_ref_Reference::set_discovered_raw(move_tail, move_tail); - } else { - java_lang_ref_Reference::set_discovered_raw(move_tail, ref_lists[to_idx].head()); - } - ref_lists[to_idx].set_head(move_head); - ref_lists[to_idx].inc_length(refs_to_move); - - // Remove the chain from the from list. - if (move_tail == new_head) { - // We found the end of the from list. - ref_lists[from_idx].set_head(nullptr); - } else { - ref_lists[from_idx].set_head(new_head); - } - ref_lists[from_idx].dec_length(refs_to_move); - if (ref_lists[from_idx].length() == 0) { - break; - } + + size_t to_len = ref_lists[to_idx].length(); + if (to_len >= avg_refs) { + // this list is full enough; move on to next + to_idx++; + continue; + } + size_t refs_to_move = MIN2(remaining_to_move, avg_refs - to_len); + assert(refs_to_move > 0, "otherwise the code below will fail"); + + oop move_head = ref_lists[from_idx].head(); + oop move_tail = move_head; + oop new_head = move_head; + // find an element to split the list on + for (size_t j = 0; j < refs_to_move; ++j) { + move_tail = new_head; + new_head = java_lang_ref_Reference::discovered(new_head); + } + + // Add the chain to the to list. + if (ref_lists[to_idx].head() == nullptr) { + // to list is empty. Make a loop at the end. + java_lang_ref_Reference::set_discovered_raw(move_tail, move_tail); + } else { + java_lang_ref_Reference::set_discovered_raw(move_tail, ref_lists[to_idx].head()); + } + ref_lists[to_idx].set_head(move_head); + ref_lists[to_idx].inc_length(refs_to_move); + + // Remove the chain from the from list. + if (move_tail == new_head) { + // We found the end of the from list. + ref_lists[from_idx].set_head(nullptr); } else { - to_idx = (to_idx + 1) % _num_queues; + ref_lists[from_idx].set_head(new_head); } + ref_lists[from_idx].dec_length(refs_to_move); + + remaining_to_move -= refs_to_move; } } #ifdef ASSERT @@ -699,7 +699,7 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) #endif } -void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_task, bool marks_oops_alive) { +void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_task, WorkerThreads* workers, bool marks_oops_alive) { log_debug(gc, ref)("ReferenceProcessor::execute queues: %d, %s, marks_oops_alive: %s", num_queues(), processing_is_mt() ? "RefProcThreadModel::Multi" : "RefProcThreadModel::Single", @@ -707,7 +707,6 @@ void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_tas proxy_task.prepare_run_task(task, num_queues(), processing_is_mt() ? RefProcThreadModel::Multi : RefProcThreadModel::Single, marks_oops_alive); if (processing_is_mt()) { - WorkerThreads* workers = Universe::heap()->safepoint_workers(); assert(workers != nullptr, "can not dispatch multi threaded without workers"); assert(workers->active_workers() >= num_queues(), "Ergonomically chosen workers(%u) should be less than or equal to active workers(%u)", @@ -720,7 +719,12 @@ void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_tas } } +static uint num_active_workers(WorkerThreads* workers) { + return workers != nullptr ? workers->active_workers() : 1; +} + void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times) { size_t const num_soft_refs = phase_times.ref_discovered(REF_SOFT); @@ -733,7 +737,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_ta return; } - RefProcMTDegreeAdjuster a(this, SoftWeakFinalRefsPhase, num_total_refs); + RefProcMTDegreeAdjuster a(this, SoftWeakFinalRefsPhase, num_active_workers(workers), num_total_refs); if (processing_is_mt()) { RefProcBalanceQueuesTimeTracker tt(SoftWeakFinalRefsPhase, &phase_times); @@ -747,7 +751,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_ta log_reflist("SoftWeakFinalRefsPhase Final before", _discoveredFinalRefs, _max_num_queues); RefProcSoftWeakFinalPhaseTask phase_task(*this, &phase_times); - run_task(phase_task, proxy_task, false); + run_task(phase_task, proxy_task, workers, false); verify_total_count_zero(_discoveredSoftRefs, "SoftReference"); verify_total_count_zero(_discoveredWeakRefs, "WeakReference"); @@ -755,6 +759,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_ta } void ReferenceProcessor::process_final_keep_alive(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times) { size_t const num_final_refs = phase_times.ref_discovered(REF_FINAL); @@ -764,7 +769,7 @@ void ReferenceProcessor::process_final_keep_alive(RefProcProxyTask& proxy_task, return; } - RefProcMTDegreeAdjuster a(this, KeepAliveFinalRefsPhase, num_final_refs); + RefProcMTDegreeAdjuster a(this, KeepAliveFinalRefsPhase, num_active_workers(workers), num_final_refs); if (processing_is_mt()) { RefProcBalanceQueuesTimeTracker tt(KeepAliveFinalRefsPhase, &phase_times); @@ -773,12 +778,13 @@ void ReferenceProcessor::process_final_keep_alive(RefProcProxyTask& proxy_task, // Traverse referents of final references and keep them and followers alive. RefProcKeepAliveFinalPhaseTask phase_task(*this, &phase_times); - run_task(phase_task, proxy_task, true); + run_task(phase_task, proxy_task, workers, true); verify_total_count_zero(_discoveredFinalRefs, "FinalReference"); } void ReferenceProcessor::process_phantom_refs(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times) { size_t const num_phantom_refs = phase_times.ref_discovered(REF_PHANTOM); @@ -788,7 +794,7 @@ void ReferenceProcessor::process_phantom_refs(RefProcProxyTask& proxy_task, return; } - RefProcMTDegreeAdjuster a(this, PhantomRefsPhase, num_phantom_refs); + RefProcMTDegreeAdjuster a(this, PhantomRefsPhase, num_active_workers(workers), num_phantom_refs); if (processing_is_mt()) { RefProcBalanceQueuesTimeTracker tt(PhantomRefsPhase, &phase_times); @@ -798,7 +804,7 @@ void ReferenceProcessor::process_phantom_refs(RefProcProxyTask& proxy_task, log_reflist("PhantomRefsPhase Phantom before", _discoveredPhantomRefs, _max_num_queues); RefProcPhantomPhaseTask phase_task(*this, &phase_times); - run_task(phase_task, proxy_task, false); + run_task(phase_task, proxy_task, workers, false); verify_total_count_zero(_discoveredPhantomRefs, "PhantomReference"); } @@ -1137,10 +1143,11 @@ bool RefProcMTDegreeAdjuster::use_max_threads(RefProcPhases phase) const { RefProcMTDegreeAdjuster::RefProcMTDegreeAdjuster(ReferenceProcessor* rp, RefProcPhases phase, + uint num_active_workers, size_t ref_count): _rp(rp), _saved_num_queues(_rp->num_queues()) { - uint workers = ergo_proc_thread_count(ref_count, _rp->num_queues(), phase); + uint workers = ergo_proc_thread_count(ref_count, num_active_workers, phase); _rp->set_active_mt_degree(workers); } diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index 4be8f3f6f16..a29ee7fca86 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -185,6 +185,7 @@ class DiscoveredListIterator { class ReferenceProcessor : public ReferenceDiscoverer { friend class RefProcTask; friend class RefProcKeepAliveFinalPhaseTask; + friend class RefProcMTDegreeAdjuster; public: // Names of sub-phases of reference processing. Indicates the type of the reference // processed and the associated phase number at the end. @@ -253,19 +254,22 @@ class ReferenceProcessor : public ReferenceDiscoverer { DiscoveredList* _discoveredFinalRefs; DiscoveredList* _discoveredPhantomRefs; - void run_task(RefProcTask& task, RefProcProxyTask& proxy_task, bool marks_oops_alive); + void run_task(RefProcTask& task, RefProcProxyTask& proxy_task, WorkerThreads* threads, bool marks_oops_alive); // Drop Soft/Weak/Final references with a null or live referent, and clear // and enqueue non-Final references. void process_soft_weak_final_refs(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times); // Keep alive followers of Final references, and enqueue. void process_final_keep_alive(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times); // Drop and keep alive live Phantom references, or clear and enqueue if dead. void process_phantom_refs(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times); // Work methods used by the process_* methods. All methods return the number of @@ -292,12 +296,14 @@ class ReferenceProcessor : public ReferenceDiscoverer { _always_clear_soft_ref_policy : _default_soft_ref_policy; _current_soft_ref_policy->setup(); // snapshot the policy threshold } + + void set_active_mt_degree(uint v); + public: static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_NONE); } uint num_queues() const { return _num_queues; } uint max_num_queues() const { return _max_num_queues; } - void set_active_mt_degree(uint v); void start_discovery(bool always_clear) { enable_discovery(); @@ -416,6 +422,7 @@ class ReferenceProcessor : public ReferenceDiscoverer { // Process references found during GC (called by the garbage collector) ReferenceProcessorStats process_discovered_references(RefProcProxyTask& proxy_task, + WorkerThreads* workers, ReferenceProcessorPhaseTimes& phase_times); // If a discovery is in process that is being superseded, abandon it: all @@ -589,6 +596,7 @@ class RefProcMTDegreeAdjuster : public StackObj { public: RefProcMTDegreeAdjuster(ReferenceProcessor* rp, RefProcPhases phase, + uint num_active_workers, size_t ref_count); ~RefProcMTDegreeAdjuster(); }; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp b/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp index 79689ab8648..43cb513df33 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp @@ -105,6 +105,7 @@ #include "oops/oopsHierarchy.hpp" #include "utilities/globalDefinitions.hpp" +class CollectedHeap; class Klass; class StringDedupThread; class ThreadClosure; @@ -115,6 +116,7 @@ class ThreadClosure; // feature. Other functions in the StringDedup class are called where // needed, without requiring GC-specific code. class StringDedup : public AllStatic { + friend class CollectedHeap; friend class StringDedupThread; class Config; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupProcessor.hpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupProcessor.hpp index 3f1f1c19886..5d3929c5817 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupProcessor.hpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupProcessor.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" #include "utilities/macros.hpp" +class CollectedHeap; class JavaThread; class OopStorage; @@ -42,6 +43,8 @@ class OopStorage; // incremental operations for resizing and for removing dead entries, so // safepoint checks can be performed between steps in those operations. class StringDedup::Processor : public CHeapObj { + friend class CollectedHeap; + Processor(); ~Processor() = default; diff --git a/test/micro/org/openjdk/bench/valhalla/types/Int128.java b/src/hotspot/share/gc/shared/vmThreadCpuTimeScope.hpp similarity index 66% rename from test/micro/org/openjdk/bench/valhalla/types/Int128.java rename to src/hotspot/share/gc/shared/vmThreadCpuTimeScope.hpp index d698af75439..afad94932c2 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/Int128.java +++ b/src/hotspot/share/gc/shared/vmThreadCpuTimeScope.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -19,17 +19,26 @@ * 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. + * */ -package org.openjdk.bench.valhalla.types; -public interface Int128 { +#ifndef SHARE_GC_SHARED_VMTHREADCPUTIMESCOPE_HPP +#define SHARE_GC_SHARED_VMTHREADCPUTIMESCOPE_HPP - public int intValue(); +#include "memory/allocation.hpp" - public long longValue(); +class VMThread; - public long hiValue(); +class VMThreadCPUTimeScope : public StackObj { +private: + jlong _start; + bool _enabled; + bool _is_gc_operation; + VMThread* _thread; - public long loValue(); +public: + VMThreadCPUTimeScope(VMThread* thread, bool is_gc_operation); + ~VMThreadCPUTimeScope(); +}; -} +#endif // SHARE_GC_SHARED_VMTHREADCPUTIMESCOPE_HPP diff --git a/src/hotspot/share/gc/shared/vmThreadCpuTimeScope.inline.hpp b/src/hotspot/share/gc/shared/vmThreadCpuTimeScope.inline.hpp new file mode 100644 index 00000000000..db8b96b68bf --- /dev/null +++ b/src/hotspot/share/gc/shared/vmThreadCpuTimeScope.inline.hpp @@ -0,0 +1,58 @@ +/* + * 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. + * + * 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 "gc/shared/vmThreadCpuTimeScope.hpp" + +#include "gc/shared/collectedHeap.inline.hpp" +#include "memory/universe.hpp" +#include "runtime/cpuTimeCounters.hpp" +#include "runtime/os.hpp" +#include "runtime/vmThread.hpp" + +inline VMThreadCPUTimeScope::VMThreadCPUTimeScope(VMThread* thread, bool is_gc_operation) + : _start(0), + _enabled(os::is_thread_cpu_time_supported()), + _is_gc_operation(is_gc_operation), + _thread(thread) { + if (_is_gc_operation && _enabled) { + _start = os::thread_cpu_time(_thread); + } +} + +inline VMThreadCPUTimeScope::~VMThreadCPUTimeScope() { + if (!_enabled) { + return; + } + + jlong end = (_is_gc_operation || UsePerfData) ? os::thread_cpu_time(_thread) : 0; + + if (_is_gc_operation) { + jlong duration = end > _start ? end - _start : 0; + Universe::heap()->add_vmthread_cpu_time(duration); + } + + if (UsePerfData) { + CPUTimeCounters::update_counter(CPUTimeGroups::CPUTimeType::vm, end); + } +} diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index 9f58016a6f1..ad1dca47503 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -274,7 +274,7 @@ class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeG bool ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) { C1ShenandoahPreBarrierCodeGenClosure pre_code_gen_cl; - _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, + _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "shenandoah_pre_barrier_slow", false, &pre_code_gen_cl); if (_pre_barrier_c1_runtime_code_blob == nullptr) { @@ -282,7 +282,7 @@ bool ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) } if (ShenandoahLoadRefBarrier) { C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_strong_code_gen_cl(ON_STRONG_OOP_REF); - _load_reference_barrier_strong_rt_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, + _load_reference_barrier_strong_rt_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "shenandoah_load_reference_barrier_strong_slow", false, &lrb_strong_code_gen_cl); if (_load_reference_barrier_strong_rt_code_blob == nullptr) { @@ -290,7 +290,7 @@ bool ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) } C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_strong_native_code_gen_cl(ON_STRONG_OOP_REF | IN_NATIVE); - _load_reference_barrier_strong_native_rt_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, + _load_reference_barrier_strong_native_rt_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "shenandoah_load_reference_barrier_strong_native_slow", false, &lrb_strong_native_code_gen_cl); if (_load_reference_barrier_strong_native_rt_code_blob == nullptr) { @@ -298,7 +298,7 @@ bool ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) } C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_weak_code_gen_cl(ON_WEAK_OOP_REF); - _load_reference_barrier_weak_rt_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, + _load_reference_barrier_weak_rt_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "shenandoah_load_reference_barrier_weak_slow", false, &lrb_weak_code_gen_cl); if (_load_reference_barrier_weak_rt_code_blob == nullptr) { @@ -306,7 +306,7 @@ bool ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) } C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_phantom_code_gen_cl(ON_PHANTOM_OOP_REF | IN_NATIVE); - _load_reference_barrier_phantom_rt_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID, + _load_reference_barrier_phantom_rt_code_blob = Runtime1::generate_blob(buffer_blob, StubId::NO_STUBID, "shenandoah_load_reference_barrier_phantom_slow", false, &lrb_phantom_code_gen_cl); return (_load_reference_barrier_phantom_rt_code_blob != nullptr); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index eb87a9dc4c1..144773908ca 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -91,7 +91,7 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand // we hit max_cset. When max_cset is hit, we terminate the cset selection. Note that in this scheme, // ShenandoahGarbageThreshold is the soft threshold which would be ignored until min_garbage is hit. - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste); size_t free_target = (capacity / 100 * ShenandoahMinFreeThreshold) + max_cset; size_t min_garbage = (free_target > actual_free ? (free_target - actual_free) : 0); @@ -233,7 +233,7 @@ static double saturate(double value, double min, double max) { // in operation mode. We want some way to decide that the average rate has changed, while keeping average // allocation rate computation independent. bool ShenandoahAdaptiveHeuristics::should_start_gc() { - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->soft_available(); size_t allocated = _space_info->bytes_allocated_since_gc_start(); @@ -349,10 +349,7 @@ void ShenandoahAdaptiveHeuristics::adjust_spike_threshold(double amount) { } size_t ShenandoahAdaptiveHeuristics::min_free_threshold() { - // Note that soft_max_capacity() / 100 * min_free_threshold is smaller than max_capacity() / 100 * min_free_threshold. - // We want to behave conservatively here, so use max_capacity(). By returning a larger value, we cause the GC to - // trigger when the remaining amount of free shrinks below the larger threshold. - return _space_info->max_capacity() / 100 * ShenandoahMinFreeThreshold; + return ShenandoahHeap::heap()->soft_max_capacity() / 100 * ShenandoahMinFreeThreshold; } ShenandoahAllocationRate::ShenandoahAllocationRate() : diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp index 403405b984d..592bba67757 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp @@ -47,7 +47,7 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp bool ShenandoahCompactHeuristics::should_start_gc() { size_t max_capacity = _space_info->max_capacity(); - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->available(); // Make sure the code below treats available without the soft tail. diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp index b8d85de0487..4e12b1d41e8 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp @@ -53,7 +53,7 @@ void ShenandoahGlobalHeuristics::choose_global_collection_set(ShenandoahCollecti size_t cur_young_garbage) const { auto heap = ShenandoahGenerationalHeap::heap(); size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); - size_t capacity = heap->young_generation()->max_capacity(); + size_t capacity = heap->soft_max_capacity(); size_t garbage_threshold = region_size_bytes * ShenandoahGarbageThreshold / 100; size_t ignore_threshold = region_size_bytes * ShenandoahIgnoreGarbageThreshold / 100; const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp index 29b94e2f68f..2131f95b413 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp @@ -37,7 +37,6 @@ class ShenandoahSpaceInfo { public: virtual const char* name() const = 0; - virtual size_t soft_max_capacity() const = 0; virtual size_t max_capacity() const = 0; virtual size_t soft_available() const = 0; virtual size_t available() const = 0; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp index e6f60dc1c83..205135751aa 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp @@ -42,7 +42,7 @@ ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {} bool ShenandoahStaticHeuristics::should_start_gc() { size_t max_capacity = _space_info->max_capacity(); - size_t capacity = _space_info->soft_max_capacity(); + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); size_t available = _space_info->available(); // Make sure the code below treats available without the soft tail. diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index 3aca436104b..fbb165858dc 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -66,7 +66,7 @@ void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollection auto heap = ShenandoahGenerationalHeap::heap(); - size_t capacity = heap->young_generation()->max_capacity(); + size_t capacity = heap->soft_max_capacity(); size_t garbage_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahGarbageThreshold / 100; size_t ignore_threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahIgnoreGarbageThreshold / 100; const uint tenuring_threshold = heap->age_census()->tenuring_threshold(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index d635781f90f..df2cd18042f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -184,9 +184,10 @@ void ShenandoahArguments::initialize() { // Current default is good for generational collectors that run frequent young GCs. // With Shenandoah, GC cycles are much less frequent, so we need we need sizing policy // to converge faster over smaller number of resizing decisions. - if (FLAG_IS_DEFAULT(TLABAllocationWeight)) { + if (strcmp(ShenandoahGCMode, "generational") && FLAG_IS_DEFAULT(TLABAllocationWeight)) { FLAG_SET_DEFAULT(TLABAllocationWeight, 90); } + // In generational mode, let TLABAllocationWeight keeps its default value of 35. if (GCCardSizeInBytes < ShenandoahMinCardSizeInBytes) { vm_exit_during_initialization( @@ -217,6 +218,10 @@ void ShenandoahArguments::initialize_alignments() { } SpaceAlignment = align; HeapAlignment = align; + + if (FLAG_IS_DEFAULT(TLABSize)) { + TLABSize = MAX2(ShenandoahHeapRegion::region_size_bytes() / 256, (size_t) 32 * 1024); + } } CollectedHeap* ShenandoahArguments::create_heap() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index ffafcc5840d..7c9fa759835 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -64,7 +64,9 @@ void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) { ShenandoahMarkingContext* const ctx = heap->marking_context(); - msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj->klass()), obj->klass()->external_name()); + Klass* obj_klass = ShenandoahForwarding::klass(obj); + + msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj_klass), obj_klass->external_name()); msg.append(" %3s allocated after mark start\n", ctx->allocated_after_mark_start(obj) ? "" : "not"); msg.append(" %3s after update watermark\n", cast_from_oop(obj) >= r->get_update_watermark() ? "" : "not"); msg.append(" %3s marked strong\n", ctx->is_marked_strong(obj) ? "" : "not"); @@ -75,6 +77,10 @@ void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) { } msg.append(" mark:%s\n", mw_ss.freeze()); msg.append(" region: %s", ss.freeze()); + if (obj_klass == vmClasses::Class_klass()) { + msg.append(" mirrored klass: " PTR_FORMAT "\n", p2i(obj->metadata_field(java_lang_Class::klass_offset()))); + msg.append(" mirrored array klass: " PTR_FORMAT "\n", p2i(obj->metadata_field(java_lang_Class::array_klass_offset()))); + } } void ShenandoahAsserts::print_non_obj(ShenandoahMessageBuffer& msg, void* loc) { @@ -266,20 +272,22 @@ void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* } // Do additional checks for special objects: their fields can hold metadata as well. - // We want to check class loading/unloading did not corrupt them. + // We want to check class loading/unloading did not corrupt them. We can only reasonably + // trust the forwarded objects, as the from-space object can have the klasses effectively + // dead. if (Universe::is_fully_initialized() && (obj_klass == vmClasses::Class_klass())) { - Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset()); + const Metadata* klass = fwd->metadata_field(java_lang_Class::klass_offset()); if (klass != nullptr && !Metaspace::contains(klass)) { print_failure(_safe_all, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", - "Instance class mirror should point to Metaspace", + "Mirrored instance class should point to Metaspace", file, line); } - Metadata* array_klass = obj->metadata_field(java_lang_Class::array_klass_offset()); + const Metadata* array_klass = fwd->metadata_field(java_lang_Class::array_klass_offset()); if (array_klass != nullptr && !Metaspace::contains(array_klass)) { print_failure(_safe_all, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", - "Array class mirror should point to Metaspace", + "Mirrored array class should point to Metaspace", file, line); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index fda97c4836e..2f264cae70f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -1145,22 +1145,22 @@ void ShenandoahConcurrentGC::op_update_refs() { ShenandoahHeap::heap()->update_heap_references(true /*concurrent*/); } -class ShenandoahUpdateThreadClosure : public HandshakeClosure { +class ShenandoahUpdateThreadHandshakeClosure : public HandshakeClosure { private: // This closure runs when thread is stopped for handshake, which means // we can use non-concurrent closure here, as long as it only updates // locations modified by the thread itself, i.e. stack locations. ShenandoahNonConcUpdateRefsClosure _cl; public: - ShenandoahUpdateThreadClosure(); + ShenandoahUpdateThreadHandshakeClosure(); void do_thread(Thread* thread); }; -ShenandoahUpdateThreadClosure::ShenandoahUpdateThreadClosure() : +ShenandoahUpdateThreadHandshakeClosure::ShenandoahUpdateThreadHandshakeClosure() : HandshakeClosure("Shenandoah Update Thread Roots") { } -void ShenandoahUpdateThreadClosure::do_thread(Thread* thread) { +void ShenandoahUpdateThreadHandshakeClosure::do_thread(Thread* thread) { if (thread->is_Java_thread()) { JavaThread* jt = JavaThread::cast(thread); ResourceMark rm; @@ -1169,7 +1169,7 @@ void ShenandoahUpdateThreadClosure::do_thread(Thread* thread) { } void ShenandoahConcurrentGC::op_update_thread_roots() { - ShenandoahUpdateThreadClosure cl; + ShenandoahUpdateThreadHandshakeClosure cl; Handshake::execute(&cl); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 1acb6a23e7a..8e303980cef 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -880,7 +880,7 @@ HeapWord* ShenandoahFreeSet::allocate_from_regions(Iter& iterator, ShenandoahAll for (idx_t idx = iterator.current(); iterator.has_next(); idx = iterator.next()) { ShenandoahHeapRegion* r = _heap->get_region(idx); size_t min_size = (req.type() == ShenandoahAllocRequest::_alloc_tlab) ? req.min_size() : req.size(); - if (alloc_capacity(r) >= min_size) { + if (alloc_capacity(r) >= min_size * HeapWordSize) { HeapWord* result = try_allocate_in(r, req, in_new_region); if (result != nullptr) { return result; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 9a511de939c..f686334d3d5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -183,7 +183,7 @@ void ShenandoahGeneration::log_status(const char *msg) const { // byte size in proper unit and proper unit for byte size are consistent. const size_t v_used = used(); const size_t v_used_regions = used_regions_size(); - const size_t v_soft_max_capacity = soft_max_capacity(); + const size_t v_soft_max_capacity = ShenandoahHeap::heap()->soft_max_capacity(); const size_t v_max_capacity = max_capacity(); const size_t v_available = available(); const size_t v_humongous_waste = get_humongous_waste(); @@ -799,14 +799,13 @@ void ShenandoahGeneration::cancel_marking() { ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type, uint max_workers, - size_t max_capacity, - size_t soft_max_capacity) : + size_t max_capacity) : _type(type), _task_queues(new ShenandoahObjToScanQueueSet(max_workers)), _ref_processor(new ShenandoahReferenceProcessor(MAX2(max_workers, 1U))), _affiliated_region_count(0), _humongous_waste(0), _evacuation_reserve(0), _used(0), _bytes_allocated_since_gc_start(0), - _max_capacity(max_capacity), _soft_max_capacity(soft_max_capacity), + _max_capacity(max_capacity), _heuristics(nullptr) { _is_marking_complete.set(); @@ -952,7 +951,7 @@ size_t ShenandoahGeneration::available_with_reserve() const { } size_t ShenandoahGeneration::soft_available() const { - return available(soft_max_capacity()); + return available(ShenandoahHeap::heap()->soft_max_capacity()); } size_t ShenandoahGeneration::available(size_t capacity) const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 242acbdea8c..2b7aca342da 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -71,7 +71,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { volatile size_t _used; volatile size_t _bytes_allocated_since_gc_start; size_t _max_capacity; - size_t _soft_max_capacity; ShenandoahHeuristics* _heuristics; @@ -105,8 +104,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { public: ShenandoahGeneration(ShenandoahGenerationType type, uint max_workers, - size_t max_capacity, - size_t soft_max_capacity); + size_t max_capacity); ~ShenandoahGeneration(); bool is_young() const { return _type == YOUNG; } @@ -126,7 +124,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode); - size_t soft_max_capacity() const override { return _soft_max_capacity; } size_t max_capacity() const override { return _max_capacity; } virtual size_t used_regions() const; virtual size_t used_regions_size() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 731868310f4..5bfa526138d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -53,21 +53,6 @@ class ShenandoahGenerationalInitLogger : public ShenandoahInitLogger { ShenandoahGenerationalInitLogger logger; logger.print_all(); } - - void print_heap() override { - ShenandoahInitLogger::print_heap(); - - ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); - - ShenandoahYoungGeneration* young = heap->young_generation(); - log_info(gc, init)("Young Generation Soft Size: " EXACTFMT, EXACTFMTARGS(young->soft_max_capacity())); - log_info(gc, init)("Young Generation Max: " EXACTFMT, EXACTFMTARGS(young->max_capacity())); - - ShenandoahOldGeneration* old = heap->old_generation(); - log_info(gc, init)("Old Generation Soft Size: " EXACTFMT, EXACTFMTARGS(old->soft_max_capacity())); - log_info(gc, init)("Old Generation Max: " EXACTFMT, EXACTFMTARGS(old->max_capacity())); - } - protected: void print_gc_specific() override { ShenandoahInitLogger::print_gc_specific(); @@ -141,8 +126,8 @@ void ShenandoahGenerationalHeap::initialize_heuristics() { size_t initial_capacity_old = max_capacity() - max_capacity_young; size_t max_capacity_old = max_capacity() - initial_capacity_young; - _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young, initial_capacity_young); - _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old, initial_capacity_old); + _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young); + _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old); _young_generation->initialize_heuristics(mode()); _old_generation->initialize_heuristics(mode()); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index ed5a6f3d9a5..930c8ef7105 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -36,6 +36,9 @@ class ShenandoahGenerationalControlThread; class ShenandoahAgeCensus; class ShenandoahGenerationalHeap : public ShenandoahHeap { + void print_tracing_info() const override; + void stop() override; + public: explicit ShenandoahGenerationalHeap(ShenandoahCollectorPolicy* policy); void post_initialize() override; @@ -53,7 +56,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { } void print_init_logger() const override; - void print_tracing_info() const override; size_t unsafe_max_tlab_alloc(Thread *thread) const override; @@ -126,8 +128,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { void gc_threads_do(ThreadClosure* tcl) const override; - void stop() override; - bool requires_barriers(stackChunkOop obj) const override; // Used for logging the result of a region transfer outside the heap lock diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp index c6277e3898e..6099c41f262 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp @@ -50,10 +50,6 @@ size_t ShenandoahGlobalGeneration::used_regions_size() const { return ShenandoahHeap::heap()->capacity(); } -size_t ShenandoahGlobalGeneration::soft_max_capacity() const { - return ShenandoahHeap::heap()->soft_max_capacity(); -} - size_t ShenandoahGlobalGeneration::available() const { // The collector reserve may eat into what the mutator is allowed to use. Make sure we are looking // at what is available to the mutator when reporting how much memory is available. @@ -65,8 +61,8 @@ size_t ShenandoahGlobalGeneration::soft_available() const { size_t available = this->available(); // Make sure the code below treats available without the soft tail. - assert(max_capacity() >= soft_max_capacity(), "Max capacity must be greater than soft max capacity."); - size_t soft_tail = max_capacity() - soft_max_capacity(); + assert(max_capacity() >= ShenandoahHeap::heap()->soft_max_capacity(), "Max capacity must be greater than soft max capacity."); + size_t soft_tail = max_capacity() - ShenandoahHeap::heap()->soft_max_capacity(); return (available > soft_tail) ? (available - soft_tail) : 0; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp index 5857170d4cc..a823784a459 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp @@ -32,14 +32,13 @@ // A "generation" that represents the whole heap. class ShenandoahGlobalGeneration : public ShenandoahGeneration { public: - ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity, size_t soft_max_capacity) - : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity, soft_max_capacity) { } + ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity) + : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity) { } public: const char* name() const override; size_t max_capacity() const override; - size_t soft_max_capacity() const override; size_t used_regions() const override; size_t used_regions_size() const override; size_t available() const override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 55dfb2e8de4..536f48dff37 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -32,6 +32,7 @@ #include "gc/shared/gcArguments.hpp" #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/locationPrinter.inline.hpp" #include "gc/shared/memAllocator.hpp" #include "gc/shared/plab.hpp" @@ -201,8 +202,7 @@ jint ShenandoahHeap::initialize() { assert(num_min_regions <= _num_regions, "sanity"); _minimum_size = num_min_regions * reg_size_bytes; - // Default to max heap size. - _soft_max_size = _num_regions * reg_size_bytes; + _soft_max_size = SoftMaxHeapSize; _committed = _initial_size; @@ -524,7 +524,7 @@ void ShenandoahHeap::initialize_mode() { } void ShenandoahHeap::initialize_heuristics() { - _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity(), max_capacity()); + _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity()); _global_generation->initialize_heuristics(mode()); } @@ -1245,9 +1245,9 @@ class ShenandoahRetireGCLABClosure : public ThreadClosure { } }; -class ShenandoahGCStatePropagator : public HandshakeClosure { +class ShenandoahGCStatePropagatorHandshakeClosure : public HandshakeClosure { public: - explicit ShenandoahGCStatePropagator(char gc_state) : + explicit ShenandoahGCStatePropagatorHandshakeClosure(char gc_state) : HandshakeClosure("Shenandoah GC State Change"), _gc_state(gc_state) {} @@ -1258,9 +1258,9 @@ class ShenandoahGCStatePropagator : public HandshakeClosure { char _gc_state; }; -class ShenandoahPrepareForUpdateRefs : public HandshakeClosure { +class ShenandoahPrepareForUpdateRefsHandshakeClosure : public HandshakeClosure { public: - explicit ShenandoahPrepareForUpdateRefs(char gc_state) : + explicit ShenandoahPrepareForUpdateRefsHandshakeClosure(char gc_state) : HandshakeClosure("Shenandoah Prepare for Update Refs"), _retire(ResizeTLAB), _propagator(gc_state) {} @@ -1272,7 +1272,7 @@ class ShenandoahPrepareForUpdateRefs : public HandshakeClosure { } private: ShenandoahRetireGCLABClosure _retire; - ShenandoahGCStatePropagator _propagator; + ShenandoahGCStatePropagatorHandshakeClosure _propagator; }; void ShenandoahHeap::evacuate_collection_set(bool concurrent) { @@ -1295,7 +1295,7 @@ void ShenandoahHeap::concurrent_prepare_for_update_refs() { } // This will propagate the gc state and retire gclabs and plabs for threads that require it. - ShenandoahPrepareForUpdateRefs prepare_for_update_refs(_gc_state.raw_value()); + ShenandoahPrepareForUpdateRefsHandshakeClosure prepare_for_update_refs(_gc_state.raw_value()); // The handshake won't touch worker threads (or control thread, or VM thread), so do those separately. Threads::non_java_threads_do(&prepare_for_update_refs); @@ -1327,7 +1327,7 @@ void ShenandoahHeap::concurrent_final_roots(HandshakeClosure* handshake_closure) set_gc_state_concurrent(WEAK_ROOTS, false); } - ShenandoahGCStatePropagator propagator(_gc_state.raw_value()); + ShenandoahGCStatePropagatorHandshakeClosure propagator(_gc_state.raw_value()); Threads::non_java_threads_do(&propagator); if (handshake_closure == nullptr) { Handshake::execute(&propagator); @@ -1452,27 +1452,23 @@ void ShenandoahHeap::print_heap_regions_on(outputStream* st) const { } } -size_t ShenandoahHeap::trash_humongous_region_at(ShenandoahHeapRegion* start) { +size_t ShenandoahHeap::trash_humongous_region_at(ShenandoahHeapRegion* start) const { assert(start->is_humongous_start(), "reclaim regions starting with the first one"); - - oop humongous_obj = cast_to_oop(start->bottom()); - size_t size = humongous_obj->size(); - size_t required_regions = ShenandoahHeapRegion::required_regions(size * HeapWordSize); - size_t index = start->index() + required_regions - 1; - assert(!start->has_live(), "liveness must be zero"); - for(size_t i = 0; i < required_regions; i++) { - // Reclaim from tail. Otherwise, assertion fails when printing region to trace log, - // as it expects that every region belongs to a humongous region starting with a humongous start region. - ShenandoahHeapRegion* region = get_region(index --); - - assert(region->is_humongous(), "expect correct humongous start or continuation"); + // Do not try to get the size of this humongous object. STW collections will + // have already unloaded classes, so an unmarked object may have a bad klass pointer. + ShenandoahHeapRegion* region = start; + size_t index = region->index(); + do { + assert(region->is_humongous(), "Expect correct humongous start or continuation"); assert(!region->is_cset(), "Humongous region should not be in collection set"); - region->make_trash_immediate(); - } - return required_regions; + region = get_region(++index); + } while (region != nullptr && region->is_humongous_continuation()); + + // Return number of regions trashed + return index - start->index(); } class ShenandoahCheckCleanGCLABClosure : public ThreadClosure { @@ -2020,14 +2016,14 @@ void ShenandoahHeap::parallel_heap_region_iterate(ShenandoahHeapRegionClosure* b } } -class ShenandoahRendezvousClosure : public HandshakeClosure { +class ShenandoahRendezvousHandshakeClosure : public HandshakeClosure { public: - inline ShenandoahRendezvousClosure(const char* name) : HandshakeClosure(name) {} + inline ShenandoahRendezvousHandshakeClosure(const char* name) : HandshakeClosure(name) {} inline void do_thread(Thread* thread) {} }; void ShenandoahHeap::rendezvous_threads(const char* name) { - ShenandoahRendezvousClosure cl(name); + ShenandoahRendezvousHandshakeClosure cl(name); Handshake::execute(&cl); } @@ -2069,7 +2065,7 @@ void ShenandoahHeap::prepare_update_heap_references() { void ShenandoahHeap::propagate_gc_state_to_all_threads() { assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at Shenandoah safepoint"); if (_gc_state_changed) { - ShenandoahGCStatePropagator propagator(_gc_state.raw_value()); + ShenandoahGCStatePropagatorHandshakeClosure propagator(_gc_state.raw_value()); Threads::threads_do(&propagator); _gc_state_changed = false; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 4124bf8be7f..a32334019f1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -159,6 +159,10 @@ class ShenandoahHeap : public CollectedHeap { // updated at each STW pause associated with a ShenandoahVMOp. ShenandoahGeneration* _active_generation; +protected: + void print_tracing_info() const override; + void stop() override; + public: ShenandoahHeapLock* lock() { return &_lock; @@ -204,11 +208,8 @@ class ShenandoahHeap : public CollectedHeap { void print_heap_on(outputStream* st) const override; void print_gc_on(outputStream *st) const override; - void print_tracing_info() const override; void print_heap_regions_on(outputStream* st) const; - void stop() override; - void prepare_for_verify() override; void verify(VerifyOption vo) override; @@ -828,7 +829,7 @@ class ShenandoahHeap : public CollectedHeap { static inline void atomic_clear_oop(narrowOop* addr, oop compare); static inline void atomic_clear_oop(narrowOop* addr, narrowOop compare); - size_t trash_humongous_region_at(ShenandoahHeapRegion *r); + size_t trash_humongous_region_at(ShenandoahHeapRegion *r) const; static inline void increase_object_age(oop obj, uint additional_age); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index d00a99ee728..05eb0c299a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -790,8 +790,10 @@ size_t ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) { RegionCount = align_up(max_heap_size, RegionSizeBytes) / RegionSizeBytes; guarantee(RegionCount >= MIN_NUM_REGIONS, "Should have at least minimum regions"); + // Limit TLAB size for better startup behavior and more equitable distribution of memory between contending mutator threads. guarantee(MaxTLABSizeWords == 0, "we should only set it once"); - MaxTLABSizeWords = align_down(RegionSizeWords, MinObjAlignment); + MaxTLABSizeWords = align_down(MIN2(RegionSizeWords, MAX2(RegionSizeWords / 32, (size_t) (256 * 1024) / HeapWordSize)), + MinObjAlignment); guarantee(MaxTLABSizeBytes == 0, "we should only set it once"); MaxTLABSizeBytes = MaxTLABSizeWords * HeapWordSize; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp index b5e5e6fd698..421c001b510 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp @@ -43,6 +43,7 @@ void ShenandoahInitLogger::print_heap() { log_info(gc, init)("Heap Region Count: %zu", ShenandoahHeapRegion::region_count()); log_info(gc, init)("Heap Region Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::region_size_bytes())); log_info(gc, init)("TLAB Size Max: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::max_tlab_size_bytes())); + log_info(gc, init)("Soft Max Heap Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeap::heap()->soft_max_capacity())); } void ShenandoahInitLogger::print_gc_specific() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp index 099a2c57244..dc666a34c59 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp @@ -64,7 +64,7 @@ bool ShenandoahMetricsSnapshot::is_good_progress(ShenandoahGeneration* generatio // ShenandoahCriticalFreeThreshold is expressed as a percentage. We multiple this percentage by 1/100th // of the generation capacity to determine whether the available memory within the generation exceeds the // critical threshold. - size_t free_expected = (generation->max_capacity() / 100) * ShenandoahCriticalFreeThreshold; + size_t free_expected = (ShenandoahHeap::heap()->soft_max_capacity() / 100) * ShenandoahCriticalFreeThreshold; bool prog_free = free_actual >= free_expected; log_info(gc, ergo)("%s progress for free space: %zu%s, need %zu%s", diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 35d963f1801..5cccd395d38 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -196,8 +196,8 @@ class ShenandoahConcurrentCoalesceAndFillTask : public WorkerTask { } }; -ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) - : ShenandoahGeneration(OLD, max_queues, max_capacity, soft_max_capacity), +ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity) + : ShenandoahGeneration(OLD, max_queues, max_capacity), _coalesce_and_fill_region_array(NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, ShenandoahHeap::heap()->num_regions(), mtGC)), _old_heuristics(nullptr), _region_balance(0), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp index b70a8d33b95..abc865c31cd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp @@ -88,7 +88,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration { bool coalesce_and_fill(); public: - ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity); + ShenandoahOldGeneration(uint max_queues, size_t max_capacity); ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index f581e8ef9ea..23c705348c4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -624,7 +624,7 @@ void ShenandoahDirectCardMarkRememberedSet::swap_card_tables() { #ifdef ASSERT CardValue* start_bp = &(_card_table->write_byte_map())[0]; - CardValue* end_bp = &(new_ptr)[_card_table->last_valid_index()]; + CardValue* end_bp = &(start_bp[_card_table->last_valid_index()]); while (start_bp <= end_bp) { assert(*start_bp == CardTable::clean_card_val(), "Should be clean: " PTR_FORMAT, p2i(start_bp)); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index cdf78485207..727b90e82a2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -244,18 +244,20 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { } // Do additional checks for special objects: their fields can hold metadata as well. - // We want to check class loading/unloading did not corrupt them. + // We want to check class loading/unloading did not corrupt them. We can only reasonably + // trust the forwarded objects, as the from-space object can have the klasses effectively + // dead. if (obj_klass == vmClasses::Class_klass()) { - Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset()); + const Metadata* klass = fwd->metadata_field(java_lang_Class::klass_offset()); check(ShenandoahAsserts::_safe_oop, obj, klass == nullptr || Metaspace::contains(klass), - "Instance class mirror should point to Metaspace"); + "Mirrored instance class should point to Metaspace"); - Metadata* array_klass = obj->metadata_field(java_lang_Class::array_klass_offset()); + const Metadata* array_klass = obj->metadata_field(java_lang_Class::array_klass_offset()); check(ShenandoahAsserts::_safe_oop, obj, array_klass == nullptr || Metaspace::contains(array_klass), - "Array class mirror should point to Metaspace"); + "Mirrored array class should point to Metaspace"); } // ------------ obj and fwd are safe at this point -------------- diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp index daf5d456af5..849ab691dcf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp @@ -30,8 +30,8 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) : - ShenandoahGeneration(YOUNG, max_queues, max_capacity, soft_max_capacity), +ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity) : + ShenandoahGeneration(YOUNG, max_queues, max_capacity), _old_gen_task_queues(nullptr) { } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp index a8ebab507b6..14f9a9b3004 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp @@ -34,7 +34,7 @@ class ShenandoahYoungGeneration : public ShenandoahGeneration { ShenandoahYoungHeuristics* _young_heuristics; public: - ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t max_soft_capacity); + ShenandoahYoungGeneration(uint max_queues, size_t max_capacity); ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override; diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp index 7bd24955910..8d5d8662ebc 100644 --- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp @@ -506,7 +506,7 @@ class ZLoadBarrierRuntimeStubCodeGenClosure : public StubAssemblerCodeGenClosure static address generate_c1_load_runtime_stub(BufferBlob* blob, DecoratorSet decorators, const char* name) { ZLoadBarrierRuntimeStubCodeGenClosure cl(decorators); - CodeBlob* const code_blob = Runtime1::generate_blob(blob, C1StubId::NO_STUBID /* stub_id */, name, false /* expect_oop_map*/, &cl); + CodeBlob* const code_blob = Runtime1::generate_blob(blob, StubId::NO_STUBID /* stub_id */, name, false /* expect_oop_map*/, &cl); return (code_blob != nullptr) ? code_blob->code_begin() : nullptr; } @@ -526,7 +526,7 @@ class ZStoreBarrierRuntimeStubCodeGenClosure : public StubAssemblerCodeGenClosur static address generate_c1_store_runtime_stub(BufferBlob* blob, bool self_healing, const char* name) { ZStoreBarrierRuntimeStubCodeGenClosure cl(self_healing); - CodeBlob* const code_blob = Runtime1::generate_blob(blob, C1StubId::NO_STUBID /* stub_id */, name, false /* expect_oop_map*/, &cl); + CodeBlob* const code_blob = Runtime1::generate_blob(blob, StubId::NO_STUBID /* stub_id */, name, false /* expect_oop_map*/, &cl); return (code_blob != nullptr) ? code_blob->code_begin() : nullptr; } diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index 871ff81bfdf..3d466564b54 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -55,6 +55,9 @@ class ZCollectedHeap : public CollectedHeap { size_t requested_size, size_t* actual_size) override; + void print_tracing_info() const override; + void stop() override; + public: static ZCollectedHeap* heap(); @@ -63,7 +66,6 @@ class ZCollectedHeap : public CollectedHeap { const char* name() const override; jint initialize() override; void initialize_serviceability() override; - void stop() override; size_t max_capacity() const override; size_t capacity() const override; @@ -116,7 +118,6 @@ class ZCollectedHeap : public CollectedHeap { void print_heap_on(outputStream* st) const override; void print_gc_on(outputStream* st) const override; - void print_tracing_info() const override; bool print_location(outputStream* st, void* addr) const override; void prepare_for_verify() override; diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index 7c8d689ef0f..3e3fde61e1b 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -532,13 +532,13 @@ bool ZMark::try_steal(ZMarkContext* context) { return try_steal_local(context) || try_steal_global(context); } -class ZMarkFlushStacksClosure : public HandshakeClosure { +class ZMarkFlushStacksHandshakeClosure : public HandshakeClosure { private: ZMark* const _mark; bool _flushed; public: - ZMarkFlushStacksClosure(ZMark* mark) + ZMarkFlushStacksHandshakeClosure(ZMark* mark) : HandshakeClosure("ZMarkFlushStacks"), _mark(mark), _flushed(false) {} @@ -585,7 +585,7 @@ class VM_ZMarkFlushOperation : public VM_Operation { }; bool ZMark::flush() { - ZMarkFlushStacksClosure cl(this); + ZMarkFlushStacksHandshakeClosure cl(this); VM_ZMarkFlushOperation vm_cl(&cl); Handshake::execute(&cl); VMThread::execute(&vm_cl); @@ -956,7 +956,7 @@ bool ZMark::try_end() { } // Try end marking - ZMarkFlushStacksClosure cl(this); + ZMarkFlushStacksHandshakeClosure cl(this); Threads::non_java_threads_do(&cl); // Check if non-java threads have any pending marking diff --git a/src/hotspot/share/interpreter/bytecodeTracer.cpp b/src/hotspot/share/interpreter/bytecodeTracer.cpp index 798c0bfc7d8..1f912b2b00f 100644 --- a/src/hotspot/share/interpreter/bytecodeTracer.cpp +++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp @@ -29,18 +29,14 @@ #include "interpreter/bytecodeTracer.hpp" #include "interpreter/bytecodes.hpp" #include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" #include "memory/resourceArea.hpp" #include "oops/constantPool.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" -#include "oops/resolvedFieldEntry.hpp" -#include "oops/resolvedIndyEntry.hpp" -#include "oops/resolvedMethodEntry.hpp" +#include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/osThread.hpp" -#include "runtime/timer.hpp" #include "utilities/align.hpp" // Prints the current bytecode and its attributes using bytecode-specific information. @@ -85,10 +81,11 @@ class BytecodePrinter { void bytecode_epilog(int bci, outputStream* st); public: - BytecodePrinter(int flags = 0) { - _is_wide = false; - _code = Bytecodes::_illegal; - _flags = flags; + BytecodePrinter(int flags = 0) : _is_wide(false), _code(Bytecodes::_illegal), _flags(flags) {} + +#ifndef PRODUCT + BytecodePrinter(Method* prev_method) : BytecodePrinter(0) { + _current_method = prev_method; } // This method is called while executing the raw bytecodes, so none of @@ -96,6 +93,10 @@ class BytecodePrinter { void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { ResourceMark rm; bool method_changed = _current_method != method(); + _current_method = method(); + _is_linked = method->method_holder()->is_linked(); + assert(_is_linked, "this function must be called on methods that are already executing"); + if (method_changed) { // Note 1: This code will not work as expected with true MT/MP. // Need an explicit lock or a different solution. @@ -107,9 +108,6 @@ class BytecodePrinter { st->print("[%zu] ", Thread::current()->osthread()->thread_id_for_printing()); method->print_name(st); st->cr(); - _current_method = method(); - _is_linked = method->method_holder()->is_linked(); - assert(_is_linked, "this function must be called on methods that are already executing"); } Bytecodes::Code code; if (is_wide()) { @@ -142,14 +140,13 @@ class BytecodePrinter { _is_wide = (code == Bytecodes::_wide); _code = Bytecodes::_illegal; -#ifndef PRODUCT if (TraceBytecodesStopAt != 0 && BytecodeCounter::counter_value() >= TraceBytecodesStopAt) { TraceBytecodes = false; } -#endif } +#endif - // Used for Method*::print_codes(). The input bcp comes from + // Used for Method::print_codes(). The input bcp comes from // BytecodeStream, which will skip wide bytecodes. void trace(const methodHandle& method, address bcp, outputStream* st) { _current_method = method(); @@ -179,19 +176,18 @@ class BytecodePrinter { }; #ifndef PRODUCT -// We need a global instance to keep track of the states when the bytecodes -// are executed. Access by multiple threads are controlled by ttyLocker. -static BytecodePrinter _interpreter_printer; +// We need a global instance to keep track of the method being printed so we can report that +// the method has changed. If this method is redefined and removed, that's ok because the method passed +// in won't match, and this will print the method passed in again. Racing threads changing this global +// will result in reprinting the method passed in again. +static Method* _method_currently_being_printed = nullptr; void BytecodeTracer::trace_interpreter(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { - ttyLocker ttyl; // 5065316: keep the following output coherent - // The ttyLocker also prevents races between two threads - // trying to use the single instance of BytecodePrinter. - // - // There used to be a leaf mutex here, but the ttyLocker will - // work just as well, as long as the printing operations never block. - _interpreter_printer.trace(method, bcp, tos, tos2, st); + BytecodePrinter printer(Atomic::load_acquire(&_method_currently_being_printed)); + printer.trace(method, bcp, tos, tos2, st); + // Save method currently being printed to detect when method printing changes. + Atomic::release_store(&_method_currently_being_printed, method()); } } #endif diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 64b9a30af9e..d1541d7ad0c 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -251,29 +251,7 @@ JRT_ENTRY(void, InterpreterRuntime::read_flat_field(JavaThread* current, oopDesc current->set_vm_result_oop(res); JRT_END -JRT_ENTRY(void, InterpreterRuntime::read_nullable_flat_field(JavaThread* current, oopDesc* obj, ResolvedFieldEntry* entry)) - assert(oopDesc::is_oop(obj), "Sanity check"); - assert(entry->has_null_marker(), "Otherwise should not get there"); - Handle obj_h(THREAD, obj); - - InstanceKlass* holder = entry->field_holder(); - int field_index = entry->field_index(); - InlineLayoutInfo* li= holder->inline_layout_info_adr(field_index); - -#ifdef ASSERT - fieldDescriptor fd; - bool found = holder->find_field_from_offset(entry->field_offset(), false, &fd); - assert(found, "Field not found"); - assert(fd.is_flat(), "Field must be flat"); -#endif // ASSERT - - InlineKlass* field_vklass = InlineKlass::cast(li->klass()); - oop res = field_vklass->read_payload_from_addr(obj_h(), entry->field_offset(), li->kind(), CHECK); - current->set_vm_result_oop(res); - -JRT_END - -JRT_ENTRY(void, InterpreterRuntime::write_nullable_flat_field(JavaThread* current, oopDesc* obj, oopDesc* value, ResolvedFieldEntry* entry)) +JRT_ENTRY(void, InterpreterRuntime::write_flat_field(JavaThread* current, oopDesc* obj, oopDesc* value, ResolvedFieldEntry* entry)) assert(oopDesc::is_oop(obj), "Sanity check"); Handle obj_h(THREAD, obj); assert(value == nullptr || oopDesc::is_oop(value), "Sanity check"); @@ -595,6 +573,10 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea h_method->print_value_string(), current_bci, p2i(current), current->name()); Exceptions::log_exception(h_exception, tempst.as_string()); } + if (log_is_enabled(Info, exceptions, stacktrace)) { + Exceptions::log_exception_stacktrace(h_exception, h_method, current_bci); + } + // Don't go paging in something which won't be used. // else if (extable->length() == 0) { // // disabled for now - interpreter is not using shortcut yet diff --git a/src/hotspot/share/interpreter/interpreterRuntime.hpp b/src/hotspot/share/interpreter/interpreterRuntime.hpp index 823b563ef4f..05b3fc90f0c 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.hpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp @@ -63,8 +63,7 @@ class InterpreterRuntime: AllStatic { static void register_finalizer(JavaThread* current, oopDesc* obj); static void write_heap_copy (JavaThread* current, oopDesc* value, int offset, oopDesc* rcv); static void read_flat_field(JavaThread* current, oopDesc* object, ResolvedFieldEntry* entry); - static void read_nullable_flat_field(JavaThread* current, oopDesc* object, ResolvedFieldEntry* entry); - static void write_nullable_flat_field(JavaThread* current, oopDesc* object, oopDesc* value, ResolvedFieldEntry* entry); + static void write_flat_field(JavaThread* current, oopDesc* object, oopDesc* value, ResolvedFieldEntry* entry); static void flat_array_load(JavaThread* current, arrayOopDesc* array, int index); static void flat_array_store(JavaThread* current, oopDesc* val, arrayOopDesc* array, int index); @@ -91,7 +90,6 @@ class InterpreterRuntime: AllStatic { static void throw_ArrayIndexOutOfBoundsException(JavaThread* current, arrayOopDesc* a, jint index); static void throw_ClassCastException(JavaThread* current, oopDesc* obj); static void throw_NullPointerException(JavaThread* current); - static void throw_NPE_UninitializedField_entry(JavaThread* current); static void create_exception(JavaThread* current, char* name, char* message); static void create_klass_exception(JavaThread* current, char* name, oopDesc* obj); diff --git a/src/hotspot/share/interpreter/templateInterpreter.cpp b/src/hotspot/share/interpreter/templateInterpreter.cpp index 43c4c64ce3d..0dd82addbfe 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.cpp +++ b/src/hotspot/share/interpreter/templateInterpreter.cpp @@ -209,7 +209,6 @@ address TemplateInterpreter::_throw_ArrayStoreException_entry = nu address TemplateInterpreter::_throw_ArithmeticException_entry = nullptr; address TemplateInterpreter::_throw_ClassCastException_entry = nullptr; address TemplateInterpreter::_throw_NullPointerException_entry = nullptr; -address TemplateInterpreter::_throw_NPE_UninitializedField_entry = nullptr; address TemplateInterpreter::_throw_StackOverflowError_entry = nullptr; address TemplateInterpreter::_throw_exception_entry = nullptr; address TemplateInterpreter::_cont_resume_interpreter_adapter = nullptr; diff --git a/src/hotspot/share/interpreter/templateInterpreter.hpp b/src/hotspot/share/interpreter/templateInterpreter.hpp index 89a21480d91..8f118bb6ec8 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.hpp +++ b/src/hotspot/share/interpreter/templateInterpreter.hpp @@ -106,7 +106,6 @@ class TemplateInterpreter: public AbstractInterpreter { static address _throw_ArithmeticException_entry; static address _throw_ClassCastException_entry; static address _throw_NullPointerException_entry; - static address _throw_NPE_UninitializedField_entry; static address _throw_exception_entry; static address _throw_StackOverflowError_entry; @@ -154,7 +153,6 @@ class TemplateInterpreter: public AbstractInterpreter { static address throw_exception_entry() { return _throw_exception_entry; } static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; } static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; } - static address throw_NPE_UninitializedField_entry() { return _throw_NPE_UninitializedField_entry; } static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; } static address cont_resume_interpreter_adapter() { return _cont_resume_interpreter_adapter; } diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 84e0e341392..928d1ac9f9c 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -171,7 +171,6 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException", "/ by zero"); Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException", nullptr); - Interpreter::_throw_NPE_UninitializedField_entry = generate_exception_handler("java/lang/NullPointerException", "Uninitialized null-restricted field"); Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); } diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index bc2412a90c1..a09da529b1b 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -170,9 +170,15 @@ NO_TRANSITION(jboolean, jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_ty return JNI_TRUE; NO_TRANSITION_END -JVM_ENTRY_NO_ENV(void, jfr_set_cpu_throttle(JNIEnv* env, jclass jvm, jdouble rate, jboolean auto_adapt)) +JVM_ENTRY_NO_ENV(void, jfr_set_cpu_rate(JNIEnv* env, jclass jvm, jdouble rate)) JfrEventSetting::set_enabled(JfrCPUTimeSampleEvent, rate > 0); - JfrCPUTimeThreadSampling::set_rate(rate, auto_adapt == JNI_TRUE); + JfrCPUTimeThreadSampling::set_rate(rate); +JVM_END + +JVM_ENTRY_NO_ENV(void, jfr_set_cpu_period(JNIEnv* env, jclass jvm, jlong period_nanos)) + assert(period_nanos >= 0, "invariant"); + JfrEventSetting::set_enabled(JfrCPUTimeSampleEvent, period_nanos > 0); + JfrCPUTimeThreadSampling::set_period(period_nanos); JVM_END NO_TRANSITION(void, jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong event_type_id, jlong value)) diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index dbea7f0180d..9769df57bd3 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -129,7 +129,9 @@ jlong JNICALL jfr_get_unloaded_event_classes_count(JNIEnv* env, jclass jvm); jboolean JNICALL jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_type_id, jlong event_sample_size, jlong period_ms); -void JNICALL jfr_set_cpu_throttle(JNIEnv* env, jclass jvm, jdouble rate, jboolean auto_adapt); +void JNICALL jfr_set_cpu_rate(JNIEnv* env, jclass jvm, jdouble rate); + +void JNICALL jfr_set_cpu_period(JNIEnv* env, jclass jvm, jlong period_nanos); void JNICALL jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong id, jlong value); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp index 82ef93d95b2..63efb7404e4 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp @@ -83,7 +83,8 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { (char*)"getUnloadedEventClassCount", (char*)"()J", (void*)jfr_get_unloaded_event_classes_count, (char*)"setMiscellaneous", (char*)"(JJ)V", (void*)jfr_set_miscellaneous, (char*)"setThrottle", (char*)"(JJJ)Z", (void*)jfr_set_throttle, - (char*)"setCPUThrottle", (char*)"(DZ)V", (void*)jfr_set_cpu_throttle, + (char*)"setCPURate", (char*)"(D)V", (void*)jfr_set_cpu_rate, + (char*)"setCPUPeriod", (char*)"(J)V", (void*)jfr_set_cpu_period, (char*)"emitOldObjectSamples", (char*)"(JZZ)V", (void*)jfr_emit_old_object_samples, (char*)"shouldRotateDisk", (char*)"()Z", (void*)jfr_should_rotate_disk, (char*)"exclude", (char*)"(Ljava/lang/Thread;)V", (void*)jfr_exclude_thread, diff --git a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp index 2e814cef875..a139dadc26d 100644 --- a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp +++ b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp @@ -237,7 +237,7 @@ ClassFileStream* JfrUpcalls::on_method_trace(InstanceKlass* ik, const ClassFileS ModuleEntry* module_entry = ik->module(); oop module = nullptr; if (module_entry != nullptr) { - module = module_entry->module(); + module = module_entry->module_oop(); } instanceHandle module_handle(THREAD, (instanceOop)module); diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index d7287adb1a6..42d99e2477d 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -948,22 +948,24 @@ - - - @@ -972,7 +974,7 @@ - diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index 00d41a10bf0..0be1c32728c 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -291,7 +291,7 @@ static void send_agent_event(AgentEvent& event, const JvmtiAgent* agent) { } TRACE_REQUEST_FUNC(JavaAgent) { - const JvmtiAgentList::Iterator it =JvmtiAgentList::java_agents(); + JvmtiAgentList::Iterator it = JvmtiAgentList::java_agents(); while (it.has_next()) { const JvmtiAgent* agent = it.next(); assert(agent->is_jplis(), "invariant"); @@ -300,7 +300,7 @@ TRACE_REQUEST_FUNC(JavaAgent) { } } -static void send_native_agent_events(const JvmtiAgentList::Iterator& it) { +static void send_native_agent_events(JvmtiAgentList::Iterator& it) { while (it.has_next()) { const JvmtiAgent* agent = it.next(); assert(!agent->is_jplis(), "invariant"); @@ -311,9 +311,9 @@ static void send_native_agent_events(const JvmtiAgentList::Iterator& it) { } TRACE_REQUEST_FUNC(NativeAgent) { - const JvmtiAgentList::Iterator native_agents_it = JvmtiAgentList::native_agents(); + JvmtiAgentList::Iterator native_agents_it = JvmtiAgentList::native_agents(); send_native_agent_events(native_agents_it); - const JvmtiAgentList::Iterator xrun_agents_it = JvmtiAgentList::xrun_agents(); + JvmtiAgentList::Iterator xrun_agents_it = JvmtiAgentList::xrun_agents(); send_native_agent_events(xrun_agents_it); } #else // INCLUDE_JVMTI diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp index 2f063123a3d..2793a1fb984 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp @@ -45,7 +45,7 @@ #include "signals_posix.hpp" -static const int64_t AUTOADAPT_INTERVAL_MS = 100; +static const int64_t RECOMPUTE_INTERVAL_MS = 100; static bool is_excluded(JavaThread* jt) { return jt->is_hidden_from_external_view() || @@ -163,20 +163,42 @@ void JfrCPUTimeTraceQueue::clear() { Atomic::release_store(&_head, (u4)0); } -static int64_t compute_sampling_period(double rate) { - if (rate == 0) { - return 0; +// A throttle is either a rate or a fixed period +class JfrCPUSamplerThrottle { + + union { + double _rate; + u8 _period_nanos; + }; + bool _is_rate; + +public: + + JfrCPUSamplerThrottle(double rate) : _rate(rate), _is_rate(true) { + assert(rate >= 0, "invariant"); } - return os::active_processor_count() * 1000000000.0 / rate; -} + + JfrCPUSamplerThrottle(u8 period_nanos) : _period_nanos(period_nanos), _is_rate(false) {} + + bool enabled() const { return _is_rate ? _rate > 0 : _period_nanos > 0; } + + int64_t compute_sampling_period() const { + if (_is_rate) { + if (_rate == 0) { + return 0; + } + return os::active_processor_count() * 1000000000.0 / _rate; + } + return _period_nanos; + } +}; class JfrCPUSamplerThread : public NonJavaThread { friend class JfrCPUTimeThreadSampling; private: Semaphore _sample; NonJavaThread* _sampler_thread; - double _rate; - bool _auto_adapt; + JfrCPUSamplerThrottle _throttle; volatile int64_t _current_sampling_period_ns; volatile bool _disenrolled; // top bit is used to indicate that no signal handler should proceed @@ -187,7 +209,7 @@ class JfrCPUSamplerThread : public NonJavaThread { static const u4 STOP_SIGNAL_BIT = 0x80000000; - JfrCPUSamplerThread(double rate, bool auto_adapt); + JfrCPUSamplerThread(JfrCPUSamplerThrottle& throttle); void start_thread(); @@ -195,9 +217,9 @@ class JfrCPUSamplerThread : public NonJavaThread { void disenroll(); void update_all_thread_timers(); - void auto_adapt_period_if_needed(); + void recompute_period_if_needed(); - void set_rate(double rate, bool auto_adapt); + void set_throttle(JfrCPUSamplerThrottle& throttle); int64_t get_sampling_period() const { return Atomic::load(&_current_sampling_period_ns); }; void sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now); @@ -231,18 +253,16 @@ class JfrCPUSamplerThread : public NonJavaThread { void trigger_async_processing_of_cpu_time_jfr_requests(); }; -JfrCPUSamplerThread::JfrCPUSamplerThread(double rate, bool auto_adapt) : +JfrCPUSamplerThread::JfrCPUSamplerThread(JfrCPUSamplerThrottle& throttle) : _sample(), _sampler_thread(nullptr), - _rate(rate), - _auto_adapt(auto_adapt), - _current_sampling_period_ns(compute_sampling_period(rate)), + _throttle(throttle), + _current_sampling_period_ns(throttle.compute_sampling_period()), _disenrolled(true), _active_signal_handlers(STOP_SIGNAL_BIT), _is_async_processing_of_cpu_time_jfr_requests_triggered(false), _warned_about_timer_creation_failure(false), _signal_handler_installed(false) { - assert(rate >= 0, "invariant"); } void JfrCPUSamplerThread::trigger_async_processing_of_cpu_time_jfr_requests() { @@ -321,7 +341,7 @@ void JfrCPUSamplerThread::disenroll() { void JfrCPUSamplerThread::run() { assert(_sampler_thread == nullptr, "invariant"); _sampler_thread = this; - int64_t last_auto_adapt_check = os::javaTimeNanos(); + int64_t last_recompute_check = os::javaTimeNanos(); while (true) { if (!_sample.trywait()) { // disenrolled @@ -329,9 +349,9 @@ void JfrCPUSamplerThread::run() { } _sample.signal(); - if (os::javaTimeNanos() - last_auto_adapt_check > AUTOADAPT_INTERVAL_MS * 1000000) { - auto_adapt_period_if_needed(); - last_auto_adapt_check = os::javaTimeNanos(); + if (os::javaTimeNanos() - last_recompute_check > RECOMPUTE_INTERVAL_MS * 1000000) { + recompute_period_if_needed(); + last_recompute_check = os::javaTimeNanos(); } if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) { @@ -442,42 +462,50 @@ JfrCPUTimeThreadSampling::~JfrCPUTimeThreadSampling() { } } -void JfrCPUTimeThreadSampling::create_sampler(double rate, bool auto_adapt) { +void JfrCPUTimeThreadSampling::create_sampler(JfrCPUSamplerThrottle& throttle) { assert(_sampler == nullptr, "invariant"); - _sampler = new JfrCPUSamplerThread(rate, auto_adapt); + _sampler = new JfrCPUSamplerThread(throttle); _sampler->start_thread(); _sampler->enroll(); } -void JfrCPUTimeThreadSampling::update_run_state(double rate, bool auto_adapt) { - if (rate != 0) { +void JfrCPUTimeThreadSampling::update_run_state(JfrCPUSamplerThrottle& throttle) { + if (throttle.enabled()) { if (_sampler == nullptr) { - create_sampler(rate, auto_adapt); + create_sampler(throttle); } else { - _sampler->set_rate(rate, auto_adapt); + _sampler->set_throttle(throttle); _sampler->enroll(); } return; } if (_sampler != nullptr) { - _sampler->set_rate(rate /* 0 */, auto_adapt); + _sampler->set_throttle(throttle); _sampler->disenroll(); } } -void JfrCPUTimeThreadSampling::set_rate(double rate, bool auto_adapt) { - assert(rate >= 0, "invariant"); +void JfrCPUTimeThreadSampling::set_rate(double rate) { + if (_instance == nullptr) { + return; + } + JfrCPUSamplerThrottle throttle(rate); + instance().set_throttle_value(throttle); +} + +void JfrCPUTimeThreadSampling::set_period(u8 nanos) { if (_instance == nullptr) { return; } - instance().set_rate_value(rate, auto_adapt); + JfrCPUSamplerThrottle throttle(nanos); + instance().set_throttle_value(throttle); } -void JfrCPUTimeThreadSampling::set_rate_value(double rate, bool auto_adapt) { +void JfrCPUTimeThreadSampling::set_throttle_value(JfrCPUSamplerThrottle& throttle) { if (_sampler != nullptr) { - _sampler->set_rate(rate, auto_adapt); + _sampler->set_throttle(throttle); } - update_run_state(rate, auto_adapt); + update_run_state(throttle); } void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread *thread) { @@ -704,24 +732,21 @@ void JfrCPUSamplerThread::stop_timer() { VMThread::execute(&op); } -void JfrCPUSamplerThread::auto_adapt_period_if_needed() { +void JfrCPUSamplerThread::recompute_period_if_needed() { int64_t current_period = get_sampling_period(); - if (_auto_adapt || current_period == -1) { - int64_t period = compute_sampling_period(_rate); - if (period != current_period) { - Atomic::store(&_current_sampling_period_ns, period); - update_all_thread_timers(); - } + int64_t period = _throttle.compute_sampling_period(); + if (period != current_period) { + Atomic::store(&_current_sampling_period_ns, period); + update_all_thread_timers(); } } -void JfrCPUSamplerThread::set_rate(double rate, bool auto_adapt) { - _rate = rate; - _auto_adapt = auto_adapt; - if (_rate > 0 && Atomic::load_acquire(&_disenrolled) == false) { - auto_adapt_period_if_needed(); +void JfrCPUSamplerThread::set_throttle(JfrCPUSamplerThrottle& throttle) { + _throttle = throttle; + if (_throttle.enabled() && Atomic::load_acquire(&_disenrolled) == false) { + recompute_period_if_needed(); } else { - Atomic::store(&_current_sampling_period_ns, compute_sampling_period(rate)); + Atomic::store(&_current_sampling_period_ns, _throttle.compute_sampling_period()); } } @@ -765,12 +790,18 @@ void JfrCPUTimeThreadSampling::destroy() { _instance = nullptr; } -void JfrCPUTimeThreadSampling::set_rate(double rate, bool auto_adapt) { +void JfrCPUTimeThreadSampling::set_rate(double rate) { if (rate != 0) { warn(); } } +void JfrCPUTimeThreadSampling::set_period(u8 period_nanos) { + if (period_nanos != 0) { + warn(); + } +} + void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread* thread) { } diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp index 7c0545f4772..dae0be5c3a7 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp @@ -95,14 +95,16 @@ class JfrCPUTimeTraceQueue { class JfrCPUSamplerThread; +class JfrCPUSamplerThrottle; + class JfrCPUTimeThreadSampling : public JfrCHeapObj { friend class JfrRecorder; private: JfrCPUSamplerThread* _sampler; - void create_sampler(double rate, bool auto_adapt); - void set_rate_value(double rate, bool auto_adapt); + void create_sampler(JfrCPUSamplerThrottle& throttle); + void set_throttle_value(JfrCPUSamplerThrottle& throttle); JfrCPUTimeThreadSampling(); ~JfrCPUTimeThreadSampling(); @@ -111,10 +113,13 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj { static JfrCPUTimeThreadSampling* create(); static void destroy(); - void update_run_state(double rate, bool auto_adapt); + void update_run_state(JfrCPUSamplerThrottle& throttle); + + static void set_rate(JfrCPUSamplerThrottle& throttle); public: - static void set_rate(double rate, bool auto_adapt); + static void set_rate(double rate); + static void set_period(u8 nanos); static void on_javathread_create(JavaThread* thread); static void on_javathread_terminate(JavaThread* thread); @@ -140,7 +145,8 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj { static void destroy(); public: - static void set_rate(double rate, bool auto_adapt); + static void set_rate(double rate); + static void set_period(u8 nanos); static void on_javathread_create(JavaThread* thread); static void on_javathread_terminate(JavaThread* thread); diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp index 71b7014e6ec..aa594ea6d1f 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp @@ -36,14 +36,6 @@ #include "utilities/preserveException.hpp" #include "utilities/macros.hpp" -class JfrRecorderThread : public JavaThread { - public: - JfrRecorderThread(ThreadFunction entry_point) : JavaThread(entry_point) {} - virtual ~JfrRecorderThread() {} - - virtual bool is_JfrRecorder_thread() const { return true; } -}; - static Thread* start_thread(instanceHandle thread_oop, ThreadFunction proc, TRAPS) { assert(thread_oop.not_null(), "invariant"); assert(proc != nullptr, "invariant"); diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp index df8b1f55a4e..34993e4e6cf 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp @@ -26,9 +26,9 @@ #define SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP #include "memory/allStatic.hpp" +#include "runtime/javaThread.hpp" #include "utilities/debug.hpp" -class JavaThread; class JfrCheckpointManager; class JfrPostBox; class Thread; @@ -42,4 +42,12 @@ class JfrRecorderThreadEntry : AllStatic { static bool start(JfrCheckpointManager* cp_manager, JfrPostBox* post_box, TRAPS); }; +class JfrRecorderThread : public JavaThread { + public: + JfrRecorderThread(ThreadFunction entry_point) : JavaThread(entry_point) {} + virtual ~JfrRecorderThread() {} + + virtual bool is_JfrRecorder_thread() const { return true; } +}; + #endif // SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 67d311e2a6e..e38e0427a05 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -45,6 +45,7 @@ #include "runtime/os.hpp" #include "runtime/threadIdentifier.hpp" #include "utilities/sizes.hpp" +#include "utilities/spinYield.hpp" JfrThreadLocal::JfrThreadLocal() : _sample_request(), @@ -600,7 +601,10 @@ bool JfrThreadLocal::try_acquire_cpu_time_jfr_dequeue_lock() { } void JfrThreadLocal::acquire_cpu_time_jfr_dequeue_lock() { - while (Atomic::cmpxchg(&_cpu_time_jfr_locked, UNLOCKED, DEQUEUE) != UNLOCKED); + SpinYield s; + while (Atomic::cmpxchg(&_cpu_time_jfr_locked, UNLOCKED, DEQUEUE) != UNLOCKED) { + s.wait(); + } } void JfrThreadLocal::release_cpu_time_jfr_queue_lock() { diff --git a/src/hotspot/share/jvmci/jvmciCompiler.cpp b/src/hotspot/share/jvmci/jvmciCompiler.cpp index 103105dd643..07f85a214b1 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.cpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp @@ -147,7 +147,7 @@ bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) { if (excludeModules.not_null()) { ModuleEntry* moduleEntry = method->method_holder()->module(); for (int i = 0; i < excludeModules->length(); i++) { - if (excludeModules->obj_at(i) == moduleEntry->module()) { + if (excludeModules->obj_at(i) == moduleEntry->module_oop()) { return true; } } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 95747c6428e..3b8a4fab78a 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2890,11 +2890,12 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool JVMCIObject methodObject = thisEnv->get_HotSpotNmethod_method(obj); methodHandle mh(THREAD, thisEnv->asMethod(methodObject)); jboolean isDefault = thisEnv->get_HotSpotNmethod_isDefault(obj); + jboolean profileDeopt = thisEnv->get_HotSpotNmethod_profileDeopt(obj); jlong compileIdSnapshot = thisEnv->get_HotSpotNmethod_compileIdSnapshot(obj); JVMCIObject name_string = thisEnv->get_InstalledCode_name(obj); const char* cstring = name_string.is_null() ? nullptr : thisEnv->as_utf8_string(name_string); // Create a new HotSpotNmethod instance in the peer runtime - result = PEER_JVMCIENV->new_HotSpotNmethod(mh, cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0); + result = PEER_JVMCIENV->new_HotSpotNmethod(mh, cstring, isDefault, profileDeopt, compileIdSnapshot, JVMCI_CHECK_0); JVMCINMethodHandle nmethod_handle(THREAD); nmethod* nm = JVMCIENV->get_nmethod(obj, nmethod_handle); if (result.is_null()) { diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index ae64daf9f20..23473940178 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1210,7 +1210,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, } } -JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) { +JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jboolean profileDeopt, jlong compileId, JVMCI_TRAPS) { JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros. JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject())); @@ -1230,11 +1230,12 @@ JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject))); jargs.push_oop(nameStr); jargs.push_int(isDefault); + jargs.push_int(profileDeopt); jargs.push_long(compileId); JavaValue result(T_VOID); JavaCalls::call_special(&result, ik, vmSymbols::object_initializer_name(), - vmSymbols::method_string_bool_long_signature(), + vmSymbols::method_string_bool_bool_long_signature(), &jargs, CHECK_(JVMCIObject())); return wrap(obj_h()); } else { diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index b49bba88b6b..fbe5be88c3f 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -426,7 +426,7 @@ class JVMCIEnv : public ResourceObj { JVMCIObjectArray new_byte_array_array(int length, JVMCI_TRAPS); JVMCIObject new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS); - JVMCIObject new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS); + JVMCIObject new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jboolean profileDeopt, jlong compileId, JVMCI_TRAPS); JVMCIObject new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS); JVMCIObject new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS); JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, jboolean isAvailable, jboolean c1Supported, jboolean c2Supported, JVMCI_TRAPS); diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index 432fefe56d1..8bd34f52def 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -100,10 +100,11 @@ end_class \ start_class(HotSpotNmethod, jdk_vm_ci_hotspot_HotSpotNmethod) \ boolean_field(HotSpotNmethod, isDefault) \ + boolean_field(HotSpotNmethod, profileDeopt) \ long_field(HotSpotNmethod, compileIdSnapshot) \ object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;") \ int_field(HotSpotNmethod, invalidationReason) \ - jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \ + jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZZJ)V") \ end_class \ start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode) \ primarray_field(HotSpotCompiledCode, targetCode, "[B") \ diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 24ea4936822..c0335e7c67e 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -746,6 +746,8 @@ JVM_END void JVMCINMethodData::initialize(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, + bool profile_deopt, FailedSpeculation** failed_speculations) { _failed_speculations = failed_speculations; @@ -753,16 +755,19 @@ void JVMCINMethodData::initialize(int nmethod_mirror_index, guarantee(nmethod_entry_patch_offset != -1, "missing entry barrier"); _nmethod_entry_patch_offset = nmethod_entry_patch_offset; if (nmethod_mirror_name != nullptr) { - _has_name = true; + _properties.bits._has_name = 1; char* dest = (char*) name(); strcpy(dest, nmethod_mirror_name); } else { - _has_name = false; + _properties.bits._has_name = 0; } + _properties.bits._is_default = is_default; + _properties.bits._profile_deopt = profile_deopt; } void JVMCINMethodData::copy(JVMCINMethodData* data) { - initialize(data->_nmethod_mirror_index, data->_nmethod_entry_patch_offset, data->name(), data->_failed_speculations); + initialize(data->_nmethod_mirror_index, data->_nmethod_entry_patch_offset, data->name(), data->_properties.bits._is_default, + data->_properties.bits._profile_deopt, data->_failed_speculations); } void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) { @@ -2084,6 +2089,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, char* failure_detail = nullptr; bool install_default = JVMCIENV->get_HotSpotNmethod_isDefault(nmethod_mirror) != 0; + bool profile_deopt = JVMCIENV->get_HotSpotNmethod_profileDeopt(nmethod_mirror) != 0; assert(JVMCIENV->isa_HotSpotNmethod(nmethod_mirror), "must be"); JVMCIObject name = JVMCIENV->get_InstalledCode_name(nmethod_mirror); const char* nmethod_mirror_name = name.is_null() ? nullptr : JVMCIENV->as_utf8_string(name); @@ -2130,7 +2136,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, JVMCICompileState* compile_state = JVMCIENV->compile_state(); bool failing_dep_is_call_site; result = validate_compile_task_dependencies(dependencies, compile_state, &failure_detail, failing_dep_is_call_site); - if (result != JVMCI::ok) { + if (install_default && result != JVMCI::ok) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdp = method()->method_data(); if (mdp != nullptr && !failing_dep_is_call_site) { @@ -2151,6 +2157,8 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, JVMCINMethodData* data = JVMCINMethodData::create(nmethod_mirror_index, nmethod_entry_patch_offset, nmethod_mirror_name, + install_default, + profile_deopt, failed_speculations); nm = nmethod::new_nmethod(method, compile_id, diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 95c7d32f928..f4c322e831c 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -48,9 +48,21 @@ class MetadataHandles; class JVMCINMethodData : public ResourceObj { friend class JVMCIVMStructs; - // Is HotSpotNmethod.name non-null? If so, the value is - // embedded in the end of this object. - bool _has_name; + union JVMCINMethodProperties { + uint8_t value; + struct { + // Is HotSpotNmethod.name non-null? If so, the value is + // embedded in the end of this object. + uint8_t _has_name : 1, + // HotSpotNmethod.isDefault (e.g., compilation scheduled by CompileBroker) + _is_default : 1, + // HotSpotNmethod.profileDeopt + _profile_deopt : 1, + : 5; + } bits; + }; + + JVMCINMethodProperties _properties; // Index for the HotSpotNmethod mirror in the nmethod's oops table. // This is -1 if there is no mirror in the oops table. @@ -76,6 +88,8 @@ class JVMCINMethodData : public ResourceObj { void initialize(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, + bool profile_deopt, FailedSpeculation** failed_speculations); void* operator new(size_t size, const char* nmethod_mirror_name) { @@ -88,11 +102,15 @@ class JVMCINMethodData : public ResourceObj { static JVMCINMethodData* create(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, + bool profile_deopt, FailedSpeculation** failed_speculations) { JVMCINMethodData* result = new (nmethod_mirror_name) JVMCINMethodData(); result->initialize(nmethod_mirror_index, nmethod_entry_patch_offset, nmethod_mirror_name, + is_default, + profile_deopt, failed_speculations); return result; } @@ -117,7 +135,7 @@ class JVMCINMethodData : public ResourceObj { void add_failed_speculation(nmethod* nm, jlong speculation); // Gets the JVMCI name of the nmethod (which may be null). - const char* name() { return _has_name ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : nullptr; } + const char* name() { return has_name() ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : nullptr; } // Clears the HotSpotNmethod.address field in the mirror. If nm // is dead, the HotSpotNmethod.entryPoint field is also cleared. @@ -132,6 +150,18 @@ class JVMCINMethodData : public ResourceObj { int nmethod_entry_patch_offset() { return _nmethod_entry_patch_offset; } + + bool has_name() { + return _properties.bits._has_name; + } + + bool is_default() { + return _properties.bits._is_default; + } + + bool profile_deopt() { + return _properties.bits._profile_deopt; + } }; // A top level class that represents an initialized JVMCI runtime. diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp index d5a23a59982..f68515e3be9 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.cpp +++ b/src/hotspot/share/jvmci/jvmci_globals.cpp @@ -106,7 +106,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() { } if (BootstrapJVMCI && (TieredStopAtLevel < CompLevel_full_optimization)) { jio_fprintf(defaultStream::error_stream(), - "-XX:+BootstrapJVMCI is not compatible with -XX:TieredStopAtLevel=%d\n", TieredStopAtLevel); + "-XX:+BootstrapJVMCI is not compatible with -XX:TieredStopAtLevel=%zd\n", TieredStopAtLevel); return false; } } diff --git a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp index c0a7afe2b63..de965da0f80 100644 --- a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp +++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp @@ -102,7 +102,7 @@ template(bootstrapFinished_name, "bootstrapFinished") \ template(forPrimitive_name, "forPrimitive") \ template(forPrimitive_signature, "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;") \ - template(method_string_bool_long_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \ + template(method_string_bool_bool_long_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZZJ)V") \ #endif diff --git a/src/hotspot/share/logging/logFileStreamOutput.cpp b/src/hotspot/share/logging/logFileStreamOutput.cpp index 4ade1e100b4..bc753676706 100644 --- a/src/hotspot/share/logging/logFileStreamOutput.cpp +++ b/src/hotspot/share/logging/logFileStreamOutput.cpp @@ -64,7 +64,7 @@ int LogFileStreamOutput::write_decorations(const LogDecorations& decorations) { decorations.decoration(decorator, buf, sizeof(buf))); if (written <= 0) { return -1; - } else if (static_cast(written - 2) > _decorator_padding[decorator]) { + } else if ((written - 2) > _decorator_padding[decorator]) { _decorator_padding[decorator] = written - 2; } total_written += written; diff --git a/src/hotspot/share/logging/logFileStreamOutput.hpp b/src/hotspot/share/logging/logFileStreamOutput.hpp index a9c3e4b6ee1..d1c273f9e63 100644 --- a/src/hotspot/share/logging/logFileStreamOutput.hpp +++ b/src/hotspot/share/logging/logFileStreamOutput.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -40,13 +40,14 @@ class LogFileStreamOutput : public LogOutput { protected: FILE* _stream; - size_t _decorator_padding[LogDecorators::Count]; + int _decorator_padding[LogDecorators::Count]; - LogFileStreamOutput(FILE *stream) : _fold_multilines(false), _write_error_is_shown(false), _stream(stream) { - for (size_t i = 0; i < LogDecorators::Count; i++) { - _decorator_padding[i] = 0; - } - } + LogFileStreamOutput(FILE *stream) + : _fold_multilines(false), + _write_error_is_shown(false), + _stream(stream), + _decorator_padding() + {} int write_decorations(const LogDecorations& decorations); int write_internal(const LogDecorations& decorations, const char* msg); diff --git a/src/hotspot/share/memory/guardedMemory.cpp b/src/hotspot/share/memory/guardedMemory.cpp index 4165ccdb620..dbff7ee1263 100644 --- a/src/hotspot/share/memory/guardedMemory.cpp +++ b/src/hotspot/share/memory/guardedMemory.cpp @@ -25,11 +25,12 @@ #include "nmt/memTag.hpp" #include "runtime/os.hpp" -void* GuardedMemory::wrap_copy(const void* ptr, const size_t len, const void* tag) { +void* GuardedMemory::wrap_copy(const void* ptr, const size_t len, + const void* tag, const void* tag2) { size_t total_sz = GuardedMemory::get_total_size(len); void* outerp = os::malloc(total_sz, mtInternal); if (outerp != nullptr) { - GuardedMemory guarded(outerp, len, tag); + GuardedMemory guarded(outerp, len, tag, tag2); void* innerp = guarded.get_user_ptr(); if (ptr != nullptr) { memcpy(innerp, ptr, len); @@ -58,8 +59,8 @@ void GuardedMemory::print_on(outputStream* st) const { return; } st->print_cr("GuardedMemory(" PTR_FORMAT ") base_addr=" PTR_FORMAT - " tag=" PTR_FORMAT " user_size=%zu user_data=" PTR_FORMAT, - p2i(this), p2i(_base_addr), p2i(get_tag()), get_user_size(), p2i(get_user_ptr())); + " tag=" PTR_FORMAT " tag2=" PTR_FORMAT " user_size=%zu user_data=" PTR_FORMAT, + p2i(this), p2i(_base_addr), p2i(get_tag()), p2i(get_tag2()), get_user_size(), p2i(get_user_ptr())); Guard* guard = get_head_guard(); st->print_cr(" Header guard @" PTR_FORMAT " is %s", p2i(guard), (guard->verify() ? "OK" : "BROKEN")); diff --git a/src/hotspot/share/memory/guardedMemory.hpp b/src/hotspot/share/memory/guardedMemory.hpp index f96cdd0801e..a3bbf48b0cd 100644 --- a/src/hotspot/share/memory/guardedMemory.hpp +++ b/src/hotspot/share/memory/guardedMemory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -26,6 +26,7 @@ #define SHARE_MEMORY_GUARDEDMEMORY_HPP #include "memory/allocation.hpp" +#include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" /** @@ -43,13 +44,14 @@ * |base_addr | 0xABABABABABABABAB | Head guard | * |+16 | | User data size | * |+sizeof(uintptr_t) | | Tag word | + * |+sizeof(uintptr_t) | | Tag word | * |+sizeof(void*) | 0xF1 ( | User data | * |+user_size | 0xABABABABABABABAB | Tail guard | * ------------------------------------------------------------- * * Where: * - guard padding uses "badResourceValue" (0xAB) - * - tag word is general purpose + * - tag word and tag2 word are general purpose * - user data * -- initially padded with "uninitBlockPad" (0xF1), * -- to "freeBlockPad" (0xBA), when freed @@ -111,6 +113,10 @@ class GuardedMemory : StackObj { // Wrapper on stack } bool verify() const { + // We may not be able to dereference directly. + if (!os::is_readable_range((const void*) _guard, (const void*) (_guard + GUARD_SIZE))) { + return false; + } u_char* c = (u_char*) _guard; u_char* end = c + GUARD_SIZE; while (c < end) { @@ -137,6 +143,7 @@ class GuardedMemory : StackObj { // Wrapper on stack size_t _user_size; }; void* _tag; + void* _tag2; public: void set_user_size(const size_t usz) { _user_size = usz; } size_t get_user_size() const { return _user_size; } @@ -144,6 +151,8 @@ class GuardedMemory : StackObj { // Wrapper on stack void set_tag(const void* tag) { _tag = (void*) tag; } void* get_tag() const { return _tag; } + void set_tag2(const void* tag2) { _tag2 = (void*) tag2; } + void* get_tag2() const { return _tag2; } }; // GuardedMemory::GuardHeader // Guarded Memory... @@ -162,9 +171,11 @@ class GuardedMemory : StackObj { // Wrapper on stack * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. * @param user_size the size of the user data to be wrapped. * @param tag optional general purpose tag. + * @param tag2 optional second general purpose tag. */ - GuardedMemory(void* base_ptr, const size_t user_size, const void* tag = nullptr) { - wrap_with_guards(base_ptr, user_size, tag); + GuardedMemory(void* base_ptr, const size_t user_size, + const void* tag = nullptr, const void* tag2 = nullptr) { + wrap_with_guards(base_ptr, user_size, tag, tag2); } /** @@ -189,16 +200,19 @@ class GuardedMemory : StackObj { // Wrapper on stack * @param base_ptr allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes. * @param user_size the size of the user data to be wrapped. * @param tag optional general purpose tag. + * @param tag2 optional second general purpose tag. * * @return user data pointer (inner pointer to supplied "base_ptr"). */ - void* wrap_with_guards(void* base_ptr, size_t user_size, const void* tag = nullptr) { + void* wrap_with_guards(void* base_ptr, size_t user_size, + const void* tag = nullptr, const void* tag2 = nullptr) { assert(base_ptr != nullptr, "Attempt to wrap null with memory guard"); _base_addr = (u_char*)base_ptr; get_head_guard()->build(); get_head_guard()->set_user_size(user_size); get_tail_guard()->build(); set_tag(tag); + set_tag2(tag2); set_user_bytes(uninitBlockPad); assert(verify_guards(), "Expected valid memory guards"); return get_user_ptr(); @@ -230,6 +244,20 @@ class GuardedMemory : StackObj { // Wrapper on stack */ void* get_tag() const { return get_head_guard()->get_tag(); } + /** + * Set the second general purpose tag. + * + * @param tag general purpose tag. + */ + void set_tag2(const void* tag) { get_head_guard()->set_tag2(tag); } + + /** + * Return the second general purpose tag. + * + * @return the second general purpose tag, defaults to null. + */ + void* get_tag2() const { return get_head_guard()->get_tag2(); } + /** * Return the size of the user data. * @@ -302,10 +330,12 @@ class GuardedMemory : StackObj { // Wrapper on stack * @param ptr the memory to be copied * @param len the length of the copy * @param tag optional general purpose tag (see GuardedMemory::get_tag()) + * @param tag2 optional general purpose tag (see GuardedMemory::get_tag2()) * * @return guarded wrapped memory pointer to the user area, or null if OOM. */ - static void* wrap_copy(const void* p, const size_t len, const void* tag = nullptr); + static void* wrap_copy(const void* p, const size_t len, + const void* tag = nullptr, const void* tag2 = nullptr); /** * Free wrapped copy. diff --git a/src/hotspot/share/memory/memoryReserver.cpp b/src/hotspot/share/memory/memoryReserver.cpp index 457818139cd..a6c1be5b33c 100644 --- a/src/hotspot/share/memory/memoryReserver.cpp +++ b/src/hotspot/share/memory/memoryReserver.cpp @@ -22,7 +22,6 @@ * */ -#include "jvm.h" #include "logging/log.hpp" #include "memory/memoryReserver.hpp" #include "oops/compressedOops.hpp" @@ -65,11 +64,9 @@ static void log_on_large_pages_failure(char* req_addr, size_t bytes) { // Compressed oops logging. log_debug(gc, heap, coops)("Reserve regular memory without large pages"); // JVM style warning that we did not succeed in using large pages. - char msg[128]; - jio_snprintf(msg, sizeof(msg), "Failed to reserve and commit memory using large pages. " - "req_addr: " PTR_FORMAT " bytes: %zu", - req_addr, bytes); - warning("%s", msg); + warning("Failed to reserve and commit memory using large pages. " + "req_addr: " PTR_FORMAT " bytes: %zu", + p2i(req_addr), bytes); } } diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 15696f19df5..a04ddfa09aa 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -60,6 +60,7 @@ #include "oops/compressedOops.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/objLayout.hpp" @@ -439,6 +440,9 @@ void Universe::genesis(TRAPS) { vmSymbols::initialize(); + // Initialize table for matching jmethodID, before SystemDictionary. + JmethodIDTable::initialize(); + SystemDictionary::initialize(CHECK); // Create string constants @@ -447,7 +451,6 @@ void Universe::genesis(TRAPS) { s = StringTable::intern("-2147483648", CHECK); _the_min_jint_string = OopHandle(vm_global(), s); - #if INCLUDE_CDS if (CDSConfig::is_using_archive()) { // Verify shared interfaces array. diff --git a/src/hotspot/share/nmt/memTag.hpp b/src/hotspot/share/nmt/memTag.hpp index 9255645638d..b1b59c9151a 100644 --- a/src/hotspot/share/nmt/memTag.hpp +++ b/src/hotspot/share/nmt/memTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -58,6 +58,7 @@ f(mtMetaspace, "Metaspace") \ f(mtStringDedup, "String Deduplication") \ f(mtObjectMonitor, "Object Monitors") \ + f(mtJNI, "JNI") \ f(mtNone, "Unknown") \ //end diff --git a/src/hotspot/share/nmt/memTracker.cpp b/src/hotspot/share/nmt/memTracker.cpp index 3d001bb0b11..ed5d34bc12a 100644 --- a/src/hotspot/share/nmt/memTracker.cpp +++ b/src/hotspot/share/nmt/memTracker.cpp @@ -41,7 +41,7 @@ #include "runtime/vmThread.hpp" #include "utilities/debug.hpp" #include "utilities/defaultStream.hpp" -#include "utilities/deferred.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/vmError.hpp" #ifdef _WINDOWS @@ -50,7 +50,7 @@ NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown; -Deferred MemTracker::_baseline; +DeferredStatic MemTracker::_baseline; bool MemTracker::NmtVirtualMemoryLocker::_safe_to_use; diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 8898bf08fa5..124c6163d76 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -34,8 +34,8 @@ #include "nmt/virtualMemoryTracker.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/nativeCallStack.hpp" -#include "utilities/deferred.hpp" #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \ NativeCallStack(0) : FAKE_CALLSTACK) @@ -319,7 +319,7 @@ class MemTracker : AllStatic { // Tracking level static NMT_TrackingLevel _tracking_level; // Stored baseline - static Deferred _baseline; + static DeferredStatic _baseline; }; #endif // SHARE_NMT_MEMTRACKER_HPP diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index 49ef6ef70a0..677cd174650 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -32,7 +32,7 @@ #include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" -Deferred MemoryFileTracker::Instance::_tracker; +DeferredStatic MemoryFileTracker::Instance::_tracker; MemoryFileTracker::MemoryFileTracker(bool is_detailed_mode) : _stack_storage(is_detailed_mode), _files() {} diff --git a/src/hotspot/share/nmt/memoryFileTracker.hpp b/src/hotspot/share/nmt/memoryFileTracker.hpp index 7800b1a3ba6..1b23dacab81 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.hpp +++ b/src/hotspot/share/nmt/memoryFileTracker.hpp @@ -31,10 +31,10 @@ #include "nmt/vmatree.hpp" #include "nmt/virtualMemoryTracker.hpp" #include "runtime/os.inline.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/growableArray.hpp" #include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" -#include "utilities/deferred.hpp" // The MemoryFileTracker tracks memory of 'memory files', // storage with its own memory space separate from the process. @@ -92,7 +92,7 @@ class MemoryFileTracker { const GrowableArrayCHeap& files(); class Instance : public AllStatic { - static Deferred _tracker; + static DeferredStatic _tracker; public: diff --git a/src/hotspot/share/oops/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index b5dbf8d7d3b..a550bf60659 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -143,7 +143,7 @@ void ArrayKlass::complete_create_array_klass(ArrayKlass* k, Klass* super_klass, // java.base is defined. assert((module_entry != nullptr) || ((module_entry == nullptr) && !ModuleEntryTable::javabase_defined()), "module entry not available post " JAVA_BASE_NAME " definition"); - oop module = (module_entry != nullptr) ? module_entry->module() : (oop)nullptr; + oop module_oop = (module_entry != nullptr) ? module_entry->module_oop() : (oop)nullptr; if (k->is_refArray_klass() || k->is_flatArray_klass()) { assert(super_klass != nullptr, "Must be"); @@ -152,7 +152,7 @@ void ArrayKlass::complete_create_array_klass(ArrayKlass* k, Klass* super_klass, Handle mirror(THREAD, super_klass->java_mirror()); k->set_java_mirror(mirror); } else { - java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(), Handle(), CHECK); + java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module_oop), Handle(), Handle(), CHECK); } } diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 1e8f6fbe9bb..dbc53814069 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -970,6 +970,44 @@ bool InstanceKlass::verify_code(TRAPS) { return Verifier::verify(this, should_verify_class(), THREAD); } +static void load_classes_from_loadable_descriptors_attribute(InstanceKlass *ik, TRAPS) { + ResourceMark rm(THREAD); + if (ik->loadable_descriptors() != nullptr && PreloadClasses) { + HandleMark hm(THREAD); + for (int i = 0; i < ik->loadable_descriptors()->length(); i++) { + Symbol* sig = ik->constants()->symbol_at(ik->loadable_descriptors()->at(i)); + if (!Signature::has_envelope(sig)) continue; + TempNewSymbol class_name = Signature::strip_envelope(sig); + if (class_name == ik->name()) continue; + log_info(class, preload)("Preloading of class %s during linking of class %s " + "because of the class is listed in the LoadableDescriptors attribute", + sig->as_C_string(), ik->name()->as_C_string()); + oop loader = ik->class_loader(); + Klass* klass = SystemDictionary::resolve_or_null(class_name, + Handle(THREAD, loader), THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + if (klass != nullptr) { + log_info(class, preload)("Preloading of class %s during linking of class %s " + "(cause: LoadableDescriptors attribute) succeeded", + class_name->as_C_string(), ik->name()->as_C_string()); + if (!klass->is_inline_klass()) { + // Non value class are allowed by the current spec, but it could be an indication + // of an issue so let's log a warning + log_warning(class, preload)("Preloading of class %s during linking of class %s " + "(cause: LoadableDescriptors attribute) but loaded class is not a value class", + class_name->as_C_string(), ik->name()->as_C_string()); + } + } else { + log_warning(class, preload)("Preloading of class %s during linking of class %s " + "(cause: LoadableDescriptors attribute) failed", + class_name->as_C_string(), ik->name()->as_C_string()); + } + } + } +} + void InstanceKlass::link_class(TRAPS) { assert(is_loaded(), "must be loaded"); if (!is_linked()) { @@ -1041,105 +1079,11 @@ bool InstanceKlass::link_class_impl(TRAPS) { interk->link_class_impl(CHECK_false); } - - // If a class declares a method that uses an inline class as an argument - // type or return inline type, this inline class must be loaded during the - // linking of this class because size and properties of the inline class - // must be known in order to be able to perform inline type optimizations. - // The implementation below is an approximation of this rule, the code - // iterates over all methods of the current class (including overridden - // methods), not only the methods declared by this class. This - // approximation makes the code simpler, and doesn't change the semantic - // because classes declaring methods overridden by the current class are - // linked (and have performed their own pre-loading) before the linking - // of the current class. - - - // Note: - // Inline class types are loaded during - // the loading phase (see ClassFileParser::post_process_parsed_stream()). - // Inline class types used as element types for array creation - // are not pre-loaded. Their loading is triggered by either anewarray - // or multianewarray bytecodes. - - // Could it be possible to do the following processing only if the - // class uses inline types? if (EnableValhalla) { - ResourceMark rm(THREAD); - for (AllFieldStream fs(this); !fs.done(); fs.next()) { - if (fs.is_null_free_inline_type() && fs.access_flags().is_static()) { - assert(fs.access_flags().is_strict(), "null-free fields must be strict"); - Symbol* sig = fs.signature(); - TempNewSymbol s = Signature::strip_envelope(sig); - if (s != name()) { - log_info(class, preload)("Preloading of class %s during linking of class %s. Cause: a null-free static field is declared with this type", s->as_C_string(), name()->as_C_string()); - Klass* klass = SystemDictionary::resolve_or_fail(s, - Handle(THREAD, class_loader()), true, - CHECK_false); - if (HAS_PENDING_EXCEPTION) { - log_warning(class, preload)("Preloading of class %s during linking of class %s (cause: null-free static field) failed: %s", - s->as_C_string(), name()->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string()); - return false; // Exception is still pending - } - log_info(class, preload)("Preloading of class %s during linking of class %s (cause: null-free static field) succeeded", - s->as_C_string(), name()->as_C_string()); - assert(klass != nullptr, "Sanity check"); - if (klass->is_abstract()) { - THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), - err_msg("Class %s expects class %s to be concrete value class, but it is an abstract class", - name()->as_C_string(), - InstanceKlass::cast(klass)->external_name()), false); - } - if (!klass->is_inline_klass()) { - THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), - err_msg("class %s expects class %s to be a value class but it is an identity class", - name()->as_C_string(), klass->external_name()), false); - } - InlineKlass* vk = InlineKlass::cast(klass); - // the inline_type_field_klasses_array might have been loaded with CDS, so update only if not already set and check consistency - InlineLayoutInfo* li = inline_layout_info_adr(fs.index()); - if (li->klass() == nullptr) { - li->set_klass(InlineKlass::cast(vk)); - li->set_kind(LayoutKind::REFERENCE); - } - assert(get_inline_type_field_klass(fs.index()) == vk, "Must match"); - } else { - InlineLayoutInfo* li = inline_layout_info_adr(fs.index()); - if (li->klass() == nullptr) { - li->set_klass(InlineKlass::cast(this)); - li->set_kind(LayoutKind::REFERENCE); - } - assert(get_inline_type_field_klass(fs.index()) == this, "Must match"); - } - } - } - // Aggressively preloading all classes from the LoadableDescriptors attribute - if (loadable_descriptors() != nullptr && PreloadClasses) { - HandleMark hm(THREAD); - for (int i = 0; i < loadable_descriptors()->length(); i++) { - Symbol* sig = constants()->symbol_at(loadable_descriptors()->at(i)); - if (!Signature::has_envelope(sig)) continue; - TempNewSymbol class_name = Signature::strip_envelope(sig); - if (class_name == name()) continue; - log_info(class, preload)("Preloading of class %s during linking of class %s because of the class is listed in the LoadableDescriptors attribute", sig->as_C_string(), name()->as_C_string()); - oop loader = class_loader(); - Klass* klass = SystemDictionary::resolve_or_null(class_name, - Handle(THREAD, loader), THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } - if (klass != nullptr) { - log_info(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) succeeded", class_name->as_C_string(), name()->as_C_string()); - if (!klass->is_inline_klass()) { - // Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning - log_warning(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) but loaded class is not a value class", class_name->as_C_string(), name()->as_C_string()); - } - } else { - log_warning(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) failed", class_name->as_C_string(), name()->as_C_string()); - } - } - } + // so inline classes can be scalarized in the calling conventions computed below + load_classes_from_loadable_descriptors_attribute(this, THREAD); + assert(!HAS_PENDING_EXCEPTION, "Shouldn't have pending exceptions from call above"); } // in case the class is linked in the process of linking its superclasses @@ -2690,13 +2634,26 @@ jmethodID InstanceKlass::update_jmethod_id(jmethodID* jmeths, Method* method, in return new_id; } +// Allocate the jmethodID cache. +static jmethodID* create_jmethod_id_cache(size_t size) { + jmethodID* jmeths = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); + memset(jmeths, 0, (size + 1) * sizeof(jmethodID)); + // cache size is stored in element[0], other elements offset by one + jmeths[0] = (jmethodID)size; + return jmeths; +} + +// When reading outside a lock, use this. +jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const { + return Atomic::load_acquire(&_methods_jmethod_ids); +} + +void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) { + Atomic::release_store(&_methods_jmethod_ids, jmeths); +} + // Lookup or create a jmethodID. -// This code is called by the VMThread and JavaThreads so the -// locking has to be done very carefully to avoid deadlocks -// and/or other cache consistency problems. -// -jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { - Method* method = method_h(); +jmethodID InstanceKlass::get_jmethod_id(Method* method) { int idnum = method->method_idnum(); jmethodID* jmeths = methods_jmethod_ids_acquire(); @@ -2717,15 +2674,12 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { if (jmeths == nullptr) { MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - jmeths = methods_jmethod_ids_acquire(); + jmeths = _methods_jmethod_ids; // Still null? if (jmeths == nullptr) { size_t size = idnum_allocated_count(); assert(size > (size_t)idnum, "should already have space"); - jmeths = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); - memset(jmeths, 0, (size + 1) * sizeof(jmethodID)); - // cache size is stored in element[0], other elements offset by one - jmeths[0] = (jmethodID)size; + jmeths = create_jmethod_id_cache(size); jmethodID new_id = update_jmethod_id(jmeths, method, idnum); // publish jmeths @@ -2755,10 +2709,7 @@ void InstanceKlass::update_methods_jmethod_cache() { if (old_size < size + 1) { // Allocate a larger one and copy entries to the new one. // They've already been updated to point to new methods where applicable (i.e., not obsolete). - jmethodID* new_cache = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); - memset(new_cache, 0, (size + 1) * sizeof(jmethodID)); - // The cache size is stored in element[0]; the other elements are offset by one. - new_cache[0] = (jmethodID)size; + jmethodID* new_cache = create_jmethod_id_cache(size); for (int i = 1; i <= (int)old_size; i++) { new_cache[i] = cache[i]; @@ -2769,24 +2720,30 @@ void InstanceKlass::update_methods_jmethod_cache() { } } -// Figure out how many jmethodIDs haven't been allocated, and make -// sure space for them is pre-allocated. This makes getting all -// method ids much, much faster with classes with more than 8 +// Make a jmethodID for all methods in this class. This makes getting all method +// ids much, much faster with classes with more than 8 // methods, and has a *substantial* effect on performance with jvmti // code that loads all jmethodIDs for all classes. -void InstanceKlass::ensure_space_for_methodids(int start_offset) { - int new_jmeths = 0; +void InstanceKlass::make_methods_jmethod_ids() { + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + jmethodID* jmeths = _methods_jmethod_ids; + if (jmeths == nullptr) { + jmeths = create_jmethod_id_cache(idnum_allocated_count()); + release_set_methods_jmethod_ids(jmeths); + } + int length = methods()->length(); - for (int index = start_offset; index < length; index++) { + for (int index = 0; index < length; index++) { Method* m = methods()->at(index); - jmethodID id = m->find_jmethod_id_or_null(); - if (id == nullptr) { - new_jmeths++; + int idnum = m->method_idnum(); + assert(!m->is_old(), "should not have old methods or I'm confused"); + jmethodID id = Atomic::load_acquire(&jmeths[idnum + 1]); + if (!m->is_overpass() && // skip overpasses + id == nullptr) { + id = Method::make_jmethod_id(class_loader_data(), m); + Atomic::release_store(&jmeths[idnum + 1], id); } } - if (new_jmeths != 0) { - Method::ensure_jmethod_ids(class_loader_data(), new_jmeths); - } } // Lookup a jmethodID, null if not found. Do no blocking, no allocations, no handles @@ -3230,7 +3187,7 @@ void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) { JNIid::deallocate(jni_ids()); set_jni_ids(nullptr); - jmethodID* jmeths = methods_jmethod_ids_acquire(); + jmethodID* jmeths = _methods_jmethod_ids; if (jmeths != nullptr) { release_set_methods_jmethod_ids(nullptr); FreeHeap(jmeths); @@ -4632,17 +4589,14 @@ bool InstanceKlass::should_clean_previous_versions_and_reset() { return ret; } -// This nulls out jmethodIDs for all methods in 'klass' -// It needs to be called explicitly for all previous versions of a class because these may not be cleaned up -// during class unloading. -// We can not use the jmethodID cache associated with klass directly because the 'previous' versions -// do not have the jmethodID cache filled in. Instead, we need to lookup jmethodID for each method and this -// is expensive - O(n) for one jmethodID lookup. For all contained methods it is O(n^2). -// The reason for expensive jmethodID lookup for each method is that there is no direct link between method and jmethodID. -void InstanceKlass::clear_jmethod_ids(InstanceKlass* klass) { +// This nulls out the jmethodID for all obsolete methods in the previous version of the 'klass'. +// These obsolete methods only exist in the previous version and we're about to delete the memory for them. +// The jmethodID for these are deallocated when we unload the class, so this doesn't remove them from the table. +void InstanceKlass::clear_obsolete_jmethod_ids(InstanceKlass* klass) { Array* method_refs = klass->methods(); for (int k = 0; k < method_refs->length(); k++) { Method* method = method_refs->at(k); + // Only need to clear obsolete methods. if (method != nullptr && method->is_obsolete()) { method->clear_jmethod_id(); } @@ -4692,7 +4646,7 @@ void InstanceKlass::purge_previous_version_list() { // Unlink from previous version list. assert(pv_node->class_loader_data() == loader_data, "wrong loader_data"); InstanceKlass* next = pv_node->previous_versions(); - clear_jmethod_ids(pv_node); // jmethodID maintenance for the unloaded class + clear_obsolete_jmethod_ids(pv_node); // jmethodID maintenance for the unloaded class pv_node->link_previous_versions(nullptr); // point next to null last->link_previous_versions(next); // Delete this node directly. Nothing is referring to it and we don't diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 110ba510852..86c10a71932 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -534,6 +534,9 @@ class InstanceKlass: public Klass { assert(_nest_host != nullptr, "must be"); return _nest_host; } + InstanceKlass* nest_host_or_null() { + return _nest_host; + } // Used to construct informative IllegalAccessError messages at a higher level, // if there was an issue resolving or validating the nest host. // Returns null if there was no error. @@ -886,8 +889,8 @@ class InstanceKlass: public Klass { u2 method_index); // jmethodID support - jmethodID get_jmethod_id(const methodHandle& method_h); - void ensure_space_for_methodids(int start_offset = 0); + jmethodID get_jmethod_id(Method* method); + void make_methods_jmethod_ids(); jmethodID jmethod_id_or_null(Method* method); void update_methods_jmethod_cache(); @@ -1187,10 +1190,10 @@ class InstanceKlass: public Klass { Atomic::store(&_init_thread, thread); } - inline jmethodID* methods_jmethod_ids_acquire() const; - inline void release_set_methods_jmethod_ids(jmethodID* jmeths); - // This nulls out jmethodIDs for all methods in 'klass' - static void clear_jmethod_ids(InstanceKlass* klass); + jmethodID* methods_jmethod_ids_acquire() const; + void release_set_methods_jmethod_ids(jmethodID* jmeths); + // This nulls out obsolete jmethodIDs for all methods in 'klass'. + static void clear_obsolete_jmethod_ids(InstanceKlass* klass); jmethodID update_jmethod_id(jmethodID* jmeths, Method* method, int idnum); public: diff --git a/src/hotspot/share/oops/instanceKlass.inline.hpp b/src/hotspot/share/oops/instanceKlass.inline.hpp index a78ec706c06..70380d11d35 100644 --- a/src/hotspot/share/oops/instanceKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceKlass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -86,14 +86,6 @@ inline void InstanceKlass::release_set_array_klasses(ObjArrayKlass* k) { Atomic::release_store(&_array_klasses, k); } -inline jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const { - return Atomic::load_acquire(&_methods_jmethod_ids); -} - -inline void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) { - Atomic::release_store(&_methods_jmethod_ids, jmeths); -} - // The iteration over the oops in objects is a hot path in the GC code. // By force inlining the following functions, we get similar GC performance // as the previous macro based implementation. diff --git a/src/hotspot/share/oops/jmethodIDTable.cpp b/src/hotspot/share/oops/jmethodIDTable.cpp new file mode 100644 index 00000000000..9dba79229e7 --- /dev/null +++ b/src/hotspot/share/oops/jmethodIDTable.cpp @@ -0,0 +1,194 @@ +/* + * 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. + * + * 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 "logging/log.hpp" +#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" +#include "oops/jmethodIDTable.hpp" +#include "oops/method.hpp" +#include "runtime/mutexLocker.hpp" +#include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" +#include "utilities/macros.hpp" + +// Save (jmethod, Method*) in a hashtable to lookup Method. +// The CHT is for performance because it has lock free lookup. +// The value of the next jmethodID. This only increments (always unique IDs). +static uint64_t _jmethodID_counter = 0; +// Tracks the number of jmethodID entries in the _jmethod_id_table. +// Incremented on insert, decremented on remove. Used to track if we need to resize the table. +static uint64_t _jmethodID_entry_count = 0; + +uint64_t JmethodIDTable::get_entry_count() { return _jmethodID_entry_count; } + +class JmethodEntry { + public: + uint64_t _id; + Method* _method; + + JmethodEntry(uint64_t id, Method* method) : _id(id), _method(method) {} +}; + +class JmethodIDTableConfig : public AllStatic { + public: + typedef JmethodEntry Value; + static void* allocate_node(void* context, size_t size, Value const& value) { + return AllocateHeap(size, mtJNI); + } + static void free_node(void* context, void* memory, Value const& value) { + FreeHeap(memory); + } + static uintx get_hash(Value const& value, bool* is_dead) { + *is_dead = false; + return value._id; + } + static bool is_dead(Value const& value) { + return false; + } +}; + +using MethodIdTable = ConcurrentHashTable; +static MethodIdTable* _jmethod_id_table = nullptr; + +void JmethodIDTable::initialize() { + const size_t start_size = 10; + // 2^24 is max size + const size_t end_size = 24; + // If a chain gets to 32 something might be wrong. + const size_t grow_hint = 32; + + _jmethod_id_table = new MethodIdTable(start_size, end_size, grow_hint); +} + +class JmethodIDLookup : StackObj { + private: + uint64_t _mid; + + public: + JmethodIDLookup(const uint64_t mid) : _mid(mid) {} + uintx get_hash() const { + return _mid; + } + bool equals(JmethodEntry* value) { + return _mid == value->_id; + } + + bool is_dead(JmethodEntry* value) { + return false; + } +}; + +static JmethodEntry* get_jmethod_entry(jmethodID mid) { + assert(mid != nullptr, "JNI method id should not be null"); + + Thread* current = Thread::current(); + JmethodIDLookup lookup((uint64_t)mid); + JmethodEntry* result = nullptr; + auto get = [&] (JmethodEntry* value) { + // function called if value is found so is never null + result = value; + }; + bool needs_rehashing = false; + _jmethod_id_table->get(current, lookup, get, &needs_rehashing); + assert(!needs_rehashing, "should never need rehashing"); + return result; +} + +Method* JmethodIDTable::resolve_jmethod_id(jmethodID mid) { + JmethodEntry* result = get_jmethod_entry(mid); + return result == nullptr ? nullptr : result->_method; +} + +const unsigned _resize_load_trigger = 5; // load factor that will trigger the resize + +static unsigned table_size(Thread* current) { + return 1 << _jmethod_id_table->get_size_log2(current); +} + +static bool needs_resize(Thread* current) { + return ((_jmethodID_entry_count > (_resize_load_trigger * table_size(current))) && + !_jmethod_id_table->is_max_size_reached()); +} + +// Add a method id to the jmethod_ids. +jmethodID JmethodIDTable::make_jmethod_id(Method* m) { + bool grow_hint, clean_hint; + + assert_locked_or_safepoint(JmethodIdCreation_lock); + // Update jmethodID global counter. + _jmethodID_counter++; + + JmethodEntry new_entry(_jmethodID_counter, m); + Thread* current = Thread::current(); + JmethodIDLookup lookup(_jmethodID_counter); + bool created = _jmethod_id_table->insert(current, lookup, new_entry, &grow_hint, &clean_hint); + assert(created, "must be"); + log_debug(jmethod)("Inserted jmethod id " UINT64_FORMAT_X, _jmethodID_counter); + // Increment number of entries in the table. + _jmethodID_entry_count++; + + // Resize table if it needs to grow. The _jmethod_id_table has a good distribution. + if (needs_resize(current)) { + _jmethod_id_table->grow(current); + log_info(jmethod)("Growing table to %d for " UINT64_FORMAT " entries", table_size(current), _jmethodID_counter); + } + return (jmethodID)_jmethodID_counter; +} + +void JmethodIDTable::remove(jmethodID jmid) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodIDLookup lookup((uint64_t)jmid); + Thread* current = Thread::current(); + JmethodEntry* result; + auto get = [&] (JmethodEntry* value) { + // The function that is called if value is found, so is never null. + result = value; + }; + bool removed = _jmethod_id_table->remove(current, lookup, get); + assert(removed, "must be"); + log_debug(jmethod)("Removed jmethod id " UINT64_FORMAT_X, (uint64_t)jmid); + // Decrement number of entries in the table. + _jmethodID_entry_count--; +} + +void JmethodIDTable::change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodEntry* result = get_jmethod_entry(jmid); + // Change table entry to point to the new method. + log_debug(jmethod)("Changed jmethod id " UINT64_FORMAT_X " from " PTR_FORMAT " to " PTR_FORMAT, (uint64_t)jmid, + p2i(result->_method), p2i(new_method)); + result->_method = new_method; +} + +void JmethodIDTable::clear_jmethod_id(jmethodID jmid, Method* obsolete_method) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodEntry* result = get_jmethod_entry(jmid); + // We need to make sure that jmethodID actually resolves to this method + // - multiple redefined versions may share jmethodID slots and if a method + // has already been rewired to a newer version we could be clearing + // the reference to a still existing method instance. + if (result->_method == obsolete_method) { + result->_method = nullptr; + } +} diff --git a/src/hotspot/share/oops/jmethodIDTable.hpp b/src/hotspot/share/oops/jmethodIDTable.hpp new file mode 100644 index 00000000000..cdbe5c87855 --- /dev/null +++ b/src/hotspot/share/oops/jmethodIDTable.hpp @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + * + */ + +#ifndef SHARE_OOPS_JMETHODIDTABLE_HPP +#define SHARE_OOPS_JMETHODIDTABLE_HPP + +#include "jni.h" +#include "memory/allocation.hpp" + +// Class for associating Method with jmethodID +class Method; + +class JmethodIDTable : public AllStatic { + public: + static void initialize(); + + // Given a Method return a jmethodID. + static jmethodID make_jmethod_id(Method* m); + + // Given a jmethodID, return a Method. + static Method* resolve_jmethod_id(jmethodID mid); + + // Class unloading support, remove the associations from the tables. Stale jmethodID will + // not be found and return null. + static void remove(jmethodID mid); + + // RedefineClasses support + static void change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method); + static void clear_jmethod_id(jmethodID jmid, Method* m); + + static uint64_t get_entry_count(); +}; + +#endif // SHARE_OOPS_JMETHODIDTABLE_HPP diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 23f13a475fb..546f3f05e08 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -732,17 +732,20 @@ void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_kla // Clean the implementors list and method data. if (clean_alive_klasses && current->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(current); - ik->clean_weak_instanceklass_links(); - - // JVMTI RedefineClasses creates previous versions that are not in - // the class hierarchy, so process them here. - while ((ik = ik->previous_versions()) != nullptr) { - ik->clean_weak_instanceklass_links(); - } + clean_weak_instanceklass_links(ik); } } } +void Klass::clean_weak_instanceklass_links(InstanceKlass* ik) { + ik->clean_weak_instanceklass_links(); + // JVMTI RedefineClasses creates previous versions that are not in + // the class hierarchy, so process them here. + while ((ik = ik->previous_versions()) != nullptr) { + ik->clean_weak_instanceklass_links(); + } +} + void Klass::metaspace_pointers_do(MetaspaceClosure* it) { if (log_is_enabled(Trace, aot)) { ResourceMark rm; @@ -879,7 +882,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec module_entry = ModuleEntryTable::javabase_moduleEntry(); } // Obtain java.lang.Module, if available - Handle module_handle(THREAD, ((module_entry != nullptr) ? module_entry->module() : (oop)nullptr)); + Handle module_handle(THREAD, ((module_entry != nullptr) ? module_entry->module_oop() : (oop)nullptr)); if (this->has_archived_mirror_index()) { ResourceMark rm(THREAD); diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index c48f3cd1476..576b7970247 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -755,6 +755,7 @@ class Klass : public Metadata { inline void set_prototype_header(markWord header); static ByteSize prototype_header_offset() { return in_ByteSize(offset_of(Klass, _prototype_header)); } static inline markWord default_prototype_header(Klass* k); + inline void set_prototype_header_klass(narrowKlass klass); JFR_ONLY(DEFINE_TRACE_ID_METHODS;) @@ -766,10 +767,10 @@ class Klass : public Metadata { void clean_subklass(); + // Clean out unnecessary weak klass links from the whole klass hierarchy. static void clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses = true); - static void clean_subklass_tree() { - clean_weak_klass_links(/*unloading_occurred*/ true , /* clean_alive_klasses */ false); - } + // Clean out unnecessary weak klass links from the given InstanceKlass. + static void clean_weak_instanceklass_links(InstanceKlass* ik); // Return self, except for abstract classes with exactly 1 // implementor. Then return the 1 concrete implementation. diff --git a/src/hotspot/share/oops/klass.inline.hpp b/src/hotspot/share/oops/klass.inline.hpp index c2ea52b6ab5..439e61c1b2e 100644 --- a/src/hotspot/share/oops/klass.inline.hpp +++ b/src/hotspot/share/oops/klass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -95,6 +95,10 @@ inline markWord Klass::default_prototype_header(Klass* k) { return (k == nullptr) ? markWord::prototype() : k->prototype_header(); } +inline void Klass::set_prototype_header_klass(narrowKlass klass) { + // Merge narrowKlass in existing prototype header. + _prototype_header = _prototype_header.set_narrow_klass(klass); +} // Loading the java_mirror does not keep its holder alive. See Klass::keep_alive(). inline oop Klass::java_mirror() const { diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp index ebbe77b01fe..91a960038e2 100644 --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -1180,38 +1180,42 @@ void klassItable::check_constraints(GrowableArray* supers, TRAPS) { Method* interface_method = supers->at(i); // method overridden if (target != nullptr && interface_method != nullptr) { - InstanceKlass* method_holder = target->method_holder(); - InstanceKlass* interf = interface_method->method_holder(); - HandleMark hm(THREAD); - Handle method_holder_loader(THREAD, method_holder->class_loader()); - Handle interface_loader(THREAD, interf->class_loader()); - - if (method_holder_loader() != interface_loader()) { - ResourceMark rm(THREAD); - Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(target->signature(), - _klass, - method_holder_loader, - interface_loader, - true); - if (failed_type_symbol != nullptr) { - stringStream ss; - ss.print("loader constraint violation in interface itable" - " initialization for class %s: when selecting method '", - _klass->external_name()); - interface_method->print_external_name(&ss), - ss.print("' the class loader %s for super interface %s, and the class" - " loader %s of the selected method's %s, %s have" - " different Class objects for the type %s used in the signature (%s; %s)", - interf->class_loader_data()->loader_name_and_id(), - interf->external_name(), - method_holder->class_loader_data()->loader_name_and_id(), - method_holder->external_kind(), - method_holder->external_name(), - failed_type_symbol->as_klass_external_name(), - interf->class_in_module_of_loader(false, true), - method_holder->class_in_module_of_loader(false, true)); - THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string()); + // Do not check loader constraints for overpass methods because overpass + // methods are created by the jvm to throw exceptions. + if (!target->is_overpass()) { + InstanceKlass* method_holder = target->method_holder(); + InstanceKlass* interf = interface_method->method_holder(); + HandleMark hm(THREAD); + Handle method_holder_loader(THREAD, method_holder->class_loader()); + Handle interface_loader(THREAD, interf->class_loader()); + + if (method_holder_loader() != interface_loader()) { + ResourceMark rm(THREAD); + Symbol* failed_type_symbol = + SystemDictionary::check_signature_loaders(target->signature(), + _klass, + method_holder_loader, + interface_loader, + true); + if (failed_type_symbol != nullptr) { + stringStream ss; + ss.print("loader constraint violation in interface itable" + " initialization for class %s: when selecting method '", + _klass->external_name()); + interface_method->print_external_name(&ss), + ss.print("' the class loader %s for super interface %s, and the class" + " loader %s of the selected method's %s, %s have" + " different Class objects for the type %s used in the signature (%s; %s)", + interf->class_loader_data()->loader_name_and_id(), + interf->external_name(), + method_holder->class_loader_data()->loader_name_and_id(), + method_holder->external_kind(), + method_holder->external_name(), + failed_type_symbol->as_klass_external_name(), + interf->class_in_module_of_loader(false, true), + method_holder->class_in_module_of_loader(false, true)); + THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string()); + } } } } @@ -1333,11 +1337,9 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Insta target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), Klass::PrivateLookupMode::skip); } - if (target == nullptr || !target->is_public() || target->is_abstract() || target->is_overpass()) { - assert(target == nullptr || !target->is_overpass() || target->is_public(), - "Non-public overpass method!"); + if (target == nullptr || !target->is_public() || target->is_abstract()) { // Entry does not resolve. Leave it empty for AbstractMethodError or other error. - if (!(target == nullptr) && !target->is_public()) { + if (target != nullptr && !target->is_public()) { // Stuff an IllegalAccessError throwing method in there instead. itableOffsetEntry::method_entry(_klass, method_table_offset)[m->itable_index()]. initialize(_klass, Universe::throw_illegal_access_error()); diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 0f87022eb1d..16bc1cba6eb 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -53,6 +53,7 @@ #include "nmt/memTracker.hpp" #include "oops/constMethod.hpp" #include "oops/constantPool.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "oops/methodData.hpp" @@ -2124,172 +2125,33 @@ void BreakpointInfo::clear(Method* method) { #endif // INCLUDE_JVMTI // jmethodID handling - -// This is a block allocating object, sort of like JNIHandleBlock, only a -// lot simpler. -// It's allocated on the CHeap because once we allocate a jmethodID, we can -// never get rid of it. - -static const int min_block_size = 8; - -class JNIMethodBlockNode : public CHeapObj { - friend class JNIMethodBlock; - Method** _methods; - int _number_of_methods; - int _top; - JNIMethodBlockNode* _next; - - public: - - JNIMethodBlockNode(int num_methods = min_block_size); - - ~JNIMethodBlockNode() { FREE_C_HEAP_ARRAY(Method*, _methods); } - - void ensure_methods(int num_addl_methods) { - if (_top < _number_of_methods) { - num_addl_methods -= _number_of_methods - _top; - if (num_addl_methods <= 0) { - return; - } - } - if (_next == nullptr) { - _next = new JNIMethodBlockNode(MAX2(num_addl_methods, min_block_size)); - } else { - _next->ensure_methods(num_addl_methods); - } - } -}; - -class JNIMethodBlock : public CHeapObj { - JNIMethodBlockNode _head; - JNIMethodBlockNode *_last_free; - public: - static Method* const _free_method; - - JNIMethodBlock(int initial_capacity = min_block_size) - : _head(initial_capacity), _last_free(&_head) {} - - void ensure_methods(int num_addl_methods) { - _last_free->ensure_methods(num_addl_methods); - } - - Method** add_method(Method* m) { - for (JNIMethodBlockNode* b = _last_free; b != nullptr; b = b->_next) { - if (b->_top < b->_number_of_methods) { - // top points to the next free entry. - int i = b->_top; - b->_methods[i] = m; - b->_top++; - _last_free = b; - return &(b->_methods[i]); - } else if (b->_top == b->_number_of_methods) { - // if the next free entry ran off the block see if there's a free entry - for (int i = 0; i < b->_number_of_methods; i++) { - if (b->_methods[i] == _free_method) { - b->_methods[i] = m; - _last_free = b; - return &(b->_methods[i]); - } - } - // Only check each block once for frees. They're very unlikely. - // Increment top past the end of the block. - b->_top++; - } - // need to allocate a next block. - if (b->_next == nullptr) { - b->_next = _last_free = new JNIMethodBlockNode(); - } - } - guarantee(false, "Should always allocate a free block"); - return nullptr; - } - - bool contains(Method** m) { - if (m == nullptr) return false; - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - if (b->_methods <= m && m < b->_methods + b->_number_of_methods) { - // This is a bit of extra checking, for two reasons. One is - // that contains() deals with pointers that are passed in by - // JNI code, so making sure that the pointer is aligned - // correctly is valuable. The other is that <= and > are - // technically not defined on pointers, so the if guard can - // pass spuriously; no modern compiler is likely to make that - // a problem, though (and if one did, the guard could also - // fail spuriously, which would be bad). - ptrdiff_t idx = m - b->_methods; - if (b->_methods + idx == m) { - return true; - } - } - } - return false; // not found - } - - // During class unloading the methods are cleared, which is different - // than freed. - void clear_all_methods() { - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - for (int i = 0; i< b->_number_of_methods; i++) { - b->_methods[i] = nullptr; - } - } - } -#ifndef PRODUCT - int count_methods() { - // count all allocated methods - int count = 0; - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - for (int i = 0; i< b->_number_of_methods; i++) { - if (b->_methods[i] != _free_method) count++; - } - } - return count; - } -#endif // PRODUCT -}; - -// Something that can't be mistaken for an address or a markWord -Method* const JNIMethodBlock::_free_method = (Method*)55; - -JNIMethodBlockNode::JNIMethodBlockNode(int num_methods) : _top(0), _next(nullptr) { - _number_of_methods = MAX2(num_methods, min_block_size); - _methods = NEW_C_HEAP_ARRAY(Method*, _number_of_methods, mtInternal); - for (int i = 0; i < _number_of_methods; i++) { - _methods[i] = JNIMethodBlock::_free_method; - } -} - -void Method::ensure_jmethod_ids(ClassLoaderData* cld, int capacity) { - // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock - // protects as well. - MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - if (cld->jmethod_ids() == nullptr) { - cld->set_jmethod_ids(new JNIMethodBlock(capacity)); - } else { - cld->jmethod_ids()->ensure_methods(capacity); - } -} +// jmethodIDs are 64-bit integers that will never run out and are mapped in a table +// to their Method and vice versa. If JNI code has access to stale jmethodID, this +// wastes no memory but the Method* returned is null. // Add a method id to the jmethod_ids jmethodID Method::make_jmethod_id(ClassLoaderData* cld, Method* m) { // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock + // Also have to add the method to the InstanceKlass list safely, which the lock // protects as well. assert(JmethodIdCreation_lock->owned_by_self(), "sanity check"); + jmethodID jmid = JmethodIDTable::make_jmethod_id(m); + assert(jmid != nullptr, "must be created"); - ResourceMark rm; - log_debug(jmethod)("Creating jmethodID for Method %s", m->external_name()); - if (cld->jmethod_ids() == nullptr) { - cld->set_jmethod_ids(new JNIMethodBlock()); - } - // jmethodID is a pointer to Method* - return (jmethodID)cld->jmethod_ids()->add_method(m); + // Add to growable array in CLD. + cld->add_jmethod_id(jmid); + return jmid; } +// This looks in the InstanceKlass cache, then calls back to make_jmethod_id if not found. jmethodID Method::jmethod_id() { - methodHandle mh(Thread::current(), this); - return method_holder()->get_jmethod_id(mh); + return method_holder()->get_jmethod_id(this); +} + +// Get the Method out of the table given the method id. +Method* Method::resolve_jmethod_id(jmethodID mid) { + assert(mid != nullptr, "JNI method id should not be null"); + return JmethodIDTable::resolve_jmethod_id(mid); } void Method::change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method) { @@ -2297,25 +2159,34 @@ void Method::change_method_associated_with_jmethod_id(jmethodID jmid, Method* ne // scratch method holder. assert(resolve_jmethod_id(jmid)->method_holder()->class_loader() == new_method->method_holder()->class_loader() || - new_method->method_holder()->class_loader() == nullptr, // allow Unsafe substitution + new_method->method_holder()->class_loader() == nullptr, // allow substitution to Unsafe method "changing to a different class loader"); - // Just change the method in place, jmethodID pointer doesn't change. - *((Method**)jmid) = new_method; + JmethodIDTable::change_method_associated_with_jmethod_id(jmid, new_method); } -bool Method::is_method_id(jmethodID mid) { +// If there's a jmethodID for this method, clear the Method +// but leave jmethodID for this method in the table. +// It's deallocated with class unloading. +void Method::clear_jmethod_id() { + jmethodID mid = method_holder()->jmethod_id_or_null(this); + if (mid != nullptr) { + JmethodIDTable::clear_jmethod_id(mid, this); + } +} + +bool Method::validate_jmethod_id(jmethodID mid) { Method* m = resolve_jmethod_id(mid); assert(m != nullptr, "should be called with non-null method"); InstanceKlass* ik = m->method_holder(); ClassLoaderData* cld = ik->class_loader_data(); if (cld->jmethod_ids() == nullptr) return false; - return (cld->jmethod_ids()->contains((Method**)mid)); + return (cld->jmethod_ids()->contains(mid)); } Method* Method::checked_resolve_jmethod_id(jmethodID mid) { if (mid == nullptr) return nullptr; Method* o = resolve_jmethod_id(mid); - if (o == nullptr || o == JNIMethodBlock::_free_method) { + if (o == nullptr) { return nullptr; } // Method should otherwise be valid. Assert for testing. @@ -2324,7 +2195,7 @@ Method* Method::checked_resolve_jmethod_id(jmethodID mid) { // unloaded, we need to return null here too because after a safepoint, its memory // will be reclaimed. return o->method_holder()->is_loader_alive() ? o : nullptr; -}; +} void Method::set_on_stack(const bool value) { // Set both the method itself and its constant pool. The constant pool @@ -2345,25 +2216,6 @@ void Method::record_gc_epoch() { constants()->cache()->record_gc_epoch(); } -// Called when the class loader is unloaded to make all methods weak. -void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { - loader_data->jmethod_ids()->clear_all_methods(); -} - -void Method::clear_jmethod_id() { - // Being at a safepoint prevents racing against other class redefinitions - assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); - // The jmethodID is not stored in the Method instance, we need to look it up first - jmethodID methodid = find_jmethod_id_or_null(); - // We need to make sure that jmethodID actually resolves to this method - // - multiple redefined versions may share jmethodID slots and if a method - // has already been rewired to a newer version we could be removing reference - // to a still existing method instance - if (methodid != nullptr && *((Method**)methodid) == this) { - *((Method**)methodid) = nullptr; - } -} - bool Method::has_method_vptr(const void* ptr) { Method m; // This assumes that the vtbl pointer is the first word of a C++ object. @@ -2413,13 +2265,6 @@ bool Method::is_scalarized_arg(int idx) const { return depth != 0; } -#ifndef PRODUCT -void Method::print_jmethod_ids_count(const ClassLoaderData* loader_data, outputStream* out) { - out->print("%d", loader_data->jmethod_ids()->count_methods()); -} -#endif // PRODUCT - - // Printing #ifndef PRODUCT diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index ee4ec09fdd9..2af24eb4b74 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -718,18 +718,10 @@ class Method : public Metadata { // refers to null (as is the case for any weak reference). static jmethodID make_jmethod_id(ClassLoaderData* cld, Method* mh); - // Ensure there is enough capacity in the internal tracking data - // structures to hold the number of jmethodIDs you plan to generate. - // This saves substantial time doing allocations. - static void ensure_jmethod_ids(ClassLoaderData* cld, int capacity); - // Use resolve_jmethod_id() in situations where the caller is expected // to provide a valid jmethodID; the only sanity checks are in asserts; // result guaranteed not to be null. - inline static Method* resolve_jmethod_id(jmethodID mid) { - assert(mid != nullptr, "JNI method id should not be null"); - return *((Method**)mid); - } + static Method* resolve_jmethod_id(jmethodID mid); // Use checked_resolve_jmethod_id() in situations where the caller // should provide a valid jmethodID, but might not. Null is returned @@ -737,10 +729,9 @@ class Method : public Metadata { static Method* checked_resolve_jmethod_id(jmethodID mid); static void change_method_associated_with_jmethod_id(jmethodID old_jmid_ptr, Method* new_method); - static bool is_method_id(jmethodID mid); + static bool validate_jmethod_id(jmethodID mid); - // Clear methods - static void clear_jmethod_ids(ClassLoaderData* loader_data); + // Clear jmethodID void clear_jmethod_id(); static void print_jmethod_ids_count(const ClassLoaderData* loader_data, outputStream* out) PRODUCT_RETURN; diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index 0d45300e590..736e3fa528b 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1927,7 +1927,7 @@ class CleanExtraDataMethodClosure : public CleanExtraDataClosure { }; Mutex* MethodData::extra_data_lock() { - Mutex* lock = Atomic::load(&_extra_data_lock); + Mutex* lock = Atomic::load_acquire(&_extra_data_lock); if (lock == nullptr) { // This lock could be acquired while we are holding DumpTimeTable_lock/nosafepoint lock = new Mutex(Mutex::nosafepoint-1, "MDOExtraData_lock"); diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index ddd8b78c06e..59b50ea0eb0 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -306,6 +306,7 @@ void ObjArrayKlass::metaspace_pointers_do(MetaspaceClosure* it) { } } +#if INCLUDE_CDS void ObjArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { ArrayKlass::restore_unshareable_info(loader_data, protection_domain, CHECK); if (_next_refined_array_klass != nullptr) { @@ -328,6 +329,7 @@ void ObjArrayKlass::remove_java_mirror() { _next_refined_array_klass->remove_java_mirror(); } } +#endif // INCLUDE_CDS u2 ObjArrayKlass::compute_modifier_flags() const { // The modifier for an objectArray is the same as its element diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp index 3e8c5a99772..9dd8768352c 100644 --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -101,9 +101,12 @@ class ObjArrayKlass : public ArrayKlass { oop protection_domain() const { return bottom_klass()->protection_domain(); } virtual void metaspace_pointers_do(MetaspaceClosure* iter); + +#if INCLUDE_CDS virtual void remove_unshareable_info(); virtual void remove_java_mirror(); void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); +#endif public: static ObjArrayKlass* cast(Klass* k) { diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index cc15fe944f2..e82a7a3e2bd 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -35,6 +35,7 @@ #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" +#include "memory/universe.hpp" #include "oops/method.hpp" #include "oops/methodCounters.hpp" #include "oops/trainingData.hpp" @@ -433,9 +434,9 @@ void KlassTrainingData::print_on(outputStream* st, bool name_only) const { KlassTrainingData::KlassTrainingData(InstanceKlass* klass) : TrainingData(klass) { assert(klass != nullptr, ""); - Handle hm(JavaThread::current(), klass->java_mirror()); - jobject hmj = JNIHandles::make_global(hm); - _holder_mirror = hmj; + // The OopHandle constructor will allocate a handle. We don't need to ever release it so we don't preserve + // the handle object. + OopHandle handle(Universe::vm_global(), klass->java_mirror()); _holder = klass; assert(holder() == klass, ""); } @@ -759,7 +760,6 @@ void TrainingData::DepList::prepare(ClassLoaderData* loader_data) { void KlassTrainingData::remove_unshareable_info() { TrainingData::remove_unshareable_info(); - _holder_mirror = nullptr; _comp_deps.remove_unshareable_info(); } diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index 6acf19b4d5e..1d03056871b 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -431,7 +431,6 @@ class KlassTrainingData : public TrainingData { // cross-link to live klass, or null if not loaded or encountered yet InstanceKlass* _holder; - jobject _holder_mirror; // extra link to prevent unloading by GC DepList _comp_deps; // compiles that depend on me @@ -454,7 +453,6 @@ class KlassTrainingData : public TrainingData { TrainingDataLocker::assert_locked(); _comp_deps.remove_if_existing(ctd); } - public: Symbol* name() const { precond(has_holder()); diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index da668f052a9..4991fe73ae7 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -58,6 +58,9 @@ product(bool, StressMacroExpansion, false, DIAGNOSTIC, \ "Randomize macro node expansion order") \ \ + product(bool, StressMacroElimination, false, DIAGNOSTIC, \ + "Randomize macro node elimination order") \ + \ product(bool, StressUnstableIfTraps, false, DIAGNOSTIC, \ "Randomly take unstable if traps") \ \ @@ -262,6 +265,10 @@ develop(bool, OptoCoalesce, true, \ "Use Conservative Copy Coalescing in the Register Allocator") \ \ + product(uint, IFGEdgesLimit, 10000000, DIAGNOSTIC, \ + "Maximum allowed edges in the interference graphs") \ + range(0, max_juint) \ + \ develop(bool, UseUniqueSubclasses, true, \ "Narrow an abstract reference to the unique concrete subclass") \ \ diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index d581d2c15e4..6f37c879732 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1652,14 +1652,8 @@ void SafePointNode::push_monitor(const FastLockNode *lock) { assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); assert(req() == jvms()->endoff(), "correct sizing"); int nextmon = jvms()->scloff(); - if (GenerateSynchronizationCode) { - ins_req(nextmon, lock->box_node()); - ins_req(nextmon+1, lock->obj_node()); - } else { - Node* top = Compile::current()->top(); - ins_req(nextmon, top); - ins_req(nextmon, top); - } + ins_req(nextmon, lock->box_node()); + ins_req(nextmon+1, lock->obj_node()); jvms()->set_scloff(nextmon + MonitorEdges); jvms()->set_endoff(req()); } diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 3e773683f69..ea78051c5c4 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -329,6 +329,7 @@ class JVMState : public ResourceObj { class SafePointNode : public MultiNode { friend JVMState; friend class GraphKit; + friend class LibraryCallKit; virtual bool cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 3c736e66dba..e5f8f032250 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -429,6 +429,9 @@ void PhaseChaitin::Register_Allocate() { // Create the interference graph using virtual copies build_ifg_virtual(); // Include stack slots this time + if (C->failing()) { + return; + } // The IFG is/was triangular. I am 'squaring it up' so Union can run // faster. Union requires a 'for all' operation which is slow on the @@ -472,6 +475,9 @@ void PhaseChaitin::Register_Allocate() { // Build physical interference graph uint must_spill = 0; must_spill = build_ifg_physical(&live_arena); + if (C->failing()) { + return; + } // If we have a guaranteed spill, might as well spill now if (must_spill) { if(!_lrg_map.max_lrg_id()) { @@ -513,6 +519,9 @@ void PhaseChaitin::Register_Allocate() { C->print_method(PHASE_INITIAL_SPILLING, 4); build_ifg_physical(&live_arena); + if (C->failing()) { + return; + } _ifg->SquareUp(); _ifg->Compute_Effective_Degree(); // Only do conservative coalescing if requested @@ -596,6 +605,9 @@ void PhaseChaitin::Register_Allocate() { C->print_method(PHASE_ITERATIVE_SPILLING, 4); must_spill = build_ifg_physical(&live_arena); + if (C->failing()) { + return; + } _ifg->SquareUp(); _ifg->Compute_Effective_Degree(); diff --git a/src/hotspot/share/opto/chaitin.hpp b/src/hotspot/share/opto/chaitin.hpp index cc3d3479c81..ad172f672b4 100644 --- a/src/hotspot/share/opto/chaitin.hpp +++ b/src/hotspot/share/opto/chaitin.hpp @@ -246,6 +246,9 @@ class PhaseIFG : public Phase { // Live range structure goes here LRG *_lrgs; // Array of LRG structures + // Keep track of number of edges to allow bailing out on very large IFGs + uint _edges; + public: // Largest live-range number uint _maxlrg; diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index caed130e8de..ba5bbd8c047 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -650,7 +650,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _ilt(nullptr), _stub_function(nullptr), _stub_name(nullptr), - _stub_id(-1), + _stub_id(StubId::NO_STUBID), _stub_entry_point(nullptr), _max_node_limit(MaxNodeLimit), _post_loop_opts_phase(false), @@ -752,8 +752,9 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, } if (StressLCM || StressGCM || StressIGVN || StressCCP || - StressIncrementalInlining || StressMacroExpansion || StressUnstableIfTraps || StressBailout || - StressLoopPeeling) { + StressIncrementalInlining || StressMacroExpansion || + StressMacroElimination || StressUnstableIfTraps || + StressBailout || StressLoopPeeling) { initialize_stress_seed(directive); } @@ -921,7 +922,7 @@ Compile::Compile(ciEnv* ci_env, TypeFunc_generator generator, address stub_function, const char* stub_name, - int stub_id, + StubId stub_id, int is_fancy_jump, bool pass_tls, bool return_pc, @@ -988,7 +989,8 @@ Compile::Compile(ciEnv* ci_env, // try to reuse an existing stub { - CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, _stub_id, stub_name); + BlobId blob_id = StubInfo::blob(_stub_id); + CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, blob_id); if (blob != nullptr) { RuntimeStub* rs = blob->as_runtime_stub(); _stub_entry_point = rs->entry_point(); @@ -2924,6 +2926,8 @@ void Compile::Optimize() { if (failing()) { return; } + print_method(PHASE_AFTER_MACRO_ELIMINATION, 2); + igvn.set_delay_transform(false); print_method(PHASE_ITER_GVN_AFTER_ELIMINATION, 2); } @@ -3033,6 +3037,18 @@ void Compile::Optimize() { } print_method(PHASE_BEFORE_MACRO_EXPANSION, 3); + // Do not allow new macro nodes once we start to eliminate and expand + C->reset_allow_macro_nodes(); + // Last attempt to eliminate macro nodes before expand + mex.eliminate_macro_nodes(); + if (failing()) { + return; + } + mex.eliminate_opaque_looplimit_macro_nodes(); + if (failing()) { + return; + } + print_method(PHASE_AFTER_MACRO_ELIMINATION, 2); if (mex.expand_macro_nodes()) { assert(failing(), "must bail out w/ explicit message"); return; diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index a4de2a35aa1..e648927854f 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -310,7 +310,7 @@ class Compile : public Phase { InlineTree* _ilt; // Ditto (temporary). address _stub_function; // VM entry for stub being compiled, or null const char* _stub_name; // Name of stub or adapter being compiled, or null - int _stub_id; // unique id for stub or -1 + StubId _stub_id; // unique id for stub or NO_STUBID address _stub_entry_point; // Compile code entry for generated stub, or null // Control of this compilation. @@ -579,7 +579,7 @@ class Compile : public Phase { InlineTree* ilt() const { return _ilt; } address stub_function() const { return _stub_function; } const char* stub_name() const { return _stub_name; } - int stub_id() const { return _stub_id; } + StubId stub_id() const { return _stub_id; } address stub_entry_point() const { return _stub_entry_point; } void set_stub_entry_point(address z) { _stub_entry_point = z; } @@ -1171,7 +1171,7 @@ class Compile : public Phase { // convention. Compile(ciEnv* ci_env, const TypeFunc *(*gen)(), address stub_function, const char *stub_name, - int stub_id, int is_fancy_jump, bool pass_tls, + StubId stub_id, int is_fancy_jump, bool pass_tls, bool return_pc, DirectiveSet* directive); ~Compile(); diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp index f162d534f52..5d95644df2a 100644 --- a/src/hotspot/share/opto/convertnode.cpp +++ b/src/hotspot/share/opto/convertnode.cpp @@ -272,8 +272,68 @@ Node* ConvF2HFNode::Ideal(PhaseGVN* phase, bool can_reshape) { return new ReinterpretHF2SNode(binop); } } + + // Detects following ideal graph pattern + // ConvF2HF(binopF(conF, ConvHF2F(varS))) => + // ReinterpretHF2SNode(binopHF(conHF, ReinterpretS2HFNode(varS))) + if (Float16NodeFactory::is_float32_binary_oper(in(1)->Opcode())) { + Node* binopF = in(1); + // Check if the incoming binary operation has one floating point constant + // input and the other input is a half precision to single precision upcasting node. + // We land here because a prior HalfFloat to Float conversion promotes + // an integral constant holding Float16 value to a floating point constant. + // i.e. ConvHF2F ConI(short) => ConF + Node* conF = nullptr; + Node* varS = nullptr; + if (binopF->in(1)->is_Con() && binopF->in(2)->Opcode() == Op_ConvHF2F) { + conF = binopF->in(1); + varS = binopF->in(2)->in(1); + } else if (binopF->in(2)->is_Con() && binopF->in(1)->Opcode() == Op_ConvHF2F) { + conF = binopF->in(2); + varS = binopF->in(1)->in(1); + } + + if (conF != nullptr && + varS != nullptr && + conF->bottom_type()->isa_float_constant() != nullptr && + Matcher::match_rule_supported(Float16NodeFactory::get_float16_binary_oper(binopF->Opcode())) && + Matcher::match_rule_supported(Op_ReinterpretS2HF) && + Matcher::match_rule_supported(Op_ReinterpretHF2S) && + StubRoutines::hf2f_adr() != nullptr && + StubRoutines::f2hf_adr() != nullptr) { + jfloat con = conF->bottom_type()->getf(); + // Conditions under which floating point constant can be considered for a pattern match. + // 1. conF must lie within Float16 value range, otherwise we would have rounding issues: + // Doing the operation in float32 and then rounding is not the same as + // rounding first and doing the operation in float16. + // 2. If a constant value is one of the valid IEEE 754 binary32 NaN bit patterns + // then it's safe to consider it for pattern match because of the following reasons: + // a. As per section 2.8 of JVMS, Java Virtual Machine does not support + // signaling NaN value. + // b. Any signaling NaN which takes part in a non-comparison expression + // results in a quiet NaN but preserves the significand bits of signaling NaN. + // c. The pattern being matched includes a Float to Float16 conversion after binary + // expression, this downcast will still preserve the significand bits of binary32 NaN. + bool isnan = g_isnan((jdouble)con); + if (StubRoutines::hf2f(StubRoutines::f2hf(con)) == con || isnan) { + Node* newVarHF = phase->transform(new ReinterpretS2HFNode(varS)); + Node* conHF = phase->makecon(TypeH::make(con)); + Node* binopHF = nullptr; + // Preserving original input order for semantic correctness + // of non-commutative operation. + if (binopF->in(1) == conF) { + binopHF = phase->transform(Float16NodeFactory::make(binopF->Opcode(), binopF->in(0), conHF, newVarHF)); + } else { + binopHF = phase->transform(Float16NodeFactory::make(binopF->Opcode(), binopF->in(0), newVarHF, conHF)); + } + return new ReinterpretHF2SNode(binopHF); + } + } + } + return nullptr; } + //============================================================================= //------------------------------Value------------------------------------------ const Type* ConvF2INode::Value(PhaseGVN* phase) const { diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index c566564b14d..4974fab2aba 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -823,37 +823,32 @@ const Type* DivHFNode::Value(PhaseGVN* phase) const { return bot; } - // x/x == 1, we ignore 0/0. - // Note: if t1 and t2 are zero then result is NaN (JVMS page 213) - // Does not work for variables because of NaN's - if (in(1) == in(2) && t1->base() == Type::HalfFloatCon && - !g_isnan(t1->getf()) && g_isfinite(t1->getf()) && t1->getf() != 0.0) { // could be negative ZERO or NaN - return TypeH::ONE; - } - - if (t2 == TypeH::ONE) { - return t1; - } - - // If divisor is a constant and not zero, divide the numbers if (t1->base() == Type::HalfFloatCon && - t2->base() == Type::HalfFloatCon && - t2->getf() != 0.0) { - // could be negative zero - return TypeH::make(t1->getf() / t2->getf()); - } + t2->base() == Type::HalfFloatCon) { + // IEEE 754 floating point comparison treats 0.0 and -0.0 as equals. - // If the dividend is a constant zero - // Note: if t1 and t2 are zero then result is NaN (JVMS page 213) - // Test TypeHF::ZERO is not sufficient as it could be negative zero + // Division of a zero by a zero results in NaN. + if (t1->getf() == 0.0f && t2->getf() == 0.0f) { + return TypeH::make(NAN); + } - if (t1 == TypeH::ZERO && !g_isnan(t2->getf()) && t2->getf() != 0.0) { - return TypeH::ZERO; - } + // As per C++ standard section 7.6.5 (expr.mul), behavior is undefined only if + // the second operand is 0.0. In all other situations, we can expect a standard-compliant + // C++ compiler to generate code following IEEE 754 semantics. + if (t2->getf() == 0.0) { + // If either operand is NaN, the result is NaN + if (g_isnan(t1->getf())) { + return TypeH::make(NAN); + } else { + // Division of a nonzero finite value by a zero results in a signed infinity. Also, + // division of an infinity by a finite value results in a signed infinity. + bool res_sign_neg = (jint_cast(t1->getf()) < 0) ^ (jint_cast(t2->getf()) < 0); + const TypeF* res = res_sign_neg ? TypeF::NEG_INF : TypeF::POS_INF; + return TypeH::make(res->getf()); + } + } - // If divisor or dividend is nan then result is nan. - if (g_isnan(t1->getf()) || g_isnan(t2->getf())) { - return TypeH::make(NAN); + return TypeH::make(t1->getf() / t2->getf()); } // Otherwise we give up all hope diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 6fca439d8da..f11343e9e23 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -3343,10 +3343,12 @@ void ConnectionGraph::optimize_ideal_graph(GrowableArray& ptr_cmp_worklis // Optimize objects compare. const TypeInt* ConnectionGraph::optimize_ptr_compare(Node* left, Node* right) { - assert(OptimizePtrCompare, "sanity"); + const TypeInt* UNKNOWN = TypeInt::CC; // [-1, 0,1] + if (!OptimizePtrCompare) { + return UNKNOWN; + } const TypeInt* EQ = TypeInt::CC_EQ; // [0] == ZERO const TypeInt* NE = TypeInt::CC_GT; // [1] == ONE - const TypeInt* UNKNOWN = TypeInt::CC; // [-1, 0,1] PointsToNode* ptn1 = ptnode_adr(left->_idx); PointsToNode* ptn2 = ptnode_adr(right->_idx); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 4cb6d82e42f..5fedaf1d6d9 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -3953,9 +3953,6 @@ FastLockNode* GraphKit::shared_lock(Node* obj) { // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces assert(SynchronizationEntryBCI == InvocationEntryBci, ""); - if( !GenerateSynchronizationCode ) - return nullptr; // Not locking things? - if (stopped()) // Dead monitor? return nullptr; @@ -4018,8 +4015,6 @@ void GraphKit::shared_unlock(Node* box, Node* obj) { // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces assert(SynchronizationEntryBCI == InvocationEntryBci, ""); - if( !GenerateSynchronizationCode ) - return; if (stopped()) { // Dead monitor? map()->pop_monitor(); // Kill monitor from debug info return; diff --git a/src/hotspot/share/opto/ifg.cpp b/src/hotspot/share/opto/ifg.cpp index 3793983b62a..0807f8ea5fe 100644 --- a/src/hotspot/share/opto/ifg.cpp +++ b/src/hotspot/share/opto/ifg.cpp @@ -43,6 +43,7 @@ PhaseIFG::PhaseIFG( Arena *arena ) : Phase(Interference_Graph), _arena(arena) { void PhaseIFG::init( uint maxlrg ) { _maxlrg = maxlrg; + _edges = 0; _yanked = new (_arena) VectorSet(_arena); _is_square = false; // Make uninitialized adjacency lists @@ -65,7 +66,12 @@ int PhaseIFG::add_edge( uint a, uint b ) { // Sort a and b, so that a is bigger assert( !_is_square, "only on triangular" ); if( a < b ) { uint tmp = a; a = b; b = tmp; } - return _adjs[a].insert( b ); + int ret = _adjs[a].insert(b); + _edges += ret; + if (_edges > IFGEdgesLimit) { + C->record_method_not_compilable("out of IFG edges"); + } + return ret; } // Is there an edge between a and b? @@ -299,6 +305,9 @@ void PhaseChaitin::interfere_with_live(uint lid, IndexSet* liveout) { LRG& interfering_lrg = lrgs(interfering_lid); if (rm.overlap(interfering_lrg.mask())) { _ifg->add_edge(lid, interfering_lid); + if (C->failing()) { + return; + } } interfering_lid = elements.next(); } @@ -348,6 +357,9 @@ void PhaseChaitin::build_ifg_virtual( ) { // Interfere with everything live interfere_with_live(r, liveout); + if (C->failing()) { + return; + } } // Make all inputs live @@ -391,6 +403,9 @@ void PhaseChaitin::build_ifg_virtual( ) { uint kidx = _lrg_map.live_range_id(n->in(k)); if (kidx != lidx) { _ifg->add_edge(r, kidx); + if (C->failing()) { + return; + } } } } @@ -917,6 +932,9 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { remove_bound_register_from_interfering_live_ranges(lrg, &liveout, must_spill); } interfere_with_live(lid, &liveout); + if (C->failing()) { + return 0; + } } // Area remaining in the block diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index aa162d6503b..4bca8afb4c7 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -146,6 +146,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { // The intrinsic bailed out assert(ctrl == kit.control(), "Control flow was added although the intrinsic bailed out"); + assert(jvms->map() == kit.map(), "Out of sync JVM state"); if (jvms->has_method()) { // Not a root compile. const char* msg; @@ -1745,18 +1746,15 @@ bool LibraryCallKit::inline_string_char_access(bool is_store) { } // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); value = must_be_not_null(value, true); Node* adr = array_element_address(value, index, T_CHAR); if (adr->is_top()) { - set_map(old_map); - set_sp(old_sp); return false; } - destruct_map_clone(old_map); + old_state.discard(); if (is_store) { access_store_at(value, adr, TypeAryPtr::BYTES, ch, TypeInt::CHAR, T_CHAR, IN_HEAP | MO_UNORDERED | C2_MISMATCHED); } else { @@ -2400,6 +2398,47 @@ DecoratorSet LibraryCallKit::mo_decorator_for_access_kind(AccessKind kind) { } } +LibraryCallKit::SavedState::SavedState(LibraryCallKit* kit) : + _kit(kit), + _sp(kit->sp()), + _jvms(kit->jvms()), + _map(kit->clone_map()), + _discarded(false) +{ + for (DUIterator_Fast imax, i = kit->control()->fast_outs(imax); i < imax; i++) { + Node* out = kit->control()->fast_out(i); + if (out->is_CFG()) { + _ctrl_succ.push(out); + } + } +} + +LibraryCallKit::SavedState::~SavedState() { + if (_discarded) { + _kit->destruct_map_clone(_map); + return; + } + _kit->jvms()->set_map(_map); + _kit->jvms()->set_sp(_sp); + _map->set_jvms(_kit->jvms()); + _kit->set_map(_map); + _kit->set_sp(_sp); + for (DUIterator_Fast imax, i = _kit->control()->fast_outs(imax); i < imax; i++) { + Node* out = _kit->control()->fast_out(i); + if (out->is_CFG() && out->in(0) == _kit->control() && out != _kit->map() && !_ctrl_succ.member(out)) { + _kit->_gvn.hash_delete(out); + out->set_req(0, _kit->C->top()); + _kit->C->record_for_igvn(out); + --i; --imax; + _kit->_gvn.hash_find_insert(out); + } + } +} + +void LibraryCallKit::SavedState::discard() { + _discarded = true; +} + bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, const AccessKind kind, const bool unaligned, const bool is_flat) { if (callee()->is_static()) return false; // caller must have the capability! DecoratorSet decorators = C2_UNSAFE_ACCESS; @@ -2510,8 +2549,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c offset = ConvL2X(offset); // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); Node* adr = make_unsafe_address(base, offset, type, kind == Relaxed); assert(!stopped(), "Inlining of unsafe access failed: address construction stopped unexpectedly"); @@ -2520,8 +2558,6 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c if (type != T_OBJECT && (inline_klass == nullptr || !inline_klass->has_object_fields())) { decorators |= IN_NATIVE; // off-heap primitive access } else { - set_map(old_map); - set_sp(old_sp); return false; // off-heap oop accesses are not supported } } else { @@ -2539,8 +2575,6 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c const TypePtr* adr_type = _gvn.type(adr)->isa_ptr(); if (adr_type == TypePtr::NULL_PTR) { - set_map(old_map); - set_sp(old_sp); return false; // off-heap access with zero address } @@ -2550,8 +2584,6 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c if (alias_type->adr_type() == TypeInstPtr::KLASS || alias_type->adr_type() == TypeAryPtr::RANGE) { - set_map(old_map); - set_sp(old_sp); return false; // not supported } @@ -2598,8 +2630,6 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c } if ((bt == T_OBJECT) != (type == T_OBJECT)) { // Don't intrinsify mismatched object accesses - set_map(old_map); - set_sp(old_sp); return false; } mismatched = (bt != type); @@ -2623,15 +2653,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c if (is_store) { const Type* val_t = _gvn.type(val); if (!val_t->is_inlinetypeptr() || val_t->inline_klass() != inline_klass) { - set_map(old_map); - set_sp(old_sp); return false; } } } - destruct_map_clone(old_map); - assert(!mismatched || is_flat || alias_type->adr_type()->is_oopptr(), "off-heap access can't be mismatched"); + old_state.discard(); + assert(!mismatched || alias_type->adr_type()->is_oopptr(), "off-heap access can't be mismatched"); if (mismatched) { decorators |= C2_MISMATCHED; @@ -3116,8 +3144,7 @@ bool LibraryCallKit::inline_unsafe_load_store(const BasicType type, const LoadSt // 32-bit machines ignore the high half of long offsets offset = ConvL2X(offset); // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); Node* adr = make_unsafe_address(base, offset,type, false); const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); @@ -3126,12 +3153,10 @@ bool LibraryCallKit::inline_unsafe_load_store(const BasicType type, const LoadSt if (bt != T_ILLEGAL && (is_reference_type(bt) != (type == T_OBJECT))) { // Don't intrinsify mismatched object accesses. - set_map(old_map); - set_sp(old_sp); return false; } - destruct_map_clone(old_map); + old_state.discard(); // For CAS, unlike inline_unsafe_access, there seems no point in // trying to refine types. Just use the coarse types here. diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index adbdc9d0121..645f1a0d7b8 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_OPTO_LIBRARY_CALL_HPP +#define SHARE_OPTO_LIBRARY_CALL_HPP + #include "ci/ciMethod.hpp" #include "classfile/javaClasses.hpp" #include "opto/callGenerator.hpp" @@ -135,6 +138,29 @@ class LibraryCallKit : public GraphKit { virtual int reexecute_sp() { return _reexecute_sp; } + /* When an intrinsic makes changes before bailing out, it's necessary to restore the graph + * as it was. See JDK-8359344 for what can happen wrong. It's also not always possible to + * bailout before making changes because the bailing out decision might depend on new nodes + * (their types, for instance). + * + * So, if an intrinsic might cause this situation, one must start by saving the state in a + * SavedState by constructing it, and the state will be restored on destruction. If the + * intrinsic is not bailing out, one need to call discard to prevent restoring the old state. + */ + class SavedState { + LibraryCallKit* _kit; + uint _sp; + JVMState* _jvms; + SafePointNode* _map; + Unique_Node_List _ctrl_succ; + bool _discarded; + + public: + SavedState(LibraryCallKit*); + ~SavedState(); + void discard(); + }; + // Helper functions to inline natives Node* generate_guard(Node* test, RegionNode* region, float true_prob); Node* generate_slow_guard(Node* test, RegionNode* region); @@ -443,3 +469,4 @@ class LibraryCallKit : public GraphKit { bool inline_blackhole(); }; +#endif // SHARE_OPTO_LIBRARY_CALL_HPP diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index afe6a076268..cc680f66b62 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -862,7 +862,7 @@ bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop* phase) const { uint trip_count = cl->trip_count(); // Note, max_juint is used to indicate unknown trip count. - assert(trip_count > 1, "one iteration loop should be optimized out already"); + assert(trip_count > 1, "one-iteration loop should be optimized out already"); assert(trip_count < max_juint, "exact trip_count should be less than max_juint."); // If nodes are depleted, some transform has miscalculated its needs. @@ -1399,6 +1399,7 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n CountedLoopNode *post_head = nullptr; Node* post_incr = incr; Node* main_exit = insert_post_loop(loop, old_new, main_head, main_end, post_incr, limit, post_head); + C->print_method(PHASE_AFTER_POST_LOOP, 4, post_head); //------------------------------ // Step B: Create Pre-Loop. @@ -1613,8 +1614,10 @@ void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old Node *limit = main_end->limit(); // In this case we throw away the result as we are not using it to connect anything else. + C->print_method(PHASE_BEFORE_POST_LOOP, 4, main_head); CountedLoopNode *post_head = nullptr; insert_post_loop(loop, old_new, main_head, main_end, incr, limit, post_head); + C->print_method(PHASE_AFTER_POST_LOOP, 4, post_head); // It's difficult to be precise about the trip-counts // for post loops. They are usually very short, @@ -3077,6 +3080,7 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) { return false; } } + phase->C->print_method(PHASE_BEFORE_REMOVE_EMPTY_LOOP, 4, cl); if (cl->is_pre_loop()) { // If the loop we are removing is a pre-loop then the main and post loop // can be removed as well. @@ -3179,6 +3183,7 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) { phase->_igvn.replace_input_of(cl->loopexit(), CountedLoopEndNode::TestValue, zero); phase->C->set_major_progress(); + phase->C->print_method(PHASE_AFTER_REMOVE_EMPTY_LOOP, 4, final_iv); return true; } @@ -3314,7 +3319,7 @@ void IdealLoopTree::collect_loop_core_nodes(PhaseIdealLoop* phase, Unique_Node_L } //------------------------------do_one_iteration_loop-------------------------- -// Convert one iteration loop into normal code. +// Convert one-iteration loop into normal code. bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) { if (!_head->as_Loop()->is_valid_counted_loop(T_INT)) { return false; // Only for counted loop @@ -3331,6 +3336,7 @@ bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) { } #endif + phase->C->print_method(PHASE_BEFORE_ONE_ITERATION_LOOP, 4, cl); Node *init_n = cl->init_trip(); // Loop boundaries should be constant since trip count is exact. assert((cl->stride_con() > 0 && init_n->get_int() + cl->stride_con() >= cl->limit()->get_int()) || @@ -3340,6 +3346,7 @@ bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) { // and all loop-invariant uses of the exit values will be correct. phase->_igvn.replace_node(cl->phi(), cl->init_trip()); phase->C->set_major_progress(); + phase->C->print_method(PHASE_AFTER_ONE_ITERATION_LOOP, 4, init_n); return true; } @@ -3354,7 +3361,7 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n // Compute loop trip count if possible. compute_trip_count(phase); - // Convert one iteration loop into normal code. + // Convert one-iteration loop into normal code. if (do_one_iteration_loop(phase)) { return true; } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 31707625048..9e81e1ca22b 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -746,7 +746,7 @@ class IdealLoopTree : public ResourceObj { // Micro-benchmark spamming. Remove empty loops. bool do_remove_empty_loop( PhaseIdealLoop *phase ); - // Convert one iteration loop into normal code. + // Convert one-iteration loop into normal code. bool do_one_iteration_loop( PhaseIdealLoop *phase ); // Return TRUE or FALSE if the loop should be peeled or not. Peel if we can diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 494f9b9b04a..6a61c12861a 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -4518,6 +4518,7 @@ bool PhaseIdealLoop::duplicate_loop_backedge(IdealLoopTree *loop, Node_List &old } } } + C->print_method(PHASE_BEFORE_DUPLICATE_LOOP_BACKEDGE, 4, head); // Collect data nodes that need to be clones as well int dd = dom_depth(head); @@ -4608,6 +4609,8 @@ bool PhaseIdealLoop::duplicate_loop_backedge(IdealLoopTree *loop, Node_List &old C->set_major_progress(); + C->print_method(PHASE_AFTER_DUPLICATE_LOOP_BACKEDGE, 4, outer_head); + return true; } diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 790d3124dd8..94cf2194002 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -86,14 +86,9 @@ int PhaseMacroExpand::replace_input(Node *use, Node *oldref, Node *newref) { return nreplacements; } -Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) { - Node* cmp; - if (mask != 0) { - Node* and_node = transform_later(new AndXNode(word, MakeConX(mask))); - cmp = transform_later(new CmpXNode(and_node, MakeConX(bits))); - } else { - cmp = word; - } + +Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word) { + Node* cmp = word; Node* bol = transform_later(new BoolNode(cmp, BoolTest::ne)); IfNode* iff = new IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); transform_later(iff); @@ -104,13 +99,8 @@ Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* // Fast path not-taken, i.e. slow path Node *slow_taken = transform_later(new IfTrueNode(iff)); - if (return_fast_path) { - region->init_req(edge, slow_taken); // Capture slow-control - return fast_taken; - } else { region->init_req(edge, fast_taken); // Capture fast-control return slow_taken; - } } //--------------------copy_predefined_input_for_runtime_call-------------------- @@ -2512,7 +2502,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); // Optimize test; set region slot 2 - slow_path = opt_bits_test(ctrl, region, 2, flock, 0, 0); + slow_path = opt_bits_test(ctrl, region, 2, flock); mem_phi->init_req(2, mem); // Make slow path call @@ -2573,7 +2563,7 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { FastUnlockNode *funlock = new FastUnlockNode( ctrl, obj, box ); funlock = transform_later( funlock )->as_FastUnlock(); // Optimize test; set region slot 2 - Node *slow_path = opt_bits_test(ctrl, region, 2, funlock, 0, 0); + Node *slow_path = opt_bits_test(ctrl, region, 2, funlock); Node *thread = transform_later(new ThreadLocalNode()); CallNode *call = make_slow_call((CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), @@ -2982,6 +2972,10 @@ void PhaseMacroExpand::eliminate_macro_nodes(bool eliminate_locks) { if (C->macro_count() == 0) { return; } + + if (StressMacroElimination) { + C->shuffle_macro_nodes(); + } NOT_PRODUCT(int membar_before = count_MemBar(C);) int iteration = 0; @@ -3071,6 +3065,9 @@ void PhaseMacroExpand::eliminate_macro_nodes(bool eliminate_locks) { } assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); progress = progress || success; + if (success) { + C->print_method(PHASE_AFTER_MACRO_ELIMINATION_STEP, 5, n); + } } // Ensure the graph after PhaseMacroExpand::eliminate_macro_nodes is canonical (no igvn @@ -3097,16 +3094,11 @@ void PhaseMacroExpand::eliminate_macro_nodes(bool eliminate_locks) { #endif } -//------------------------------expand_macro_nodes---------------------- -// Returns true if a failure occurred. -bool PhaseMacroExpand::expand_macro_nodes() { - refine_strip_mined_loop_macro_nodes(); - // Do not allow new macro nodes once we started to expand - C->reset_allow_macro_nodes(); - if (StressMacroExpansion) { - C->shuffle_macro_nodes(); +void PhaseMacroExpand::eliminate_opaque_looplimit_macro_nodes() { + if (C->macro_count() == 0) { + return; } - + refine_strip_mined_loop_macro_nodes(); // Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations. bool progress = true; while (progress) { @@ -3171,10 +3163,18 @@ bool PhaseMacroExpand::expand_macro_nodes() { assert(!success || (C->macro_count() == (old_macro_count - 1)), "elimination must have deleted one node from macro list"); progress = progress || success; if (success) { - C->print_method(PHASE_AFTER_MACRO_EXPANSION_STEP, 5, n); + C->print_method(PHASE_AFTER_MACRO_ELIMINATION_STEP, 5, n); } } } +} + +//------------------------------expand_macro_nodes---------------------- +// Returns true if a failure occurred. +bool PhaseMacroExpand::expand_macro_nodes() { + if (StressMacroExpansion) { + C->shuffle_macro_nodes(); + } // Clean up the graph so we're less likely to hit the maximum node // limit diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index 709f96ca5eb..319974bea14 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -204,7 +204,7 @@ class PhaseMacroExpand : public Phase { int replace_input(Node *use, Node *oldref, Node *newref); void migrate_outs(Node *old, Node *target); - Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path = false); + Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word); void copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call); CallNode* make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call, const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1, @@ -225,6 +225,7 @@ class PhaseMacroExpand : public Phase { void refine_strip_mined_loop_macro_nodes(); void eliminate_macro_nodes(bool eliminate_locks = true); bool expand_macro_nodes(); + void eliminate_opaque_looplimit_macro_nodes(); SafePointScalarObjectNode* create_scalarized_object_description(AllocateNode *alloc, SafePointNode* sfpt, Unique_Node_List* value_worklist); static bool can_eliminate_allocation(PhaseIterGVN *igvn, AllocateNode *alloc, GrowableArray *safepoints); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 3d8c14f4b68..98d4d60e6cb 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -2565,22 +2565,7 @@ void Matcher::find_shared_post_visit(Node* n, uint opcode) { n->del_req(3); break; } - case Op_LoadVectorGather: - if (is_subword_type(n->bottom_type()->is_vect()->element_basic_type())) { - Node* pair = new BinaryNode(n->in(MemNode::ValueIn), n->in(MemNode::ValueIn+1)); - n->set_req(MemNode::ValueIn, pair); - n->del_req(MemNode::ValueIn+1); - } - break; - case Op_LoadVectorGatherMasked: - if (is_subword_type(n->bottom_type()->is_vect()->element_basic_type())) { - Node* pair2 = new BinaryNode(n->in(MemNode::ValueIn + 1), n->in(MemNode::ValueIn + 2)); - Node* pair1 = new BinaryNode(n->in(MemNode::ValueIn), pair2); - n->set_req(MemNode::ValueIn, pair1); - n->del_req(MemNode::ValueIn+2); - n->del_req(MemNode::ValueIn+1); - break; - } // fall-through + case Op_LoadVectorGatherMasked: // fall-through case Op_StoreVectorScatter: { Node* pair = new BinaryNode(n->in(MemNode::ValueIn), n->in(MemNode::ValueIn+1)); n->set_req(MemNode::ValueIn, pair); diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 8c4efcd8160..b79f4fab9bb 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1152,8 +1152,7 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { assert( !method || !method->is_synchronized() || method->is_native() || - num_mon > 0 || - !GenerateSynchronizationCode, + num_mon > 0, "monitors must always exist for synchronized methods"); // Build the growable array of ScopeValues for exp stack @@ -3621,7 +3620,8 @@ void PhaseOutput::install_stub(const char* stub_name) { } else { assert(rs->is_runtime_stub(), "sanity check"); C->set_stub_entry_point(rs->entry_point()); - AOTCodeCache::store_code_blob(*rs, AOTCodeEntry::C2Blob, C->stub_id(), stub_name); + BlobId blob_id = StubInfo::blob(C->stub_id()); + AOTCodeCache::store_code_blob(*rs, AOTCodeEntry::C2Blob, blob_id); } } } diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index e38f74e7952..f06cf8c28a1 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -1142,7 +1142,7 @@ void Parse::do_exits() { // This is done late so that we can common up equivalent exceptions // (e.g., null checks) arising from multiple points within this method. // See GraphKit::add_exception_state, which performs the commoning. - bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode; + bool do_synch = method()->is_synchronized(); // record exit from a method if compiled while Dtrace is turned on. if (do_synch || C->env()->dtrace_method_probes() || _replaced_nodes_for_exceptions) { @@ -2413,7 +2413,7 @@ void Parse::return_current(Node* value) { // Do not set_parse_bci, so that return goo is credited to the return insn. set_bci(InvocationEntryBci); - if (method()->is_synchronized() && GenerateSynchronizationCode) { + if (method()->is_synchronized()) { shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node()); } if (C->env()->dtrace_method_probes()) { diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 02443aec6d0..88c9e0e9ae1 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1818,7 +1818,8 @@ bool PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { // The number of nodes shoud not increase. uint old_unique = C->unique(); - + // The hash of a node should not change, this would indicate different inputs + uint old_hash = n->hash(); Node* i = n->Ideal(this, can_reshape); // If there was no new Idealization, we are probably happy. if (i == nullptr) { @@ -1832,6 +1833,16 @@ bool PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { return true; } + if (old_hash != n->hash()) { + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Ideal optimization did not make progress but node hash changed."); + ss.print_cr(" old_hash = %d, hash = %d", old_hash, n->hash()); + n->dump_bfs(1, nullptr, "", &ss); + tty->print_cr("%s", ss.as_string()); + return true; + } + verify_empty_worklist(n); // Everything is good. @@ -2891,6 +2902,7 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No push_and(worklist, parent, use); push_cast_ii(worklist, parent, use); push_opaque_zero_trip_guard(worklist, use); + push_bool_with_cmpu_and_mask(worklist, use); } @@ -2937,6 +2949,57 @@ void PhaseCCP::push_cmpu(Unique_Node_List& worklist, const Node* use) const { } } +// Look for the following shape, which can be optimized by BoolNode::Value_cmpu_and_mask() (i.e. corresponds to case +// (1b): "(m & x) Opcode(); + if (use_op != Op_AndI && (use_op != Op_AddI || use->in(2)->find_int_con(0) != 1)) { + // Not "m & x" or "m + 1" + return; + } + for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { + Node* cmpu = use->fast_out(i); + if (cmpu->Opcode() == Op_CmpU) { + push_bool_matching_case1b(worklist, cmpu); + } + } +} + +// Push any Bool below 'cmpu' that matches case (1b) of BoolNode::Value_cmpu_and_mask(). +void PhaseCCP::push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const { + assert(cmpu->Opcode() == Op_CmpU, "must be"); + for (DUIterator_Fast imax, i = cmpu->fast_outs(imax); i < imax; i++) { + Node* bol = cmpu->fast_out(i); + if (!bol->is_Bool() || bol->as_Bool()->_test._test != BoolTest::lt) { + // Not a Bool with "in(1); + Node* addI = cmpu->in(2); + if (andI->Opcode() != Op_AndI || addI->Opcode() != Op_AddI || addI->in(2)->find_int_con(0) != 1) { + // Not "m & x" and "m + 1" + continue; + } + + Node* m = addI->in(1); + if (m == andI->in(1) || m == andI->in(2)) { + // Is "m" shared? Matched (1b) and thus we revisit Bool. + push_if_not_bottom_type(worklist, bol); + } + } +} + // If n is used in a counted loop exit condition, then the type of the counted loop's Phi depends on the type of 'n'. // Seem PhiNode::Value(). void PhaseCCP::push_counted_loop_phi(Unique_Node_List& worklist, Node* parent, const Node* use) { @@ -3184,6 +3247,7 @@ Node *PhaseCCP::transform_once( Node *n ) { hash_delete(n); // changing bottom type may force a rehash n->raise_bottom_type(t); _worklist.push(n); // n re-enters the hash table via the worklist + add_users_to_worklist(n); // if ideal or identity optimizations depend on the input type, users need to be notified } // TEMPORARY fix to ensure that 2nd GVN pass eliminates null checks diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 432a343f560..4d47158e707 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -641,6 +641,8 @@ class PhaseCCP : public PhaseIterGVN { void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const; + void push_bool_with_cmpu_and_mask(Unique_Node_List& worklist, const Node* use) const; + void push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const; public: PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index bd2daa0ac60..1b3de6e5332 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -75,6 +75,14 @@ flags(ITER_GVN_AFTER_ELIMINATION, "Iter GVN after Eliminating Allocations and Locks") \ flags(BEFORE_PRE_MAIN_POST, "Before Pre/Main/Post Loops") \ flags(AFTER_PRE_MAIN_POST, "After Pre/Main/Post Loops") \ + flags(BEFORE_POST_LOOP, "Before Post Loop") \ + flags(AFTER_POST_LOOP, "After Post Loop") \ + flags(BEFORE_REMOVE_EMPTY_LOOP, "Before Remove Empty Loop") \ + flags(AFTER_REMOVE_EMPTY_LOOP, "After Remove Empty Loop") \ + flags(BEFORE_ONE_ITERATION_LOOP, "Before Replace One-Iteration Loop") \ + flags(AFTER_ONE_ITERATION_LOOP, "After Replace One-Iteration Loop") \ + flags(BEFORE_DUPLICATE_LOOP_BACKEDGE, "Before Duplicate Loop Backedge") \ + flags(AFTER_DUPLICATE_LOOP_BACKEDGE, "After Duplicate Loop Backedge") \ flags(BEFORE_LOOP_UNROLLING, "Before Loop Unrolling") \ flags(AFTER_LOOP_UNROLLING, "After Loop Unrolling") \ flags(PHASEIDEALLOOP1, "PhaseIdealLoop 1") \ @@ -91,6 +99,8 @@ flags(PHASEIDEALLOOP_ITERATIONS, "PhaseIdealLoop iterations") \ flags(AFTER_LOOP_OPTS, "After Loop Optimizations") \ flags(AFTER_MERGE_STORES, "After Merge Stores") \ + flags(AFTER_MACRO_ELIMINATION_STEP, "After Macro Elimination Step") \ + flags(AFTER_MACRO_ELIMINATION, "After Macro Elimination") \ flags(BEFORE_MACRO_EXPANSION , "Before Macro Expansion") \ flags(AFTER_MACRO_EXPANSION_STEP, "After Macro Expansion Step") \ flags(AFTER_MACRO_EXPANSION, "After Macro Expansion") \ diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 4c37d187bff..59cd92a1390 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -90,7 +90,7 @@ #define C2_BLOB_FIELD_DEFINE(name, type) \ - type OptoRuntime:: BLOB_FIELD_NAME(name) = nullptr; + type* OptoRuntime:: BLOB_FIELD_NAME(name) = nullptr; #define C2_STUB_FIELD_NAME(name) _ ## name ## _Java #define C2_STUB_FIELD_DEFINE(name, f, t, r) \ address OptoRuntime:: C2_STUB_FIELD_NAME(name) = nullptr; @@ -101,16 +101,6 @@ C2_STUBS_DO(C2_BLOB_FIELD_DEFINE, C2_STUB_FIELD_DEFINE, C2_JVMTI_STUB_FIELD_DEFI #undef C2_STUB_FIELD_DEFINE #undef C2_JVMTI_STUB_FIELD_DEFINE -#define C2_BLOB_NAME_DEFINE(name, type) "C2 Runtime " # name "_blob", -#define C2_STUB_NAME_DEFINE(name, f, t, r) "C2 Runtime " # name, -#define C2_JVMTI_STUB_NAME_DEFINE(name) "C2 Runtime " # name, -const char* OptoRuntime::_stub_names[] = { - C2_STUBS_DO(C2_BLOB_NAME_DEFINE, C2_STUB_NAME_DEFINE, C2_JVMTI_STUB_NAME_DEFINE) -}; -#undef C2_BLOB_NAME_DEFINE -#undef C2_STUB_NAME_DEFINE -#undef C2_JVMTI_STUB_NAME_DEFINE - // This should be called in an assertion at the start of OptoRuntime routines // which are entered from compiled code (all of them) #ifdef ASSERT @@ -141,8 +131,8 @@ static bool check_compiled_frame(JavaThread* thread) { #define C2_STUB_FIELD_NAME(name) _ ## name ## _Java #define C2_STUB_TYPEFUNC(name) name ## _Type #define C2_STUB_C_FUNC(name) CAST_FROM_FN_PTR(address, name ## _C) -#define C2_STUB_NAME(name) stub_name(OptoStubId::name ## _id) -#define C2_STUB_ID(name) OptoStubId::name ## _id +#define C2_STUB_ID(name) StubId:: JOIN3(c2, name, id) +#define C2_STUB_NAME(name) stub_name(C2_STUB_ID(name)) // Almost all the C functions targeted from the generated stubs are // implemented locally to OptoRuntime with names that can be generated @@ -159,7 +149,7 @@ static bool check_compiled_frame(JavaThread* thread) { C2_STUB_TYPEFUNC(name), \ C2_STUB_C_FUNC(name), \ C2_STUB_NAME(name), \ - (int)C2_STUB_ID(name), \ + C2_STUB_ID(name), \ fancy_jump, \ pass_tls, \ pass_retpc); \ @@ -173,7 +163,7 @@ static bool check_compiled_frame(JavaThread* thread) { notify_jvmti_vthread_Type, \ C2_JVMTI_STUB_C_FUNC(name), \ C2_STUB_NAME(name), \ - (int)C2_STUB_ID(name), \ + C2_STUB_ID(name), \ 0, \ true, \ false); \ @@ -282,7 +272,7 @@ const TypeFunc* OptoRuntime::_dtrace_object_alloc_Type = nullptr; // Helper method to do generation of RunTimeStub's address OptoRuntime::generate_stub(ciEnv* env, TypeFunc_generator gen, address C_function, - const char *name, int stub_id, + const char *name, StubId stub_id, int is_fancy_jump, bool pass_tls, bool return_pc) { diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index c40aa93a592..f4c5a6ad4a9 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -29,6 +29,7 @@ #include "opto/machnode.hpp" #include "opto/optoreg.hpp" #include "runtime/stubDeclarations.hpp" +#include "runtime/stubInfo.hpp" #include "runtime/vframe.hpp" //------------------------------OptoRuntime------------------------------------ @@ -97,20 +98,6 @@ class NamedCounter : public CHeapObj { typedef const TypeFunc*(*TypeFunc_generator)(); -// define OptoStubId enum tags: uncommon_trap_id etc - -#define C2_BLOB_ID_ENUM_DECLARE(name, type) STUB_ID_NAME(name), -#define C2_STUB_ID_ENUM_DECLARE(name, f, t, r) STUB_ID_NAME(name), -#define C2_JVMTI_STUB_ID_ENUM_DECLARE(name) STUB_ID_NAME(name), -enum class OptoStubId :int { - NO_STUBID = -1, - C2_STUBS_DO(C2_BLOB_ID_ENUM_DECLARE, C2_STUB_ID_ENUM_DECLARE, C2_JVMTI_STUB_ID_ENUM_DECLARE) - NUM_STUBIDS -}; -#undef C2_BLOB_ID_ENUM_DECLARE -#undef C2_STUB_ID_ENUM_DECLARE -#undef C2_JVMTI_STUB_ID_ENUM_DECLARE - class OptoRuntime : public AllStatic { friend class Matcher; // allow access to stub names friend class AOTCodeAddressTable; @@ -118,7 +105,7 @@ class OptoRuntime : public AllStatic { private: // declare opto stub address/blob holder static fields #define C2_BLOB_FIELD_DECLARE(name, type) \ - static type BLOB_FIELD_NAME(name); + static type* BLOB_FIELD_NAME(name); #define C2_STUB_FIELD_NAME(name) _ ## name ## _Java #define C2_STUB_FIELD_DECLARE(name, f, t, r) \ static address C2_STUB_FIELD_NAME(name) ; @@ -214,11 +201,8 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _dtrace_method_entry_exit_Type; static const TypeFunc* _dtrace_object_alloc_Type; - // Stub names indexed by sharedStubId - static const char *_stub_names[]; - // define stubs - static address generate_stub(ciEnv* ci_env, TypeFunc_generator gen, address C_function, const char* name, int stub_id, int is_fancy_jump, bool pass_tls, bool return_pc); + static address generate_stub(ciEnv* ci_env, TypeFunc_generator gen, address C_function, const char* name, StubId stub_id, int is_fancy_jump, bool pass_tls, bool return_pc); // // Implementation of runtime methods @@ -286,9 +270,9 @@ class OptoRuntime : public AllStatic { static const char* stub_name(address entry); // Returns the name associated with a given stub id - static const char* stub_name(OptoStubId id) { - assert(id > OptoStubId::NO_STUBID && id < OptoStubId::NUM_STUBIDS, "stub id out of range"); - return _stub_names[(int)id]; + static const char* stub_name(StubId id) { + assert(StubInfo::is_c2(id), "not a C2 stub %s", StubInfo::name(id)); + return StubInfo::name(id); } // access to runtime stubs entry points for java code diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index b52c7b507c5..ce150bb9501 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -561,17 +561,12 @@ const Type* SubFPNode::Value(PhaseGVN* phase) const { //------------------------------sub-------------------------------------------- // A subtract node differences its two inputs. const Type* SubHFNode::sub(const Type* t1, const Type* t2) const { - // no folding if one of operands is infinity or NaN, do not do constant folding - if(g_isfinite(t1->getf()) && g_isfinite(t2->getf())) { + // Half precision floating point subtraction follows the rules of IEEE 754 + // applicable to other floating point types. + if (t1->isa_half_float_constant() != nullptr && + t2->isa_half_float_constant() != nullptr) { return TypeH::make(t1->getf() - t2->getf()); - } - else if(g_isnan(t1->getf())) { - return t1; - } - else if(g_isnan(t2->getf())) { - return t2; - } - else { + } else { return Type::HALF_FLOAT; } } @@ -1986,7 +1981,7 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { // (1b) "(x & m) in(1); const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int(); - if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) { + if (rhs_m_type != nullptr && (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1)) { // Exclude any case where m == -1 is possible. m = rhs_m; } @@ -2004,12 +1999,16 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { // Simplify a Bool (convert condition codes to boolean (1 or 0)) node, // based on local information. If the input is constant, do it. const Type* BoolNode::Value(PhaseGVN* phase) const { + const Type* input_type = phase->type(in(1)); + if (input_type == Type::TOP) { + return Type::TOP; + } const Type* t = Value_cmpu_and_mask(phase); if (t != nullptr) { return t; } - return _test.cc2logical( phase->type( in(1) ) ); + return _test.cc2logical(input_type); } #ifndef PRODUCT @@ -2124,10 +2123,12 @@ const Type* SqrtHFNode::Value(PhaseGVN* phase) const { static const Type* reverse_bytes(int opcode, const Type* con) { switch (opcode) { - case Op_ReverseBytesS: return TypeInt::make(byteswap(checked_cast(con->is_int()->get_con()))); - case Op_ReverseBytesUS: return TypeInt::make(byteswap(checked_cast(con->is_int()->get_con()))); - case Op_ReverseBytesI: return TypeInt::make(byteswap(checked_cast(con->is_int()->get_con()))); - case Op_ReverseBytesL: return TypeLong::make(byteswap(checked_cast(con->is_long()->get_con()))); + // It is valid in bytecode to load any int and pass it to a method that expects a smaller type (i.e., short, char). + // Let's cast the value to match the Java behavior. + case Op_ReverseBytesS: return TypeInt::make(byteswap(static_cast(con->is_int()->get_con()))); + case Op_ReverseBytesUS: return TypeInt::make(byteswap(static_cast(con->is_int()->get_con()))); + case Op_ReverseBytesI: return TypeInt::make(byteswap(con->is_int()->get_con())); + case Op_ReverseBytesL: return TypeLong::make(byteswap(con->is_long()->get_con())); default: ShouldNotReachHere(); } } diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index e514535c414..266a5874cea 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2535,6 +2535,82 @@ VStatus VLoopBody::construct() { return VStatus::make_success(); } +// Returns true if the given operation can be vectorized with "truncation" where the upper bits in the integer do not +// contribute to the result. This is true for most arithmetic operations, but false for operations such as +// leading/trailing zero count. +static bool can_subword_truncate(Node* in, const Type* type) { + if (in->is_Load() || in->is_Store() || in->is_Convert() || in->is_Phi()) { + return true; + } + + int opc = in->Opcode(); + + // If the node's base type is a subword type, check an additional set of nodes. + if (type == TypeInt::SHORT || type == TypeInt::CHAR) { + switch (opc) { + case Op_ReverseBytesS: + case Op_ReverseBytesUS: + return true; + } + } + + // Can be truncated: + switch (opc) { + case Op_AddI: + case Op_SubI: + case Op_MulI: + case Op_AndI: + case Op_OrI: + case Op_XorI: + return true; + } + +#ifdef ASSERT + // While shifts have subword vectorized forms, they require knowing the precise type of input loads so they are + // considered non-truncating. + if (VectorNode::is_shift_opcode(opc)) { + return false; + } + + // Vector nodes should not truncate. + if (type->isa_vect() != nullptr || type->isa_vectmask() != nullptr || in->is_Reduction()) { + return false; + } + + // Cannot be truncated: + switch (opc) { + case Op_AbsI: + case Op_DivI: + case Op_ModI: + case Op_MinI: + case Op_MaxI: + case Op_CMoveI: + case Op_Conv2B: + case Op_RotateRight: + case Op_RotateLeft: + case Op_PopCountI: + case Op_ReverseBytesI: + case Op_ReverseI: + case Op_CountLeadingZerosI: + case Op_CountTrailingZerosI: + case Op_IsInfiniteF: + case Op_IsInfiniteD: + case Op_ExtractS: + case Op_ExtractC: + case Op_ExtractB: + return false; + default: + // If this assert is hit, that means that we need to determine if the node can be safely truncated, + // and then add it to the list of truncating nodes or the list of non-truncating ones just above. + // In product, we just return false, which is always correct. + assert(false, "Unexpected node in SuperWord truncation: %s", NodeClassNames[in->Opcode()]); + } +#endif + + // Default to disallowing vector truncation + return false; +} + void VLoopTypes::compute_vector_element_type() { #ifndef PRODUCT if (_vloop.is_trace_vector_element_type()) { @@ -2589,18 +2665,19 @@ void VLoopTypes::compute_vector_element_type() { // be vectorized if the higher order bits info is imprecise. const Type* vt = vtn; int op = in->Opcode(); - if (VectorNode::is_shift_opcode(op) || op == Op_AbsI || op == Op_ReverseBytesI) { + if (!can_subword_truncate(in, vt)) { Node* load = in->in(1); - if (load->is_Load() && + // For certain operations such as shifts and abs(), use the size of the load if it exists + if ((VectorNode::is_shift_opcode(op) || op == Op_AbsI) && load->is_Load() && _vloop.in_bb(load) && (velt_type(load)->basic_type() == T_INT)) { // Only Load nodes distinguish signed (LoadS/LoadB) and unsigned // (LoadUS/LoadUB) values. Store nodes only have one version. vt = velt_type(load); } else if (op != Op_LShiftI) { - // Widen type to int to avoid the creation of vector nodes. Note + // Widen type to the node type to avoid the creation of vector nodes. Note // that left shifts work regardless of the signedness. - vt = TypeInt::INT; + vt = container_type(in); } } set_velt_type(in, vt); diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 4604d91f80f..8c5c1b6adf2 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -328,9 +328,9 @@ class Type { const TypeD *isa_double() const; // Returns null if not a Double{Top,Con,Bot} const TypeD *is_double_constant() const; // Asserts it is a DoubleCon const TypeD *isa_double_constant() const; // Returns null if not a DoubleCon - const TypeH *isa_half_float() const; // Returns null if not a Float{Top,Con,Bot} - const TypeH *is_half_float_constant() const; // Asserts it is a FloatCon - const TypeH *isa_half_float_constant() const; // Returns null if not a FloatCon + const TypeH *isa_half_float() const; // Returns null if not a HalfFloat{Top,Con,Bot} + const TypeH *is_half_float_constant() const; // Asserts it is a HalfFloatCon + const TypeH *isa_half_float_constant() const; // Returns null if not a HalfFloatCon const TypeF *isa_float() const; // Returns null if not a Float{Top,Con,Bot} const TypeF *is_float_constant() const; // Asserts it is a FloatCon const TypeF *isa_float_constant() const; // Returns null if not a FloatCon diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 5ff2590a190..97c5dbe03ef 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -822,8 +822,7 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { Node* offset = ConvL2X(argument(4)); // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); Node* addr = make_unsafe_address(base, offset, (is_mask ? T_BOOLEAN : elem_bt), true); @@ -860,8 +859,6 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", is_store, is_store ? "store" : "load", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - set_map(old_map); - set_sp(old_sp); return false; } @@ -873,8 +870,6 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", is_store, "store", num_elem, type2name(elem_bt)); - set_map(old_map); - set_sp(old_sp); return false; // not supported } } else { @@ -883,8 +878,6 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", is_store, "load", mem_num_elem, type2name(mem_elem_bt)); - set_map(old_map); - set_sp(old_sp); return false; // not supported } } @@ -892,14 +885,10 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { if (is_mask) { if (!is_store) { if (!arch_supports_vector(Op_LoadVector, num_elem, elem_bt, VecMaskUseLoad)) { - set_map(old_map); - set_sp(old_sp); return false; // not supported } } else { if (!arch_supports_vector(Op_StoreVector, num_elem, elem_bt, VecMaskUseStore)) { - set_map(old_map); - set_sp(old_sp); return false; // not supported } } @@ -914,8 +903,6 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { if (is_store) { Node* val = unbox_vector(argument(7), vbox_type, elem_bt, num_elem); if (val == nullptr) { - set_map(old_map); - set_sp(old_sp); return false; // operand unboxing failed } set_all_memory(reset_memory()); @@ -952,7 +939,7 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { set_result(box); } - destruct_map_clone(old_map); + old_state.discard(); if (needs_cpu_membar) { insert_mem_bar(Op_MemBarCPUOrder); @@ -1029,8 +1016,7 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { Node* offset = ConvL2X(argument(5)); // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); Node* addr = make_unsafe_address(base, offset, elem_bt, true); const TypePtr *addr_type = gvn().type(addr)->isa_ptr(); @@ -1043,8 +1029,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - set_map(old_map); - set_sp(old_sp); return false; } @@ -1066,8 +1050,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { if (!offset_in_range->is_con()) { log_if_needed(" ** missing constant: offsetInRange=%s", NodeClassNames[argument(8)->Opcode()]); - set_map(old_map); - set_sp(old_sp); return false; } needs_predicate = (offset_in_range->get_con() == 0); @@ -1077,8 +1059,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { log_if_needed(" ** not supported: op=%s vlen=%d etype=%s mismatched_ms=%d", is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt), mismatched_ms ? 1 : 0); - set_map(old_map); - set_sp(old_sp); return false; } } @@ -1089,8 +1069,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { !arch_supports_vector(Op_VectorBlend, mem_num_elem, mem_elem_bt, VecMaskUseLoad))) { log_if_needed(" ** not supported: op=loadMasked vlen=%d etype=%s mismatched_ms=%d", num_elem, type2name(elem_bt), mismatched_ms ? 1 : 0); - set_map(old_map); - set_sp(old_sp); return false; } @@ -1101,8 +1079,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s mismatched_ms=1", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt)); - set_map(old_map); - set_sp(old_sp); return false; } } @@ -1113,8 +1089,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt)); - set_map(old_map); - set_sp(old_sp); return false; } @@ -1135,8 +1109,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { log_if_needed(" ** unbox failed mask=%s", is_store ? NodeClassNames[argument(9)->Opcode()] : NodeClassNames[argument(8)->Opcode()]); - set_map(old_map); - set_sp(old_sp); return false; } @@ -1145,8 +1117,6 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { if (val == nullptr) { log_if_needed(" ** unbox failed vector=%s", NodeClassNames[argument(8)->Opcode()]); - set_map(old_map); - set_sp(old_sp); return false; // operand unboxing failed } set_all_memory(reset_memory()); @@ -1193,7 +1163,7 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { set_result(box); } - destruct_map_clone(old_map); + old_state.discard(); if (can_access_non_heap) { insert_mem_bar(Op_MemBarCPUOrder); @@ -1203,29 +1173,31 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { return true; } -// , -// W extends Vector, -// S extends VectorSpecies, -// M extends VectorMask, -// E> -// V loadWithMap(Class vectorClass, Class maskClass, Class elementType, int length, -// Class> vectorIndexClass, -// Object base, long offset, // Unsafe addressing -// W index_vector, M m, -// C container, int index, int[] indexMap, int indexM, S s, // Arguments for default implementation -// LoadVectorOperationWithMap defaultImpl) +// +// , +// W extends Vector, +// S extends VectorSpecies, +// M extends VectorMask, +// E> +// V loadWithMap(Class vClass, Class mClass, Class eClass, int length, +// Class> vectorIndexClass, int indexLength, +// Object base, long offset, +// W indexVector1, W indexVector2, W indexVector3, W indexVector4, +// M m, C container, int index, int[] indexMap, int indexM, S s, +// LoadVectorOperationWithMap defaultImpl) // // , // W extends Vector, // M extends VectorMask, // E> -// void storeWithMap(Class vectorClass, Class maskClass, Class elementType, -// int length, Class> vectorIndexClass, Object base, long offset, // Unsafe addressing -// W index_vector, V v, M m, -// C container, int index, int[] indexMap, int indexM, // Arguments for default implementation -// StoreVectorOperationWithMap defaultImpl) +// void storeWithMap(Class vClass, Class mClass, Class eClass, int length, +// Class> vectorIndexClass, int indexLength, +// Object base, long offset, // Unsafe addressing +// W indexVector, V v, M m, +// C container, int index, int[] indexMap, int indexM, // Arguments for default implementation +// StoreVectorOperationWithMap defaultImpl) // bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { const TypeInstPtr* vector_klass = gvn().type(argument(0))->isa_instptr(); @@ -1233,16 +1205,19 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr(); const TypeInt* vlen = gvn().type(argument(3))->isa_int(); const TypeInstPtr* vector_idx_klass = gvn().type(argument(4))->isa_instptr(); + const TypeInt* idx_vlen = gvn().type(argument(5))->isa_int(); if (vector_klass == nullptr || vector_klass->const_oop() == nullptr || elem_klass == nullptr || elem_klass->const_oop() == nullptr || vlen == nullptr || !vlen->is_con() || - vector_idx_klass == nullptr || vector_idx_klass->const_oop() == nullptr) { - log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s", + vector_idx_klass == nullptr || vector_idx_klass->const_oop() == nullptr || + idx_vlen == nullptr || !idx_vlen->is_con()) { + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s idx_vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()], - NodeClassNames[argument(4)->Opcode()]); + NodeClassNames[argument(4)->Opcode()], + NodeClassNames[argument(5)->Opcode()]); return false; // not enough info for intrinsification } @@ -1259,8 +1234,10 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { BasicType elem_bt = elem_type->basic_type(); int num_elem = vlen->get_con(); + int idx_num_elem = idx_vlen->get_con(); - const Type* vmask_type = gvn().type(is_scatter ? argument(10) : argument(9)); + Node* m = is_scatter ? argument(11) : argument(13); + const Type* vmask_type = gvn().type(m); bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { if (mask_klass == nullptr || mask_klass->const_oop() == nullptr) { @@ -1298,23 +1275,32 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { // Check that the vector holding indices is supported by architecture // For sub-word gathers expander receive index array. - if (!is_subword_type(elem_bt) && !arch_supports_vector(Op_LoadVector, num_elem, T_INT, VecMaskNotUsed)) { - log_if_needed(" ** not supported: arity=%d op=%s/loadindex vlen=%d etype=int is_masked_op=%d", - is_scatter, is_scatter ? "scatter" : "gather", - num_elem, is_masked_op ? 1 : 0); - return false; // not supported + if (!is_subword_type(elem_bt) && !arch_supports_vector(Op_LoadVector, idx_num_elem, T_INT, VecMaskNotUsed)) { + log_if_needed(" ** not supported: arity=%d op=%s/loadindex vlen=%d etype=int is_masked_op=%d", + is_scatter, is_scatter ? "scatter" : "gather", + idx_num_elem, is_masked_op ? 1 : 0); + return false; // not supported } - Node* base = argument(5); - Node* offset = ConvL2X(argument(6)); + Node* base = argument(6); + Node* offset = ConvL2X(argument(7)); // Save state and restore on bailout - uint old_sp = sp(); - SafePointNode* old_map = clone_map(); + SavedState old_state(this); - Node* addr = make_unsafe_address(base, offset, elem_bt, true); + Node* addr = nullptr; + if (!is_subword_type(elem_bt)) { + addr = make_unsafe_address(base, offset, elem_bt, true); + } else { + assert(!is_scatter, "Only supports gather operation for subword types now"); + uint header = arrayOopDesc::base_offset_in_bytes(elem_bt); + assert(offset->is_Con() && offset->bottom_type()->is_long()->get_con() == header, + "offset must be the array base offset"); + Node* index = argument(15); + addr = array_element_address(base, index, elem_bt); + } - const TypePtr *addr_type = gvn().type(addr)->isa_ptr(); + const TypePtr* addr_type = gvn().type(addr)->isa_ptr(); const TypeAryPtr* arr_type = addr_type->isa_aryptr(); // The array must be consistent with vector type @@ -1322,8 +1308,6 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", is_scatter, is_scatter ? "scatter" : "gather", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - set_map(old_map); - set_sp(old_sp); return false; } @@ -1331,80 +1315,63 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); ciKlass* vbox_idx_klass = vector_idx_klass->const_oop()->as_instance()->java_lang_Class_klass(); if (vbox_idx_klass == nullptr) { - set_map(old_map); - set_sp(old_sp); return false; } - Node* index_vect = nullptr; + // Get the indexes for gather/scatter. + Node* indexes = nullptr; const TypeInstPtr* vbox_idx_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_idx_klass); - if (!is_subword_type(elem_bt)) { - index_vect = unbox_vector(argument(8), vbox_idx_type, T_INT, num_elem); - if (index_vect == nullptr) { - set_map(old_map); - set_sp(old_sp); + if (is_subword_type(elem_bt)) { + Node* indexMap = argument(16); + Node* indexM = argument(17); + indexes = array_element_address(indexMap, indexM, T_INT); + } else { + // Get the first index vector. + indexes = unbox_vector(argument(9), vbox_idx_type, T_INT, idx_num_elem); + if (indexes == nullptr) { return false; } } + // Get the vector mask value. Node* mask = nullptr; if (is_masked_op) { ciKlass* mbox_klass = mask_klass->const_oop()->as_instance()->java_lang_Class_klass(); const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); - mask = unbox_vector(is_scatter ? argument(10) : argument(9), mbox_type, elem_bt, num_elem); + mask = unbox_vector(m, mbox_type, elem_bt, num_elem); if (mask == nullptr) { - log_if_needed(" ** unbox failed mask=%s", - is_scatter ? NodeClassNames[argument(10)->Opcode()] - : NodeClassNames[argument(9)->Opcode()]); - set_map(old_map); - set_sp(old_sp); + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[m->Opcode()]); return false; } } const TypeVect* vector_type = TypeVect::make(elem_bt, num_elem); if (is_scatter) { - Node* val = unbox_vector(argument(9), vbox_type, elem_bt, num_elem); + Node* val = unbox_vector(argument(10), vbox_type, elem_bt, num_elem); if (val == nullptr) { - set_map(old_map); - set_sp(old_sp); return false; // operand unboxing failed } set_all_memory(reset_memory()); Node* vstore = nullptr; if (mask != nullptr) { - vstore = gvn().transform(new StoreVectorScatterMaskedNode(control(), memory(addr), addr, addr_type, val, index_vect, mask)); + vstore = gvn().transform(new StoreVectorScatterMaskedNode(control(), memory(addr), addr, addr_type, val, indexes, mask)); } else { - vstore = gvn().transform(new StoreVectorScatterNode(control(), memory(addr), addr, addr_type, val, index_vect)); + vstore = gvn().transform(new StoreVectorScatterNode(control(), memory(addr), addr, addr_type, val, indexes)); } set_memory(vstore, addr_type); } else { Node* vload = nullptr; - Node* index = argument(11); - Node* indexMap = argument(12); - Node* indexM = argument(13); if (mask != nullptr) { - if (is_subword_type(elem_bt)) { - Node* index_arr_base = array_element_address(indexMap, indexM, T_INT); - vload = gvn().transform(new LoadVectorGatherMaskedNode(control(), memory(addr), addr, addr_type, vector_type, index_arr_base, mask, index)); - } else { - vload = gvn().transform(new LoadVectorGatherMaskedNode(control(), memory(addr), addr, addr_type, vector_type, index_vect, mask)); - } + vload = gvn().transform(new LoadVectorGatherMaskedNode(control(), memory(addr), addr, addr_type, vector_type, indexes, mask)); } else { - if (is_subword_type(elem_bt)) { - Node* index_arr_base = array_element_address(indexMap, indexM, T_INT); - vload = gvn().transform(new LoadVectorGatherNode(control(), memory(addr), addr, addr_type, vector_type, index_arr_base, index)); - } else { - vload = gvn().transform(new LoadVectorGatherNode(control(), memory(addr), addr, addr_type, vector_type, index_vect)); - } + vload = gvn().transform(new LoadVectorGatherNode(control(), memory(addr), addr, addr_type, vector_type, indexes)); } Node* box = box_vector(vload, vbox_type, elem_bt, num_elem); set_result(box); } - destruct_map_clone(old_map); - + old_state.discard(); C->set_max_vector_size(MAX2(C->max_vector_size(), (uint)(num_elem * type2aelembytes(elem_bt)))); return true; } diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index e72c3880c79..3caaf7c59d7 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1117,25 +1117,18 @@ class LoadVectorNode : public LoadNode { // Load Vector from memory via index map class LoadVectorGatherNode : public LoadVectorNode { public: - LoadVectorGatherNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, Node* indices, Node* offset = nullptr) + LoadVectorGatherNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, Node* indices) : LoadVectorNode(c, mem, adr, at, vt) { init_class_id(Class_LoadVectorGather); add_req(indices); DEBUG_ONLY(bool is_subword = is_subword_type(vt->element_basic_type())); assert(is_subword || indices->bottom_type()->is_vect(), "indices must be in vector"); - assert(is_subword || !offset, ""); assert(req() == MemNode::ValueIn + 1, "match_edge expects that index input is in MemNode::ValueIn"); - if (offset) { - add_req(offset); - } } virtual int Opcode() const; virtual uint match_edge(uint idx) const { - return idx == MemNode::Address || - idx == MemNode::ValueIn || - ((is_subword_type(vect_type()->element_basic_type())) && - idx == MemNode::ValueIn + 1); + return idx == MemNode::Address || idx == MemNode::ValueIn; } virtual int store_Opcode() const { // Ensure it is different from any store opcode to avoid folding when indices are used @@ -1254,23 +1247,19 @@ class LoadVectorMaskedNode : public LoadVectorNode { // Load Vector from memory via index map under the influence of a predicate register(mask). class LoadVectorGatherMaskedNode : public LoadVectorNode { public: - LoadVectorGatherMaskedNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, Node* indices, Node* mask, Node* offset = nullptr) + LoadVectorGatherMaskedNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, Node* indices, Node* mask) : LoadVectorNode(c, mem, adr, at, vt) { init_class_id(Class_LoadVectorGatherMasked); add_req(indices); add_req(mask); assert(req() == MemNode::ValueIn + 2, "match_edge expects that last input is in MemNode::ValueIn+1"); - if (is_subword_type(vt->element_basic_type())) { - add_req(offset); - } + assert(is_subword_type(vt->element_basic_type()) || indices->bottom_type()->is_vect(), "indices must be in vector"); } virtual int Opcode() const; virtual uint match_edge(uint idx) const { return idx == MemNode::Address || idx == MemNode::ValueIn || - idx == MemNode::ValueIn + 1 || - (is_subword_type(vect_type()->is_vect()->element_basic_type()) && - idx == MemNode::ValueIn + 2); } + idx == MemNode::ValueIn + 1; } virtual int store_Opcode() const { // Ensure it is different from any store opcode to avoid folding when indices and mask are used return -1; diff --git a/src/hotspot/share/prims/jniCheck.cpp b/src/hotspot/share/prims/jniCheck.cpp index 18f3bd5cfa9..774c628f464 100644 --- a/src/hotspot/share/prims/jniCheck.cpp +++ b/src/hotspot/share/prims/jniCheck.cpp @@ -350,24 +350,33 @@ check_is_obj_or_inline_array(JavaThread* thr, jarray jArray) { } } +// Arbitrary (but well-known) tag for GetStringChars +const void* STRING_TAG = (void*)0x47114711; + +// Arbitrary (but well-known) tag for GetStringUTFChars +const void* STRING_UTF_TAG = (void*) 0x48124812; + +// Arbitrary (but well-known) tag for GetPrimitiveArrayCritical +const void* CRITICAL_TAG = (void*)0x49134913; + /* * Copy and wrap array elements for bounds checking. * Remember the original elements (GuardedMemory::get_tag()) */ static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array, - void* orig_elements) { + void* orig_elements, jboolean is_critical = JNI_FALSE) { void* result; IN_VM( oop a = JNIHandles::resolve_non_null(array); size_t len = arrayOop(a)->length() << TypeArrayKlass::cast(a->klass())->log2_element_size(); - result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements); + result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements, is_critical ? CRITICAL_TAG : nullptr); ) return result; } static void* check_wrapped_array(JavaThread* thr, const char* fn_name, - void* obj, void* carray, size_t* rsz) { + void* obj, void* carray, size_t* rsz, jboolean is_critical) { if (carray == nullptr) { tty->print_cr("%s: elements vector null" PTR_FORMAT, fn_name, p2i(obj)); NativeReportJNIFatalError(thr, "Elements vector null"); @@ -386,6 +395,29 @@ static void* check_wrapped_array(JavaThread* thr, const char* fn_name, DEBUG_ONLY(guarded.print_on(tty);) // This may crash. NativeReportJNIFatalError(thr, err_msg("%s: unrecognized elements", fn_name)); } + if (orig_result == STRING_TAG || orig_result == STRING_UTF_TAG) { + bool was_utf = orig_result == STRING_UTF_TAG; + tty->print_cr("%s: called on something allocated by %s", + fn_name, was_utf ? "GetStringUTFChars" : "GetStringChars"); + DEBUG_ONLY(guarded.print_on(tty);) // This may crash. + NativeReportJNIFatalError(thr, err_msg("%s called on something allocated by %s", + fn_name, was_utf ? "GetStringUTFChars" : "GetStringChars")); + } + + if (is_critical && (guarded.get_tag2() != CRITICAL_TAG)) { + tty->print_cr("%s: called on something not allocated by GetPrimitiveArrayCritical", fn_name); + DEBUG_ONLY(guarded.print_on(tty);) // This may crash. + NativeReportJNIFatalError(thr, err_msg("%s called on something not allocated by GetPrimitiveArrayCritical", + fn_name)); + } + + if (!is_critical && (guarded.get_tag2() == CRITICAL_TAG)) { + tty->print_cr("%s: called on something allocated by GetPrimitiveArrayCritical", fn_name); + DEBUG_ONLY(guarded.print_on(tty);) // This may crash. + NativeReportJNIFatalError(thr, err_msg("%s called on something allocated by GetPrimitiveArrayCritical", + fn_name)); + } + if (rsz != nullptr) { *rsz = guarded.get_user_size(); } @@ -395,7 +427,7 @@ static void* check_wrapped_array(JavaThread* thr, const char* fn_name, static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name, void* obj, void* carray, jint mode, jboolean is_critical) { size_t sz; - void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz); + void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz, is_critical); switch (mode) { case 0: memcpy(orig_result, carray, sz); @@ -439,7 +471,7 @@ Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) { } // jmethodIDs are handles in the class loader data, // but that can be expensive so check it last - else if (!Method::is_method_id(method_id)) { + else if (!Method::validate_jmethod_id(method_id)) { ReportJNIFatalError(thr, fatal_non_weak_method); } return m; @@ -1430,9 +1462,6 @@ JNI_ENTRY_CHECKED(jsize, return result; JNI_END -// Arbitrary (but well-known) tag -const void* STRING_TAG = (void*)0x47114711; - JNI_ENTRY_CHECKED(const jchar *, checked_jni_GetStringChars(JNIEnv *env, jstring str, @@ -1535,9 +1564,6 @@ JNI_ENTRY_CHECKED(jlong, return result; JNI_END -// Arbitrary (but well-known) tag - different than GetStringChars -const void* STRING_UTF_TAG = (void*) 0x48124812; - JNI_ENTRY_CHECKED(const char *, checked_jni_GetStringUTFChars(JNIEnv *env, jstring str, @@ -1859,7 +1885,7 @@ JNI_ENTRY_CHECKED(void *, ) void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy); if (result != nullptr) { - result = check_jni_wrap_copy_array(thr, array, result); + result = check_jni_wrap_copy_array(thr, array, result, JNI_TRUE); } functionExit(thr); return result; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 54b63e47471..6f6e3ae78b8 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3143,7 +3143,7 @@ JVM_ENTRY(jobject, JVM_CreateThreadSnapshot(JNIEnv* env, jobject jthread)) oop snapshot = ThreadSnapshotFactory::get_thread_snapshot(jthread, THREAD); return JNIHandles::make_local(THREAD, snapshot); #else - return nullptr; + THROW_NULL(vmSymbols::java_lang_UnsupportedOperationException()); #endif JVM_END diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index fef71737c78..7e76cbabc65 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -2987,12 +2987,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Called or calling method is a native method. - The implementation is unable to pop this frame. - - - The thread is a suspended virtual thread and the implementation - was unable to pop the current frame. + The implementation is unable to pop this frame + (e.g. called or calling method is a native method). Thread was not suspended and was not the current thread. @@ -3078,8 +3074,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - The frame at depth is executing a - native method. + A event cannot be generated for this frame + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -3188,12 +3184,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The result type of the called method is not @@ -3240,12 +3232,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The result type of the called method is not @@ -3288,12 +3276,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The result type of the called method is not long. @@ -3333,12 +3317,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The result type of the called method is not float. @@ -3378,12 +3358,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The result type of the called method is not double. @@ -3417,12 +3393,8 @@ err = (*jvmti)->Deallocate(jvmti, stack_info); - Attempted to return early from a frame - corresponding to a native method. - The thread is a suspended virtual thread and the implementation was - unable to force its current frame to return. - Or the implementation is unable to provide - this functionality on this frame. + The implementation is unable to force the current frame to return + (e.g. current frame is executing a native method). The called method has a result type. @@ -5928,7 +5900,8 @@ class C2 extends C1 implements I2 { Object or a subclass of Object. - Not a visible frame + The implementation is unable to get the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6031,7 +6004,8 @@ class C2 extends C1 implements I2 { boolean. - Not a visible frame + The implementation is unable to get the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6085,7 +6059,8 @@ class C2 extends C1 implements I2 { The variable type is not long. - Not a visible frame + The implementation is unable to get the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6139,7 +6114,8 @@ class C2 extends C1 implements I2 { The variable type is not float. - Not a visible frame + The implementation is unable to get the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6193,7 +6169,8 @@ class C2 extends C1 implements I2 { The variable type is not double. - Not a visible frame + The implementation is unable to get the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6252,12 +6229,8 @@ class C2 extends C1 implements I2 { with the variable type. - Not a visible frame - - - The thread is a suspended virtual thread and the implementation does not support - setting the value of locals in the frame of the given depth. - See Local Variables. + The implementation is unable to set the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6316,12 +6289,8 @@ class C2 extends C1 implements I2 { boolean. - Not a visible frame - - - The thread is a suspended virtual thread and the implementation does not support - setting the value of locals in the frame of the given depth. - See Local Variables. + The implementation is unable to set the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6375,12 +6344,8 @@ class C2 extends C1 implements I2 { The variable type is not long. - Not a visible frame - - - The thread is a suspended virtual thread and the implementation does not support - setting the value of locals in the frame of the given depth. - See Local Variables. + The implementation is unable to set the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6434,12 +6399,8 @@ class C2 extends C1 implements I2 { The variable type is not float. - Not a visible frame - - - The thread is a suspended virtual thread and the implementation does not support - setting the value of locals in the frame of the given depth. - See Local Variables. + The implementation is unable to set the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -6493,12 +6454,8 @@ class C2 extends C1 implements I2 { The variable type is not double. - Not a visible frame - - - The thread is a suspended virtual thread and the implementation does not support - setting the value of locals in the frame of the given depth. - See Local Variables. + The implementation is unable to set the frame locals + (e.g. the frame at depth is executing a native method). Thread was not suspended and was not the current thread. @@ -12050,7 +12007,7 @@ myInit() { Information about the frame is not available (e.g. for native frames), - or the function cannot be performed on the thread's current frame. + or the implementation is unable to provide this functionality on this frame. Item already set. diff --git a/src/hotspot/share/prims/jvmtiAgent.cpp b/src/hotspot/share/prims/jvmtiAgent.cpp index d26c581a2a5..4bf7a447398 100644 --- a/src/hotspot/share/prims/jvmtiAgent.cpp +++ b/src/hotspot/share/prims/jvmtiAgent.cpp @@ -31,6 +31,7 @@ #include "prims/jvmtiEnvBase.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" +#include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -82,11 +83,7 @@ JvmtiAgent::JvmtiAgent(const char* name, const char* options, bool is_absolute_p _xrun(false) {} JvmtiAgent* JvmtiAgent::next() const { - return _next; -} - -void JvmtiAgent::set_next(JvmtiAgent* agent) { - _next = agent; + return Atomic::load_acquire(&_next); } const char* JvmtiAgent::name() const { diff --git a/src/hotspot/share/prims/jvmtiAgent.hpp b/src/hotspot/share/prims/jvmtiAgent.hpp index fbbb193453f..b2e312c8030 100644 --- a/src/hotspot/share/prims/jvmtiAgent.hpp +++ b/src/hotspot/share/prims/jvmtiAgent.hpp @@ -52,7 +52,6 @@ class JvmtiAgent : public CHeapObj { bool _xrun; JvmtiAgent* next() const; - void set_next(JvmtiAgent* agent); void convert_xrun_agent(); void set_xrun(); diff --git a/src/hotspot/share/prims/jvmtiAgentList.cpp b/src/hotspot/share/prims/jvmtiAgentList.cpp index a4b7606056d..7128dc8f5d1 100644 --- a/src/hotspot/share/prims/jvmtiAgentList.cpp +++ b/src/hotspot/share/prims/jvmtiAgentList.cpp @@ -31,7 +31,7 @@ #include "runtime/atomic.hpp" #include "runtime/os.inline.hpp" -JvmtiAgent* JvmtiAgentList::_list = nullptr; +JvmtiAgent* JvmtiAgentList::_head = nullptr; // Selection as a function of the filter. JvmtiAgent* JvmtiAgentList::Iterator::select(JvmtiAgent* agent) const { @@ -61,68 +61,59 @@ JvmtiAgent* JvmtiAgentList::Iterator::select(JvmtiAgent* agent) const { return nullptr; } -static inline JvmtiAgent* head(JvmtiAgent** list) { - assert(list != nullptr, "invariant"); - return Atomic::load_acquire(list); -} - -// The storage list is a single cas-linked-list, to allow for concurrent iterations. -// Especially during initial loading of agents, there exist an order requirement to iterate oldest -> newest. -// Our concurrent storage linked-list is newest -> oldest. -// The correct order is preserved by the iterator, by storing a filtered set of entries in a stack. -JvmtiAgentList::Iterator::Iterator(JvmtiAgent** list, Filter filter) : - _stack(new GrowableArrayCHeap(16)), _filter(filter) { - JvmtiAgent* next = head(list); - while (next != nullptr) { - next = select(next); - if (next != nullptr) { - _stack->push(next); - next = next->next(); - } - } +JvmtiAgentList::Iterator::Iterator(JvmtiAgent* head, Filter filter) : _filter(filter), _next(select(head)) { } bool JvmtiAgentList::Iterator::has_next() const { - assert(_stack != nullptr, "invariant"); - return _stack->is_nonempty(); -} - -const JvmtiAgent* JvmtiAgentList::Iterator::next() const { - assert(has_next(), "invariant"); - return _stack->pop(); + return _next != nullptr; } JvmtiAgent* JvmtiAgentList::Iterator::next() { - return const_cast(const_cast(this)->next()); + assert(_next != nullptr, "must be"); + JvmtiAgent* result = _next; + _next = select(_next->next()); + return result; + } JvmtiAgentList::Iterator JvmtiAgentList::agents() { - return Iterator(&_list, Iterator::NOT_XRUN); + return Iterator(head(), Iterator::NOT_XRUN); } JvmtiAgentList::Iterator JvmtiAgentList::java_agents() { - return Iterator(&_list, Iterator::JAVA); + return Iterator(head(), Iterator::JAVA); } JvmtiAgentList::Iterator JvmtiAgentList::native_agents() { - return Iterator(&_list, Iterator::NATIVE); + return Iterator(head(), Iterator::NATIVE); } JvmtiAgentList::Iterator JvmtiAgentList::xrun_agents() { - return Iterator(&_list, Iterator::XRUN); + return Iterator(head(), Iterator::XRUN); } JvmtiAgentList::Iterator JvmtiAgentList::all() { - return Iterator(&_list, Iterator::ALL); + return Iterator(head(), Iterator::ALL); } void JvmtiAgentList::add(JvmtiAgent* agent) { assert(agent != nullptr, "invariant"); - JvmtiAgent* next; - do { - next = head(&_list); - agent->set_next(next); - } while (Atomic::cmpxchg(&_list, next, agent) != next); + + // address of the pointer to add new agent (&_head when the list is empty or &agent->_next of the last agent in the list) + JvmtiAgent** tail_ptr = &_head; + while (true) { + JvmtiAgent* next = Atomic::load(tail_ptr); + if (next == nullptr) { + // *tail_ptr == nullptr here + if (Atomic::cmpxchg(tail_ptr, (JvmtiAgent*)nullptr, agent) != nullptr) { + // another thread added an agent, reload next from tail_ptr + continue; + } + // successfully set, exit + break; + } + tail_ptr = &next->_next; + } } void JvmtiAgentList::add(const char* name, const char* options, bool absolute_path) { @@ -143,6 +134,10 @@ static void assert_initialized(JvmtiAgentList::Iterator& it) { } #endif +JvmtiAgent* JvmtiAgentList::head() { + return Atomic::load_acquire(&_head); +} + // In case an agent did not enable the VMInit callback, or if it is an -Xrun agent, // it gets an initializiation timestamp here. void JvmtiAgentList::initialize() { @@ -283,6 +278,6 @@ void JvmtiAgentList::disable_agent_list() { assert(CDSConfig::is_dumping_final_static_archive(), "use this only for -XX:AOTMode=create!"); assert(!Universe::is_bootstrapping() && !Universe::is_fully_initialized(), "must do this very early"); log_info(aot)("Disabled all JVMTI agents during -XX:AOTMode=create"); - _list = nullptr; // Pretend that no agents have been added. + _head = nullptr; // Pretend that no agents have been added. #endif } diff --git a/src/hotspot/share/prims/jvmtiAgentList.hpp b/src/hotspot/share/prims/jvmtiAgentList.hpp index f8199ddb1a7..f757020c2a1 100644 --- a/src/hotspot/share/prims/jvmtiAgentList.hpp +++ b/src/hotspot/share/prims/jvmtiAgentList.hpp @@ -25,15 +25,12 @@ #ifndef SHARE_PRIMS_JVMTIAGENTLIST_HPP #define SHARE_PRIMS_JVMTIAGENTLIST_HPP -#include "nmt/memTag.hpp" #include "prims/jvmtiAgent.hpp" -#include "utilities/growableArray.hpp" class JvmtiEnv; -// Maintains a single cas linked-list of JvmtiAgents. +// Maintains thread-safe linked list of JvmtiAgents. class JvmtiAgentList : AllStatic { - friend class Iterator; friend class JvmtiExport; public: class Iterator { @@ -46,20 +43,20 @@ class JvmtiAgentList : AllStatic { NOT_XRUN, ALL }; - GrowableArrayCHeap* _stack; const Filter _filter; - Iterator() : _stack(nullptr), _filter(ALL) {} - Iterator(JvmtiAgent** list, Filter filter); + JvmtiAgent* _next; + Iterator(): _filter(ALL), _next(nullptr) {} + Iterator(JvmtiAgent* head, Filter filter); JvmtiAgent* select(JvmtiAgent* agent) const; public: bool has_next() const NOT_JVMTI_RETURN_(false); JvmtiAgent* next() NOT_JVMTI_RETURN_(nullptr); - const JvmtiAgent* next() const NOT_JVMTI_RETURN_(nullptr); - ~Iterator() { delete _stack; } }; private: - static JvmtiAgent* _list; + static JvmtiAgent* _head; + + static JvmtiAgent* head(); static void initialize(); static void convert_xrun_agents(); diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index d8011174863..21a142df4f3 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -22,7 +22,6 @@ * */ -#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/modules.hpp" @@ -675,7 +674,7 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) { // add the jar file to the bootclasspath log_info(class, load)("opened: %s", zip_entry->name()); #if INCLUDE_CDS - ClassLoaderExt::append_boot_classpath(zip_entry); + ClassLoader::append_boot_classpath(zip_entry); #else ClassLoader::add_to_boot_append_entries(zip_entry); #endif @@ -2764,9 +2763,11 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth int result_length = ik->methods()->length(); jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); int index; - bool jmethodids_found = true; int skipped = 0; // skip overpass methods + // Make jmethodIDs for all non-overpass methods. + ik->make_methods_jmethod_ids(); + for (index = 0; index < result_length; index++) { Method* m = ik->methods()->at(index); // Depending on can_maintain_original_method_order capability use the original @@ -2779,20 +2780,8 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth skipped++; continue; } - jmethodID id; - if (jmethodids_found) { - id = m->find_jmethod_id_or_null(); - if (id == nullptr) { - // If we find an uninitialized value, make sure there is - // enough space for all the uninitialized values we might - // find. - ik->ensure_space_for_methodids(index); - jmethodids_found = false; - id = m->jmethod_id(); - } - } else { - id = m->jmethod_id(); - } + jmethodID id = m->find_jmethod_id_or_null(); + assert(id != nullptr, "should be created above"); result_list[result_index] = id; } diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index 13822f73f77..10614f445d3 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -943,12 +943,12 @@ class JvmtiClassFileLoadHookPoster : public StackObj { ModuleEntry* module_entry = InstanceKlass::cast(klass)->module(); assert(module_entry != nullptr, "module_entry should always be set"); if (module_entry->is_named() && - module_entry->module() != nullptr && + module_entry->module_oop() != nullptr && !module_entry->has_default_read_edges()) { if (!module_entry->set_has_default_read_edges()) { // We won a potential race. // Add read edges to the unnamed modules of the bootstrap and app class loaders - Handle class_module(_thread, module_entry->module()); // Obtain j.l.r.Module + Handle class_module(_thread, module_entry->module_oop()); // Obtain j.l.r.Module JvmtiExport::add_default_read_edges(class_module, _thread); } } diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index 0059636099e..d20de5f44a3 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -120,6 +120,7 @@ address JvmtiBreakpoint::getBcp() const { } void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { + assert(!_method->is_old(), "the breakpoint method shouldn't be old"); ((Method*)_method->*meth_act)(_bci); // add/remove breakpoint to/from versions of the method that are EMCP. @@ -183,8 +184,16 @@ void JvmtiBreakpoint::print_on(outputStream* out) const { // // Modify the Breakpoints data structure at a safepoint // +// The caller of VM_ChangeBreakpoints operation should ensure that +// _bp.method is preserved until VM_ChangeBreakpoints is processed. void VM_ChangeBreakpoints::doit() { + if (_bp->method()->is_old()) { + // The bp->_method became old because VMOp with class redefinition happened for this class + // after JvmtiBreakpoint was created but before JVM_ChangeBreakpoints started. + // All class breakpoints are cleared during redefinition, so don't set/clear this breakpoint. + return; + } switch (_operation) { case SET_BREAKPOINT: _breakpoints->set_at_safepoint(*_bp); @@ -249,6 +258,9 @@ int JvmtiBreakpoints::set(JvmtiBreakpoint& bp) { if (find(bp) != -1) { return JVMTI_ERROR_DUPLICATE; } + + // Ensure that bp._method is not deallocated before VM_ChangeBreakpoints::doit(). + methodHandle mh(Thread::current(), bp.method()); VM_ChangeBreakpoints set_breakpoint(VM_ChangeBreakpoints::SET_BREAKPOINT, &bp); VMThread::execute(&set_breakpoint); return JVMTI_ERROR_NONE; @@ -259,6 +271,8 @@ int JvmtiBreakpoints::clear(JvmtiBreakpoint& bp) { return JVMTI_ERROR_NOT_FOUND; } + // Ensure that bp._method is not deallocated before VM_ChangeBreakpoints::doit(). + methodHandle mh(Thread::current(), bp.method()); VM_ChangeBreakpoints clear_breakpoint(VM_ChangeBreakpoints::CLEAR_BREAKPOINT, &bp); VMThread::execute(&clear_breakpoint); return JVMTI_ERROR_NONE; diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 3b5944288d4..f483ef58d5b 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -3838,6 +3838,13 @@ void VM_RedefineClasses::AdjustAndCleanMetadata::do_klass(Klass* k) { void VM_RedefineClasses::update_jmethod_ids() { for (int j = 0; j < _matching_methods_length; ++j) { Method* old_method = _matching_old_methods[j]; + // The method_idnum should be within the range of 1..number-of-methods + // until incremented later for obsolete methods. + // The increment is so if a jmethodID is created for an old obsolete method + // it gets a new jmethodID cache slot in the InstanceKlass. + // They're cleaned out later when all methods of the previous version are purged. + assert(old_method->method_idnum() <= _old_methods->length(), + "shouldn't be incremented yet for obsolete methods"); jmethodID jmid = old_method->find_jmethod_id_or_null(); if (jmid != nullptr) { // There is a jmethodID, change it to point to the new method diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index d3bf8862d37..477633620da 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -71,6 +71,67 @@ typedef ObjectBitSet JVMTIBitSet; + +// Helper class to store objects to visit. +class JvmtiHeapwalkVisitStack { +private: + enum { + initial_visit_stack_size = 4000 + }; + + GrowableArray* _visit_stack; + JVMTIBitSet _bitset; + + static GrowableArray* create_visit_stack() { + return new (mtServiceability) GrowableArray(initial_visit_stack_size, mtServiceability); + } + +public: + JvmtiHeapwalkVisitStack(): _visit_stack(create_visit_stack()) { + } + ~JvmtiHeapwalkVisitStack() { + if (_visit_stack != nullptr) { + delete _visit_stack; + } + } + + bool is_empty() const { + return _visit_stack->is_empty(); + } + + void push(const JvmtiHeapwalkObject& obj) { + _visit_stack->push(obj); + } + + // If the object hasn't been visited then push it onto the visit stack + // so that it will be visited later. + void check_for_visit(const JvmtiHeapwalkObject& obj) { + if (!is_visited(obj)) { + _visit_stack->push(obj); + } + } + + JvmtiHeapwalkObject pop() { + return _visit_stack->pop(); + } + + bool is_visited(const JvmtiHeapwalkObject& obj) /*const*/ { // TODO: _bitset.is_marked() should be const + // The method is called only for objects from visit_stack to ensure an object is not visited twice. + // Flat objects can be added to visit_stack only when we visit their holder object, so we cannot get duplicate reference to it. + if (obj.is_flat()) { + return false; + } + return _bitset.is_marked(obj.obj()); + } + + void mark_visited(const JvmtiHeapwalkObject& obj) { + if (!obj.is_flat()) { + _bitset.mark_obj(obj.obj()); + } + } +}; + + bool JvmtiTagMap::_has_object_free_events = false; // create a JvmtiTagMap @@ -78,12 +139,14 @@ JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) : _env(env), _lock(Mutex::nosafepoint, "JvmtiTagMap_lock"), _needs_cleaning(false), - _posting_events(false) { + _posting_events(false), + _converting_flat_object(false) { assert(JvmtiThreadState_lock->is_locked(), "sanity check"); assert(((JvmtiEnvBase *)env)->tag_map() == nullptr, "tag map already exists for environment"); _hashmap = new JvmtiTagMapTable(); + _flat_hashmap = new JvmtiFlatTagMapTable(); // finally add us to the environment ((JvmtiEnvBase *)env)->release_set_tag_map(this); @@ -99,6 +162,7 @@ JvmtiTagMap::~JvmtiTagMap() { // finally destroy the hashmap delete _hashmap; _hashmap = nullptr; + delete _flat_hashmap; } // Called by env_dispose() to reclaim memory before deallocation. @@ -107,6 +171,7 @@ JvmtiTagMap::~JvmtiTagMap() { void JvmtiTagMap::clear() { MutexLocker ml(lock(), Mutex::_no_safepoint_check_flag); _hashmap->clear(); + _flat_hashmap->clear(); } // returns the tag map for the given environments. If the tag map @@ -125,15 +190,10 @@ JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) { return tag_map; } -// iterate over all entries in the tag map. -void JvmtiTagMap::entry_iterate(JvmtiTagMapKeyClosure* closure) { - hashmap()->entry_iterate(closure); -} - // returns true if the hashmaps are empty -bool JvmtiTagMap::is_empty() { +bool JvmtiTagMap::is_empty() const { assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking"); - return hashmap()->is_empty(); + return _hashmap->is_empty() && _flat_hashmap->is_empty(); } // This checks for posting before operations that use @@ -167,13 +227,187 @@ void JvmtiTagMap::check_hashmaps_for_heapwalk(GrowableArray* objects) { } } -// Return the tag value for an object, or 0 if the object is -// not tagged -// -static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) { - return tag_map->hashmap()->find(o); +// Converts entries from JvmtiFlatTagMapTable to JvmtiTagMapTable in batches. +// 1. (JvmtiTagMap is locked) +// reads entries from JvmtiFlatTagMapTable (describe flat value objects); +// 2. (JvmtiTagMap is unlocked) +// creates heap-allocated copies of the flat object; +// 3. (JvmtiTagMap is locked) +// ensures source entry still exists, removes it from JvmtiFlatTagMapTable, adds new entry to JvmtiTagMapTable. +// If some error occurs in step 2 (OOM?), the process stops. +class JvmtiTagMapFlatEntryConverter: public StackObj { +private: + struct Entry { + // source flat value object + Handle holder; + int offset; + InlineKlass* inline_klass; + LayoutKind layout_kind; + // converted heap-allocated object + Handle dst; + + Entry(): holder(), offset(0), inline_klass(nullptr), dst() {} + Entry(Handle holder, int offset, InlineKlass* inline_klass, LayoutKind lk) + : holder(holder), offset(offset), inline_klass(inline_klass), layout_kind(lk), dst() {} + }; + + int _batch_size; + GrowableArray _entries; + bool _has_error; + +public: + JvmtiTagMapFlatEntryConverter(int batch_size): _batch_size(batch_size), _entries(batch_size, mtServiceability), _has_error(false) { } + ~JvmtiTagMapFlatEntryConverter() {} + + // returns false if there is nothing to convert + bool import_entries(JvmtiFlatTagMapTable* table) { + if (_has_error) { + // stop the process to avoid infinite loop + return false; + } + + class Importer: public JvmtiFlatTagMapKeyClosure { + private: + GrowableArray& _entries; + int _batch_size; + public: + Importer(GrowableArray& entries, int batch_size): _entries(entries), _batch_size(batch_size) {} + + bool do_entry(JvmtiFlatTagMapKey& key, jlong& tag) { + Entry entry(Handle(Thread::current(), key.holder()), key.offset(), key.inline_klass(), key.layout_kind()); + _entries.append(entry); + + return _entries.length() < _batch_size; + } + } importer(_entries, _batch_size); + table->entry_iterate(&importer); + + return !_entries.is_empty(); + } + + void convert() { + for (int i = 0; i < _entries.length(); i++) { + EXCEPTION_MARK; + Entry& entry = _entries.at(i); + oop obj = entry.inline_klass->read_payload_from_addr(entry.holder(), entry.offset, entry.layout_kind, JavaThread::current()); + + if (HAS_PENDING_EXCEPTION) { + tty->print_cr("Exception in JvmtiTagMapFlatEntryConverter: "); + java_lang_Throwable::print(PENDING_EXCEPTION, tty); + tty->cr(); + CLEAR_PENDING_EXCEPTION; + // stop the conversion + _has_error = true; + } else { + entry.dst = Handle(Thread::current(), obj); + } + } + } + + // returns number of converted entries + int move(JvmtiFlatTagMapTable* src_table, JvmtiTagMapTable* dst_table) { + int count = 0; + for (int i = 0; i < _entries.length(); i++) { + Entry& entry = _entries.at(i); + if (entry.dst() == nullptr) { + // some error during conversion, skip the entry + continue; + } + JvmtiHeapwalkObject obj(entry.holder(), entry.offset, entry.inline_klass, entry.layout_kind); + jlong tag = src_table->remove(obj); + + if (tag != 0) { // ensure the entry is still in the src_table + dst_table->add(entry.dst(), tag); + count++; + } else { + + } + } + // and clean the array + _entries.clear(); + return count; + } +}; + + +void JvmtiTagMap::convert_flat_object_entries() { + Thread* current = Thread::current(); + assert(current->is_Java_thread(), "must be executed on JavaThread"); + + log_debug(jvmti, table)("convert_flat_object_entries, main table size = %d, flat table size = %d", + _hashmap->number_of_entries(), _flat_hashmap->number_of_entries()); + + { + MonitorLocker ml(lock(), Mutex::_no_safepoint_check_flag); + // If another thread is converting, let it finish. + while (_converting_flat_object) { + ml.wait(); + } + if (_flat_hashmap->is_empty()) { + // nothing to convert + return; + } + _converting_flat_object = true; + } + + const int BATCH_SIZE = 1024; + JvmtiTagMapFlatEntryConverter converter(BATCH_SIZE); + + int count = 0; + while (true) { + HandleMark hm(current); + { + MonitorLocker ml(lock(), Mutex::_no_safepoint_check_flag); + if (!converter.import_entries(_flat_hashmap)) { + break; + } + } + // Convert flat objects to heap-allocated without table lock (so agent callbacks can get/set tags). + converter.convert(); + { + MonitorLocker ml(lock(), Mutex::_no_safepoint_check_flag); + count += converter.move(_flat_hashmap, _hashmap); + } + } + + log_info(jvmti, table)("%d flat value objects are converted, flat table size = %d", + count, _flat_hashmap->number_of_entries()); + { + MonitorLocker ml(lock(), Mutex::_no_safepoint_check_flag); + _converting_flat_object = false; + ml.notify_all(); + } } +jlong JvmtiTagMap::find(const JvmtiHeapwalkObject& obj) const { + jlong tag = _hashmap->find(obj); + if (tag == 0 && obj.is_value()) { + tag = _flat_hashmap->find(obj); + } + return tag; +} + +void JvmtiTagMap::add(const JvmtiHeapwalkObject& obj, jlong tag) { + if (obj.is_flat()) { + // we may have tag for equal (non-flat) object in _hashmap, try to update it 1st + if (!_hashmap->update(obj, tag)) { + // no entry in _hashmap, add to _flat_hashmap + _flat_hashmap->add(obj, tag); + } + } else { + _hashmap->add(obj, tag); + } +} + +void JvmtiTagMap::remove(const JvmtiHeapwalkObject& obj) { + if (!_hashmap->remove(obj)) { + if (obj.is_value()) { + _flat_hashmap->remove(obj); + } + } +} + + // A CallbackWrapper is a support class for querying and tagging an object // around a callback to a profiler. The constructor does pre-callback // work to get the tag value, klass tag value, ... and the destructor @@ -192,8 +426,7 @@ static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) { class CallbackWrapper : public StackObj { private: JvmtiTagMap* _tag_map; - JvmtiTagMapTable* _hashmap; - oop _o; + const JvmtiHeapwalkObject& _o; jlong _obj_size; jlong _obj_tag; jlong _klass_tag; @@ -202,34 +435,36 @@ class CallbackWrapper : public StackObj { JvmtiTagMap* tag_map() const { return _tag_map; } // invoked post-callback to tag, untag, or update the tag of an object - void inline post_callback_tag_update(oop o, JvmtiTagMapTable* hashmap, - jlong obj_tag); + void inline post_callback_tag_update(const JvmtiHeapwalkObject& o, JvmtiTagMap* tag_map, jlong obj_tag); + public: - CallbackWrapper(JvmtiTagMap* tag_map, oop o) { + CallbackWrapper(JvmtiTagMap* tag_map, const JvmtiHeapwalkObject& o) + : _tag_map(tag_map), _o(o) + { assert(Thread::current()->is_VM_thread() || tag_map->is_locked(), "MT unsafe or must be VM thread"); - // object to tag - _o = o; - // object size - _obj_size = (jlong)_o->size() * wordSize; - - // record the context - _tag_map = tag_map; - _hashmap = tag_map->hashmap(); + if (!o.is_flat()) { + // common case: we have oop + _obj_size = (jlong)o.obj()->size() * wordSize; + } else { + // flat value object, we know its InstanceKlass + assert(_o.inline_klass() != nullptr, "must be"); + _obj_size = _o.inline_klass()->size() * wordSize;; + } // get object tag - _obj_tag = _hashmap->find(_o); + _obj_tag = _tag_map->find(_o); // get the class and the class's tag value assert(vmClasses::Class_klass()->is_mirror_instance_klass(), "Is not?"); - _klass_tag = tag_for(tag_map, _o->klass()->java_mirror()); + _klass_tag = _tag_map->find(_o.klass()->java_mirror()); } ~CallbackWrapper() { - post_callback_tag_update(_o, _hashmap, _obj_tag); + post_callback_tag_update(_o, _tag_map, _obj_tag); } inline jlong* obj_tag_p() { return &_obj_tag; } @@ -239,17 +474,17 @@ class CallbackWrapper : public StackObj { }; // callback post-callback to tag, untag, or update the tag of an object -void inline CallbackWrapper::post_callback_tag_update(oop o, - JvmtiTagMapTable* hashmap, +void inline CallbackWrapper::post_callback_tag_update(const JvmtiHeapwalkObject& o, + JvmtiTagMap* tag_map, jlong obj_tag) { if (obj_tag == 0) { // callback has untagged the object, remove the entry if present - hashmap->remove(o); + tag_map->remove(o); } else { // object was previously tagged or not present - the callback may have // changed the tag value assert(Thread::current()->is_VM_thread(), "must be VMThread"); - hashmap->add(o, obj_tag); + tag_map->add(o, obj_tag); } } @@ -271,9 +506,8 @@ void inline CallbackWrapper::post_callback_tag_update(oop o, // class TwoOopCallbackWrapper : public CallbackWrapper { private: + const JvmtiHeapwalkObject& _referrer; bool _is_reference_to_self; - JvmtiTagMapTable* _referrer_hashmap; - oop _referrer; jlong _referrer_obj_tag; jlong _referrer_klass_tag; jlong* _referrer_tag_p; @@ -281,8 +515,8 @@ class TwoOopCallbackWrapper : public CallbackWrapper { bool is_reference_to_self() const { return _is_reference_to_self; } public: - TwoOopCallbackWrapper(JvmtiTagMap* tag_map, oop referrer, oop o) : - CallbackWrapper(tag_map, o) + TwoOopCallbackWrapper(JvmtiTagMap* tag_map, const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& o) : + CallbackWrapper(tag_map, o), _referrer(referrer) { // self reference needs to be handled in a special way _is_reference_to_self = (referrer == o); @@ -291,24 +525,20 @@ class TwoOopCallbackWrapper : public CallbackWrapper { _referrer_klass_tag = klass_tag(); _referrer_tag_p = obj_tag_p(); } else { - _referrer = referrer; - // record the context - _referrer_hashmap = tag_map->hashmap(); - // get object tag - _referrer_obj_tag = _referrer_hashmap->find(_referrer); + _referrer_obj_tag = tag_map->find(_referrer); _referrer_tag_p = &_referrer_obj_tag; // get referrer class tag. - _referrer_klass_tag = tag_for(tag_map, _referrer->klass()->java_mirror()); + _referrer_klass_tag = tag_map->find(_referrer.klass()->java_mirror()); } } ~TwoOopCallbackWrapper() { if (!is_reference_to_self()) { post_callback_tag_update(_referrer, - _referrer_hashmap, + tag_map(), _referrer_obj_tag); } } @@ -336,17 +566,15 @@ void JvmtiTagMap::set_tag(jobject object, jlong tag) { // resolve the object oop o = JNIHandles::resolve_non_null(object); - // see if the object is already tagged - JvmtiTagMapTable* hashmap = _hashmap; - + JvmtiHeapwalkObject obj(o); if (tag == 0) { // remove the entry if present - hashmap->remove(o); + _hashmap->remove(obj); } else { // if the object is already tagged or not present then we add/update // the tag - hashmap->add(o, tag); + add(obj, tag); } } @@ -362,7 +590,7 @@ jlong JvmtiTagMap::get_tag(jobject object) { // resolve the object oop o = JNIHandles::resolve_non_null(object); - return tag_for(this, o); + return find(o); } @@ -375,13 +603,28 @@ class ClassFieldDescriptor: public CHeapObj { int _field_index; int _field_offset; char _field_type; + InlineKlass* _inline_klass; // nullptr for heap object + LayoutKind _layout_kind; public: - ClassFieldDescriptor(int index, char type, int offset) : - _field_index(index), _field_offset(offset), _field_type(type) { + ClassFieldDescriptor(int index, const FieldStreamBase& fld) : + _field_index(index), _field_offset(fld.offset()), _field_type(fld.signature()->char_at(0)) { + if (fld.is_flat()) { + const fieldDescriptor& fd = fld.field_descriptor(); + InstanceKlass* holder_klass = fd.field_holder(); + InlineLayoutInfo* layout_info = holder_klass->inline_layout_info_adr(fd.index()); + _inline_klass = layout_info->klass(); + _layout_kind = layout_info->kind(); + } else { + _inline_klass = nullptr; + _layout_kind = LayoutKind::REFERENCE; + } } int field_index() const { return _field_index; } char field_type() const { return _field_type; } int field_offset() const { return _field_offset; } + bool is_flat() const { return _inline_klass != nullptr; } + InlineKlass* inline_klass() const { return _inline_klass; } + LayoutKind layout_kind() const { return _layout_kind; } }; class ClassFieldMap: public CHeapObj { @@ -400,7 +643,7 @@ class ClassFieldMap: public CHeapObj { static int interfaces_field_count(InstanceKlass* ik); // add a field - void add(int index, char type, int offset); + void add(int index, const FieldStreamBase& fld); public: ~ClassFieldMap(); @@ -411,7 +654,7 @@ class ClassFieldMap: public CHeapObj { // functions to create maps of static or instance fields static ClassFieldMap* create_map_of_static_fields(Klass* k); - static ClassFieldMap* create_map_of_instance_fields(oop obj); + static ClassFieldMap* create_map_of_instance_fields(Klass* k); }; ClassFieldMap::ClassFieldMap() { @@ -436,8 +679,8 @@ int ClassFieldMap::interfaces_field_count(InstanceKlass* ik) { return count; } -void ClassFieldMap::add(int index, char type, int offset) { - ClassFieldDescriptor* field = new ClassFieldDescriptor(index, type, offset); +void ClassFieldMap::add(int index, const FieldStreamBase& fld) { + ClassFieldDescriptor* field = new ClassFieldDescriptor(index, fld); _fields->append(field); } @@ -462,7 +705,7 @@ ClassFieldMap* ClassFieldMap::create_map_of_static_fields(Klass* k) { if (!fld.access_flags().is_static()) { continue; } - field_map->add(index, fld.signature()->char_at(0), fld.offset()); + field_map->add(index, fld); } return field_map; @@ -471,8 +714,8 @@ ClassFieldMap* ClassFieldMap::create_map_of_static_fields(Klass* k) { // Returns a heap allocated ClassFieldMap to describe the instance fields // of the given class. All instance fields are included (this means public // and private fields declared in superclasses too). -ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) { - InstanceKlass* ik = InstanceKlass::cast(obj->klass()); +ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(Klass* k) { + InstanceKlass* ik = InstanceKlass::cast(k); // create the field map ClassFieldMap* field_map = new ClassFieldMap(); @@ -492,7 +735,7 @@ ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) { if (fld.access_flags().is_static()) { continue; } - field_map->add(start_index + index, fld.signature()->char_at(0), fld.offset()); + field_map->add(start_index + index, fld); } // update total_field_number for superclass (decrease by the field count in the current class) total_field_number = start_index; @@ -522,9 +765,9 @@ class JvmtiCachedClassFieldMap : public CHeapObj { static void add_to_class_list(InstanceKlass* ik); public: - // returns the field map for a given object (returning map cached + // returns the field map for a given klass (returning map cached // by InstanceKlass if possible - static ClassFieldMap* get_map_of_instance_fields(oop obj); + static ClassFieldMap* get_map_of_instance_fields(Klass* k); // removes the field map from all instanceKlasses - should be // called before VM operation completes @@ -576,13 +819,12 @@ void JvmtiCachedClassFieldMap::add_to_class_list(InstanceKlass* ik) { _class_list->push(ik); } -// returns the instance field map for the given object +// returns the instance field map for the given klass // (returns field map cached by the InstanceKlass if possible) -ClassFieldMap* JvmtiCachedClassFieldMap::get_map_of_instance_fields(oop obj) { +ClassFieldMap* JvmtiCachedClassFieldMap::get_map_of_instance_fields(Klass *k) { assert(Thread::current()->is_VM_thread(), "must be VMThread"); assert(ClassFieldMapCacheMark::is_active(), "ClassFieldMapCacheMark not active"); - Klass* k = obj->klass(); InstanceKlass* ik = InstanceKlass::cast(k); // return cached map if possible @@ -591,7 +833,7 @@ ClassFieldMap* JvmtiCachedClassFieldMap::get_map_of_instance_fields(oop obj) { assert(cached_map->field_map() != nullptr, "missing field list"); return cached_map->field_map(); } else { - ClassFieldMap* field_map = ClassFieldMap::create_map_of_instance_fields(obj); + ClassFieldMap* field_map = ClassFieldMap::create_map_of_instance_fields(k); cached_map = new JvmtiCachedClassFieldMap(field_map); ik->set_jvmti_cached_class_field_map(cached_map); add_to_class_list(ik); @@ -643,9 +885,9 @@ static inline bool is_filtered_by_heap_filter(jlong obj_tag, } // helper function to indicate if an object is filtered by a klass filter -static inline bool is_filtered_by_klass_filter(oop obj, Klass* klass_filter) { +static inline bool is_filtered_by_klass_filter(const JvmtiHeapwalkObject& obj, Klass* klass_filter) { if (klass_filter != nullptr) { - if (obj->klass() != klass_filter) { + if (obj.klass() != klass_filter) { return true; } } @@ -676,9 +918,11 @@ static inline void copy_to_jvalue(jvalue *v, address addr, jvmtiPrimitiveType va // returns visit control flags static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb, CallbackWrapper* wrapper, - oop str, + const JvmtiHeapwalkObject& obj, void* user_data) { + assert(!obj.is_flat(), "cannot be flat"); + oop str = obj.obj(); assert(str->klass() == vmClasses::String_klass(), "not a string"); typeArrayOop s_value = java_lang_String::value(str); @@ -727,13 +971,14 @@ static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb, // returns visit control flags static jint invoke_array_primitive_value_callback(jvmtiArrayPrimitiveValueCallback cb, CallbackWrapper* wrapper, - oop obj, + const JvmtiHeapwalkObject& obj, void* user_data) { - assert(obj->is_typeArray(), "not a primitive array"); + assert(!obj.is_flat(), "cannot be flat"); + assert(obj.obj()->is_typeArray(), "not a primitive array"); // get base address of first element - typeArrayOop array = typeArrayOop(obj); + typeArrayOop array = typeArrayOop(obj.obj()); BasicType type = TypeArrayKlass::cast(array->klass())->element_type(); void* elements = array->base(type); @@ -823,7 +1068,7 @@ static jint invoke_primitive_field_callback_for_static_fields // of a given object static jint invoke_primitive_field_callback_for_instance_fields( CallbackWrapper* wrapper, - oop obj, + const JvmtiHeapwalkObject& obj, jvmtiPrimitiveFieldCallback cb, void* user_data) { @@ -831,7 +1076,7 @@ static jint invoke_primitive_field_callback_for_instance_fields( static jvmtiHeapReferenceInfo reference_info = { 0 }; // get the map of the instance fields - ClassFieldMap* fields = JvmtiCachedClassFieldMap::get_map_of_instance_fields(obj); + ClassFieldMap* fields = JvmtiCachedClassFieldMap::get_map_of_instance_fields(obj.klass()); // invoke the callback for each instance primitive field for (int i=0; ifield_count(); i++) { @@ -845,9 +1090,8 @@ static jint invoke_primitive_field_callback_for_instance_fields( // one-to-one mapping jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type; - // get offset and field value - int offset = field->field_offset(); - address addr = cast_from_oop
(obj) + offset; + // get field value + address addr = cast_from_oop
(obj.obj()) + obj.offset() + field->field_offset(); jvalue value; copy_to_jvalue(&value, addr, value_type); @@ -944,6 +1188,7 @@ class IterateOverHeapObjectClosure: public ObjectClosure { // invoked for each object in the heap void IterateOverHeapObjectClosure::do_object(oop o) { + assert(o != nullptr, "Heap iteration should never produce null!"); // check if iteration has been halted if (is_iteration_aborted()) return; @@ -953,14 +1198,15 @@ void IterateOverHeapObjectClosure::do_object(oop o) { } // skip if object is a dormant shared object whose mirror hasn't been loaded - if (o != nullptr && o->klass()->java_mirror() == nullptr) { + if (o->klass()->java_mirror() == nullptr) { log_debug(aot, heap)("skipped dormant archived object " INTPTR_FORMAT " (%s)", p2i(o), o->klass()->external_name()); return; } // prepare for the calllback - CallbackWrapper wrapper(tag_map(), o); + JvmtiHeapwalkObject wrapper_obj(o); + CallbackWrapper wrapper(tag_map(), wrapper_obj); // if the object is tagged and we're only interested in untagged objects // then don't invoke the callback. Similarly, if the object is untagged @@ -1012,6 +1258,10 @@ class IterateThroughHeapObjectClosure: public ObjectClosure { return is_abort; } + void visit_object(const JvmtiHeapwalkObject& obj); + void visit_flat_fields(const JvmtiHeapwalkObject& obj); + void visit_flat_array_elements(const JvmtiHeapwalkObject& obj); + public: IterateThroughHeapObjectClosure(JvmtiTagMap* tag_map, Klass* klass, @@ -1027,24 +1277,29 @@ class IterateThroughHeapObjectClosure: public ObjectClosure { { } - void do_object(oop o); + void do_object(oop obj); }; // invoked for each object in the heap void IterateThroughHeapObjectClosure::do_object(oop obj) { + assert(obj != nullptr, "Heap iteration should never produce null!"); // check if iteration has been halted if (is_iteration_aborted()) return; - // apply class filter - if (is_filtered_by_klass_filter(obj, klass())) return; - // skip if object is a dormant shared object whose mirror hasn't been loaded - if (obj != nullptr && obj->klass()->java_mirror() == nullptr) { + if (obj != nullptr && obj->klass()->java_mirror() == nullptr) { log_debug(aot, heap)("skipped dormant archived object " INTPTR_FORMAT " (%s)", p2i(obj), obj->klass()->external_name()); return; } + visit_object(obj); +} + +void IterateThroughHeapObjectClosure::visit_object(const JvmtiHeapwalkObject& obj) { + // apply class filter + if (is_filtered_by_klass_filter(obj, klass())) return; + // prepare for callback CallbackWrapper wrapper(tag_map(), obj); @@ -1054,8 +1309,8 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { } // for arrays we need the length, otherwise -1 - bool is_array = obj->is_array(); - int len = is_array ? arrayOop(obj)->length() : -1; + bool is_array = obj.klass()->is_array_klass(); + int len = is_array ? arrayOop(obj.obj())->length() : -1; // invoke the object callback (if callback is provided) if (callbacks()->heap_iteration_callback != nullptr) { @@ -1069,19 +1324,20 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { } // for objects and classes we report primitive fields if callback provided - if (callbacks()->primitive_field_callback != nullptr && obj->is_instance()) { + if (callbacks()->primitive_field_callback != nullptr && obj.klass()->is_instance_klass()) { jint res; jvmtiPrimitiveFieldCallback cb = callbacks()->primitive_field_callback; - if (obj->klass() == vmClasses::Class_klass()) { + if (obj.klass() == vmClasses::Class_klass()) { + assert(!obj.is_flat(), "Class object cannot be flattened"); res = invoke_primitive_field_callback_for_static_fields(&wrapper, - obj, - cb, - (void*)user_data()); + obj.obj(), + cb, + (void*)user_data()); } else { res = invoke_primitive_field_callback_for_instance_fields(&wrapper, - obj, - cb, - (void*)user_data()); + obj, + cb, + (void*)user_data()); } if (check_flags_for_abort(res)) return; } @@ -1089,28 +1345,108 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { // string callback if (!is_array && callbacks()->string_primitive_value_callback != nullptr && - obj->klass() == vmClasses::String_klass()) { + obj.klass() == vmClasses::String_klass()) { jint res = invoke_string_value_callback( callbacks()->string_primitive_value_callback, &wrapper, obj, - (void*)user_data() ); + (void*)user_data()); if (check_flags_for_abort(res)) return; } // array callback if (is_array && callbacks()->array_primitive_value_callback != nullptr && - obj->is_typeArray()) { + obj.klass()->is_typeArray_klass()) { jint res = invoke_array_primitive_value_callback( callbacks()->array_primitive_value_callback, &wrapper, obj, - (void*)user_data() ); + (void*)user_data()); if (check_flags_for_abort(res)) return; } -}; + // All info for the object is reported. + + // If the object has flat fields, report them as heap objects. + if (obj.klass()->is_instance_klass()) { + if (InstanceKlass::cast(obj.klass())->has_inline_type_fields()) { + visit_flat_fields(obj); + // check if iteration has been halted + if (is_iteration_aborted()) { + return; + } + } + } + // If the object is flat array, report all elements as heap objects. + if (is_array && obj.obj()->is_flatArray()) { + assert(!obj.is_flat(), "Array object cannot be flattened"); + visit_flat_array_elements(obj); + } +} + +void IterateThroughHeapObjectClosure::visit_flat_fields(const JvmtiHeapwalkObject& obj) { + // iterate over instance fields + ClassFieldMap* fields = JvmtiCachedClassFieldMap::get_map_of_instance_fields(obj.klass()); + for (int i = 0; i < fields->field_count(); i++) { + ClassFieldDescriptor* field = fields->field_at(i); + // skip non-flat and (for safety) primitive fields + if (!field->is_flat() || is_primitive_field_type(field->field_type())) { + continue; + } + + int field_offset = field->field_offset(); + if (obj.is_flat()) { + // the object is inlined, its fields are stored without the header + field_offset += obj.offset() - obj.inline_klass()->payload_offset(); + } + // check for possible nulls + bool can_be_null = field->layout_kind() == LayoutKind::NULLABLE_ATOMIC_FLAT; + if (can_be_null) { + address payload = cast_from_oop
(obj.obj()) + field_offset; + if (field->inline_klass()->is_payload_marked_as_null(payload)) { + continue; + } + } + JvmtiHeapwalkObject field_obj(obj.obj(), field_offset, field->inline_klass(), field->layout_kind()); + + visit_object(field_obj); + + // check if iteration has been halted + if (is_iteration_aborted()) { + return; + } + } +} + +void IterateThroughHeapObjectClosure::visit_flat_array_elements(const JvmtiHeapwalkObject& obj) { + assert(!obj.is_flat() && obj.obj()->is_flatArray() , "sanity check"); + flatArrayOop array = flatArrayOop(obj.obj()); + FlatArrayKlass* faklass = FlatArrayKlass::cast(array->klass()); + InlineKlass* vk = InlineKlass::cast(faklass->element_klass()); + bool need_null_check = faklass->layout_kind() == LayoutKind::NULLABLE_ATOMIC_FLAT; + + for (int index = 0; index < array->length(); index++) { + address addr = (address)array->value_at_addr(index, faklass->layout_helper()); + // check for null + if (need_null_check) { + if (vk->is_payload_marked_as_null(addr)) { + continue; + } + } + + // offset in the array oop + int offset = (int)(addr - cast_from_oop
(array)); + JvmtiHeapwalkObject elem(obj.obj(), offset, vk, faklass->layout_kind()); + + visit_object(elem); + + // check if iteration has been halted + if (is_iteration_aborted()) { + return; + } + } +} // Deprecated function to iterate over all objects in the heap void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter, @@ -1135,6 +1471,8 @@ void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter, VM_HeapIterateOperation op(&blk, &dead_objects); VMThread::execute(&op); } + convert_flat_object_entries(); + // Post events outside of Heap_lock post_dead_objects(&dead_objects); } @@ -1162,6 +1500,8 @@ void JvmtiTagMap::iterate_through_heap(jint heap_filter, VM_HeapIterateOperation op(&blk, &dead_objects); VMThread::execute(&op); } + convert_flat_object_entries(); + // Post events outside of Heap_lock post_dead_objects(&dead_objects); } @@ -1175,7 +1515,7 @@ void JvmtiTagMap::remove_dead_entries_locked(GrowableArray* objects) { } log_info(jvmti, table)("TagMap table needs cleaning%s", ((objects != nullptr) ? " and posting" : "")); - hashmap()->remove_dead_entries(objects); + _hashmap->remove_dead_entries(objects); _needs_cleaning = false; } } @@ -1328,6 +1668,9 @@ class TagObjectCollector : public JvmtiTagMapKeyClosure { jvmtiError JvmtiTagMap::get_objects_with_tags(const jlong* tags, jint count, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { + // ensure flat object conversion is completed + convert_flat_object_entries(); + TagObjectCollector collector(env(), tags, count); { // iterate over all tagged objects @@ -1336,7 +1679,7 @@ jvmtiError JvmtiTagMap::get_objects_with_tags(const jlong* tags, // will race with the gc_notification thread in the tiny // window where the object is not marked but hasn't been notified that // it is collected yet. - entry_iterate(&collector); + _hashmap->entry_iterate(&collector); } return collector.result(count_ptr, object_result_ptr, tag_result_ptr); } @@ -1376,7 +1719,7 @@ class BasicHeapWalkContext: public HeapWalkContext { jvmtiObjectReferenceCallback _object_ref_callback; // used for caching - oop _last_referrer; + JvmtiHeapwalkObject _last_referrer; jlong _last_referrer_tag; public: @@ -1389,7 +1732,7 @@ class BasicHeapWalkContext: public HeapWalkContext { _heap_root_callback(heap_root_callback), _stack_ref_callback(stack_ref_callback), _object_ref_callback(object_ref_callback), - _last_referrer(nullptr), + _last_referrer(), _last_referrer_tag(0) { } @@ -1398,8 +1741,8 @@ class BasicHeapWalkContext: public HeapWalkContext { jvmtiStackReferenceCallback stack_ref_callback() const { return _stack_ref_callback; } jvmtiObjectReferenceCallback object_ref_callback() const { return _object_ref_callback; } - oop last_referrer() const { return _last_referrer; } - void set_last_referrer(oop referrer) { _last_referrer = referrer; } + JvmtiHeapwalkObject last_referrer() const { return _last_referrer; } + void set_last_referrer(const JvmtiHeapwalkObject& referrer) { _last_referrer = referrer; } jlong last_referrer_tag() const { return _last_referrer_tag; } void set_last_referrer_tag(jlong value) { _last_referrer_tag = value; } }; @@ -1472,80 +1815,87 @@ class CallbackInvoker : AllStatic { // context needed for all heap walks static JvmtiTagMap* _tag_map; static const void* _user_data; - static GrowableArray* _visit_stack; - static JVMTIBitSet* _bitset; + static JvmtiHeapwalkVisitStack* _visit_stack; // accessors static JvmtiTagMap* tag_map() { return _tag_map; } static const void* user_data() { return _user_data; } - static GrowableArray* visit_stack() { return _visit_stack; } + static JvmtiHeapwalkVisitStack* visit_stack() { return _visit_stack; } // if the object hasn't been visited then push it onto the visit stack // so that it will be visited later - static inline bool check_for_visit(oop obj) { - if (!_bitset->is_marked(obj)) visit_stack()->push(obj); + static inline bool check_for_visit(const JvmtiHeapwalkObject&obj) { + visit_stack()->check_for_visit(obj); return true; } + // return element count if the obj is array, -1 otherwise + static jint get_array_length(const JvmtiHeapwalkObject& obj) { + if (!obj.klass()->is_array_klass()) { + return -1; + } + assert(!obj.is_flat(), "array cannot be flat"); + return (jint)arrayOop(obj.obj())->length(); + } + + // invoke basic style callbacks static inline bool invoke_basic_heap_root_callback - (jvmtiHeapRootKind root_kind, oop obj); + (jvmtiHeapRootKind root_kind, const JvmtiHeapwalkObject& obj); static inline bool invoke_basic_stack_ref_callback (jvmtiHeapRootKind root_kind, jlong thread_tag, jint depth, jmethodID method, - int slot, oop obj); + int slot, const JvmtiHeapwalkObject& obj); static inline bool invoke_basic_object_reference_callback - (jvmtiObjectReferenceKind ref_kind, oop referrer, oop referree, jint index); + (jvmtiObjectReferenceKind ref_kind, const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index); // invoke advanced style callbacks static inline bool invoke_advanced_heap_root_callback - (jvmtiHeapReferenceKind ref_kind, oop obj); + (jvmtiHeapReferenceKind ref_kind, const JvmtiHeapwalkObject& obj); static inline bool invoke_advanced_stack_ref_callback (jvmtiHeapReferenceKind ref_kind, jlong thread_tag, jlong tid, int depth, - jmethodID method, jlocation bci, jint slot, oop obj); + jmethodID method, jlocation bci, jint slot, const JvmtiHeapwalkObject& obj); static inline bool invoke_advanced_object_reference_callback - (jvmtiHeapReferenceKind ref_kind, oop referrer, oop referree, jint index); + (jvmtiHeapReferenceKind ref_kind, const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index); // used to report the value of primitive fields static inline bool report_primitive_field - (jvmtiHeapReferenceKind ref_kind, oop obj, jint index, address addr, char type); + (jvmtiHeapReferenceKind ref_kind, const JvmtiHeapwalkObject& obj, jint index, address addr, char type); public: // initialize for basic mode static void initialize_for_basic_heap_walk(JvmtiTagMap* tag_map, - GrowableArray* visit_stack, const void* user_data, BasicHeapWalkContext context, - JVMTIBitSet* bitset); + JvmtiHeapwalkVisitStack* visit_stack); // initialize for advanced mode static void initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map, - GrowableArray* visit_stack, const void* user_data, AdvancedHeapWalkContext context, - JVMTIBitSet* bitset); + JvmtiHeapwalkVisitStack* visit_stack); // functions to report roots - static inline bool report_simple_root(jvmtiHeapReferenceKind kind, oop o); + static inline bool report_simple_root(jvmtiHeapReferenceKind kind, const JvmtiHeapwalkObject& o); static inline bool report_jni_local_root(jlong thread_tag, jlong tid, jint depth, - jmethodID m, oop o); + jmethodID m, const JvmtiHeapwalkObject& o); static inline bool report_stack_ref_root(jlong thread_tag, jlong tid, jint depth, - jmethodID method, jlocation bci, jint slot, oop o); + jmethodID method, jlocation bci, jint slot, const JvmtiHeapwalkObject& o); // functions to report references - static inline bool report_array_element_reference(oop referrer, oop referree, jint index); - static inline bool report_class_reference(oop referrer, oop referree); - static inline bool report_class_loader_reference(oop referrer, oop referree); - static inline bool report_signers_reference(oop referrer, oop referree); - static inline bool report_protection_domain_reference(oop referrer, oop referree); - static inline bool report_superclass_reference(oop referrer, oop referree); - static inline bool report_interface_reference(oop referrer, oop referree); - static inline bool report_static_field_reference(oop referrer, oop referree, jint slot); - static inline bool report_field_reference(oop referrer, oop referree, jint slot); - static inline bool report_constant_pool_reference(oop referrer, oop referree, jint index); - static inline bool report_primitive_array_values(oop array); - static inline bool report_string_value(oop str); - static inline bool report_primitive_instance_field(oop o, jint index, address value, char type); - static inline bool report_primitive_static_field(oop o, jint index, address value, char type); + static inline bool report_array_element_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index); + static inline bool report_class_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_class_loader_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_signers_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_protection_domain_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_superclass_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_interface_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree); + static inline bool report_static_field_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint slot); + static inline bool report_field_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint slot); + static inline bool report_constant_pool_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index); + static inline bool report_primitive_array_values(const JvmtiHeapwalkObject& array); + static inline bool report_string_value(const JvmtiHeapwalkObject& str); + static inline bool report_primitive_instance_field(const JvmtiHeapwalkObject& o, jint index, address value, char type); + static inline bool report_primitive_static_field(const JvmtiHeapwalkObject& o, jint index, address value, char type); }; // statics @@ -1554,42 +1904,37 @@ BasicHeapWalkContext CallbackInvoker::_basic_context; AdvancedHeapWalkContext CallbackInvoker::_advanced_context; JvmtiTagMap* CallbackInvoker::_tag_map; const void* CallbackInvoker::_user_data; -GrowableArray* CallbackInvoker::_visit_stack; -JVMTIBitSet* CallbackInvoker::_bitset; +JvmtiHeapwalkVisitStack* CallbackInvoker::_visit_stack; // initialize for basic heap walk (IterateOverReachableObjects et al) void CallbackInvoker::initialize_for_basic_heap_walk(JvmtiTagMap* tag_map, - GrowableArray* visit_stack, const void* user_data, BasicHeapWalkContext context, - JVMTIBitSet* bitset) { + JvmtiHeapwalkVisitStack* visit_stack) { _tag_map = tag_map; - _visit_stack = visit_stack; _user_data = user_data; _basic_context = context; _advanced_context.invalidate(); // will trigger assertion if used _heap_walk_type = basic; - _bitset = bitset; + _visit_stack = visit_stack; } // initialize for advanced heap walk (FollowReferences) void CallbackInvoker::initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map, - GrowableArray* visit_stack, const void* user_data, AdvancedHeapWalkContext context, - JVMTIBitSet* bitset) { + JvmtiHeapwalkVisitStack* visit_stack) { _tag_map = tag_map; - _visit_stack = visit_stack; _user_data = user_data; _advanced_context = context; _basic_context.invalidate(); // will trigger assertion if used _heap_walk_type = advanced; - _bitset = bitset; + _visit_stack = visit_stack; } // invoke basic style heap root callback -inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, oop obj) { +inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, const JvmtiHeapwalkObject& obj) { // if we heap roots should be reported jvmtiHeapRootCallback cb = basic_context()->heap_root_callback(); if (cb == nullptr) { @@ -1616,7 +1961,7 @@ inline bool CallbackInvoker::invoke_basic_stack_ref_callback(jvmtiHeapRootKind r jint depth, jmethodID method, int slot, - oop obj) { + const JvmtiHeapwalkObject& obj) { // if we stack refs should be reported jvmtiStackReferenceCallback cb = basic_context()->stack_ref_callback(); if (cb == nullptr) { @@ -1643,8 +1988,8 @@ inline bool CallbackInvoker::invoke_basic_stack_ref_callback(jvmtiHeapRootKind r // invoke basic style object reference callback inline bool CallbackInvoker::invoke_basic_object_reference_callback(jvmtiObjectReferenceKind ref_kind, - oop referrer, - oop referree, + const JvmtiHeapwalkObject& referrer, + const JvmtiHeapwalkObject& referree, jint index) { BasicHeapWalkContext* context = basic_context(); @@ -1655,7 +2000,7 @@ inline bool CallbackInvoker::invoke_basic_object_reference_callback(jvmtiObjectR if (referrer == context->last_referrer()) { referrer_tag = context->last_referrer_tag(); } else { - referrer_tag = tag_for(tag_map(), referrer); + referrer_tag = tag_map()->find(referrer); } // do the callback @@ -1687,7 +2032,7 @@ inline bool CallbackInvoker::invoke_basic_object_reference_callback(jvmtiObjectR // invoke advanced style heap root callback inline bool CallbackInvoker::invoke_advanced_heap_root_callback(jvmtiHeapReferenceKind ref_kind, - oop obj) { + const JvmtiHeapwalkObject& obj) { AdvancedHeapWalkContext* context = advanced_context(); // check that callback is provided @@ -1712,7 +2057,7 @@ inline bool CallbackInvoker::invoke_advanced_heap_root_callback(jvmtiHeapReferen } // for arrays we need the length, otherwise -1 - jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); + jint len = get_array_length(obj); // invoke the callback jint res = (*cb)(ref_kind, @@ -1741,7 +2086,7 @@ inline bool CallbackInvoker::invoke_advanced_stack_ref_callback(jvmtiHeapReferen jmethodID method, jlocation bci, jint slot, - oop obj) { + const JvmtiHeapwalkObject& obj) { AdvancedHeapWalkContext* context = advanced_context(); // check that callback is provider @@ -1775,7 +2120,7 @@ inline bool CallbackInvoker::invoke_advanced_stack_ref_callback(jvmtiHeapReferen reference_info.stack_local.slot = slot; // for arrays we need the length, otherwise -1 - jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); + jint len = get_array_length(obj); // call into the agent int res = (*cb)(ref_kind, @@ -1808,8 +2153,8 @@ inline bool CallbackInvoker::invoke_advanced_stack_ref_callback(jvmtiHeapReferen // invoke the object reference callback to report a reference inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeapReferenceKind ref_kind, - oop referrer, - oop obj, + const JvmtiHeapwalkObject& referrer, + const JvmtiHeapwalkObject& obj, jint index) { // field index is only valid field in reference_info @@ -1842,7 +2187,7 @@ inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeap reference_info.field.index = index; // for arrays we need the length, otherwise -1 - jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1); + jint len = get_array_length(obj); // invoke the callback int res = (*cb)(ref_kind, @@ -1865,7 +2210,7 @@ inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeap } // report a "simple root" -inline bool CallbackInvoker::report_simple_root(jvmtiHeapReferenceKind kind, oop obj) { +inline bool CallbackInvoker::report_simple_root(jvmtiHeapReferenceKind kind, const JvmtiHeapwalkObject& obj) { assert(kind != JVMTI_HEAP_REFERENCE_STACK_LOCAL && kind != JVMTI_HEAP_REFERENCE_JNI_LOCAL, "not a simple root"); @@ -1881,8 +2226,8 @@ inline bool CallbackInvoker::report_simple_root(jvmtiHeapReferenceKind kind, oop // invoke the primitive array values -inline bool CallbackInvoker::report_primitive_array_values(oop obj) { - assert(obj->is_typeArray(), "not a primitive array"); +inline bool CallbackInvoker::report_primitive_array_values(const JvmtiHeapwalkObject& obj) { + assert(obj.klass()->is_typeArray_klass(), "not a primitive array"); AdvancedHeapWalkContext* context = advanced_context(); assert(context->array_primitive_value_callback() != nullptr, "no callback"); @@ -1910,8 +2255,8 @@ inline bool CallbackInvoker::report_primitive_array_values(oop obj) { } // invoke the string value callback -inline bool CallbackInvoker::report_string_value(oop str) { - assert(str->klass() == vmClasses::String_klass(), "not a string"); +inline bool CallbackInvoker::report_string_value(const JvmtiHeapwalkObject& str) { + assert(str.klass() == vmClasses::String_klass(), "not a string"); AdvancedHeapWalkContext* context = advanced_context(); assert(context->string_primitive_value_callback() != nullptr, "no callback"); @@ -1940,7 +2285,7 @@ inline bool CallbackInvoker::report_string_value(oop str) { // invoke the primitive field callback inline bool CallbackInvoker::report_primitive_field(jvmtiHeapReferenceKind ref_kind, - oop obj, + const JvmtiHeapwalkObject& obj, jint index, address addr, char type) @@ -1988,7 +2333,7 @@ inline bool CallbackInvoker::report_primitive_field(jvmtiHeapReferenceKind ref_k // instance field -inline bool CallbackInvoker::report_primitive_instance_field(oop obj, +inline bool CallbackInvoker::report_primitive_instance_field(const JvmtiHeapwalkObject& obj, jint index, address value, char type) { @@ -2000,7 +2345,7 @@ inline bool CallbackInvoker::report_primitive_instance_field(oop obj, } // static field -inline bool CallbackInvoker::report_primitive_static_field(oop obj, +inline bool CallbackInvoker::report_primitive_static_field(const JvmtiHeapwalkObject& obj, jint index, address value, char type) { @@ -2012,7 +2357,7 @@ inline bool CallbackInvoker::report_primitive_static_field(oop obj, } // report a JNI local (root object) to the profiler -inline bool CallbackInvoker::report_jni_local_root(jlong thread_tag, jlong tid, jint depth, jmethodID m, oop obj) { +inline bool CallbackInvoker::report_jni_local_root(jlong thread_tag, jlong tid, jint depth, jmethodID m, const JvmtiHeapwalkObject& obj) { if (is_basic_heap_walk()) { return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_JNI_LOCAL, thread_tag, @@ -2039,7 +2384,7 @@ inline bool CallbackInvoker::report_stack_ref_root(jlong thread_tag, jmethodID method, jlocation bci, jint slot, - oop obj) { + const JvmtiHeapwalkObject& obj) { if (is_basic_heap_walk()) { return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_STACK_LOCAL, thread_tag, @@ -2060,7 +2405,7 @@ inline bool CallbackInvoker::report_stack_ref_root(jlong thread_tag, } // report an object referencing a class. -inline bool CallbackInvoker::report_class_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_class_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1); } else { @@ -2069,7 +2414,7 @@ inline bool CallbackInvoker::report_class_reference(oop referrer, oop referree) } // report a class referencing its class loader. -inline bool CallbackInvoker::report_class_loader_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_class_loader_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS_LOADER, referrer, referree, -1); } else { @@ -2078,7 +2423,7 @@ inline bool CallbackInvoker::report_class_loader_reference(oop referrer, oop ref } // report a class referencing its signers. -inline bool CallbackInvoker::report_signers_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_signers_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_SIGNERS, referrer, referree, -1); } else { @@ -2087,7 +2432,7 @@ inline bool CallbackInvoker::report_signers_reference(oop referrer, oop referree } // report a class referencing its protection domain.. -inline bool CallbackInvoker::report_protection_domain_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_protection_domain_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_PROTECTION_DOMAIN, referrer, referree, -1); } else { @@ -2096,7 +2441,7 @@ inline bool CallbackInvoker::report_protection_domain_reference(oop referrer, oo } // report a class referencing its superclass. -inline bool CallbackInvoker::report_superclass_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_superclass_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { // Send this to be consistent with past implementation return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1); @@ -2106,7 +2451,7 @@ inline bool CallbackInvoker::report_superclass_reference(oop referrer, oop refer } // report a class referencing one of its interfaces. -inline bool CallbackInvoker::report_interface_reference(oop referrer, oop referree) { +inline bool CallbackInvoker::report_interface_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_INTERFACE, referrer, referree, -1); } else { @@ -2115,7 +2460,7 @@ inline bool CallbackInvoker::report_interface_reference(oop referrer, oop referr } // report a class referencing one of its static fields. -inline bool CallbackInvoker::report_static_field_reference(oop referrer, oop referree, jint slot) { +inline bool CallbackInvoker::report_static_field_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint slot) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_STATIC_FIELD, referrer, referree, slot); } else { @@ -2124,7 +2469,7 @@ inline bool CallbackInvoker::report_static_field_reference(oop referrer, oop ref } // report an array referencing an element object -inline bool CallbackInvoker::report_array_element_reference(oop referrer, oop referree, jint index) { +inline bool CallbackInvoker::report_array_element_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_ARRAY_ELEMENT, referrer, referree, index); } else { @@ -2133,7 +2478,7 @@ inline bool CallbackInvoker::report_array_element_reference(oop referrer, oop re } // report an object referencing an instance field object -inline bool CallbackInvoker::report_field_reference(oop referrer, oop referree, jint slot) { +inline bool CallbackInvoker::report_field_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint slot) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_FIELD, referrer, referree, slot); } else { @@ -2142,7 +2487,7 @@ inline bool CallbackInvoker::report_field_reference(oop referrer, oop referree, } // report an array referencing an element object -inline bool CallbackInvoker::report_constant_pool_reference(oop referrer, oop referree, jint index) { +inline bool CallbackInvoker::report_constant_pool_reference(const JvmtiHeapwalkObject& referrer, const JvmtiHeapwalkObject& referree, jint index) { if (is_basic_heap_walk()) { return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CONSTANT_POOL, referrer, referree, index); } else { @@ -2269,7 +2614,7 @@ class StackRefCollector { bool StackRefCollector::set_thread(oop o) { _threadObj = o; - _thread_tag = tag_for(_tag_map, _threadObj); + _thread_tag = _tag_map->find(_threadObj); _tid = java_lang_Thread::thread_id(_threadObj); _is_top_frame = true; @@ -2402,16 +2747,10 @@ bool StackRefCollector::process_frames(vframe* vf) { // class VM_HeapWalkOperation: public VM_Operation { private: - enum { - initial_visit_stack_size = 4000 - }; - bool _is_advanced_heap_walk; // indicates FollowReferences JvmtiTagMap* _tag_map; Handle _initial_object; - GrowableArray* _visit_stack; // the visit stack - - JVMTIBitSet _bitset; + JvmtiHeapwalkVisitStack _visit_stack; // Dead object tags in JvmtiTagMap GrowableArray* _dead_objects; @@ -2422,10 +2761,6 @@ class VM_HeapWalkOperation: public VM_Operation { bool _reporting_primitive_array_values; bool _reporting_string_values; - GrowableArray* create_visit_stack() { - return new (mtServiceability) GrowableArray(initial_visit_stack_size, mtServiceability); - } - // accessors bool is_advanced_heap_walk() const { return _is_advanced_heap_walk; } JvmtiTagMap* tag_map() const { return _tag_map; } @@ -2437,13 +2772,14 @@ class VM_HeapWalkOperation: public VM_Operation { bool is_reporting_primitive_array_values() const { return _reporting_primitive_array_values; } bool is_reporting_string_values() const { return _reporting_string_values; } - GrowableArray* visit_stack() const { return _visit_stack; } + JvmtiHeapwalkVisitStack* visit_stack() { return &_visit_stack; } // iterate over the various object types - inline bool iterate_over_array(oop o); - inline bool iterate_over_type_array(oop o); - inline bool iterate_over_class(oop o); - inline bool iterate_over_object(oop o); + inline bool iterate_over_array(const JvmtiHeapwalkObject& o); + inline bool iterate_over_flat_array(const JvmtiHeapwalkObject& o); + inline bool iterate_over_type_array(const JvmtiHeapwalkObject& o); + inline bool iterate_over_class(const JvmtiHeapwalkObject& o); + inline bool iterate_over_object(const JvmtiHeapwalkObject& o); // root collection inline bool collect_simple_roots(); @@ -2452,7 +2788,7 @@ class VM_HeapWalkOperation: public VM_Operation { inline bool collect_vthread_stack_refs(oop vt); // visit an object - inline bool visit(oop o); + inline bool visit(const JvmtiHeapwalkObject& o); public: VM_HeapWalkOperation(JvmtiTagMap* tag_map, @@ -2486,10 +2822,8 @@ VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map, _reporting_primitive_fields = false; _reporting_primitive_array_values = false; _reporting_string_values = false; - _visit_stack = create_visit_stack(); _dead_objects = objects; - - CallbackInvoker::initialize_for_basic_heap_walk(tag_map, _visit_stack, user_data, callbacks, &_bitset); + CallbackInvoker::initialize_for_basic_heap_walk(tag_map, user_data, callbacks, &_visit_stack); } VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map, @@ -2504,23 +2838,18 @@ VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map, _reporting_primitive_fields = (callbacks.primitive_field_callback() != nullptr);; _reporting_primitive_array_values = (callbacks.array_primitive_value_callback() != nullptr);; _reporting_string_values = (callbacks.string_primitive_value_callback() != nullptr);; - _visit_stack = create_visit_stack(); _dead_objects = objects; - CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, _visit_stack, user_data, callbacks, &_bitset); + CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, user_data, callbacks, &_visit_stack); } VM_HeapWalkOperation::~VM_HeapWalkOperation() { - if (_following_object_refs) { - assert(_visit_stack != nullptr, "checking"); - delete _visit_stack; - _visit_stack = nullptr; - } } // an array references its class and has a reference to // each element in the array -inline bool VM_HeapWalkOperation::iterate_over_array(oop o) { - objArrayOop array = objArrayOop(o); +inline bool VM_HeapWalkOperation::iterate_over_array(const JvmtiHeapwalkObject& o) { + assert(!o.is_flat(), "Array object cannot be flattened"); + objArrayOop array = objArrayOop(o.obj()); // array reference to its class oop mirror = ObjArrayKlass::cast(array->klass())->java_mirror(); @@ -2544,9 +2873,48 @@ inline bool VM_HeapWalkOperation::iterate_over_array(oop o) { return true; } +// similar to iterate_over_array(), but itrates over flat array +inline bool VM_HeapWalkOperation::iterate_over_flat_array(const JvmtiHeapwalkObject& o) { + assert(!o.is_flat(), "Array object cannot be flattened"); + flatArrayOop array = flatArrayOop(o.obj()); + FlatArrayKlass* faklass = FlatArrayKlass::cast(array->klass()); + InlineKlass* vk = InlineKlass::cast(faklass->element_klass()); + bool need_null_check = faklass->layout_kind() == LayoutKind::NULLABLE_ATOMIC_FLAT; + + // array reference to its class + oop mirror = faklass->java_mirror(); + if (!CallbackInvoker::report_class_reference(o, mirror)) { + return false; + } + + // iterate over the array and report each reference to a + // non-null element + for (int index = 0; index < array->length(); index++) { + address addr = (address)array->value_at_addr(index, faklass->layout_helper()); + + // check for null + if (need_null_check) { + if (vk->is_payload_marked_as_null(addr)) { + continue; + } + } + + // offset in the array oop + int offset = (int)(addr - cast_from_oop
(array)); + JvmtiHeapwalkObject elem(o.obj(), offset, vk, faklass->layout_kind()); + + // report the array reference + if (!CallbackInvoker::report_array_element_reference(o, elem, index)) { + return false; + } + } + return true; +} + // a type array references its class -inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) { - Klass* k = o->klass(); +inline bool VM_HeapWalkOperation::iterate_over_type_array(const JvmtiHeapwalkObject& o) { + assert(!o.is_flat(), "Array object cannot be flattened"); + Klass* k = o.klass(); oop mirror = k->java_mirror(); if (!CallbackInvoker::report_class_reference(o, mirror)) { return false; @@ -2580,9 +2948,10 @@ static inline bool verify_static_oop(InstanceKlass* ik, // a class references its super class, interfaces, class loader, ... // and finally its static fields -inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { +inline bool VM_HeapWalkOperation::iterate_over_class(const JvmtiHeapwalkObject& o) { + assert(!o.is_flat(), "Klass object cannot be flattened"); + Klass* klass = java_lang_Class::as_Klass(o.obj()); int i; - Klass* klass = java_lang_Class::as_Klass(java_class); if (klass->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(klass); @@ -2593,7 +2962,8 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { } // get the java mirror - oop mirror = klass->java_mirror(); + oop mirror_oop = klass->java_mirror(); + JvmtiHeapwalkObject mirror(mirror_oop); // super (only if something more interesting than java.lang.Object) InstanceKlass* java_super = ik->java_super(); @@ -2682,8 +3052,8 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { ClassFieldDescriptor* field = field_map->field_at(i); char type = field->field_type(); if (!is_primitive_field_type(type)) { - oop fld_o = mirror->obj_field(field->field_offset()); - assert(verify_static_oop(ik, mirror, field->field_offset()), "sanity check"); + oop fld_o = mirror_oop->obj_field(field->field_offset()); + assert(verify_static_oop(ik, mirror_oop, field->field_offset()), "sanity check"); if (fld_o != nullptr) { int slot = field->field_index(); if (!CallbackInvoker::report_static_field_reference(mirror, fld_o, slot)) { @@ -2693,7 +3063,7 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { } } else { if (is_reporting_primitive_fields()) { - address addr = cast_from_oop
(mirror) + field->field_offset(); + address addr = cast_from_oop
(mirror_oop) + field->field_offset(); int slot = field->field_index(); if (!CallbackInvoker::report_primitive_static_field(mirror, slot, addr, type)) { delete field_map; @@ -2713,33 +3083,51 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { // an object references a class and its instance fields // (static fields are ignored here as we report these as // references from the class). -inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { +inline bool VM_HeapWalkOperation::iterate_over_object(const JvmtiHeapwalkObject& o) { // reference to the class - if (!CallbackInvoker::report_class_reference(o, o->klass()->java_mirror())) { + if (!CallbackInvoker::report_class_reference(o, o.klass()->java_mirror())) { return false; } // iterate over instance fields - ClassFieldMap* field_map = JvmtiCachedClassFieldMap::get_map_of_instance_fields(o); + ClassFieldMap* field_map = JvmtiCachedClassFieldMap::get_map_of_instance_fields(o.klass()); for (int i=0; ifield_count(); i++) { ClassFieldDescriptor* field = field_map->field_at(i); char type = field->field_type(); + int slot = field->field_index(); + int field_offset = field->field_offset(); + if (o.is_flat()) { + // the object is inlined, its fields are stored without the header + field_offset += o.offset() - o.inline_klass()->payload_offset(); + } if (!is_primitive_field_type(type)) { - oop fld_o = o->obj_field_access(field->field_offset()); - // ignore any objects that aren't visible to profiler - if (fld_o != nullptr) { - assert(Universe::heap()->is_in(fld_o), "unsafe code should not " - "have references to Klass* anymore"); - int slot = field->field_index(); - if (!CallbackInvoker::report_field_reference(o, fld_o, slot)) { + if (field->is_flat()) { + // check for possible nulls + bool can_be_null = field->layout_kind() == LayoutKind::NULLABLE_ATOMIC_FLAT; + if (can_be_null) { + address payload = cast_from_oop
(o.obj()) + field_offset; + if (field->inline_klass()->is_payload_marked_as_null(payload)) { + continue; + } + } + JvmtiHeapwalkObject field_obj(o.obj(), field_offset, field->inline_klass(), field->layout_kind()); + if (!CallbackInvoker::report_field_reference(o, field_obj, slot)) { return false; } + } else { + oop fld_o = o.obj()->obj_field_access(field_offset); + // ignore any objects that aren't visible to profiler + if (fld_o != nullptr) { + assert(Universe::heap()->is_in(fld_o), "unsafe code should not have references to Klass* anymore"); + if (!CallbackInvoker::report_field_reference(o, fld_o, slot)) { + return false; + } + } } } else { if (is_reporting_primitive_fields()) { // primitive instance field - address addr = cast_from_oop
(o) + field->field_offset(); - int slot = field->field_index(); + address addr = cast_from_oop
(o.obj()) + field_offset; if (!CallbackInvoker::report_primitive_instance_field(o, slot, addr, type)) { return false; } @@ -2749,7 +3137,7 @@ inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { // if the object is a java.lang.String if (is_reporting_string_values() && - o->klass() == vmClasses::String_klass()) { + o.klass() == vmClasses::String_klass()) { if (!CallbackInvoker::report_string_value(o)) { return false; } @@ -2778,7 +3166,7 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() { // Preloaded classes and loader from the system dictionary blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS); - CLDToOopClosure cld_closure(&blk, false); + CLDToOopClosure cld_closure(&blk, ClassLoaderData::_claim_none); ClassLoaderDataGraph::always_strong_cld_do(&cld_closure); if (blk.stopped()) { return false; @@ -2818,7 +3206,7 @@ inline bool VM_HeapWalkOperation::collect_stack_refs(JavaThread* java_thread, return false; } // no last java frame but there may be JNI locals - blk->set_context(tag_for(_tag_map, threadObj), java_lang_Thread::thread_id(threadObj), 0, (jmethodID)nullptr); + blk->set_context(_tag_map->find(threadObj), java_lang_Thread::thread_id(threadObj), 0, (jmethodID)nullptr); java_thread->active_handles()->oops_do(blk); return !blk->stopped(); } @@ -2918,23 +3306,26 @@ inline bool VM_HeapWalkOperation::collect_vthread_stack_refs(oop vt) { // second get all the outbound references from this object (in other words, all // the objects referenced by this object). // -bool VM_HeapWalkOperation::visit(oop o) { +bool VM_HeapWalkOperation::visit(const JvmtiHeapwalkObject& o) { // mark object as visited - assert(!_bitset.is_marked(o), "can't visit same object more than once"); - _bitset.mark_obj(o); + assert(!visit_stack()->is_visited(o), "can't visit same object more than once"); + visit_stack()->mark_visited(o); + Klass* klass = o.klass(); // instance - if (o->is_instance()) { - if (o->klass() == vmClasses::Class_klass()) { - if (!java_lang_Class::is_primitive(o)) { + if (klass->is_instance_klass()) { + if (klass == vmClasses::Class_klass()) { + assert(!o.is_flat(), "Class object cannot be flattened"); + if (!java_lang_Class::is_primitive(o.obj())) { // a java.lang.Class return iterate_over_class(o); } } else { // we report stack references only when initial object is not specified // (in the case we start from heap roots which include platform thread stack references) - if (initial_object().is_null() && java_lang_VirtualThread::is_subclass(o->klass())) { - if (!collect_vthread_stack_refs(o)) { + if (initial_object().is_null() && java_lang_VirtualThread::is_subclass(klass)) { + assert(!o.is_flat(), "VirtualThread object cannot be flattened"); + if (!collect_vthread_stack_refs(o.obj())) { return false; } } @@ -2942,13 +3333,18 @@ bool VM_HeapWalkOperation::visit(oop o) { } } + // flat object array + if (klass->is_flatArray_klass()) { + return iterate_over_flat_array(o); + } + // object array - if (o->is_objArray()) { + if (klass->is_objArray_klass()) { return iterate_over_array(o); } // type array - if (o->is_typeArray()) { + if (klass->is_typeArray_klass()) { return iterate_over_type_array(o); } @@ -2980,8 +3376,8 @@ void VM_HeapWalkOperation::doit() { // visit each object until all reachable objects have been // visited or the callback asked to terminate the iteration. while (!visit_stack()->is_empty()) { - oop o = visit_stack()->pop(); - if (!_bitset.is_marked(o)) { + const JvmtiHeapwalkObject o = visit_stack()->pop(); + if (!visit_stack()->is_visited(o)) { if (!visit(o)) { break; } @@ -3010,6 +3406,8 @@ void JvmtiTagMap::iterate_over_reachable_objects(jvmtiHeapRootCallback heap_root VM_HeapWalkOperation op(this, Handle(), context, user_data, &dead_objects); VMThread::execute(&op); } + convert_flat_object_entries(); + // Post events outside of Heap_lock post_dead_objects(&dead_objects); } @@ -3032,6 +3430,8 @@ void JvmtiTagMap::iterate_over_objects_reachable_from_object(jobject object, VM_HeapWalkOperation op(this, initial_object, context, user_data, &dead_objects); VMThread::execute(&op); } + convert_flat_object_entries(); + // Post events outside of Heap_lock post_dead_objects(&dead_objects); } @@ -3064,6 +3464,8 @@ void JvmtiTagMap::follow_references(jint heap_filter, VM_HeapWalkOperation op(this, initial_object, context, user_data, &dead_objects); VMThread::execute(&op); } + convert_flat_object_entries(); + // Post events outside of Heap_lock post_dead_objects(&dead_objects); } diff --git a/src/hotspot/share/prims/jvmtiTagMap.hpp b/src/hotspot/share/prims/jvmtiTagMap.hpp index 08ab52ed686..0d260c9047c 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.hpp +++ b/src/hotspot/share/prims/jvmtiTagMap.hpp @@ -32,7 +32,9 @@ class JvmtiEnv; class JvmtiTagMapTable; +class JvmtiFlatTagMapTable; class JvmtiTagMapKeyClosure; +class JvmtiHeapwalkObject; class JvmtiTagMap : public CHeapObj { private: @@ -40,11 +42,15 @@ class JvmtiTagMap : public CHeapObj { JvmtiEnv* _env; // the jvmti environment Monitor _lock; // lock for this tag map JvmtiTagMapTable* _hashmap; // the hashmap for tags + JvmtiFlatTagMapTable* _flat_hashmap; + bool _needs_cleaning; bool _posting_events; static bool _has_object_free_events; + bool _converting_flat_object; + // create a tag map JvmtiTagMap(JvmtiEnv* env); @@ -53,19 +59,25 @@ class JvmtiTagMap : public CHeapObj { void check_hashmap(GrowableArray* objects); - void entry_iterate(JvmtiTagMapKeyClosure* closure); + // moves entries from _flat_hashmap to _hashmap + void convert_flat_object_entries(); + + public: + // for inernal use + jlong find(const JvmtiHeapwalkObject& obj) const; + void add(const JvmtiHeapwalkObject& obj, jlong tag); + void remove(const JvmtiHeapwalkObject& obj); public: // indicates if this tag map is locked - bool is_locked() { return lock()->is_locked(); } + bool is_locked() const { return lock()->is_locked(); } + inline const Monitor* lock() const { return &_lock; } inline Monitor* lock() { return &_lock; } - JvmtiTagMapTable* hashmap() { return _hashmap; } - // returns true if the hashmaps are empty - bool is_empty(); + bool is_empty() const; - // return tag for the given environment + // return tag map for the given environment static JvmtiTagMap* tag_map_for(JvmtiEnv* env); // destroy tag map @@ -118,7 +130,7 @@ class JvmtiTagMap : public CHeapObj { static void gc_notification(size_t num_dead_entries) NOT_JVMTI_RETURN; void flush_object_free_events(); - void clear(); // Clear tagmap table after the env is disposed. + void clear(); // Clear hash tables after the env is disposed. // For ServiceThread static void flush_all_object_free_events() NOT_JVMTI_RETURN; diff --git a/src/hotspot/share/prims/jvmtiTagMapTable.cpp b/src/hotspot/share/prims/jvmtiTagMapTable.cpp index f45ceb719a6..8db8ecd0fe3 100644 --- a/src/hotspot/share/prims/jvmtiTagMapTable.cpp +++ b/src/hotspot/share/prims/jvmtiTagMapTable.cpp @@ -25,114 +25,86 @@ #include "memory/allocation.hpp" #include "memory/universe.hpp" #include "oops/fieldStreams.inline.hpp" +#include "oops/inlineKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/weakHandle.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiTagMapTable.hpp" -JvmtiTagMapKey::JvmtiTagMapKey(oop obj) : _obj(obj) {} - -JvmtiTagMapKey::JvmtiTagMapKey(const JvmtiTagMapKey& src) : _h() { - // move object into Handle when copying into the table - if (src._obj != nullptr) { - _is_weak = !src._obj->klass()->is_inline_klass(); - - // obj was read with AS_NO_KEEPALIVE, or equivalent, like during - // a heap walk. The object needs to be kept alive when it is published. - Universe::heap()->keep_alive(src._obj); - - if (_is_weak) { - _wh = WeakHandle(JvmtiExport::weak_tag_storage(), src._obj); - } else { - _h = OopHandle(JvmtiExport::jvmti_oop_storage(), src._obj); - } - } else { - // resizing needs to create a copy. - if (_is_weak) { - _wh = src._wh; - } else { - _h = src._h; - } - } - // obj is always null after a copy. - _obj = nullptr; +static unsigned get_value_object_hash(oop holder, int offset, Klass* klass) { + assert(klass->is_inline_klass(), "Must be InlineKlass"); + // For inline types, use the klass as a hash code and let the equals match the obj. + // It might have a long bucket but TBD to improve this if a customer situation arises. + return (unsigned)((int64_t)klass >> 3); } -void JvmtiTagMapKey::release_handle() { - if (_is_weak) { - _wh.release(JvmtiExport::weak_tag_storage()); - } else { - _h.release(JvmtiExport::jvmti_oop_storage()); - } -} - -oop JvmtiTagMapKey::object() const { - assert(_obj == nullptr, "Must have a handle and not object"); - return _is_weak ? _wh.resolve() : _h.resolve(); -} - -oop JvmtiTagMapKey::object_no_keepalive() const { - assert(_obj == nullptr, "Must have a handle and not object"); - return _is_weak ? _wh.peek() : _h.peek(); -} - -unsigned JvmtiTagMapKey::get_hash(const JvmtiTagMapKey& entry) { - oop obj = entry._obj; - assert(obj != nullptr, "must lookup obj to hash"); - if (obj->is_inline_type()) { - // For inline types, use the klass as a hash code and let the equals match the obj. - // It might have a long bucket but TBD to improve this if a customer situation arises. - return (unsigned)((int64_t)obj->klass() >> 3); - } else { - return (unsigned)obj->identity_hash(); - } +static unsigned get_value_object_hash(const JvmtiHeapwalkObject & obj) { + assert(obj.is_value(), "Must be value class"); + return get_value_object_hash(obj.obj(), obj.offset(), obj.inline_klass()); } static bool equal_oops(oop obj1, oop obj2); // forward declaration -static bool equal_fields(char type, oop obj1, oop obj2, int offset) { +static bool equal_fields(char type, oop obj1, int offset1, oop obj2, int offset2) { switch (type) { case JVM_SIGNATURE_BOOLEAN: - return obj1->bool_field(offset) == obj2->bool_field(offset); + return obj1->bool_field(offset1) == obj2->bool_field(offset2); case JVM_SIGNATURE_CHAR: - return obj1->char_field(offset) == obj2->char_field(offset); + return obj1->char_field(offset1) == obj2->char_field(offset2); case JVM_SIGNATURE_FLOAT: - return obj1->float_field(offset) == obj2->float_field(offset); + return obj1->float_field(offset1) == obj2->float_field(offset2); case JVM_SIGNATURE_DOUBLE: - return obj1->double_field(offset) == obj2->double_field(offset); + return obj1->double_field(offset1) == obj2->double_field(offset2); case JVM_SIGNATURE_BYTE: - return obj1->byte_field(offset) == obj2->byte_field(offset); + return obj1->byte_field(offset1) == obj2->byte_field(offset2); case JVM_SIGNATURE_SHORT: - return obj1->short_field(offset) == obj2->short_field(offset); + return obj1->short_field(offset1) == obj2->short_field(offset2); case JVM_SIGNATURE_INT: - return obj1->int_field(offset) == obj2->int_field(offset); + return obj1->int_field(offset1) == obj2->int_field(offset2); case JVM_SIGNATURE_LONG: - return obj1->long_field(offset) == obj2->long_field(offset); + return obj1->long_field(offset1) == obj2->long_field(offset2); case JVM_SIGNATURE_CLASS: case JVM_SIGNATURE_ARRAY: - return equal_oops(obj1->obj_field(offset), obj2->obj_field(offset)); + return equal_oops(obj1->obj_field(offset1), obj2->obj_field(offset2)); } ShouldNotReachHere(); } +static bool is_null_flat_field(oop obj, int offset, InlineKlass* klass) { + return klass->is_payload_marked_as_null(cast_from_oop
(obj) + offset); +} + // For heap-allocated objects offset is 0 and 'klass' is obj1->klass() (== obj2->klass()). // For flattened objects offset is the offset in the holder object, 'klass' is inlined object class. -static bool equal_value_objects(oop obj1, oop obj2, InlineKlass* klass, int offset) { +// The object must be prechecked for non-null values. +static bool equal_value_objects(oop obj1, int offset1, oop obj2, int offset2, InlineKlass* klass) { for (JavaFieldStream fld(klass); !fld.done(); fld.next()) { // ignore static fields if (fld.access_flags().is_static()) { continue; } - int field_offset = offset + fld.offset() - (offset > 0 ? klass->payload_offset() : 0); + int field_offset1 = offset1 + fld.offset() - (offset1 > 0 ? klass->payload_offset() : 0); + int field_offset2 = offset2 + fld.offset() - (offset2 > 0 ? klass->payload_offset() : 0); if (fld.is_flat()) { // flat value field InstanceKlass* holder_klass = fld.field_holder(); InlineKlass* field_klass = holder_klass->get_inline_type_field_klass(fld.index()); - if (!equal_value_objects(obj1, obj2, field_klass, field_offset)) { + if (!fld.is_null_free_inline_type()) { + bool field1_is_null = is_null_flat_field(obj1, field_offset1, field_klass); + bool field2_is_null = is_null_flat_field(obj2, field_offset2, field_klass); + if (field1_is_null != field2_is_null) { + return false; + } + if (field1_is_null) { // if both fields are null, go to next field + continue; + } + } + + if (!equal_value_objects(obj1, field_offset1, obj2, field_offset2, field_klass)) { return false; } } else { - if (!equal_fields(fld.signature()->char_at(0), obj1, obj2, field_offset)) { + if (!equal_fields(fld.signature()->char_at(0), obj1, field_offset1, obj2, field_offset2)) { return false; } } @@ -140,29 +112,101 @@ static bool equal_value_objects(oop obj1, oop obj2, InlineKlass* klass, int offs return true; } +// handles null oops static bool equal_oops(oop obj1, oop obj2) { if (obj1 == obj2) { return true; } - if (EnableValhalla) { - if (obj1 != nullptr && obj2 != nullptr && obj1->klass() == obj2->klass() && obj1->is_inline_type()) { - InlineKlass* vk = InlineKlass::cast(obj1->klass()); - return equal_value_objects(obj1, obj2, vk, 0); - } + if (obj1 != nullptr && obj2 != nullptr && obj1->klass() == obj2->klass() && obj1->is_inline_type()) { + InlineKlass* vk = InlineKlass::cast(obj1->klass()); + return equal_value_objects(obj1, 0, obj2, 0, vk); } return false; } -bool JvmtiTagMapKey::equals(const JvmtiTagMapKey& lhs, const JvmtiTagMapKey& rhs) { - oop lhs_obj = lhs._obj != nullptr ? lhs._obj : lhs.object_no_keepalive(); - oop rhs_obj = rhs._obj != nullptr ? rhs._obj : rhs.object_no_keepalive(); - return equal_oops(lhs_obj, rhs_obj); + +bool JvmtiHeapwalkObject::equals(const JvmtiHeapwalkObject& obj1, const JvmtiHeapwalkObject& obj2) { + if (obj1 == obj2) { // the same oop/offset/inline_klass + return true; + } + + if (obj1.is_value() && obj1.inline_klass() == obj2.inline_klass()) { + // instances of the same value class + return equal_value_objects(obj1.obj(), obj1.offset(), obj2.obj(), obj2.offset(), obj1.inline_klass()); + } + return false; } -// Inline types don't use hash for this table. -static inline bool fast_no_hash_check(oop obj) { - return (obj->fast_no_hash_check() && !obj->is_inline_type()); + +JvmtiTagMapKey::JvmtiTagMapKey(const JvmtiHeapwalkObject* obj) : _obj(obj) { +} + +JvmtiTagMapKey::JvmtiTagMapKey(const JvmtiTagMapKey& src): _h() { + if (src._obj != nullptr) { + // move object into Handle when copying into the table + assert(!src._obj->is_flat(), "cannot put flat object to JvmtiTagMapKey"); + _is_weak = !src._obj->is_value(); + + // obj was read with AS_NO_KEEPALIVE, or equivalent, like during + // a heap walk. The object needs to be kept alive when it is published. + Universe::heap()->keep_alive(src._obj->obj()); + + if (_is_weak) { + _wh = WeakHandle(JvmtiExport::weak_tag_storage(), src._obj->obj()); + } else { + _h = OopHandle(JvmtiExport::jvmti_oop_storage(), src._obj->obj()); + } + } else { + // resizing needs to create a copy. + _is_weak = src._is_weak; + if (_is_weak) { + _wh = src._wh; + } else { + _h = src._h; + } + } + // obj is always null after a copy. + _obj = nullptr; +} + +void JvmtiTagMapKey::release_handle() { + if (_is_weak) { + _wh.release(JvmtiExport::weak_tag_storage()); + } else { + _h.release(JvmtiExport::jvmti_oop_storage()); + } +} + +JvmtiHeapwalkObject JvmtiTagMapKey::heapwalk_object() const { + return _obj != nullptr ? JvmtiHeapwalkObject(_obj->obj(), _obj->offset(), _obj->inline_klass(), _obj->layout_kind()) + : JvmtiHeapwalkObject(object_no_keepalive()); +} + +oop JvmtiTagMapKey::object() const { + assert(_obj == nullptr, "Must have a handle and not object"); + return _is_weak ? _wh.resolve() : _h.resolve(); +} + +oop JvmtiTagMapKey::object_no_keepalive() const { + assert(_obj == nullptr, "Must have a handle and not object"); + return _is_weak ? _wh.peek() : _h.peek(); +} + +unsigned JvmtiTagMapKey::get_hash(const JvmtiTagMapKey& entry) { + const JvmtiHeapwalkObject* obj = entry._obj; + assert(obj != nullptr, "must lookup obj to hash"); + if (obj->is_value()) { + return get_value_object_hash(*obj); + } else { + return (unsigned)obj->obj()->identity_hash(); + } +} + +bool JvmtiTagMapKey::equals(const JvmtiTagMapKey& lhs, const JvmtiTagMapKey& rhs) { + JvmtiHeapwalkObject lhs_obj = lhs.heapwalk_object(); + JvmtiHeapwalkObject rhs_obj = rhs.heapwalk_object(); + return JvmtiHeapwalkObject::equals(lhs_obj, rhs_obj); } static const int INITIAL_TABLE_SIZE = 1007; @@ -190,25 +234,33 @@ JvmtiTagMapTable::~JvmtiTagMapTable() { clear(); } -jlong JvmtiTagMapTable::find(oop obj) { +jlong* JvmtiTagMapTable::lookup(const JvmtiHeapwalkObject& obj) const { if (is_empty()) { return 0; } - if (fast_no_hash_check(obj)) { - // Objects in the table all have a hashcode, unless inlined types. - return 0; + if (!obj.is_value()) { + if (obj.obj()->fast_no_hash_check()) { + // Objects in the table all have a hashcode, unless inlined types. + return nullptr; + } } + JvmtiTagMapKey entry(&obj); + jlong* found = _table.get(entry); + return found; +} + - JvmtiTagMapKey jtme(obj); - jlong* found = _table.get(jtme); +jlong JvmtiTagMapTable::find(const JvmtiHeapwalkObject& obj) const { + jlong* found = lookup(obj); return found == nullptr ? 0 : *found; } -void JvmtiTagMapTable::add(oop obj, jlong tag) { - JvmtiTagMapKey new_entry(obj); +void JvmtiTagMapTable::add(const JvmtiHeapwalkObject& obj, jlong tag) { + assert(!obj.is_flat(), "Cannot add flat object to JvmtiTagMapTable"); + JvmtiTagMapKey new_entry(&obj); bool is_added; - if (fast_no_hash_check(obj)) { + if (!obj.is_value() && obj.obj()->fast_no_hash_check()) { // Can't be in the table so add it fast. is_added = _table.put_when_absent(new_entry, tag); } else { @@ -224,12 +276,21 @@ void JvmtiTagMapTable::add(oop obj, jlong tag) { } } -void JvmtiTagMapTable::remove(oop obj) { - JvmtiTagMapKey jtme(obj); - auto clean = [] (JvmtiTagMapKey& entry, jlong tag) { +bool JvmtiTagMapTable::update(const JvmtiHeapwalkObject& obj, jlong tag) { + jlong* found = lookup(obj); + if (found == nullptr) { + return false; + } + *found = tag; + return true; +} + +bool JvmtiTagMapTable::remove(const JvmtiHeapwalkObject& obj) { + JvmtiTagMapKey entry(&obj); + auto clean = [](JvmtiTagMapKey & entry, jlong tag) { entry.release_handle(); }; - _table.remove(jtme, clean); + return _table.remove(entry, clean); } void JvmtiTagMapTable::entry_iterate(JvmtiTagMapKeyClosure* closure) { @@ -253,3 +314,120 @@ void JvmtiTagMapTable::remove_dead_entries(GrowableArray* objects) { } is_dead(objects); _table.unlink(&is_dead); } + + +JvmtiFlatTagMapKey::JvmtiFlatTagMapKey(const JvmtiHeapwalkObject& obj) + : _holder(obj.obj()), _offset(obj.offset()), _inline_klass(obj.inline_klass()), _layout_kind(obj.layout_kind()) { +} + +JvmtiFlatTagMapKey::JvmtiFlatTagMapKey(const JvmtiFlatTagMapKey& src) : _h() { + // move object into Handle when copying into the table + if (src._holder != nullptr) { + // Holder object was read with AS_NO_KEEPALIVE. Needs to be kept alive when it is published. + Universe::heap()->keep_alive(src._holder); + _h = OopHandle(JvmtiExport::jvmti_oop_storage(), src._holder); + } else { + // resizing needs to create a copy. + _h = src._h; + } + // holder object is always null after a copy. + _holder = nullptr; + _offset = src._offset; + _inline_klass = src._inline_klass; + _layout_kind = src._layout_kind; +} + +JvmtiHeapwalkObject JvmtiFlatTagMapKey::heapwalk_object() const { + return JvmtiHeapwalkObject(_holder != nullptr ? _holder : holder_no_keepalive(), _offset, _inline_klass, _layout_kind); +} + +oop JvmtiFlatTagMapKey::holder() const { + assert(_holder == nullptr, "Must have a handle and not object"); + return _h.resolve(); +} + +oop JvmtiFlatTagMapKey::holder_no_keepalive() const { + assert(_holder == nullptr, "Must have a handle and not object"); + return _h.peek(); + +} + +void JvmtiFlatTagMapKey::release_handle() { + _h.release(JvmtiExport::jvmti_oop_storage()); +} + +unsigned JvmtiFlatTagMapKey::get_hash(const JvmtiFlatTagMapKey& entry) { + return get_value_object_hash(entry._holder, entry._offset, entry._inline_klass); +} + +bool JvmtiFlatTagMapKey::equals(const JvmtiFlatTagMapKey& lhs, const JvmtiFlatTagMapKey& rhs) { + if (lhs._inline_klass == rhs._inline_klass) { + oop lhs_obj = lhs._holder != nullptr ? lhs._holder : lhs._h.peek(); + oop rhs_obj = rhs._holder != nullptr ? rhs._holder : rhs._h.peek(); + return equal_value_objects(lhs_obj, lhs._offset, rhs_obj, rhs._offset, lhs._inline_klass); + } + return false; +} + + +JvmtiFlatTagMapTable::JvmtiFlatTagMapTable(): _table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {} + +JvmtiFlatTagMapTable::~JvmtiFlatTagMapTable() { + clear(); +} + +jlong JvmtiFlatTagMapTable::find(const JvmtiHeapwalkObject& obj) const { + if (is_empty()) { + return 0; + } + + JvmtiFlatTagMapKey entry(obj); + jlong* found = _table.get(entry); + return found == nullptr ? 0 : *found; +} + +void JvmtiFlatTagMapTable::add(const JvmtiHeapwalkObject& obj, jlong tag) { + assert(obj.is_value() && obj.is_flat(), "Must be flattened value object"); + JvmtiFlatTagMapKey entry(obj); + bool is_added; + jlong* value = _table.put_if_absent(entry, tag, &is_added); + *value = tag; // assign the new tag + if (is_added) { + if (_table.maybe_grow(5, true /* use_large_table_sizes */)) { + int max_bucket_size = DEBUG_ONLY(_table.verify()) NOT_DEBUG(0); + log_info(jvmti, table) ("JvmtiFlatTagMapTable table resized to %d for %d entries max bucket %d", + _table.table_size(), _table.number_of_entries(), max_bucket_size); + } + } +} + +jlong JvmtiFlatTagMapTable::remove(const JvmtiHeapwalkObject& obj) { + JvmtiFlatTagMapKey entry(obj); + jlong ret = 0; + auto clean = [&](JvmtiFlatTagMapKey& entry, jlong tag) { + ret = tag; + entry.release_handle(); + }; + _table.remove(entry, clean); + return ret; +} + +void JvmtiFlatTagMapTable::entry_iterate(JvmtiFlatTagMapKeyClosure* closure) { + _table.iterate(closure); +} + +void JvmtiFlatTagMapTable::clear() { + struct RemoveAll { + bool do_entry(JvmtiFlatTagMapKey& entry, const jlong& tag) { + entry.release_handle(); + return true; + } + } remove_all; + // The unlink method of ResourceHashTable gets a pointer to a type whose 'do_entry(K,V)' method is callled + // while iterating over all the elements of the table. If the do_entry() method returns true the element + // will be removed. + // In this case, we always return true from do_entry to clear all the elements. + _table.unlink(&remove_all); + + assert(_table.number_of_entries() == 0, "should have removed all entries"); +} diff --git a/src/hotspot/share/prims/jvmtiTagMapTable.hpp b/src/hotspot/share/prims/jvmtiTagMapTable.hpp index dc0ba1da183..042167713fb 100644 --- a/src/hotspot/share/prims/jvmtiTagMapTable.hpp +++ b/src/hotspot/share/prims/jvmtiTagMapTable.hpp @@ -27,11 +27,53 @@ #include "gc/shared/collectedHeap.hpp" #include "memory/allocation.hpp" +#include "oops/layoutKind.hpp" #include "oops/weakHandle.hpp" #include "utilities/resizeableResourceHash.hpp" class JvmtiEnv; -class JvmtiTagMapKeyClosure; + +// Describes an object which can be tagged during heap walk operation. +// - generic heap object: _obj: oop, offset == 0, _inline_klass == nullptr; +// - value heap object: _obj: oop, offset == 0, _inline_klass == _obj.klass(); +// - flat value object: _obj: holder object, offset == offset in the holder, _inline_klass == klass of the flattened object; +class JvmtiHeapwalkObject { + oop _obj; // for flattened value object this is holder object + int _offset; // == 0 for heap objects + InlineKlass* _inline_klass; // for value object, nullptr otherwise + LayoutKind _layout_kind; // layout kind in holder object, used only for flat->heap conversion + + static InlineKlass* inline_klass_or_null(oop obj) { + Klass* k = obj->klass(); + return k->is_inline_klass() ? InlineKlass::cast(k) : nullptr; + } +public: + JvmtiHeapwalkObject(): _obj(nullptr), _offset(0), _inline_klass(nullptr), _layout_kind(LayoutKind::UNKNOWN) {} + JvmtiHeapwalkObject(oop obj): _obj(obj), _offset(0), _inline_klass(inline_klass_or_null(obj)), _layout_kind(LayoutKind::REFERENCE) {} + JvmtiHeapwalkObject(oop obj, int offset, InlineKlass* ik, LayoutKind lk): _obj(obj), _offset(offset), _inline_klass(ik), _layout_kind(lk) {} + + inline bool is_empty() const { return _obj == nullptr; } + inline bool is_value() const { return _inline_klass != nullptr; } + inline bool is_flat() const { return _offset != 0; } + + inline oop obj() const { return _obj; } + inline int offset() const { return _offset; } + inline InlineKlass* inline_klass() const { return _inline_klass; } + inline LayoutKind layout_kind() const { return _layout_kind; } + + inline Klass* klass() const { return is_value() ? _inline_klass : obj()->klass(); } + + static bool equals(const JvmtiHeapwalkObject& obj1, const JvmtiHeapwalkObject& obj2); + + bool operator==(const JvmtiHeapwalkObject& other) const { + // need to compare inline_klass too to handle the case when flat object has flat field at offset 0 + return _obj == other._obj && _offset == other._offset && _inline_klass == other._inline_klass; + } + bool operator!=(const JvmtiHeapwalkObject& other) const { + return !(*this == other); + } +}; + // The oop is needed for lookup rather than creating a WeakHandle during // lookup because the HeapWalker may walk soon to be dead objects and @@ -41,22 +83,31 @@ class JvmtiTagMapKeyClosure; // Its get_hash() and equals() methods are also used for getting the hash // value of a Key and comparing two Keys, respectively. // -// Valhalla: Keep just one tag for all equal value objects including heap allocated value objects. +// Value objects: keep just one tag for all equal value objects including heap allocated value objects. // We have to keep a strong reference to each unique value object with a non-zero tag. +// During heap walking flattened value object tags stored in separate JvmtiFlatTagMapTable, +// converted to standard strong entries in JvmtiTagMapTable outside of sefepoint. +// All equal value objects should have the same tag. +// Keep value objects alive (1 copy for each "value") until their tags are removed. + class JvmtiTagMapKey : public CHeapObj { - // All equal value objects should have the same tag. - // Keep value objects alive (1 copy for each "value") until their tags are removed. union { WeakHandle _wh; OopHandle _h; // for value objects (_is_weak == false) }; bool _is_weak; - oop _obj; // temporarily hold obj while searching + // temporarily hold obj while searching + const JvmtiHeapwalkObject* _obj; + public: - JvmtiTagMapKey(oop obj); + JvmtiTagMapKey(const JvmtiHeapwalkObject* obj); + // Copy ctor is called when we put entry to the hash table. JvmtiTagMapKey(const JvmtiTagMapKey& src); + JvmtiTagMapKey& operator=(const JvmtiTagMapKey&) = delete; + JvmtiHeapwalkObject heapwalk_object() const; + oop object() const; oop object_no_keepalive() const; void release_handle(); @@ -67,22 +118,35 @@ class JvmtiTagMapKey : public CHeapObj { typedef ResizeableResourceHashtable ResizableResourceHT; + AnyObj::C_HEAP, mtServiceability, + JvmtiTagMapKey::get_hash, + JvmtiTagMapKey::equals> ResizableResourceHT; + +// A supporting class for iterating over all entries in Hashmap +class JvmtiTagMapKeyClosure { +public: + virtual bool do_entry(JvmtiTagMapKey& key, jlong& value) = 0; +}; class JvmtiTagMapTable : public CHeapObj { private: ResizableResourceHT _table; + jlong* lookup(const JvmtiHeapwalkObject& obj) const; + public: JvmtiTagMapTable(); ~JvmtiTagMapTable(); - jlong find(oop obj); - void add(oop obj, jlong tag); + int number_of_entries() const { return _table.number_of_entries(); } + + jlong find(const JvmtiHeapwalkObject& obj) const; + // obj cannot be flat + void add(const JvmtiHeapwalkObject& obj, jlong tag); + // update the tag if the entry exists, returns false otherwise + bool update(const JvmtiHeapwalkObject& obj, jlong tag); - void remove(oop obj); + bool remove(const JvmtiHeapwalkObject& obj); // iterate over all entries in the hashmap void entry_iterate(JvmtiTagMapKeyClosure* closure); @@ -94,10 +158,74 @@ class JvmtiTagMapTable : public CHeapObj { void clear(); }; -// A supporting class for iterating over all entries in Hashmap -class JvmtiTagMapKeyClosure { - public: - virtual bool do_entry(JvmtiTagMapKey& key, jlong& value) = 0; + +// This class is the Key type for hash table to keep flattened value objects during heap walk operations. +// The objects needs to be moved to JvmtiTagMapTable outside of safepoint. +class JvmtiFlatTagMapKey: public CHeapObj { +private: + // holder object + OopHandle _h; + // temporarily holds holder object while searching + oop _holder; + int _offset; + InlineKlass* _inline_klass; + LayoutKind _layout_kind; +public: + JvmtiFlatTagMapKey(const JvmtiHeapwalkObject& obj); + // Copy ctor is called when we put entry to the hash table. + JvmtiFlatTagMapKey(const JvmtiFlatTagMapKey& src); + + JvmtiFlatTagMapKey& operator=(const JvmtiFlatTagMapKey&) = delete; + + JvmtiHeapwalkObject heapwalk_object() const; + + oop holder() const; + oop holder_no_keepalive() const; + int offset() const { return _offset; } + InlineKlass* inline_klass() const { return _inline_klass; } + LayoutKind layout_kind() const { return _layout_kind; } + + void release_handle(); + + static unsigned get_hash(const JvmtiFlatTagMapKey& entry); + static bool equals(const JvmtiFlatTagMapKey& lhs, const JvmtiFlatTagMapKey& rhs); +}; + +typedef +ResizeableResourceHashtable FlatObjectHashtable; + +// A supporting class for iterating over all entries in JvmtiFlatTagMapTable. +class JvmtiFlatTagMapKeyClosure { +public: + virtual bool do_entry(JvmtiFlatTagMapKey& key, jlong& value) = 0; +}; + +class JvmtiFlatTagMapTable: public CHeapObj { +private: + FlatObjectHashtable _table; + +public: + JvmtiFlatTagMapTable(); + ~JvmtiFlatTagMapTable(); + + int number_of_entries() const { return _table.number_of_entries(); } + + jlong find(const JvmtiHeapwalkObject& obj) const; + // obj must be flat + void add(const JvmtiHeapwalkObject& obj, jlong tag); + + // returns tag for the entry, 0 is not found + jlong remove(const JvmtiHeapwalkObject& obj); + + // iterate over entries in the hashmap + void entry_iterate(JvmtiFlatTagMapKeyClosure* closure); + + bool is_empty() const { return _table.number_of_entries() == 0; } + + void clear(); }; #endif // SHARE_VM_PRIMS_TAGMAPTABLE_HPP diff --git a/src/hotspot/share/prims/scopedMemoryAccess.cpp b/src/hotspot/share/prims/scopedMemoryAccess.cpp index 8ef5b96f37d..c1d1b8cd8c0 100644 --- a/src/hotspot/share/prims/scopedMemoryAccess.cpp +++ b/src/hotspot/share/prims/scopedMemoryAccess.cpp @@ -105,15 +105,15 @@ static frame get_last_frame(JavaThread* jt) { return last_frame; } -class ScopedAsyncExceptionHandshake : public AsyncExceptionHandshake { +class ScopedAsyncExceptionHandshakeClosure : public AsyncExceptionHandshakeClosure { OopHandle _session; public: - ScopedAsyncExceptionHandshake(OopHandle& session, OopHandle& error) - : AsyncExceptionHandshake(error), + ScopedAsyncExceptionHandshakeClosure(OopHandle& session, OopHandle& error) + : AsyncExceptionHandshakeClosure(error), _session(session) {} - ~ScopedAsyncExceptionHandshake() { + ~ScopedAsyncExceptionHandshakeClosure() { _session.release(Universe::vm_global()); } @@ -122,17 +122,17 @@ class ScopedAsyncExceptionHandshake : public AsyncExceptionHandshake { bool ignored; if (is_accessing_session(jt, _session.resolve(), ignored)) { // Throw exception to unwind out from the scoped access - AsyncExceptionHandshake::do_thread(thread); + AsyncExceptionHandshakeClosure::do_thread(thread); } } }; -class CloseScopedMemoryClosure : public HandshakeClosure { +class CloseScopedMemoryHandshakeClosure : public HandshakeClosure { jobject _session; jobject _error; public: - CloseScopedMemoryClosure(jobject session, jobject error) + CloseScopedMemoryHandshakeClosure(jobject session, jobject error) : HandshakeClosure("CloseScopedMemory") , _session(session) , _error(error) {} @@ -159,7 +159,7 @@ class CloseScopedMemoryClosure : public HandshakeClosure { // the scoped access. OopHandle session(Universe::vm_global(), JNIHandles::resolve(_session)); OopHandle error(Universe::vm_global(), JNIHandles::resolve(_error)); - jt->install_async_exception(new ScopedAsyncExceptionHandshake(session, error)); + jt->install_async_exception(new ScopedAsyncExceptionHandshakeClosure(session, error)); } else if (!in_scoped) { frame last_frame = get_last_frame(jt); if (last_frame.is_compiled_frame() && last_frame.can_be_deoptimized()) { @@ -213,7 +213,7 @@ class CloseScopedMemoryClosure : public HandshakeClosure { * closed (deopt), this method returns false, signalling that the session cannot be closed safely. */ JVM_ENTRY(void, ScopedMemoryAccess_closeScope(JNIEnv *env, jobject receiver, jobject session, jobject error)) - CloseScopedMemoryClosure cl(session, error); + CloseScopedMemoryHandshakeClosure cl(session, error); Handshake::execute(&cl); JVM_END diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6ca2f1d4c4e..c7765ecae34 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -90,6 +90,7 @@ #include "runtime/javaThread.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/keepStackGCProcessed.hpp" +#include "runtime/lightweightSynchronizer.hpp" #include "runtime/lockStack.hpp" #include "runtime/os.hpp" #include "runtime/stackFrameStream.inline.hpp" @@ -2353,7 +2354,7 @@ WB_END #endif // INCLUDE_CDS WB_ENTRY(jboolean, WB_HandshakeReadMonitors(JNIEnv* env, jobject wb, jobject thread_handle)) - class ReadMonitorsClosure : public HandshakeClosure { + class ReadMonitorsHandshakeClosure : public HandshakeClosure { jboolean _executed; void do_thread(Thread* th) { @@ -2388,24 +2389,24 @@ WB_ENTRY(jboolean, WB_HandshakeReadMonitors(JNIEnv* env, jobject wb, jobject thr } public: - ReadMonitorsClosure() : HandshakeClosure("WB_HandshakeReadMonitors"), _executed(false) {} + ReadMonitorsHandshakeClosure() : HandshakeClosure("WB_HandshakeReadMonitors"), _executed(false) {} jboolean executed() const { return _executed; } }; - ReadMonitorsClosure rmc; + ReadMonitorsHandshakeClosure rmhc; if (thread_handle != nullptr) { ThreadsListHandle tlh; JavaThread* target = nullptr; bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, nullptr); if (is_alive) { - Handshake::execute(&rmc, &tlh, target); + Handshake::execute(&rmhc, &tlh, target); } } - return rmc.executed(); + return rmhc.executed(); WB_END WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle, jboolean all_threads)) - class TraceSelfClosure : public HandshakeClosure { + class TraceSelfHandshakeClosure : public HandshakeClosure { jint _num_threads_completed; void do_thread(Thread* th) { @@ -2419,27 +2420,27 @@ WB_ENTRY(jint, WB_HandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_han } public: - TraceSelfClosure(Thread* thread) : HandshakeClosure("WB_TraceSelf"), _num_threads_completed(0) {} + TraceSelfHandshakeClosure(Thread* thread) : HandshakeClosure("WB_TraceSelf"), _num_threads_completed(0) {} jint num_threads_completed() const { return _num_threads_completed; } }; - TraceSelfClosure tsc(Thread::current()); + TraceSelfHandshakeClosure tshc(Thread::current()); if (all_threads) { - Handshake::execute(&tsc); + Handshake::execute(&tshc); } else if (thread_handle != nullptr) { ThreadsListHandle tlh; JavaThread* target = nullptr; bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, nullptr); if (is_alive) { - Handshake::execute(&tsc, &tlh, target); + Handshake::execute(&tshc, &tlh, target); } } - return tsc.num_threads_completed(); + return tshc.num_threads_completed(); WB_END WB_ENTRY(void, WB_AsyncHandshakeWalkStack(JNIEnv* env, jobject wb, jobject thread_handle)) - class TraceSelfClosure : public AsyncHandshakeClosure { + class TraceSelfHandshakeClosure : public AsyncHandshakeClosure { JavaThread* _self; void do_thread(Thread* th) { assert(th->is_Java_thread(), "sanity"); @@ -2454,15 +2455,15 @@ WB_ENTRY(void, WB_AsyncHandshakeWalkStack(JNIEnv* env, jobject wb, jobject threa } public: - TraceSelfClosure(JavaThread* self_target) : AsyncHandshakeClosure("WB_TraceSelf"), _self(self_target) {} + TraceSelfHandshakeClosure(JavaThread* self_target) : AsyncHandshakeClosure("WB_TraceSelf"), _self(self_target) {} }; if (thread_handle != nullptr) { ThreadsListHandle tlh; JavaThread* target = nullptr; bool is_alive = tlh.cv_internal_thread_to_JavaThread(thread_handle, &target, nullptr); if (is_alive) { - TraceSelfClosure* tsc = new TraceSelfClosure(target); - Handshake::execute(tsc, target); + TraceSelfHandshakeClosure* tshc = new TraceSelfHandshakeClosure(target); + Handshake::execute(tshc, target); } } WB_END diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 789ec469415..adb561ef41b 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -547,6 +547,7 @@ static SpecialFlag const special_jvm_flags[] = { #endif { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, + { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -1848,15 +1849,6 @@ bool Arguments::check_vm_args_consistency() { } #endif -#ifndef _LP64 - if (LockingMode == LM_LEGACY) { - FLAG_SET_CMDLINE(LockingMode, LM_LIGHTWEIGHT); - // Self-forwarding in bit 3 of the mark-word conflicts - // with 4-byte-aligned stack-locks. - warning("Legacy locking not supported on this platform"); - } -#endif - if (UseObjectMonitorTable && LockingMode != LM_LIGHTWEIGHT) { // ObjectMonitorTable requires lightweight locking. FLAG_SET_CMDLINE(UseObjectMonitorTable, false); @@ -2087,6 +2079,18 @@ int Arguments::process_patch_mod_option(const char* patch_mod_tail) { return JNI_OK; } +// Temporary system property to disable preview patching and enable the new preview mode +// feature for testing/development. Once the preview mode feature is finished, the value +// will be always 'true' and this code, and all related dead-code can be removed. +#define DISABLE_PREVIEW_PATCHING_DEFAULT false + +bool Arguments::disable_preview_patching() { + const char* prop = get_property("DISABLE_PREVIEW_PATCHING"); + return (prop != nullptr) + ? strncmp(prop, "true", strlen("true")) == 0 + : DISABLE_PREVIEW_PATCHING_DEFAULT; +} + // VALUECLASS_STR must match string used in the build #define VALUECLASS_STR "valueclasses" #define VALUECLASS_JAR "-" VALUECLASS_STR ".jar" @@ -2094,11 +2098,17 @@ int Arguments::process_patch_mod_option(const char* patch_mod_tail) { // Finalize --patch-module args and --enable-preview related to value class module patches. // Create all numbered properties passing module patches. int Arguments::finalize_patch_module() { - // If --enable-preview and EnableValhalla is true, each module may have value classes that - // are to be patched into the module. + // If --enable-preview and EnableValhalla is true, modules may have preview mode resources. + bool enable_valhalla_preview = enable_preview() && EnableValhalla; + // Whether to use module patching, or the new preview mode feature for preview resources. + bool disable_patching = disable_preview_patching(); + + // This must be called, even with 'false', to enable resource lookup from JImage. + ClassLoader::init_jimage(disable_patching && enable_valhalla_preview); + // For each -valueclasses.jar in /lib/valueclasses/ // appends the equivalent of --patch-module =/lib/valueclasses/-valueclasses.jar - if (enable_preview() && EnableValhalla) { + if (!disable_patching && enable_valhalla_preview) { char * valueclasses_dir = AllocateHeap(JVM_MAXPATHLEN, mtArguments); const char * fileSep = os::file_separator(); @@ -2131,7 +2141,7 @@ int Arguments::finalize_patch_module() { } // Create numbered properties for each module that has been patched either - // by --patch-module or --enable-preview + // by --patch-module (or --enable-preview if disable_patching is false). // Format is "jdk.module.patch.==" if (_patch_mod_prefix != nullptr) { char * prop_value = AllocateHeap(JVM_MAXPATHLEN + JVM_MAXPATHLEN + 1, mtArguments); @@ -3863,9 +3873,6 @@ void Arguments::set_compact_headers_flags() { FLAG_SET_DEFAULT(UseObjectMonitorTable, true); } } - if (UseCompactObjectHeaders && LockingMode != LM_LIGHTWEIGHT) { - FLAG_SET_DEFAULT(LockingMode, LM_LIGHTWEIGHT); - } if (UseCompactObjectHeaders && !UseCompressedClassPointers) { FLAG_SET_DEFAULT(UseCompressedClassPointers, true); } diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index bc2de98a638..f5a1a102fcf 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -486,6 +486,8 @@ class Arguments : AllStatic { // Set up the underlying pieces of the boot class path static void add_patch_mod_prefix(const char *module_name, const char *path, bool allow_append, bool allow_cds); static int finalize_patch_module(); + static bool disable_preview_patching(); + static void set_boot_class_path(const char *value, bool has_jimage) { // During start up, set by os::set_boot_path() assert(get_boot_class_path() == nullptr, "Boot class path previously set"); diff --git a/src/hotspot/share/runtime/continuation.cpp b/src/hotspot/share/runtime/continuation.cpp index 727dcf8fc26..7d0fda21d64 100644 --- a/src/hotspot/share/runtime/continuation.cpp +++ b/src/hotspot/share/runtime/continuation.cpp @@ -170,12 +170,6 @@ freeze_result Continuation::try_preempt(JavaThread* current, oop continuation) { return res; } -#ifndef PRODUCT -static jlong java_tid(JavaThread* thread) { - return java_lang_Thread::thread_id(thread->threadObj()); -} -#endif - ContinuationEntry* Continuation::get_continuation_entry_for_continuation(JavaThread* thread, oop continuation) { if (thread == nullptr || continuation == nullptr) { return nullptr; @@ -405,9 +399,8 @@ frame Continuation::continuation_bottom_sender(JavaThread* thread, const frame& ContinuationEntry* ce = get_continuation_entry_for_sp(thread, callee.sp()); assert(ce != nullptr, "callee.sp(): " INTPTR_FORMAT, p2i(callee.sp())); - log_develop_debug(continuations)("continuation_bottom_sender: [" JLONG_FORMAT "] [%d] callee: " INTPTR_FORMAT - " sender_sp: " INTPTR_FORMAT, - java_tid(thread), thread->osthread()->thread_id(), p2i(callee.sp()), p2i(sender_sp)); + log_develop_debug(continuations)("continuation_bottom_sender: [%d] callee: " INTPTR_FORMAT " sender_sp: " INTPTR_FORMAT, + thread->osthread()->thread_id(), p2i(callee.sp()), p2i(sender_sp)); frame entry = ce->to_frame(); if (callee.is_interpreted_frame()) { diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index a928b0443ee..49074eda188 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -457,9 +457,9 @@ class FreezeBase : public StackObj { static frame sender(const frame& f) { return f.is_interpreted_frame() ? sender(f) : sender(f); } template static inline frame sender(const frame& f); - template frame new_heap_frame(frame& f, frame& caller); + template frame new_heap_frame(frame& f, frame& caller, int size_adjust = 0); inline void set_top_frame_metadata_pd(const frame& hf); - inline void patch_pd(frame& callee, const frame& caller); + inline void patch_pd(frame& callee, const frame& caller, bool is_bottom_frame); void adjust_interpreted_frame_unextended_sp(frame& f); static inline void prepare_freeze_interpreted_top_frame(frame& f); static inline void relativize_interpreted_frame_metadata(const frame& f, const frame& hf); @@ -1159,7 +1159,7 @@ void FreezeBase::patch(const frame& f, frame& hf, const frame& caller, bool is_b assert(!caller.is_empty(), ""); } - patch_pd(hf, caller); + patch_pd(hf, caller, is_bottom_frame); if (f.is_interpreted_frame()) { assert(hf.is_heap_frame(), "should be"); @@ -1256,13 +1256,35 @@ freeze_result FreezeBase::recurse_freeze_compiled_frame(frame& f, frame& caller, intptr_t* const stack_frame_top = ContinuationHelper::CompiledFrame::frame_top(f, callee_argsize, callee_interpreted); intptr_t* const stack_frame_bottom = ContinuationHelper::CompiledFrame::frame_bottom(f); // including metadata between f and its stackargs - const int argsize = ContinuationHelper::CompiledFrame::stack_argsize(f) + frame::metadata_words_at_top; - const int fsize = pointer_delta_as_int(stack_frame_bottom + argsize, stack_frame_top); + int argsize = ContinuationHelper::CompiledFrame::stack_argsize(f) + frame::metadata_words_at_top; + int fsize = pointer_delta_as_int(stack_frame_bottom + argsize, stack_frame_top); + + int real_frame_size = 0; + bool augmented = f.was_augmented_on_entry(real_frame_size); + if (augmented) { + // The args reside inside the frame so clear argsize. If the caller is compiled, + // this will cause the stack arguments passed by the caller to be freezed when + // freezing the caller frame itself. If the caller is interpreted this will have + // the effect of discarding the arg area created in the i2c stub. + argsize = 0; + fsize = real_frame_size - (callee_interpreted ? 0 : callee_argsize); +#ifdef ASSERT + nmethod* nm = f.cb()->as_nmethod(); + Method* method = nm->method(); + address return_pc = ContinuationHelper::CompiledFrame::return_pc(f); + CodeBlob* caller_cb = CodeCache::find_blob_fast(return_pc); + assert(nm->is_compiled_by_c2() || (caller_cb->is_nmethod() && caller_cb->as_nmethod()->is_compiled_by_c2()), "caller or callee should be c2 compiled"); + assert((!caller_cb->is_nmethod() && nm->is_compiled_by_c2()) || + (nm->compiler_type() != caller_cb->as_nmethod()->compiler_type()) || + (nm->is_compiled_by_c2() && !method->is_static() && method->method_holder()->is_inline_klass()), + "frame should not be extended"); +#endif + } - log_develop_trace(continuations)("recurse_freeze_compiled_frame %s _size: %d fsize: %d argsize: %d", + log_develop_trace(continuations)("recurse_freeze_compiled_frame %s _size: %d fsize: %d argsize: %d augmented: %d", ContinuationHelper::Frame::frame_method(f) != nullptr ? ContinuationHelper::Frame::frame_method(f)->name_and_sig_as_C_string() : "", - _freeze_size, fsize, argsize); + _freeze_size, fsize, argsize, augmented); // we'd rather not yield inside methods annotated with @JvmtiMountTransition assert(!ContinuationHelper::Frame::frame_method(f)->jvmti_mount_transition(), ""); @@ -1273,10 +1295,11 @@ freeze_result FreezeBase::recurse_freeze_compiled_frame(frame& f, frame& caller, bool is_bottom_frame = result == freeze_ok_bottom; assert(!caller.is_empty() || is_bottom_frame, ""); + assert(!is_bottom_frame || !augmented, "thaw extended frame without caller?"); DEBUG_ONLY(before_freeze_java_frame(f, caller, fsize, argsize, is_bottom_frame);) - frame hf = new_heap_frame(f, caller); + frame hf = new_heap_frame(f, caller, augmented ? real_frame_size - f.cb()->as_nmethod()->frame_size() : 0); intptr_t* heap_frame_top = ContinuationHelper::CompiledFrame::frame_top(hf, callee_argsize, callee_interpreted); @@ -1938,6 +1961,7 @@ class ThawBase : public StackObj { void clear_chunk(stackChunkOop chunk); template int remove_top_compiled_frame_from_chunk(stackChunkOop chunk, int &argsize); + int remove_scalarized_frames(StackChunkFrameStream& scfs, stackChunkOop chunk, int &argsize); void copy_from_chunk(intptr_t* from, intptr_t* to, int size); void thaw_lockstack(stackChunkOop chunk); @@ -1961,7 +1985,7 @@ class ThawBase : public StackObj { inline void before_thaw_java_frame(const frame& hf, const frame& caller, bool bottom, int num_frame); inline void after_thaw_java_frame(const frame& f, bool bottom); - inline void patch(frame& f, const frame& caller, bool bottom); + inline void patch(frame& f, const frame& caller, bool bottom, bool augmented = false); void clear_bitmap_bits(address start, address end); NOINLINE void recurse_thaw_interpreted_frame(const frame& hf, frame& caller, int num_frames); @@ -1971,7 +1995,7 @@ class ThawBase : public StackObj { void push_return_frame(frame& f); inline frame new_entry_frame(); - template frame new_stack_frame(const frame& hf, frame& caller, bool bottom); + template frame new_stack_frame(const frame& hf, frame& caller, bool bottom, int size_adjust = 0); inline void patch_pd(frame& f, const frame& sender); inline void patch_pd(frame& f, intptr_t* caller_sp); inline intptr_t* align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom); @@ -2048,6 +2072,47 @@ inline void ThawBase::clear_chunk(stackChunkOop chunk) { chunk->set_max_thawing_size(0); } +int ThawBase::remove_scalarized_frames(StackChunkFrameStream& f, stackChunkOop chunk, int &argsize) { + DEBUG_ONLY(intptr_t* const chunk_sp = chunk->start_address() + chunk->sp();) + intptr_t* top = f.sp(); + + while (f.cb()->as_nmethod_or_null()->needs_stack_repair()) { + f.next(SmallRegisterMap::instance(), false /* stop */); + } + assert(!f.is_done(), ""); + assert(f.is_compiled(), ""); + + intptr_t* bottom = f.sp() + f.cb()->frame_size(); + argsize = f.stack_argsize(); + int frames_size = bottom - top; + + f.next(SmallRegisterMap::instance(), true /* stop */); + bool empty = f.is_done(); + assert(!empty || argsize == chunk->argsize(), ""); + + if (empty) { + clear_chunk(chunk); + } else { + chunk->set_sp(chunk->sp() + frames_size); + chunk->set_max_thawing_size(chunk->max_thawing_size() - frames_size); + // We set chunk->pc to the return pc into the next frame + chunk->set_pc(f.pc()); +#ifdef ASSERT + { + intptr_t* retaddr_slot = (chunk_sp + + frames_size + - frame::sender_sp_ret_address_offset()); + assert(f.pc() == ContinuationHelper::return_address_at(retaddr_slot), + "unexpected pc"); + } +#endif + } + assert(empty == chunk->is_empty(), ""); + // returns the size required to store the frame on stack, and because it is a + // compiled frame, it must include a copy of the arguments passed by the caller + return frames_size + argsize + frame::metadata_words_at_top; +} + template int ThawBase::remove_top_compiled_frame_from_chunk(stackChunkOop chunk, int &argsize) { bool empty = false; @@ -2056,6 +2121,10 @@ int ThawBase::remove_top_compiled_frame_from_chunk(stackChunkOop chunk, int &arg assert(chunk_sp == f.sp(), ""); assert(chunk_sp == f.unextended_sp(), ""); + if (f.cb()->as_nmethod_or_null()->needs_stack_repair()) { + return remove_scalarized_frames(f, chunk, argsize); + } + int frame_size = f.cb()->frame_size(); argsize = f.stack_argsize(); @@ -2357,13 +2426,19 @@ bool ThawBase::recurse_thaw_java_frame(frame& caller, int num_frames) { DEBUG_ONLY(_frames++;) int argsize = _stream.stack_argsize(); + CodeBlob* cb = _stream.cb(); _stream.next(SmallRegisterMap::instance()); assert(_stream.to_frame().is_empty() == _stream.is_done(), ""); - // we never leave a compiled caller of an interpreted frame as the top frame in the chunk - // as it makes detecting that situation and adjusting unextended_sp tricky - if (num_frames == 1 && !_stream.is_done() && FKind::interpreted && _stream.is_compiled()) { + // We never leave a compiled caller of an interpreted frame as the top frame in the chunk + // as it makes detecting that situation and adjusting unextended_sp tricky. We also always + // thaw the caller of a frame that needs_stack_repair, as it would otherwise complicate things: + // - Regardless of whether the frame was extended or not, we would need to copy the right arg + // size if its greater than the one given by the normal method signature (non-scalarized). + // - If the frame was indeed extended, leaving its caller as the top frame would complicate walking + // the chunk (we need unextended_sp, but we only have sp). + if (num_frames == 1 && !_stream.is_done() && ((FKind::interpreted && _stream.is_compiled()) || (FKind::compiled && cb->as_nmethod_or_null()->needs_stack_repair()))) { log_develop_trace(continuations)("thawing extra compiled frame to not leave a compiled interpreted-caller at top"); num_frames++; } @@ -2423,15 +2498,15 @@ inline void ThawBase::after_thaw_java_frame(const frame& f, bool bottom) { #endif } -inline void ThawBase::patch(frame& f, const frame& caller, bool bottom) { +inline void ThawBase::patch(frame& f, const frame& caller, bool bottom, bool augmented) { assert(!bottom || caller.fp() == _cont.entryFP(), ""); if (bottom) { ContinuationHelper::Frame::patch_pc(caller, _cont.is_empty() ? caller.pc() : StubRoutines::cont_returnBarrier()); - } else { + } else if (caller.is_compiled_frame()){ // caller might have been deoptimized during thaw but we've overwritten the return address when copying f from the heap. // If the caller is not deoptimized, pc is unchanged. - ContinuationHelper::Frame::patch_pc(caller, caller.raw_pc()); + ContinuationHelper::Frame::patch_pc(caller, caller.raw_pc(), augmented /*callee_augmented*/); } patch_pd(f, caller); @@ -2594,17 +2669,24 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n _align_size += frame::align_wiggle; // we add one whether or not we've aligned because we add it in recurse_freeze_compiled_frame } + int fsize = 0; + int added_argsize = 0; + bool augmented = hf.was_augmented_on_entry(fsize); + if (!augmented) { + added_argsize = (is_bottom_frame || caller.is_interpreted_frame()) ? hf.compiled_frame_stack_argsize() : 0; + fsize += added_argsize; + } + assert(!is_bottom_frame || !augmented, ""); + + // new_stack_frame must construct the resulting frame using hf.pc() rather than hf.raw_pc() because the frame is not // yet laid out in the stack, and so the original_pc is not stored in it. // As a result, f.is_deoptimized_frame() is always false and we must test hf to know if the frame is deoptimized. - frame f = new_stack_frame(hf, caller, is_bottom_frame); + frame f = new_stack_frame(hf, caller, is_bottom_frame, augmented ? fsize - hf.cb()->frame_size() : 0); + assert(f.cb()->frame_size() == (int)(caller.sp() - f.sp()), ""); + intptr_t* const stack_frame_top = f.sp(); intptr_t* const heap_frame_top = hf.unextended_sp(); - - const int added_argsize = (is_bottom_frame || caller.is_interpreted_frame()) ? hf.compiled_frame_stack_argsize() : 0; - int fsize = ContinuationHelper::CompiledFrame::size(hf) + added_argsize; - assert(fsize <= (int)(caller.unextended_sp() - f.unextended_sp()), ""); - intptr_t* from = heap_frame_top - frame::metadata_words_at_bottom; intptr_t* to = stack_frame_top - frame::metadata_words_at_bottom; // copy metadata, except the metadata at the top of the (unextended) entry frame @@ -2617,7 +2699,7 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n copy_from_chunk(from, to, sz); // copying good oops because we invoked barriers above - patch(f, caller, is_bottom_frame); + patch(f, caller, is_bottom_frame, augmented); // f.is_deoptimized_frame() is always false and we must test hf.is_deoptimized_frame() (see comment above) assert(!f.is_deoptimized_frame(), ""); diff --git a/src/hotspot/share/runtime/continuationHelper.hpp b/src/hotspot/share/runtime/continuationHelper.hpp index 0b3e6c72452..8d9a379a58c 100644 --- a/src/hotspot/share/runtime/continuationHelper.hpp +++ b/src/hotspot/share/runtime/continuationHelper.hpp @@ -65,13 +65,14 @@ class ContinuationHelper { class ContinuationHelper::Frame : public AllStatic { public: static const bool interpreted = false; + static const bool compiled = false; static const bool stub = false; static const bool native = false; static inline intptr_t** callee_link_address(const frame& f); static Method* frame_method(const frame& f); static inline address real_pc(const frame& f); - static inline void patch_pc(const frame& f, address pc); + static inline void patch_pc(const frame& f, address pc, bool callee_augmented = false); static address* return_pc_address(const frame& f); static address return_pc(const frame& f); static bool is_stub(CodeBlob* cb); @@ -127,6 +128,8 @@ class ContinuationHelper::NonInterpretedUnknownFrame : public ContinuationHelper class ContinuationHelper::CompiledFrame : public ContinuationHelper::NonInterpretedFrame { public: + static const bool compiled = true; + static bool is_instance(const frame& f); #ifdef ASSERT diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 1dd7799453f..3f88b69c5b4 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1096,9 +1096,9 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m return bt; JRT_END -class DeoptimizeMarkedClosure : public HandshakeClosure { +class DeoptimizeMarkedHandshakeClosure : public HandshakeClosure { public: - DeoptimizeMarkedClosure() : HandshakeClosure("Deoptimize") {} + DeoptimizeMarkedHandshakeClosure() : HandshakeClosure("Deoptimize") {} void do_thread(Thread* thread) { JavaThread* jt = JavaThread::cast(thread); jt->deoptimize_marked_methods(); @@ -1111,7 +1111,7 @@ void Deoptimization::deoptimize_all_marked() { // Make the dependent methods not entrant CodeCache::make_marked_nmethods_deoptimized(); - DeoptimizeMarkedClosure deopt; + DeoptimizeMarkedHandshakeClosure deopt; if (SafepointSynchronize::is_at_safepoint()) { Threads::java_threads_do(&deopt); } else { @@ -2483,6 +2483,14 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr ShouldNotReachHere(); } +#if INCLUDE_JVMCI + // Deoptimization count is used by the CompileBroker to reason about compilations + // it requests so do not pollute the count for deoptimizations in non-default (i.e. + // non-CompilerBroker) compilations. + if (nm->jvmci_skip_profile_deopt()) { + update_trap_state = false; + } +#endif // Setting +ProfileTraps fixes the following, on all platforms: // The result is infinite heroic-opt-uncommon-trap/deopt/recompile cycles, since the // recompile relies on a MethodData* to record heroic opt failures. @@ -2593,7 +2601,6 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr trap_mdo->inc_tenure_traps(); } } - if (inc_recompile_count) { trap_mdo->inc_overflow_recompile_count(); if ((uint)trap_mdo->overflow_recompile_count() > diff --git a/src/hotspot/share/runtime/escapeBarrier.cpp b/src/hotspot/share/runtime/escapeBarrier.cpp index 8f9a8b59dd6..2005527bb8b 100644 --- a/src/hotspot/share/runtime/escapeBarrier.cpp +++ b/src/hotspot/share/runtime/escapeBarrier.cpp @@ -165,9 +165,9 @@ bool EscapeBarrier::deoptimize_objects_all_threads() { bool EscapeBarrier::_deoptimizing_objects_for_all_threads = false; bool EscapeBarrier::_self_deoptimization_in_progress = false; -class EscapeBarrierSuspendHandshake : public HandshakeClosure { +class EscapeBarrierSuspendHandshakeClosure : public HandshakeClosure { public: - EscapeBarrierSuspendHandshake(const char* name) : + EscapeBarrierSuspendHandshakeClosure(const char* name) : HandshakeClosure(name) { } void do_thread(Thread* th) { } }; @@ -196,7 +196,7 @@ void EscapeBarrier::sync_and_suspend_one() { } // Use a handshake to synchronize with the target thread. - EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendOne"); + EscapeBarrierSuspendHandshakeClosure sh("EscapeBarrierSuspendOne"); Handshake::execute(&sh, _deoptee_thread); assert(!_deoptee_thread->has_last_Java_frame() || _deoptee_thread->frame_anchor()->walkable(), "stack should be walkable now"); @@ -242,7 +242,7 @@ void EscapeBarrier::sync_and_suspend_all() { } // Use a handshake to synchronize with the other threads. - EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendAll"); + EscapeBarrierSuspendHandshakeClosure sh("EscapeBarrierSuspendAll"); Handshake::execute(&sh); #ifdef ASSERT for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 9ea79bea6af..e1b90239e3e 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -382,8 +382,8 @@ void frame::deoptimize(JavaThread* thread) { #if defined ASSERT && !defined AARCH64 // Stub call site does not look like NativeCall on AArch64 NativeCall* call = nativeCall_before(this->pc()); address dest = call->destination(); - assert(dest == Runtime1::entry_for(C1StubId::buffer_inline_args_no_receiver_id) || - dest == Runtime1::entry_for(C1StubId::buffer_inline_args_id), "unexpected safepoint in entry point"); + assert(dest == Runtime1::entry_for(StubId::c1_buffer_inline_args_no_receiver_id) || + dest == Runtime1::entry_for(StubId::c1_buffer_inline_args_id), "unexpected safepoint in entry point"); #endif return; } @@ -1478,8 +1478,8 @@ void frame::describe(FrameValues& values, int frame_no, const RegisterMap* reg_m // For now just label the frame nmethod* nm = cb()->as_nmethod(); values.describe(-1, info_address, - FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method J %s%s", frame_no, - p2i(nm), + FormatBuffer<1024>("#%d nmethod (%s %d) " INTPTR_FORMAT " for method J %s%s", frame_no, + nm->is_compiled_by_c1() ? "c1" : "c2", nm->frame_size(), p2i(nm), nm->method()->name_and_sig_as_C_string(), (_deopt_state == is_deoptimized) ? " (deoptimized)" : @@ -1489,36 +1489,18 @@ void frame::describe(FrameValues& values, int frame_no, const RegisterMap* reg_m { // mark arguments (see nmethod::print_nmethod_labels) Method* m = nm->method(); + CompiledEntrySignature ces(m); + ces.compute_calling_conventions(false); + const GrowableArray* sig_cc = nm->is_compiled_by_c2() ? ces.sig_cc() : ces.sig(); + const VMRegPair* regs = nm->is_compiled_by_c2() ? ces.regs_cc() : ces.regs(); + int stack_slot_offset = nm->frame_size() * wordSize; // offset, in bytes, to caller sp - int sizeargs = m->size_of_parameters(); - - BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); - VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); - { - int sig_index = 0; - if (!m->is_static()) { - sig_bt[sig_index++] = T_OBJECT; // 'this' - } - for (SignatureStream ss(m->signature()); !ss.at_return_type(); ss.next()) { - BasicType t = ss.type(); - assert(type2size[t] == 1 || type2size[t] == 2, "size is 1 or 2"); - sig_bt[sig_index++] = t; - if (type2size[t] == 2) { - sig_bt[sig_index++] = T_VOID; - } - } - assert(sig_index == sizeargs, ""); - } - int stack_arg_slots = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs); - assert(stack_arg_slots == nm->as_nmethod()->num_stack_arg_slots(false /* rounded */) || nm->is_osr_method(), ""); int out_preserve = SharedRuntime::out_preserve_stack_slots(); int sig_index = 0; int arg_index = (m->is_static() ? 0 : -1); - for (SignatureStream ss(m->signature()); !ss.at_return_type(); ) { + for (ExtendedSignature sig = ExtendedSignature(sig_cc, SigEntryFilter()); !sig.at_end(); ++sig) { bool at_this = (arg_index == -1); - bool at_old_sp = false; - BasicType t = (at_this ? T_OBJECT : ss.type()); - assert(t == sig_bt[sig_index], "sigs in sync"); + BasicType t = (*sig)._bt; VMReg fst = regs[sig_index].first(); if (fst->is_stack()) { assert(((int)fst->reg2stack()) >= 0, "reg2stack: %d", fst->reg2stack()); @@ -1532,9 +1514,6 @@ void frame::describe(FrameValues& values, int frame_no, const RegisterMap* reg_m } sig_index += type2size[t]; arg_index += 1; - if (!at_this) { - ss.next(); - } } } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index fb7f8169b2f..0668e3b7353 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -293,6 +293,9 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseInlineCaches, true, \ "Use Inline Caches for virtual calls ") \ \ + develop(bool, VerifyInlineCaches, true, \ + "Verify Inline Caches") \ + \ product(bool, InlineArrayCopy, true, DIAGNOSTIC, \ "Inline arraycopy native that is known to be part of " \ "base library DLL") \ @@ -975,10 +978,6 @@ const int ObjectAlignmentInBytes = 8; "Inject thread creation failures for " \ "UseDynamicNumberOfCompilerThreads") \ \ - develop(bool, GenerateSynchronizationCode, true, \ - "generate locking/unlocking code for synchronized methods and " \ - "monitors") \ - \ product_pd(bool, ImplicitNullChecks, DIAGNOSTIC, \ "Generate code for implicit null checks") \ \ @@ -1594,9 +1593,7 @@ const int ObjectAlignmentInBytes = 8; range(0.0, 100.0) \ \ product(uintx, StartAggressiveSweepingAt, 10, \ - "Start aggressive sweeping if X[%] of the code cache is free." \ - "Segmented code cache: X[%] of the non-profiled heap." \ - "Non-segmented code cache: X[%] of the total code cache") \ + "Start aggressive sweeping if less than X[%] of the total code cache is free.")\ range(0, 100) \ \ /* interpreter debugging */ \ @@ -2007,13 +2004,6 @@ const int ObjectAlignmentInBytes = 8; "Mark all threads after a safepoint, and clear on a modify " \ "fence. Add cleanliness checks.") \ \ - product(int, LockingMode, LM_LIGHTWEIGHT, \ - "(Deprecated) Select locking mode: " \ - "0: (Deprecated) monitors only (LM_MONITOR), " \ - "1: (Deprecated) monitors & legacy stack-locking (LM_LEGACY), " \ - "2: monitors & new lightweight locking (LM_LIGHTWEIGHT, default)") \ - range(0, 2) \ - \ product(bool, UseObjectMonitorTable, false, DIAGNOSTIC, \ "With Lightweight Locking mode, use a table to record inflated " \ "monitors rather than the first word of the object.") \ diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index 2c827b61602..c55803242de 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -705,7 +705,7 @@ void HandshakeState::handle_unsafe_access_error() { // back to Java until resumed we cannot create the exception // object yet. Add a new unsafe access error operation to // the end of the queue and try again in the next attempt. - Handshake::execute(new UnsafeAccessErrorHandshake(), _handshakee); + Handshake::execute(new UnsafeAccessErrorHandshakeClosure(), _handshakee); log_info(handshake)("JavaThread " INTPTR_FORMAT " skipping unsafe access processing due to suspend.", p2i(_handshakee)); return; } diff --git a/src/hotspot/share/runtime/handshake.hpp b/src/hotspot/share/runtime/handshake.hpp index ca9cef76f5d..c6f3aad08db 100644 --- a/src/hotspot/share/runtime/handshake.hpp +++ b/src/hotspot/share/runtime/handshake.hpp @@ -35,7 +35,7 @@ class HandshakeOperation; class AsyncHandshakeOperation; class JavaThread; -class UnsafeAccessErrorHandshake; +class UnsafeAccessErrorHandshakeClosure; class ThreadsListHandle; // A handshake closure is a callback that is executed for a JavaThread @@ -86,7 +86,7 @@ class JvmtiRawMonitor; // operation is only done by either VMThread/Handshaker on behalf of the // JavaThread or by the target JavaThread itself. class HandshakeState { - friend UnsafeAccessErrorHandshake; + friend UnsafeAccessErrorHandshakeClosure; friend JavaThread; // This a back reference to the JavaThread, // the target for all operation in the queue. diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index 30862c92604..18911a7635b 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -68,6 +68,7 @@ void compilationPolicy_init(); void codeCache_init(); void VM_Version_init(); void icache_init2(); +void initialize_stub_info(); // must precede all blob/stub generation void preuniverse_stubs_init(); void initial_stubs_init(); @@ -131,6 +132,8 @@ jint init_globals() { VM_Version_init(); // depends on codeCache_init for emitting code VMRegImpl::set_regName(); // need this before generate_stubs (for printing oop maps). icache_init2(); // depends on VM_Version for choosing the mechanism + // ensure we know about all blobs, stubs and entries + initialize_stub_info(); // initialize stubs needed before we can init the universe preuniverse_stubs_init(); jint status = universe_init(); // dependent on codeCache_init and preuniverse_stubs_init @@ -147,10 +150,10 @@ jint init_globals() { AOTCodeCache::init2(); // depends on universe_init, must be before initial_stubs_init AsyncLogWriter::initialize(); - initial_stubs_init(); // initial stub routines + initial_stubs_init(); // stubgen initial stub routines // stack overflow exception blob is referenced by the interpreter + AOTCodeCache::init_early_stubs_table(); // need this after stubgen initial stubs and before shared runtime initial stubs SharedRuntime::generate_initial_stubs(); - AOTCodeCache::init_early_stubs_table(); // need this after initial_stubs gc_barrier_stubs_init(); // depends on universe_init, must be before interpreter_init continuations_init(); // must precede continuation stub generation continuation_stubs_init(); // depends on continuations_init diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index aa0b5dca3e4..bd96f92c47a 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -471,8 +471,8 @@ void before_exit(JavaThread* thread, bool halt) { NativeHeapTrimmer::cleanup(); - // Stop concurrent GC threads - Universe::heap()->stop(); + // Run before exit and then stop concurrent GC threads + Universe::heap()->before_exit(); // Print GC/heap related information. Log(gc, exit) log; @@ -513,7 +513,6 @@ void before_exit(JavaThread* thread, bool halt) { os::terminate_signal_thread(); print_statistics(); - Universe::heap()->print_tracing_info(); { MutexLocker ml(BeforeExit_lock); _before_exit_status = BEFORE_EXIT_DONE; diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 5637493a31a..874cf7cc530 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1125,16 +1125,16 @@ void JavaThread::handle_async_exception(oop java_throwable) { } } -void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) { +void JavaThread::install_async_exception(AsyncExceptionHandshakeClosure* aehc) { // Do not throw asynchronous exceptions against the compiler thread // or if the thread is already exiting. if (!can_call_java() || is_exiting()) { - delete aeh; + delete aehc; return; } - oop exception = aeh->exception(); - Handshake::execute(aeh, this); // Install asynchronous handshake + oop exception = aehc->exception(); + Handshake::execute(aehc, this); // Install asynchronous handshake ResourceMark rm; if (log_is_enabled(Info, exceptions)) { @@ -1152,25 +1152,25 @@ void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) { } } -class InstallAsyncExceptionHandshake : public HandshakeClosure { - AsyncExceptionHandshake* _aeh; +class InstallAsyncExceptionHandshakeClosure : public HandshakeClosure { + AsyncExceptionHandshakeClosure* _aehc; public: - InstallAsyncExceptionHandshake(AsyncExceptionHandshake* aeh) : - HandshakeClosure("InstallAsyncException"), _aeh(aeh) {} - ~InstallAsyncExceptionHandshake() { - // If InstallAsyncExceptionHandshake was never executed we need to clean up _aeh. - delete _aeh; + InstallAsyncExceptionHandshakeClosure(AsyncExceptionHandshakeClosure* aehc) : + HandshakeClosure("InstallAsyncException"), _aehc(aehc) {} + ~InstallAsyncExceptionHandshakeClosure() { + // If InstallAsyncExceptionHandshakeClosure was never executed we need to clean up _aehc. + delete _aehc; } void do_thread(Thread* thr) { JavaThread* target = JavaThread::cast(thr); - target->install_async_exception(_aeh); - _aeh = nullptr; + target->install_async_exception(_aehc); + _aehc = nullptr; } }; void JavaThread::send_async_exception(JavaThread* target, oop java_throwable) { OopHandle e(Universe::vm_global(), java_throwable); - InstallAsyncExceptionHandshake iaeh(new AsyncExceptionHandshake(e)); + InstallAsyncExceptionHandshakeClosure iaeh(new AsyncExceptionHandshakeClosure(e)); Handshake::execute(&iaeh, target); } diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 52397255d81..5b5e73dfe07 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -53,7 +53,7 @@ #include "utilities/ticks.hpp" #endif -class AsyncExceptionHandshake; +class AsyncExceptionHandshakeClosure; class DeoptResourceMark; class InternalOOMEMark; class JNIHandleBlock; @@ -234,13 +234,13 @@ class JavaThread: public Thread { // Asynchronous exception support private: - friend class InstallAsyncExceptionHandshake; - friend class AsyncExceptionHandshake; + friend class InstallAsyncExceptionHandshakeClosure; + friend class AsyncExceptionHandshakeClosure; friend class HandshakeState; void handle_async_exception(oop java_throwable); public: - void install_async_exception(AsyncExceptionHandshake* aec = nullptr); + void install_async_exception(AsyncExceptionHandshakeClosure* aec = nullptr); bool has_async_exception_condition(); inline void set_pending_unsafe_access_error(); static void send_async_exception(JavaThread* jt, oop java_throwable); @@ -1169,7 +1169,7 @@ class JavaThread: public Thread { // Used by the interpreter in fullspeed mode for frame pop, method // entry, method exit and single stepping support. This field is // only set to non-zero at a safepoint or using a direct handshake - // (see EnterInterpOnlyModeClosure). + // (see EnterInterpOnlyModeHandshakeClosure). // It can be set to zero asynchronously to this threads execution (i.e., without // safepoint/handshake or a lock) so we have to be very careful. // Accesses by other threads are synchronized using JvmtiThreadState_lock though. diff --git a/src/hotspot/share/runtime/javaThread.inline.hpp b/src/hotspot/share/runtime/javaThread.inline.hpp index 136a9d84151..be76407f511 100644 --- a/src/hotspot/share/runtime/javaThread.inline.hpp +++ b/src/hotspot/share/runtime/javaThread.inline.hpp @@ -73,13 +73,13 @@ inline bool JavaThread::clear_carrier_thread_suspended() { } #endif -class AsyncExceptionHandshake : public AsyncHandshakeClosure { +class AsyncExceptionHandshakeClosure : public AsyncHandshakeClosure { OopHandle _exception; public: - AsyncExceptionHandshake(OopHandle& o, const char* name = "AsyncExceptionHandshake") + AsyncExceptionHandshakeClosure(OopHandle& o, const char* name = "AsyncExceptionHandshakeClosure") : AsyncHandshakeClosure(name), _exception(o) { } - ~AsyncExceptionHandshake() { + ~AsyncExceptionHandshakeClosure() { Thread* current = Thread::current(); // Can get here from the VMThread via install_async_exception() bail out. if (current->is_Java_thread()) { @@ -103,9 +103,9 @@ class AsyncExceptionHandshake : public AsyncHandshakeClosure { bool is_async_exception() { return true; } }; -class UnsafeAccessErrorHandshake : public AsyncHandshakeClosure { +class UnsafeAccessErrorHandshakeClosure : public AsyncHandshakeClosure { public: - UnsafeAccessErrorHandshake() : AsyncHandshakeClosure("UnsafeAccessErrorHandshake") {} + UnsafeAccessErrorHandshakeClosure() : AsyncHandshakeClosure("UnsafeAccessErrorHandshakeClosure") {} void do_thread(Thread* thr) { JavaThread* self = JavaThread::cast(thr); assert(self == JavaThread::current(), "must be"); @@ -117,7 +117,7 @@ class UnsafeAccessErrorHandshake : public AsyncHandshakeClosure { inline void JavaThread::set_pending_unsafe_access_error() { if (!has_async_exception_condition()) { - Handshake::execute(new UnsafeAccessErrorHandshake(), this); + Handshake::execute(new UnsafeAccessErrorHandshakeClosure(), this); } } diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index b90f8c23a6d..5f1c2ee61ae 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -84,7 +84,6 @@ Monitor* CompileTaskWait_lock = nullptr; Monitor* MethodCompileQueue_lock = nullptr; Monitor* CompileThread_lock = nullptr; Monitor* Compilation_lock = nullptr; -Mutex* CompileTaskAlloc_lock = nullptr; Mutex* CompileStatistics_lock = nullptr; Mutex* DirectivesStack_lock = nullptr; Monitor* Terminator_lock = nullptr; @@ -236,7 +235,7 @@ void mutex_init() { MUTEX_DEFN(Service_lock , PaddedMonitor, service); // used for service thread operations MUTEX_DEFN(Notification_lock , PaddedMonitor, service); // used for notification thread operations - MUTEX_DEFN(JmethodIdCreation_lock , PaddedMutex , nosafepoint-2); // used for creating jmethodIDs. + MUTEX_DEFN(JmethodIdCreation_lock , PaddedMutex , nosafepoint-1); // used for creating jmethodIDs can also lock HandshakeState_lock MUTEX_DEFN(InvokeMethodTypeTable_lock , PaddedMutex , safepoint); MUTEX_DEFN(InvokeMethodIntrinsicTable_lock , PaddedMonitor, safepoint); MUTEX_DEFN(AdapterHandlerLibrary_lock , PaddedMutex , safepoint); @@ -346,7 +345,6 @@ void mutex_init() { MUTEX_DEFL(G1RareEvent_lock , PaddedMutex , Threads_lock, true); } - MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMutex , MethodCompileQueue_lock); MUTEX_DEFL(CompileTaskWait_lock , PaddedMonitor, MethodCompileQueue_lock); #if INCLUDE_PARALLELGC diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 640747c3fe9..72454ca04ca 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -86,7 +86,6 @@ extern Monitor* CompileThread_lock; // a lock held by compile threa extern Monitor* Compilation_lock; // a lock used to pause compilation extern Mutex* TrainingData_lock; // a lock used when accessing training records extern Monitor* TrainingReplayQueue_lock; // a lock held when class are added/removed to the training replay queue -extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated extern Monitor* CompileTaskWait_lock; // a lock held when CompileTasks are waited/notified extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index ee1f0a3b081..db2256d70cb 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1042,7 +1042,7 @@ void os::print_hex_dump(outputStream* st, const_address start, const_address end } print_hex_location(st, p, unitsize, ascii_form); p += unitsize; - logical_p += unitsize; + logical_p = (const_address) ((uintptr_t)logical_p + unitsize); cols++; if (cols >= cols_per_line) { if (print_ascii && !ascii_form.is_empty()) { @@ -1125,7 +1125,7 @@ void os::print_environment_variables(outputStream* st, const char** env_list) { void os::print_jvmti_agent_info(outputStream* st) { #if INCLUDE_JVMTI - const JvmtiAgentList::Iterator it = JvmtiAgentList::all(); + JvmtiAgentList::Iterator it = JvmtiAgentList::all(); if (it.has_next()) { st->print_cr("JVMTI agents:"); } else { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index b26ec280e72..6648b08637c 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -293,12 +293,7 @@ class os: AllStatic { static jlong elapsed_counter(); static jlong elapsed_frequency(); - // The "virtual time" of a thread is the amount of time a thread has - // actually run. The first function indicates whether the OS supports - // this functionality for the current thread, and if so the second - // returns the elapsed virtual time for the current thread. - static bool supports_vtime(); - static double elapsedVTime(); + static double elapsed_process_cpu_time(); // Return current local time in a string (YYYY-MM-DD HH:MM:SS). // It is MT safe, but not async-safe, as reading time zone diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp index 4e7c4b93d53..37629c0d226 100644 --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -559,9 +559,9 @@ char* Reflection::verify_class_access_msg(const Klass* current_class, current_class_name, module_from_name, new_class_name, module_to_name, module_from_name, module_to_name); } else { - oop jlm = module_to->module(); - assert(jlm != nullptr, "Null jlm in module_to ModuleEntry"); - intptr_t identity_hash = jlm->identity_hash(); + oop module_oop = module_to->module_oop(); + assert(module_oop != nullptr, "should have been initialized"); + intptr_t identity_hash = module_oop->identity_hash(); size_t len = 160 + strlen(current_class_name) + 2*strlen(module_from_name) + strlen(new_class_name) + 2*sizeof(uintx); msg = NEW_RESOURCE_ARRAY(char, len); @@ -586,9 +586,9 @@ char* Reflection::verify_class_access_msg(const Klass* current_class, current_class_name, module_from_name, new_class_name, module_to_name, module_to_name, package_name, module_from_name); } else { - oop jlm = module_from->module(); - assert(jlm != nullptr, "Null jlm in module_from ModuleEntry"); - intptr_t identity_hash = jlm->identity_hash(); + oop module_oop = module_from->module_oop(); + assert(module_oop != nullptr, "should have been initialized"); + intptr_t identity_hash = module_oop->identity_hash(); size_t len = 170 + strlen(current_class_name) + strlen(new_class_name) + 2*strlen(module_to_name) + strlen(package_name) + 2*sizeof(uintx); msg = NEW_RESOURCE_ARRAY(char, len); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index fdd961445f7..aeeb06dfee2 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -100,59 +100,62 @@ #define SHARED_STUB_FIELD_DEFINE(name, type) \ - type SharedRuntime::BLOB_FIELD_NAME(name); + type* SharedRuntime::BLOB_FIELD_NAME(name); SHARED_STUBS_DO(SHARED_STUB_FIELD_DEFINE) #undef SHARED_STUB_FIELD_DEFINE nmethod* SharedRuntime::_cont_doYield_stub; +#if 0 +// TODO tweak global stub name generation to match this #define SHARED_STUB_NAME_DECLARE(name, type) "Shared Runtime " # name "_blob", const char *SharedRuntime::_stub_names[] = { SHARED_STUBS_DO(SHARED_STUB_NAME_DECLARE) }; +#endif //----------------------------generate_stubs----------------------------------- void SharedRuntime::generate_initial_stubs() { // Build this early so it's available for the interpreter. _throw_StackOverflowError_blob = - generate_throw_exception(SharedStubId::throw_StackOverflowError_id, + generate_throw_exception(StubId::shared_throw_StackOverflowError_id, CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError)); } void SharedRuntime::generate_stubs() { _wrong_method_blob = - generate_resolve_blob(SharedStubId::wrong_method_id, + generate_resolve_blob(StubId::shared_wrong_method_id, CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method)); _wrong_method_abstract_blob = - generate_resolve_blob(SharedStubId::wrong_method_abstract_id, + generate_resolve_blob(StubId::shared_wrong_method_abstract_id, CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_abstract)); _ic_miss_blob = - generate_resolve_blob(SharedStubId::ic_miss_id, + generate_resolve_blob(StubId::shared_ic_miss_id, CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss)); _resolve_opt_virtual_call_blob = - generate_resolve_blob(SharedStubId::resolve_opt_virtual_call_id, + generate_resolve_blob(StubId::shared_resolve_opt_virtual_call_id, CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C)); _resolve_virtual_call_blob = - generate_resolve_blob(SharedStubId::resolve_virtual_call_id, + generate_resolve_blob(StubId::shared_resolve_virtual_call_id, CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C)); _resolve_static_call_blob = - generate_resolve_blob(SharedStubId::resolve_static_call_id, + generate_resolve_blob(StubId::shared_resolve_static_call_id, CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C)); _throw_delayed_StackOverflowError_blob = - generate_throw_exception(SharedStubId::throw_delayed_StackOverflowError_id, + generate_throw_exception(StubId::shared_throw_delayed_StackOverflowError_id, CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError)); _throw_AbstractMethodError_blob = - generate_throw_exception(SharedStubId::throw_AbstractMethodError_id, + generate_throw_exception(StubId::shared_throw_AbstractMethodError_id, CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError)); _throw_IncompatibleClassChangeError_blob = - generate_throw_exception(SharedStubId::throw_IncompatibleClassChangeError_id, + generate_throw_exception(StubId::shared_throw_IncompatibleClassChangeError_id, CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); _throw_NullPointerException_at_call_blob = - generate_throw_exception(SharedStubId::throw_NullPointerException_at_call_id, + generate_throw_exception(StubId::shared_throw_NullPointerException_at_call_id, CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call)); #if COMPILER2_OR_JVMCI @@ -160,15 +163,15 @@ void SharedRuntime::generate_stubs() { bool support_wide = is_wide_vector(MaxVectorSize); if (support_wide) { _polling_page_vectors_safepoint_handler_blob = - generate_handler_blob(SharedStubId::polling_page_vectors_safepoint_handler_id, + generate_handler_blob(StubId::shared_polling_page_vectors_safepoint_handler_id, CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception)); } #endif // COMPILER2_OR_JVMCI _polling_page_safepoint_handler_blob = - generate_handler_blob(SharedStubId::polling_page_safepoint_handler_id, + generate_handler_blob(StubId::shared_polling_page_safepoint_handler_id, CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception)); _polling_page_return_handler_blob = - generate_handler_blob(SharedStubId::polling_page_return_handler_id, + generate_handler_blob(StubId::shared_polling_page_return_handler_id, CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception)); generate_deopt_blob(); diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 418aef8b01d..9bc87071e90 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -34,7 +34,7 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "runtime/signature.hpp" -#include "runtime/stubDeclarations.hpp" +#include "runtime/stubInfo.hpp" #include "utilities/macros.hpp" class AdapterHandlerEntry; @@ -48,44 +48,34 @@ class SigEntry; // Java exceptions), locking/unlocking mechanisms, statistical // information, etc. -// define SharedStubId enum tags: wrong_method_id, etc - -#define SHARED_STUB_ID_ENUM_DECLARE(name, type) STUB_ID_NAME(name), -enum class SharedStubId :int { - NO_STUBID = -1, - SHARED_STUBS_DO(SHARED_STUB_ID_ENUM_DECLARE) - NUM_STUBIDS -}; -#undef SHARED_STUB_ID_ENUM_DECLARE - class SharedRuntime: AllStatic { private: // Declare shared stub fields #define SHARED_STUB_FIELD_DECLARE(name, type) \ - static type BLOB_FIELD_NAME(name); + static type* BLOB_FIELD_NAME(name); SHARED_STUBS_DO(SHARED_STUB_FIELD_DECLARE) #undef SHARED_STUB_FIELD_DECLARE #ifdef ASSERT - static bool is_resolve_id(SharedStubId id) { - return (id == SharedStubId::wrong_method_id || - id == SharedStubId::wrong_method_abstract_id || - id == SharedStubId::ic_miss_id || - id == SharedStubId::resolve_opt_virtual_call_id || - id == SharedStubId::resolve_virtual_call_id || - id == SharedStubId::resolve_static_call_id); + static bool is_resolve_id(StubId id) { + return (id == StubId::shared_wrong_method_id || + id == StubId::shared_wrong_method_abstract_id || + id == StubId::shared_ic_miss_id || + id == StubId::shared_resolve_opt_virtual_call_id || + id == StubId::shared_resolve_virtual_call_id || + id == StubId::shared_resolve_static_call_id); } - static bool is_polling_page_id(SharedStubId id) { - return (id == SharedStubId::polling_page_vectors_safepoint_handler_id || - id == SharedStubId::polling_page_safepoint_handler_id || - id == SharedStubId::polling_page_return_handler_id); + static bool is_polling_page_id(StubId id) { + return (id == StubId::shared_polling_page_vectors_safepoint_handler_id || + id == StubId::shared_polling_page_safepoint_handler_id || + id == StubId::shared_polling_page_return_handler_id); } - static bool is_throw_id(SharedStubId id) { - return (id == SharedStubId::throw_AbstractMethodError_id || - id == SharedStubId::throw_IncompatibleClassChangeError_id || - id == SharedStubId::throw_NullPointerException_at_call_id || - id == SharedStubId::throw_StackOverflowError_id || - id == SharedStubId::throw_delayed_StackOverflowError_id); + static bool is_throw_id(StubId id) { + return (id == StubId::shared_throw_AbstractMethodError_id || + id == StubId::shared_throw_IncompatibleClassChangeError_id || + id == StubId::shared_throw_NullPointerException_at_call_id || + id == StubId::shared_throw_StackOverflowError_id || + id == StubId::shared_throw_delayed_StackOverflowError_id); } #endif @@ -95,18 +85,15 @@ class SharedRuntime: AllStatic { // counterpart the continuation do_enter method. static nmethod* _cont_doYield_stub; - // Stub names indexed by SharedStubId - static const char *_stub_names[]; - #ifndef PRODUCT // Counters static int64_t _nof_megamorphic_calls; // total # of megamorphic calls (through vtable) #endif // !PRODUCT private: - static SafepointBlob* generate_handler_blob(SharedStubId id, address call_ptr); - static RuntimeStub* generate_resolve_blob(SharedStubId id, address destination); - static RuntimeStub* generate_throw_exception(SharedStubId id, address runtime_entry); + static SafepointBlob* generate_handler_blob(StubId id, address call_ptr); + static RuntimeStub* generate_resolve_blob(StubId id, address destination); + static RuntimeStub* generate_throw_exception(StubId id, address runtime_entry); public: static void generate_initial_stubs(void); static void generate_stubs(void); @@ -121,9 +108,9 @@ class SharedRuntime: AllStatic { #endif static void init_adapter_library(); - static const char *stub_name(SharedStubId id) { - assert(id > SharedStubId::NO_STUBID && id < SharedStubId::NUM_STUBIDS, "stub id out of range"); - return _stub_names[(int)id]; + static const char *stub_name(StubId id) { + assert(StubInfo::is_shared(id), "not a shared stub %s", StubInfo::name(id)); + return StubInfo::name(id); } // max bytes for each dtrace string parameter diff --git a/src/hotspot/share/runtime/sharedRuntimeMath.hpp b/src/hotspot/share/runtime/sharedRuntimeMath.hpp index 91dda2a4fe8..01ba4d93335 100644 --- a/src/hotspot/share/runtime/sharedRuntimeMath.hpp +++ b/src/hotspot/share/runtime/sharedRuntimeMath.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -67,64 +67,9 @@ static inline void set_low(double* d, int low) { *d = conv.d; } -static double copysignA(double x, double y) { - DoubleIntConv convX; - convX.d = x; - convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000); - return convX.d; -} - -/* - * ==================================================== - * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * scalbn (double x, int n) - * scalbn(x,n) returns x* 2**n computed by exponent - * manipulation rather than by actually performing an - * exponentiation or a multiplication. - */ - static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ hugeX = 1.0e+300, tiny = 1.0e-300; -static double scalbnA(double x, int n) { - int k,hx,lx; - hx = high(x); - lx = low(x); - k = (hx&0x7ff00000)>>20; /* extract exponent */ - if (k==0) { /* 0 or subnormal x */ - if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ - x *= two54; - hx = high(x); - k = ((hx&0x7ff00000)>>20) - 54; - if (n< -50000) return tiny*x; /*underflow*/ - } - if (k==0x7ff) return x+x; /* NaN or Inf */ - k = k+n; - if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ - if (k > 0) { /* normal result */ - set_high(&x, (hx&0x800fffff)|(k<<20)); - return x; - } - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return hugeX*copysignA(hugeX,x); /*overflow*/ - else return tiny*copysignA(tiny,x); /*underflow*/ - } - k += 54; /* subnormal result */ - set_high(&x, (hx&0x800fffff)|(k<<20)); - return x*twom54; -} - #endif // SHARE_RUNTIME_SHAREDRUNTIMEMATH_HPP diff --git a/src/hotspot/share/runtime/sharedRuntimeTrans.cpp b/src/hotspot/share/runtime/sharedRuntimeTrans.cpp index ee44151e433..a06bd724bb7 100644 --- a/src/hotspot/share/runtime/sharedRuntimeTrans.cpp +++ b/src/hotspot/share/runtime/sharedRuntimeTrans.cpp @@ -657,7 +657,7 @@ static double __ieee754_pow(double x, double y) { z = one-(r-z); j = high(z); j += (n<<20); - if((j>>20)<=0) z = scalbnA(z,n); /* subnormal output */ + if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ else set_high(&z, high(z) + (n<<20)); return s*z; } diff --git a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp b/src/hotspot/share/runtime/sharedRuntimeTrig.cpp index 86958ea2bd2..985198efd5d 100644 --- a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp +++ b/src/hotspot/share/runtime/sharedRuntimeTrig.cpp @@ -200,7 +200,7 @@ static int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, con } /* compute n */ - z = scalbnA(z,q0); /* actual value of z */ + z = scalbn(z,q0); /* actual value of z */ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ n = (int) z; z -= (double)n; @@ -233,7 +233,7 @@ static int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, con } if(ih==2) { z = one - z; - if(carry!=0) z -= scalbnA(one,q0); + if(carry!=0) z -= scalbn(one,q0); } } @@ -259,7 +259,7 @@ static int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, con jz -= 1; q0 -= 24; while(iq[jz]==0) { jz--; q0-=24;} } else { /* break z into 24-bit if necessary */ - z = scalbnA(z,-q0); + z = scalbn(z,-q0); if(z>=two24B) { fw = (double)((int)(twon24*z)); iq[jz] = (int)(z-two24B*fw); @@ -269,7 +269,7 @@ static int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, con } /* convert integer "bit" chunk to floating-point value */ - fw = scalbnA(one,q0); + fw = scalbn(one,q0); for(i=jz;i>=0;i--) { q[i] = fw*(double)iq[i]; fw*=twon24; } diff --git a/src/hotspot/share/runtime/stackChunkFrameStream.hpp b/src/hotspot/share/runtime/stackChunkFrameStream.hpp index 207203dbb35..3f72d9a1210 100644 --- a/src/hotspot/share/runtime/stackChunkFrameStream.hpp +++ b/src/hotspot/share/runtime/stackChunkFrameStream.hpp @@ -47,6 +47,7 @@ class StackChunkFrameStream : public StackObj { intptr_t* _unextended_sp; // used only when mixed CodeBlob* _cb; mutable const ImmutableOopMap* _oopmap; + bool _callee_augmented; #ifndef PRODUCT stackChunkOop _chunk; @@ -68,7 +69,7 @@ class StackChunkFrameStream : public StackObj { intptr_t* sp() const { return _sp; } inline address pc() const { return get_pc(); } inline intptr_t* fp() const; - inline intptr_t* unextended_sp() const { return frame_kind == ChunkFrames::Mixed ? _unextended_sp : _sp; } + inline intptr_t* unextended_sp() const { return _unextended_sp; } inline address orig_pc() const; inline bool is_interpreted() const; diff --git a/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp b/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp index 734d31d3390..b0fd3354867 100644 --- a/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp +++ b/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp @@ -55,14 +55,16 @@ StackChunkFrameStream::StackChunkFrameStream(stackChunkOop chunk) DE _end = chunk->bottom_address(); _sp = chunk->start_address() + chunk->sp(); assert(_sp <= chunk->end_address() + frame::metadata_words, ""); + _callee_augmented = false; get_cb(); if (frame_kind == ChunkFrames::Mixed) { _unextended_sp = (!is_done() && is_interpreted()) ? unextended_sp_for_interpreter_frame() : _sp; assert(_unextended_sp >= _sp - frame::metadata_words, ""); + } else { + _unextended_sp = _sp; } - DEBUG_ONLY(else _unextended_sp = nullptr;) if (is_stub()) { get_oopmap(pc(), 0); @@ -86,10 +88,12 @@ StackChunkFrameStream::StackChunkFrameStream(stackChunkOop chunk, co if (frame_kind == ChunkFrames::Mixed) { _unextended_sp = f.unextended_sp(); assert(_unextended_sp >= _sp - frame::metadata_words, ""); + } else { + _unextended_sp = _sp; } - DEBUG_ONLY(else _unextended_sp = nullptr;) assert(_sp >= chunk->start_address(), ""); assert(_sp <= chunk->end_address() + frame::metadata_words, ""); + _callee_augmented = false; if (f.cb() != nullptr) { _oopmap = nullptr; @@ -216,6 +220,7 @@ template inline void StackChunkFrameStream::next(RegisterMapT* map, bool stop) { update_reg_map(map); bool is_runtime_stub = is_stub(); + _callee_augmented = false; if (frame_kind == ChunkFrames::Mixed) { if (is_interpreted()) { next_for_interpreter_frame(); @@ -224,11 +229,24 @@ inline void StackChunkFrameStream::next(RegisterMapT* map, bool stop if (_sp >= _end - frame::metadata_words) { _sp = _end; } - _unextended_sp = is_interpreted() ? unextended_sp_for_interpreter_frame() : _sp; + if (is_interpreted()) { + _unextended_sp = unextended_sp_for_interpreter_frame(); + } else if (cb()->is_nmethod() && cb()->as_nmethod()->needs_stack_repair()) { + _unextended_sp = frame::repair_sender_sp(cb()->as_nmethod(), _unextended_sp, (intptr_t**)(_sp - frame::sender_sp_offset)); + _callee_augmented = _unextended_sp != _sp; + } else { + _unextended_sp = _sp; + } } assert(_unextended_sp >= _sp - frame::metadata_words, ""); } else { - _sp += cb()->frame_size(); + _sp = _unextended_sp + cb()->frame_size(); + if (cb()->is_nmethod() && cb()->as_nmethod()->needs_stack_repair()) { + _unextended_sp = frame::repair_sender_sp(cb()->as_nmethod(), _unextended_sp, (intptr_t**)(_sp - frame::sender_sp_offset)); + _callee_augmented = _unextended_sp != _sp; + } else { + _unextended_sp = _sp; + } } assert(!is_interpreted() || _unextended_sp == unextended_sp_for_interpreter_frame(), ""); diff --git a/src/hotspot/share/runtime/stackOverflow.cpp b/src/hotspot/share/runtime/stackOverflow.cpp index 2d7f89cc687..e2bd157c555 100644 --- a/src/hotspot/share/runtime/stackOverflow.cpp +++ b/src/hotspot/share/runtime/stackOverflow.cpp @@ -89,7 +89,7 @@ void StackOverflow::create_stack_guard_pages() { assert(is_aligned(low_addr, os::vm_page_size()), "Stack base should be the start of a page"); assert(is_aligned(len, os::vm_page_size()), "Stack size should be a multiple of page size"); - int must_commit = os::must_commit_stack_guard_pages(); + bool must_commit = os::must_commit_stack_guard_pages(); // warning("Guarding at " PTR_FORMAT " for len %zu\n", low_addr, len); if (must_commit && !os::create_stack_guard_pages((char *) low_addr, len)) { diff --git a/src/hotspot/share/runtime/stubCodeGenerator.cpp b/src/hotspot/share/runtime/stubCodeGenerator.cpp index eafd2ad572e..4e5f1635e42 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.cpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.cpp @@ -69,11 +69,13 @@ void StubCodeDesc::print() const { print_on(tty); } StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) { _masm = new MacroAssembler(code); - _blob_id = StubGenBlobId::NO_BLOBID; + _blob_id = BlobId::NO_BLOBID; _print_code = PrintStubCode || print_code; } -StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, StubGenBlobId blob_id, bool print_code) { +StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, BlobId blob_id, bool print_code) { + assert(StubInfo::is_stubgen(blob_id), + "not a stubgen blob %s", StubInfo::name(blob_id)); _masm = new MacroAssembler(code); _blob_id = blob_id; _print_code = PrintStubCode || print_code; @@ -119,7 +121,7 @@ void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) { } #ifdef ASSERT -void StubCodeGenerator::verify_stub(StubGenStubId stub_id) { +void StubCodeGenerator::verify_stub(StubId stub_id) { assert(StubRoutines::stub_to_blob(stub_id) == blob_id(), "wrong blob %s for generation of stub %s", StubRoutines::get_blob_name(blob_id()), StubRoutines::get_stub_name(stub_id)); } #endif @@ -134,7 +136,7 @@ StubCodeMark::StubCodeMark(StubCodeGenerator* cgen, const char* group, const cha _cdesc->set_begin(_cgen->assembler()->pc()); } -StubCodeMark::StubCodeMark(StubCodeGenerator* cgen, StubGenStubId stub_id) : StubCodeMark(cgen, "StubRoutines", StubRoutines::get_stub_name(stub_id)) { +StubCodeMark::StubCodeMark(StubCodeGenerator* cgen, StubId stub_id) : StubCodeMark(cgen, "StubRoutines", StubRoutines::get_stub_name(stub_id)) { #ifdef ASSERT cgen->verify_stub(stub_id); #endif diff --git a/src/hotspot/share/runtime/stubCodeGenerator.hpp b/src/hotspot/share/runtime/stubCodeGenerator.hpp index 41bd7e49b31..7d8944c85ea 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.hpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,6 +27,7 @@ #include "asm/assembler.hpp" #include "memory/allocation.hpp" +#include "runtime/stubInfo.hpp" // All the basic framework for stub code generation/debugging/printing. @@ -98,32 +99,29 @@ class StubCodeDesc: public CHeapObj { // forward declare blob and stub id enums -enum StubGenBlobId : int; -enum StubGenStubId : int; - // The base class for all stub-generating code generators. // Provides utility functions. class StubCodeGenerator: public StackObj { private: bool _print_code; - StubGenBlobId _blob_id; + BlobId _blob_id; protected: MacroAssembler* _masm; public: StubCodeGenerator(CodeBuffer* code, bool print_code = false); - StubCodeGenerator(CodeBuffer* code, StubGenBlobId blob_id, bool print_code = false); + StubCodeGenerator(CodeBuffer* code, BlobId blob_id, bool print_code = false); ~StubCodeGenerator(); MacroAssembler* assembler() const { return _masm; } - StubGenBlobId blob_id() { return _blob_id; } + BlobId blob_id() { return _blob_id; } virtual void stub_prolog(StubCodeDesc* cdesc); // called by StubCodeMark constructor virtual void stub_epilog(StubCodeDesc* cdesc); // called by StubCodeMark destructor #ifdef ASSERT - void verify_stub(StubGenStubId stub_id); + void verify_stub(StubId stub_id); #endif }; @@ -139,7 +137,7 @@ class StubCodeMark: public StackObj { public: StubCodeMark(StubCodeGenerator* cgen, const char* group, const char* name); - StubCodeMark(StubCodeGenerator* cgen, StubGenStubId stub_id); + StubCodeMark(StubCodeGenerator* cgen, StubId stub_id); ~StubCodeMark(); }; diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index 00034e6d4d1..e73a99a9609 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -26,22 +26,60 @@ #ifndef SHARE_RUNTIME_STUBDECLARATIONS_HPP #define SHARE_RUNTIME_STUBDECLARATIONS_HPP +#include "code/codeBlob.hpp" +#include "oops/klass.hpp" #include "utilities/macros.hpp" -// macros for generating definitions and declarations for shared, c1 -// and opto blob fields and associated stub ids +// Macros for generating definitions and declarations for shared, c1, +// opto and stubgen blobs and associated stub and entry ids. +// +// The template macros that follow define blobs, stubs and entries in +// each stub group. Invocations of the macros with different macro +// arguments can be used to generate definitions and declarations of +// types, data and methods/functions which support blob, stub and +// entry management. +// +// In particular, they are used to generate 3 global enums that list +// all blobs, stubs and entries across stub groups. They are also used +// to generate local (per-stub group) enums listing every stub in the +// group. The former are provided ot allow systematic management of +// blobs, stubs and entries by generic code. The latter are used by +// code which generates and consumes stubs in a specific group. An API +// is provided to convert between global and local ids where needed +// (see class StubInfo). -// Different shared stubs can have different blob types and may -// include some JFR stubs +// Shared stub declarations +// +// Every shared stub has a unique associated blob whose type must be +// defined as part of the stub declaration. The blob type determines +// how many entries are associated with the stub, normally 1. A build +// may optionally include some JFR stubs. +// +// n.b resolve, handler and throw stubs must remain grouped +// contiguously and in the same order so that id values can be range +// checked +// +// Alongside the global and local enums, shared declations are used to +// generate the following code elements in class SharedRuntime: +// +// Shared Stub blob fields +// +// Static field declarations/definitons for fields of class +// SharedRuntime are generated to store shared blobs +// +// static * _; +// +// Shared stub field names +// +// Stubs are provided with names in the format "Shared Runtime +// _blob". // -// n.b resolve, handler and throw stubs must remain grouped in the -// same order to allow id values to be range checked #if INCLUDE_JFR // do_blob(name, type) #define SHARED_JFR_STUBS_DO(do_blob) \ - do_blob(jfr_write_checkpoint, RuntimeStub*) \ - do_blob(jfr_return_lease, RuntimeStub*) \ + do_blob(jfr_write_checkpoint, RuntimeStub) \ + do_blob(jfr_return_lease, RuntimeStub) \ #else #define SHARED_JFR_STUBS_DO(do_blob) @@ -51,28 +89,33 @@ // // do_blob(name, type) #define SHARED_STUBS_DO(do_blob) \ - do_blob(deopt, DeoptimizationBlob*) \ + do_blob(deopt, DeoptimizationBlob) \ /* resolve stubs */ \ - do_blob(wrong_method, RuntimeStub*) \ - do_blob(wrong_method_abstract, RuntimeStub*) \ - do_blob(ic_miss, RuntimeStub*) \ - do_blob(resolve_opt_virtual_call, RuntimeStub*) \ - do_blob(resolve_virtual_call, RuntimeStub*) \ - do_blob(resolve_static_call, RuntimeStub*) \ + do_blob(wrong_method, RuntimeStub) \ + do_blob(wrong_method_abstract, RuntimeStub) \ + do_blob(ic_miss, RuntimeStub) \ + do_blob(resolve_opt_virtual_call, RuntimeStub) \ + do_blob(resolve_virtual_call, RuntimeStub) \ + do_blob(resolve_static_call, RuntimeStub) \ /* handler stubs */ \ - do_blob(polling_page_vectors_safepoint_handler, SafepointBlob*) \ - do_blob(polling_page_safepoint_handler, SafepointBlob*) \ - do_blob(polling_page_return_handler, SafepointBlob*) \ + do_blob(polling_page_vectors_safepoint_handler, SafepointBlob) \ + do_blob(polling_page_safepoint_handler, SafepointBlob) \ + do_blob(polling_page_return_handler, SafepointBlob) \ /* throw stubs */ \ - do_blob(throw_AbstractMethodError, RuntimeStub*) \ - do_blob(throw_IncompatibleClassChangeError, RuntimeStub*) \ - do_blob(throw_NullPointerException_at_call, RuntimeStub*) \ - do_blob(throw_StackOverflowError, RuntimeStub*) \ - do_blob(throw_delayed_StackOverflowError, RuntimeStub*) \ + do_blob(throw_AbstractMethodError, RuntimeStub) \ + do_blob(throw_IncompatibleClassChangeError, RuntimeStub) \ + do_blob(throw_NullPointerException_at_call, RuntimeStub) \ + do_blob(throw_StackOverflowError, RuntimeStub) \ + do_blob(throw_delayed_StackOverflowError, RuntimeStub) \ /* other stubs */ \ SHARED_JFR_STUBS_DO(do_blob) \ -// C1 stubs are always generated in a generic CodeBlob +// C1 stub declarations +// +// C1 stubs are always generated in a unique associated generic +// CodeBlob with a single entry. C1 stubs are stored in an array +// indexed by local enum. So, no other code elements need to be +// generated via this macro. #ifdef COMPILER1 // client macro to operate on c1 stubs @@ -126,14 +169,42 @@ #define C1_STUBS_DO(do_blob) #endif -// Opto stubs can be stored as entries with just an address or as -// blobs of different types. The former may include some JVMTI stubs. +// C2 stub declarations // -// n.b. blobs and stub defines are generated in the order defined by +// C2 stubs are always generated in a unique associated generic +// CodeBlob and have a single entry. In some cases, including JVMTI +// stubs, a standard code blob is employed and only the stub entry +// address is retained. In others a specialized code blob with +// stub-specific properties (e.g. frame size) is required so the blob +// address needs to be stored. In these latter cases the declaration +// includes the relevant storage type. +// +// n.b. blob and stub enum tags are generated in the order defined by // C2_STUBS_DO, allowing dependencies from any givem stub on its // predecessors to be guaranteed. That explains the initial placement // of the blob declarations and intermediate placement of the jvmti // stubs. +// +// Alongside the local and global enums, C2 declarations are used to +// generate several elements of class OptoRuntime. +// +// C2 Stub blob/address fields +// +// Static field declarations/definitions for fields of class +// OptoRuntime are generated to store either C2 blob or C2 blob entry +// addresses: +// +// static * __Java; +// static address _; +// +// C2 stub blob/field names +// +// C2 stubs are provided with names in the format "C2 Runtime +// _blob". +// +// A stub creation method OptoRuntime::generate(ciEnv* env) is +// generated which invokes the C2 compiler to generate each stub in +// declaration order. #ifdef COMPILER2 // do_jvmti_stub(name) @@ -154,12 +225,20 @@ // do_stub(name, fancy_jump, pass_tls, return_pc) // do_jvmti_stub(name) // -// n.b. non-jvmti stubs may employ a special type of jump (0, 1 or 2) -// and require access to TLS and the return pc. jvmti stubs always -// employ jump 0, and require no special access +// do_blob is used for stubs that are generated via direct invocation +// of the assembler to write into a blob of the appropriate type +// +// do_stub is used for stubs that are generated as C2 compiler IR +// intrinsics, using the supplied arguments to determine wheher nodes +// in the IR graph employ a special type of jump (0, 1 or 2) or +// provide access to TLS and the return pc. +// +// do_jvmti_stub generates a JVMTI stub as an IR intrinsic which +// employs jump 0, and requires no special access + #define C2_STUBS_DO(do_blob, do_stub, do_jvmti_stub) \ - do_blob(uncommon_trap, UncommonTrapBlob*) \ - do_blob(exception, ExceptionBlob*) \ + do_blob(uncommon_trap, UncommonTrapBlob) \ + do_blob(exception, ExceptionBlob) \ do_stub(new_instance, 0, true, false) \ do_stub(new_array, 0, true, false) \ do_stub(new_array_nozero, 0, true, false) \ @@ -182,7 +261,9 @@ #define C2_STUBS_DO(do_blob, do_stub, do_jvmti_stub) #endif -// Stub Generator Blobs and Stubs Overview +// Stubgen stub declarations +// +// Stub Generator Blobs, Stubs and Entries Overview // // StubGenerator stubs do not require their own individual blob. They // are generated in batches into one of five distinct BufferBlobs: @@ -193,75 +274,52 @@ // 4) Compiler stubs // 5) Final stubs // -// Creation of each successive BufferBlobs is staged to ensure that +// Most StubGen stubs have a single entry point. However, in some +// cases there are additional entry points. +// +// Creation of each successive BufferBlob is staged to ensure that // specific VM subsystems required by those stubs are suitably -// initialized before generated code attempt to reference data or +// initialized before generated code attempts to reference data or // addresses exported by those subsystems. The sequencing of // initialization must be taken into account when adding a new stub // declaration. // -// StubGenerator stubs are declared using template macros, one set of -// declarations per blob (see below), with arch-specific stubs for any -// gven blob declared after generic stubs for that blob. Blobs are -// created in a fixed order during startup, which is reflected in the -// order of the declaration set. Stubs within a blob are currently -// created in an order determined by the arch-specific generator code -// which may not reflect the order of stub declarations. It is not -// straightforward to enforce a strict ordering. not least because -// arch-specific stub creation may need to be interleaved with generic -// stub creation. -// -// Blob and stub declaration templates are used to generate a variety -// of C++ code elements needed to manage stubs. -// -// Blob identifiers: -// -// public enum StubGenBlobId is generated to identify each of the -// StubGenerator blobs in blob declaration order. This enum is -// provided for use by client code to identify a specific blob. For a -// blob declared with name the associated enum value is -// StubGenBlobId::_id. -// -// Global stub identifiers: -// -// public enum StubGenStubId is generated to identify all declared -// stubs across all blobs, sorted first by blob declaration order and -// then within a blob by stub declaration order, generic stubs before -// arch-specific stubs. This enum is provided for use by client code -// to identify a specific stub, independent of the blob it belongs to. -// For a stub declared with name the associated enum value -// is StubGenStubId::_id. -// -// Blob-local stub identifiers: -// -// For each blob , public enum StubGenStubId_ is -// generated to enumerate all stubs within the blob in stub -// declaration order, generic stubs before arch-specific stubs. This -// enum is provided only in a non-product build and is intended for -// internal use by class StubRoutines to validate stub declarations. -// For a stub declared with name belonging to blob -// the associated enum value is -// StubGenStubId::__id. +// StubGen blobs, stubs and entries are declared using template +// macros, grouped hierarchically by blob and stub, with arch-specific +// stubs for any given blob declared after generic stubs for that +// blob. Stub declarations must follow the blob start (do_blob) +// declaration for their containing blob. Entry declarations must +// follow the the stub start (do_stub) declaration for their +// containing stub. +// +// Blob and stub declarations are used to generate a variety of C++ +// code elements needed to manage stubs, including the global and +// local blob, stub and entry enum types mentioned above. The blob +// declaration order must reflect the order in which blob create +// operations are invoked during startup. Stubs within a blob are +// currently generated in an order determined by the arch-specific +// generator code which may not always reflect the order of stub +// declarations (it is not straightforward to enforce a strict +// ordering, not least because arch-specific stub creation may need to +// be interleaved with generic stub creation). +// +// Alongside the global enums, the stubgen declarations are used to +// define the following elements of class StubRoutines: // // Stub names and associated getters: // -// Two private static fields are generated to hold the names of the -// four generated blobs and all the generated stubs. -// -// const char* StubRoutines::_blob_names[]; -// const char* StubRoutines::_stub_names[]; -// -// The entry in _blob_names for a blob declared with name -// will be "". +// Name strings are generated for each blob where a blob declared with +// name argument will be named using string "". // -// The entry in _stub_names for a stub declared with name -// will be "". +// Name strings are also generated for each stub where a stub declared +// with name argument will be named using string +// "". // // Corresponding public static lookup methods are generated to allow // names to be looked up by blob or global stub id. // -// const char* StubRoutines::get_blob_name(StubGenBlobId id) -// const char* StubRoutines::get_stub_name(StubGenStubId id) +// const char* StubRoutines::get_blob_name(BlobId id) +// const char* StubRoutines::get_stub_name(StubId id) // // These name lookup methods should be used by generic and // cpu-specific client code to ensure that blobs and stubs are @@ -359,7 +417,6 @@ // static void set_f2i_fixup(address a) { _f2i_fixup = a; } // - //-------------------------------------------------- // Stub Generator Blob, Stub and Entry Declarations // ------------------------------------------------- @@ -425,15 +482,17 @@ // given blob. This enum is private to the stub management code and // used to validate correct use of stubs within a given blob. // -// The do_stub template receives a blob name and stub name as argument. +// The do_stub template receives a blob name and stub name as +// argument. // // do_stub(blob_name, stub_name) // -// do_stub is primarily used to define a global enum tag for a stub -// and a constant string name, both for use by client code. It is also -// used to declare a tag within the blob-local enum type used to -// validate correct use of stubs within their declared blob. Finally, -// it is also used to declare a name for each stub. +// do_stub is primarily used to define values associated with the stub +// wiht name stub_name, a global enum tag for it and a constant string +// name, both for use by client code. It is also used to declare a tag +// within the blob-local enum type used to validate correct use of +// stubs within their declared blob. Finally, it is also used to +// declare a name string for the stub. // // The do_entry and do_entry_array templates receive 4 or 5 arguments // @@ -463,6 +522,14 @@ // its own named getter. In the latter case multiple do_entry or // do_entry_init declarations are associated with the stub. // +// All the above entry macros are used to declare enum tages that +// identify the entry. Three different enums are generated via these +// macros: a per-stub enum that indexes and provides a count for the +// entries associated with the owning stub; a per-blob enume that +// indexes and provides a count for the entries associated with the +// owning blob; and a global enum that indexes and provides a count +// for all entries associated with generated stubs. +// // blob_name and stub_name are the names of the blob and stub to which // the entry belongs. // @@ -558,6 +625,17 @@ do_blob(preuniverse) \ do_stub(preuniverse, fence) \ do_entry(preuniverse, fence, fence_entry, fence_entry) \ + do_stub(preuniverse, atomic_add) \ + do_entry(preuniverse, atomic_add, atomic_add_entry, atomic_add_entry) \ + do_stub(preuniverse, atomic_xchg) \ + do_entry(preuniverse, atomic_xchg, atomic_xchg_entry, \ + atomic_xchg_entry) \ + do_stub(preuniverse, atomic_cmpxchg) \ + do_entry(preuniverse, atomic_cmpxchg, atomic_cmpxchg_entry, \ + atomic_cmpxchg_entry) \ + do_stub(preuniverse, atomic_cmpxchg_long) \ + do_entry(preuniverse, atomic_cmpxchg_long, atomic_cmpxchg_long_entry, \ + atomic_cmpxchg_long_entry) \ /* merge in stubs and entries declared in arch header */ \ STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ do_arch_entry, do_arch_entry_init) \ @@ -580,16 +658,6 @@ do_stub(initial, catch_exception) \ do_entry(initial, catch_exception, catch_exception_entry, \ catch_exception_entry) \ - do_stub(initial, atomic_add) \ - do_entry(initial, atomic_add, atomic_add_entry, atomic_add_entry) \ - do_stub(initial, atomic_xchg) \ - do_entry(initial, atomic_xchg, atomic_xchg_entry, atomic_xchg_entry) \ - do_stub(initial, atomic_cmpxchg) \ - do_entry(initial, atomic_cmpxchg, atomic_cmpxchg_entry, \ - atomic_cmpxchg_entry) \ - do_stub(initial, atomic_cmpxchg_long) \ - do_entry(initial, atomic_cmpxchg_long, atomic_cmpxchg_long_entry, \ - atomic_cmpxchg_long_entry) \ do_stub(initial, updateBytesCRC32) \ do_entry(initial, updateBytesCRC32, updateBytesCRC32, \ updateBytesCRC32) \ @@ -644,12 +712,13 @@ do_entry, do_entry_init, \ do_entry_array, \ do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ + do_arch_entry, \ + do_arch_entry_init) \ do_blob(continuation) \ do_stub(continuation, cont_thaw) \ do_entry(continuation, cont_thaw, cont_thaw, cont_thaw) \ do_stub(continuation, cont_preempt) \ - do_entry(continuation, cont_prempt, cont_preempt_stub, \ + do_entry(continuation, cont_preempt, cont_preempt_stub, \ cont_preempt_stub) \ do_stub(continuation, cont_returnBarrier) \ do_entry(continuation, cont_returnBarrier, cont_returnBarrier, \ @@ -658,7 +727,7 @@ do_entry(continuation, cont_returnBarrierExc, cont_returnBarrierExc, \ cont_returnBarrierExc) \ /* merge in stubs and entries declared in arch header */ \ - STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ + STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ do_arch_entry, do_arch_entry_init) \ end_blob(continuation) \ @@ -812,7 +881,7 @@ do_entry(compiler, bigIntegerLeftShiftWorker, \ bigIntegerLeftShiftWorker, bigIntegerLeftShift) \ /* merge in stubs and entries declared in arch header */ \ - STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ + STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ do_arch_entry, do_arch_entry_init) \ end_blob(compiler) \ @@ -981,9 +1050,59 @@ end_blob(final) \ +// The whole shebang! +// +// client macro for emitting StubGenerator blobs, stubs and entries + +#define STUBGEN_ALL_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_PREUNIVERSE_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_INITIAL_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_CONTINUATION_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_COMPILER_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_FINAL_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + // Convenience macros for use by template implementations -#define STUB_ID_NAME(base) base##_id +#define JOIN2(name, suffix) \ + name ## _ ## suffix + +#define JOIN3(prefix, name, suffix) \ + prefix ## _ ## name ## _ ## suffix + +#define JOIN4(prefix, prefix2, name, suffix) \ + prefix ## _ ## prefix2 ## _ ## name ## _ ## suffix + +#define STUB_ID_NAME(base) JOIN2(base, id) // emit a runtime or stubgen stub field name @@ -991,12 +1110,35 @@ // emit a runtime blob field name -#define BLOB_FIELD_NAME(base) _##base##_blob +#define BLOB_FIELD_NAME(base) _## base ## _blob // emit a stubgen blob field name #define STUBGEN_BLOB_FIELD_NAME(base) _ ## base ## _stubs_code +// first some macros that add an increment + +#define COUNT1(_1) \ + + 1 + +#define COUNT2(_1, _2) \ + + 1 + +#define COUNT4(_1, _2, _3, _4) \ + + 1 + +#define COUNT5(_1, _2, _3, _4, _5) \ + + 1 + +#define COUNT6(_1, _2, _3, _4, _5, _6) \ + + 1 + +#define SHARED_COUNT2(_1, type) \ + + type :: ENTRY_COUNT + +#define STUBGEN_COUNT5(_1, _2, _3, _4, count) \ + + count + // Convenience templates that emit nothing // ignore do_blob(blob_name, type) declarations @@ -1030,47 +1172,6 @@ // ignore do_arch_entry(arch, blob_name, stub_name, fieldname, getter_name, init_function) declarations #define DO_ARCH_ENTRY_EMPTY6(arch, blob_name, stub_name, field_name, getter_name, init_function) -// The whole shebang! -// -// client macro for emitting StubGenerator blobs, stubs and entries - -#define STUBGEN_ALL_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - STUBGEN_PREUNIVERSE_BLOBS_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - STUBGEN_INITIAL_BLOBS_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - STUBGEN_CONTINUATION_BLOBS_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - STUBGEN_COMPILER_BLOBS_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - STUBGEN_FINAL_BLOBS_DO(do_blob, end_blob, \ - do_stub, \ - do_entry, do_entry_init, \ - do_entry_array, \ - do_arch_blob, \ - do_arch_entry, do_arch_entry_init) \ - // client macro to operate only on StubGenerator blobs #define STUBGEN_BLOBS_DO(do_blob) \ @@ -1091,7 +1192,7 @@ DO_ARCH_BLOB_EMPTY2, \ DO_ARCH_ENTRY_EMPTY5, DO_ARCH_ENTRY_EMPTY6) \ -// client macro to operate only on StubGenerator blobs and stubs +// client macros to operate only on StubGenerator blobs and stubs #define STUBGEN_BLOBS_STUBS_DO(do_blob, end_blob, do_stub) \ STUBGEN_ALL_DO(do_blob, end_blob, \ @@ -1101,6 +1202,17 @@ DO_ARCH_BLOB_EMPTY2, \ DO_ARCH_ENTRY_EMPTY5,DO_ARCH_ENTRY_EMPTY6) \ +// client macro to operate only on StubGenerator generci and arch entries + +#define STUBGEN_ALL_ENTRIES_DO(do_entry, do_entry_init, do_entry_array, \ + do_arch_entry, do_arch_entry_init) \ + STUBGEN_ALL_DO(DO_BLOB_EMPTY1, DO_BLOB_EMPTY1, \ + DO_STUB_EMPTY2, \ + do_entry, do_entry_init, \ + do_entry_array, \ + DO_ARCH_BLOB_EMPTY2, \ + do_arch_entry, do_arch_entry_init) \ + // client macro to operate only on StubGenerator entries #define STUBGEN_ENTRIES_DO(do_entry, do_entry_init, do_entry_array) \ diff --git a/src/hotspot/share/runtime/stubInfo.cpp b/src/hotspot/share/runtime/stubInfo.cpp new file mode 100644 index 00000000000..bca6ff344ea --- /dev/null +++ b/src/hotspot/share/runtime/stubInfo.cpp @@ -0,0 +1,1110 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Red Hat, Inc. 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. + * + */ + +#include "code/codeBlob.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/stubDeclarations.hpp" +#include "runtime/stubInfo.hpp" + +// define static data fields of class Stubdata + +struct StubInfo::GroupDetails StubInfo::_group_table[StubInfo::GROUP_TABLE_SIZE]; +struct StubInfo::BlobDetails StubInfo::_blob_table[StubInfo::BLOB_TABLE_SIZE]; +struct StubInfo::StubDetails StubInfo::_stub_table[StubInfo::STUB_TABLE_SIZE]; +struct StubInfo::EntryDetails StubInfo::_entry_table[StubInfo::ENTRY_TABLE_SIZE]; + +// helpers to access table elements using enums as indices + +struct StubInfo::GroupDetails& StubInfo::group_details(StubGroup g) { + int idx = static_cast(g); + assert(idx >= 0 && idx < GROUP_TABLE_SIZE, "invalid stub group index %d", idx); + return _group_table[idx]; +} + +struct StubInfo::BlobDetails& StubInfo::blob_details(BlobId b) { + int idx = static_cast(b); + assert(idx >= 0 && idx < BLOB_TABLE_SIZE, "invalid blob index %d", idx); + return _blob_table[idx]; +} + +struct StubInfo::StubDetails& StubInfo::stub_details(StubId s) { + int idx = static_cast(s); + assert(idx >= 0 && idx < STUB_TABLE_SIZE, "invalid stub index %d", idx); + return _stub_table[idx]; +} + +struct StubInfo::EntryDetails& StubInfo::entry_details(EntryId e) { + int idx = static_cast(e); + assert(idx >= 0 && idx < ENTRY_TABLE_SIZE, "invalid entry index %d", idx); + return _entry_table[idx]; +} + +// helpers to step through blob, stub or entry enum sequences + +BlobId StubInfo::next(BlobId id) { + int idx = static_cast(id); + // allow for id to be NO_BLOBID but not NUM_BLOBIDS + assert(idx >= -1 && idx < BLOB_TABLE_SIZE, "invalid blob index %d", idx); + return static_cast(idx + 1); +} + +StubId StubInfo::next(StubId id) { + int idx = static_cast(id); + // allow for id to be NO_STUBID but not NUM_STUBIDS + assert(idx >= -1 && idx < STUB_TABLE_SIZE, "invalid stub index %d", idx); + return static_cast(idx + 1); +} + +EntryId StubInfo::next(EntryId id) { + int idx = static_cast(id); + // allow for id to be NO_ENTRYID but not NUM_ENTRYIDS + assert(idx >= -1 && idx < ENTRY_TABLE_SIZE, "invalid entry index %d", idx); + return static_cast(idx + 1); +} + +BlobId StubInfo::next_in_group(StubGroup stub_group, BlobId blob_id) { + int idx = static_cast(blob_id); + // id must be strictly between NO_BLOBID and NUM_BLOBIDS + assert(idx > -1 && idx < STUB_TABLE_SIZE, "invalid stub index %d", idx); + assert(blob_details(blob_id)._group == stub_group, "blob does not belong to stub group!"); + struct GroupDetails& group = group_details(stub_group); + if (blob_id == group._max) { + return BlobId::NO_BLOBID; + } else { + return static_cast(idx + 1); + } +} + +StubId StubInfo::next_in_blob(BlobId blob_id, StubId stub_id) { + int idx = static_cast(stub_id); + // id must be strictly between NO_STUBID and NUM_STUBIDS + assert(idx > -1 && idx < STUB_TABLE_SIZE, "invalid stub index %d", idx); + assert(stub_details(stub_id)._blob == blob_id, "stub does not belong to blob!"); + struct BlobDetails& blob = blob_details(blob_id); + if (stub_id == blob._max) { + return StubId::NO_STUBID; + } else { + return static_cast(idx + 1); + } +} + +EntryId StubInfo::next_in_stub(StubId stub_id, EntryId entry_id) { + int idx = static_cast(entry_id); + // id must be strictly between NO_ENTRYID and NUM_ENTRYIDS + assert(idx > -1 && idx < ENTRY_TABLE_SIZE, "invalid entry index %d", idx); + assert(entry_details(entry_id)._stub == stub_id, "entry does not belong to stub!"); + struct StubDetails& stub = stub_details(stub_id); + if (entry_id == stub._max) { + return EntryId::NO_ENTRYID; + } else { + return static_cast(idx + 1); + } +} + +// name retrieval + +const char* StubInfo::name(StubGroup stub_group) { + return group_details(stub_group)._name; +} + +const char* StubInfo::name(BlobId id) { + return blob_details(id)._name; +} + +const char* StubInfo::name(StubId id) { + return stub_details(id)._name; +} + +const char* StubInfo::name(EntryId id) { + return entry_details(id)._name; +} + +int StubInfo::span(EntryId second, EntryId first) { + // normally when the two ids are equal the entry span is 1 but we + // have a special case when the base and max are both NO_ENTRYID in + // which case the entry count is 0 + int idx1 = static_cast(first); + int idx2 = static_cast(second); + assert ((idx1 < 0 && idx2 < 0) || (idx1 >= 0 && idx2 >= idx1), "bad entry ids first %d and second %d", idx1, idx2); + if (idx1 < 0) { + return 0; + } + // span is inclusive of first and second + return idx2 + 1 - idx1; +} + +int StubInfo::span(StubId second, StubId first) { + // normally when the two ids are equal the entry span is 1 but we + // have a special case when the base and max are both NO_STUBID in + // which case the entry count is 0. n.b. that only happens in the + // case where a stub group is empty e.g. when either C1 or C2 is + // omitted from the build + int idx1 = static_cast(first); + int idx2 = static_cast(second); + assert((idx1 < 0 && idx2 < 0) || (idx1 >= 0 && idx2 >= idx1), "bad stub ids first %d and second %d", idx1, idx2); + if (idx1 < 0) { + return 0; + } + // span is inclusive of first and second + return idx2 + 1 - idx1; +} + +int StubInfo::span(BlobId second, BlobId first) { + // normally when the two ids are equal the entry span is 1 but we + // have a special case when the base and max are both NO_BLOBID in + // which case the entry count is 0. n.b. that only happens in the + // case where a stub group is empty e.g. when either C1 or C2 is + // omitted from the build + int idx1 = static_cast(first); + int idx2 = static_cast(second); + assert((idx1 < 0 && idx2 < 0) || (idx1 >= 0 && idx2 >= idx1), "bad blob ids first %d and second %d", idx1, idx2); + if (idx1 < 0) { + return 0; + } + // span is inclusive of first and second + return idx2 + 1 - idx1; +} + +#ifdef ASSERT +// helpers to check sequencing of blobs stubs and entries +bool StubInfo::is_next(BlobId second, BlobId first) { + return next(first) == second; +} + +bool StubInfo::is_next(StubId second, StubId first) { + return next(first) == second; +} + +bool StubInfo::is_next(EntryId second, EntryId first) { + return next(first) == second; +} +#endif // ASSERT + +// implementation of the counting methods used to populate the +// stubgroup, blob, stub and entry tables + +void StubInfo::process_shared_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry, + EntryId declaredMax) { + // for shared declarations we update the blob, stub and entry tables + // all in one go based on each unique blob declaration. We may need + // to write more than one entry table element if the stub has + // multiple entries + assert(group_cursor == StubGroup::SHARED, "must be"); + assert(is_next (declaredBlob, blob_cursor), "Out of order declaration for shared blob %s", name); + assert(is_next(declaredStub, stub_cursor), "Out of order declaration for shared stub %s", name); + assert(is_next(declaredEntry, entry_cursor), "Out of order declaration for shared entry %s", name); + assert(span(declaredMax, declaredEntry) > 0, "Invalid entry count %d for entry %s", span(declaredMax, declaredEntry), name); + // if this is the first shared blob then record it as teh base id + // and also update entry base + if (group_details(group_cursor)._base == BlobId::NO_BLOBID) { + group_details(group_cursor)._base = declaredBlob; + group_details(group_cursor)._entry_base = declaredEntry; + } + // update the high water mark for blobs and entries in the stub + // group unconditionally + group_details(group_cursor)._max = declaredBlob; + group_details(group_cursor)._entry_max = declaredMax; + // move forward to this blob + blob_cursor = declaredBlob; + // link the blob to its group and its unique stub + blob_details(blob_cursor)._group = group_cursor; + blob_details(blob_cursor)._base = declaredStub; + blob_details(blob_cursor)._max = declaredStub; + blob_details(blob_cursor)._name = name; + // move forward to this stub + stub_cursor = declaredStub; + // link the stub to its blob and its entries + stub_details(stub_cursor)._blob = declaredBlob; + stub_details(stub_cursor)._base = declaredEntry; + stub_details(stub_cursor)._max = declaredMax; + stub_details(stub_cursor)._is_entry_array = false; + stub_details(stub_cursor)._name = name; + // move forward to last entry + entry_cursor = declaredMax; + // fill out the entry table for the the declared entry up to last entry + EntryId id = declaredEntry; + entry_details(id)._stub = declaredStub; + entry_details(id)._array_base = EntryId::NO_ENTRYID; + entry_details(id)._name = name; + // fill any subsequent entries + while (id != declaredMax) { + id = next(id); + entry_details(id)._stub = declaredStub; + entry_details(id)._array_base = EntryId::NO_ENTRYID; + entry_details(id)._name = name; + } +} + +void StubInfo::process_c1_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry) { + // for c1 declarations we update the blob, stub and entry tables all + // in one go based on each unique blob declaration + assert(group_cursor == StubGroup::C1, "must be"); + assert(is_next(declaredBlob, blob_cursor), "Out of order declaration for c1 blob %s", name); + assert(is_next(declaredStub, stub_cursor), "Out of order declaration for c1 stub %s", name); + assert(is_next(declaredEntry, entry_cursor), "Out of order declaration for c1 entry %s", name); + // if this is the first c1 blob then record it and the entry + if (group_details(group_cursor)._base == BlobId::NO_BLOBID) { + group_details(group_cursor)._base = declaredBlob; + group_details(group_cursor)._entry_base = declaredEntry; + } + // update the high water mark for blobs and entries in the stub + // group unconditionally + group_details(group_cursor)._max = declaredBlob; + group_details(group_cursor)._entry_max = declaredEntry; + // move forward to this blob + blob_cursor = declaredBlob; + // link the blob to its group and its unique stub + blob_details(blob_cursor)._group = group_cursor; + blob_details(blob_cursor)._base = declaredStub; + blob_details(blob_cursor)._max = declaredStub; + blob_details(blob_cursor)._name = name; + // move forward to this stub + stub_cursor = declaredStub; + // link the stub to its blob and its entries + stub_details(stub_cursor)._blob = declaredBlob; + stub_details(stub_cursor)._base = declaredEntry; + stub_details(stub_cursor)._max = declaredEntry; + stub_details(stub_cursor)._is_entry_array = false; + stub_details(stub_cursor)._name = name; + // move forward to entry + entry_cursor = declaredEntry; + // fill out the entry table element + entry_details(entry_cursor)._stub = declaredStub; + entry_details(entry_cursor)._array_base = EntryId::NO_ENTRYID; + entry_details(entry_cursor)._name = name; +} + +void StubInfo::process_c2_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry) { + // for c2 declarations we update the blob, stub and entry tables all + // in one go based on the same details garnered from each unique + // blob, stub r jvmti stub declaration + assert(group_cursor == StubGroup::C2, "must be"); + assert(is_next(declaredBlob, blob_cursor), "Out of order declaration for c2 blob %s", name); + assert(is_next(declaredStub, stub_cursor), "Out of order declaration for c2 stub %s", name); + assert(is_next(declaredEntry, entry_cursor), "Out of order declaration for c2 entry %s", name); + // if this is the first c2 blob then record it and the entry + if (group_details(group_cursor)._base == BlobId::NO_BLOBID) { + group_details(group_cursor)._base = declaredBlob; + group_details(group_cursor)._entry_base = declaredEntry; + } + // update the high water mark for blobs and entries in the stub + // group unconditionally + group_details(group_cursor)._max = declaredBlob; + group_details(group_cursor)._entry_max = declaredEntry; + // move forward to this blob + blob_cursor = declaredBlob; + // link the blob to its group and its unique stub + blob_details(blob_cursor)._group = group_cursor; + blob_details(blob_cursor)._base = declaredStub; + blob_details(blob_cursor)._max = declaredStub; + blob_details(blob_cursor)._name = name; + // move forward to this stub + stub_cursor = declaredStub; + // link the stub to its blob and its entries + stub_details(stub_cursor)._blob = declaredBlob; + stub_details(stub_cursor)._base = declaredEntry; + stub_details(stub_cursor)._max = declaredEntry; + stub_details(stub_cursor)._is_entry_array = false; + stub_details(stub_cursor)._name = name; + // move forward to entry + entry_cursor = declaredEntry; + // fill out the entry table element + entry_details(entry_cursor)._stub = declaredStub; + entry_details(entry_cursor)._array_base = EntryId::NO_ENTRYID; + entry_details(entry_cursor)._name = name; +} + +void StubInfo::process_stubgen_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob) { + // for stubgen blob declarations we update the blob table, allowing + // us to link subsequent stubs to that blob + assert(group_cursor == StubGroup::STUBGEN, "must be"); + assert(is_next(declaredBlob, blob_cursor), "Out of order declaration for stubgen blob %s", name); + // if this is the first stubgen blob then record it + if (group_details(group_cursor)._base == BlobId::NO_BLOBID) { + group_details(group_cursor)._base = declaredBlob; + } + // update the high water mark for blobs in the stub group unconditionally + group_details(group_cursor)._max = declaredBlob; + // move forward to this blob + blob_cursor = declaredBlob; + // link the blob to its group + blob_details(blob_cursor)._group = group_cursor; + // clear the blob table base and max - they are set when we first + // encounter a stub. likewise the blob table entry base and entry + // max -- they are set when we first encounter an entry + blob_details(blob_cursor)._base = StubId::NO_STUBID; + blob_details(blob_cursor)._max = StubId::NO_STUBID; + blob_details(blob_cursor)._entry_base = EntryId::NO_ENTRYID; + blob_details(blob_cursor)._entry_max = EntryId::NO_ENTRYID; + blob_details(blob_cursor)._name = name; +} + +void StubInfo::process_stubgen_stub(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub) { + // for stubgen stub declarations we update the stub table, allowing + // us to link subsequent entries to that stub + assert(group_cursor == StubGroup::STUBGEN, "must be"); + // FIXME use stub name here + assert(declaredBlob == blob_cursor, "Stubgen stub %s in scope of incorrect blob %s", name, blob_details(blob_cursor)._name); + assert(is_next(declaredStub, stub_cursor), "Out of order declaration for stubgen stub %s", name); + // if this is the first stubgen stub then record it + if (blob_details(blob_cursor)._base == StubId::NO_STUBID) { + blob_details(blob_cursor)._base = declaredStub; + } + // update the high water mark for stubs in the blob unconditionally + blob_details(blob_cursor)._max = declaredStub; + // move forward to this stub + stub_cursor = declaredStub; + // link the stub to its blob + stub_details(stub_cursor)._blob = blob_cursor; + // clear the stub table base and max - they are set when we + // encounter an entry + stub_details(stub_cursor)._base = EntryId::NO_ENTRYID; + stub_details(stub_cursor)._max = EntryId::NO_ENTRYID; + stub_details(stub_cursor)._name = name;; +} + +void StubInfo::process_stubgen_entry(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry, + int arrayCount) { + // for stubgen entry declarations we update the entry table + assert(group_cursor == StubGroup::STUBGEN, "must be"); + assert(declaredBlob == blob_cursor, "Stubgen entry %s in scope of wrong blob %s", name, blob_details(blob_cursor)._name); + assert(declaredStub == stub_cursor, "Stubgen entry %s declares stub in scope of wrong stub %s", name, stub_details(stub_cursor)._name); + assert(is_next(declaredEntry, entry_cursor), "Out of order declaration for stubgen entry %s", name); + assert(arrayCount >= 0, "Invalid array count %d", arrayCount); + // if this is the first stubgen entry in the group then record it + if (group_details(group_cursor)._entry_base == EntryId::NO_ENTRYID) { + group_details(group_cursor)._entry_base = declaredEntry; + } + // update the high water mark for entries in the group unconditionally + group_details(group_cursor)._entry_max = declaredEntry; + // if this is the first stubgen entry in the blob then record it + if (blob_details(blob_cursor)._entry_base == EntryId::NO_ENTRYID) { + blob_details(blob_cursor)._entry_base = declaredEntry; + } + // update the high water mark for entries in the group unconditionally + blob_details(blob_cursor)._entry_max = declaredEntry; + // if this is the first stubgen entry in the stub then record it + if (stub_details(stub_cursor)._base == EntryId::NO_ENTRYID) { + stub_details(stub_cursor)._base = declaredEntry; + } + // move forward to this entry + if (arrayCount == 0) { + // simply link the entry to its blob + entry_cursor = declaredEntry; + entry_details(entry_cursor)._stub = stub_cursor; + entry_details(entry_cursor)._array_base = EntryId::NO_ENTRYID; + entry_details(entry_cursor)._name = name; + } else { + // populate multiple entries and link them all to the first entry + for (int i = 0; i < arrayCount; i++) { + entry_cursor = next(entry_cursor); + entry_details(entry_cursor)._stub = stub_cursor; + entry_details(entry_cursor)._array_base = declaredEntry; + // TODO: consider allocating names labelled with index + entry_details(entry_cursor)._name = name; + } + } + // update the high water mark for entries in the stub unconditionally + stub_details(stub_cursor)._max = entry_cursor; +} + +// The stubgroup, blob, stub and entry tables defined above are +// populated by iterating over all blob, stub and entry declarations +// and incrementally updating the associated table entries. The +// following macros invoke static methods of StubInfo that receive +// and, where appropriate, update cursors identifying current +// positions in each table. + +#define PROCESS_SHARED_BLOB(name, type) \ + process_shared_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Shared Runtime " # name "_blob", \ + BlobId:: JOIN3(shared, name, id), \ + StubId:: JOIN3(shared, name, id), \ + EntryId:: JOIN3(shared, name, id), \ + EntryId:: JOIN3(shared, name, max)); \ + +#define PROCESS_C1_BLOB(name) \ + process_c1_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "C1 Runtime " # name "_blob", \ + BlobId:: JOIN3(c1, name, id), \ + StubId:: JOIN3(c1, name, id), \ + EntryId:: JOIN3(c1, name, id)); \ + +#define PROCESS_C2_BLOB(name, type) \ + process_c2_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "C2 Runtime " # name "_blob", \ + BlobId:: JOIN3(c2, name, id), \ + StubId:: JOIN3(c2, name, id), \ + EntryId:: JOIN3(c2, name, id)); \ + +#define PROCESS_C2_STUB(name, fancy_jump, pass_tls, return_pc) \ + process_c2_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "C2 Runtime " # name "_blob", \ + BlobId:: JOIN3(c2, name, id), \ + StubId:: JOIN3(c2, name, id), \ + EntryId:: JOIN3(c2, name, id)); \ + +#define PROCESS_C2_JVMTI_STUB(name) \ + process_c2_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "C2 Runtime " # name "_blob", \ + BlobId:: JOIN3(c2, name, id), \ + StubId:: JOIN3(c2, name, id), \ + EntryId:: JOIN3(c2, name, id)); \ + +#define PROCESS_STUBGEN_BLOB(blob) \ + process_stubgen_blob(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # blob "_blob", \ + BlobId:: JOIN3(stubgen, blob, id)); \ + +#define PROCESS_STUBGEN_STUB(blob, stub) \ + process_stubgen_stub(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # stub "_stub", \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id)); \ + +#define PROCESS_STUBGEN_ENTRY(blob, stub, field_name, getter_name) \ + process_stubgen_entry(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # field_name "_entry", \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id), \ + EntryId:: JOIN3(stubgen, field_name, id), \ + 0); \ + +#define PROCESS_STUBGEN_ENTRY_INIT(blob, stub, field_name, getter_name, \ + init_funcion) \ + process_stubgen_entry(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # field_name "_entry", \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id), \ + EntryId:: JOIN3(stubgen, field_name, id), \ + 0); \ + +#define PROCESS_STUBGEN_ENTRY_ARRAY(blob, stub, field_name, getter_name, \ + count) \ + process_stubgen_entry(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # field_name "_entry", \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id), \ + EntryId:: JOIN3(stubgen, field_name, id), \ + count); \ + +#define PROCESS_STUBGEN_ENTRY_ARCH(arch_name, blob, stub, field_name, \ + getter_name) \ + process_stubgen_entry(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + #arch_name "_" # field_name, \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id), \ + EntryId:: JOIN4(stubgen, arch_name, \ + field_name, id), \ + 0); \ + +#define PROCESS_STUBGEN_ENTRY_ARCH_INIT(arch_name, blob, stub, \ + field_name, getter_name, \ + init_function) \ + process_stubgen_entry(_group_cursor, _blob_cursor, \ + _stub_cursor, _entry_cursor, \ + "Stub Generator " # arch_name "_" # field_name "_entry", \ + BlobId:: JOIN3(stubgen, blob, id), \ + StubId:: JOIN3(stubgen, stub, id), \ + EntryId:: JOIN4(stubgen, arch_name, \ + field_name, id), \ + 0); \ + +void StubInfo::populate_stub_tables() { + StubGroup _group_cursor; + BlobId _blob_cursor = BlobId::NO_BLOBID; + StubId _stub_cursor = StubId::NO_STUBID; + EntryId _entry_cursor = EntryId::NO_ENTRYID; + + _group_cursor = StubGroup::SHARED; + group_details(_group_cursor)._name = "Shared Stubs"; + group_details(_group_cursor)._base = BlobId::NO_BLOBID; + group_details(_group_cursor)._max = BlobId::NO_BLOBID; + group_details(_group_cursor)._entry_base = EntryId::NO_ENTRYID; + group_details(_group_cursor)._entry_max = EntryId::NO_ENTRYID; + SHARED_STUBS_DO(PROCESS_SHARED_BLOB); + + _group_cursor = StubGroup::C1; + group_details(_group_cursor)._name = "C1 Stubs"; + group_details(_group_cursor)._base = BlobId::NO_BLOBID; + group_details(_group_cursor)._max = BlobId::NO_BLOBID; + group_details(_group_cursor)._entry_base = EntryId::NO_ENTRYID; + group_details(_group_cursor)._entry_max = EntryId::NO_ENTRYID; + C1_STUBS_DO(PROCESS_C1_BLOB); + + _group_cursor = StubGroup::C2; + group_details(_group_cursor)._name = "C2 Stubs"; + group_details(_group_cursor)._base = BlobId::NO_BLOBID; + group_details(_group_cursor)._max = BlobId::NO_BLOBID; + group_details(_group_cursor)._entry_base = EntryId::NO_ENTRYID; + group_details(_group_cursor)._entry_max = EntryId::NO_ENTRYID; + C2_STUBS_DO(PROCESS_C2_BLOB, PROCESS_C2_STUB, PROCESS_C2_JVMTI_STUB); + + _group_cursor = StubGroup::STUBGEN; + group_details(_group_cursor)._name = "StubGen Stubs"; + group_details(_group_cursor)._base = BlobId::NO_BLOBID; + group_details(_group_cursor)._max = BlobId::NO_BLOBID; + group_details(_group_cursor)._entry_base = EntryId::NO_ENTRYID; + group_details(_group_cursor)._entry_max = EntryId::NO_ENTRYID; + STUBGEN_ALL_DO(PROCESS_STUBGEN_BLOB, DO_BLOB_EMPTY1, + PROCESS_STUBGEN_STUB, + PROCESS_STUBGEN_ENTRY, PROCESS_STUBGEN_ENTRY_INIT, + PROCESS_STUBGEN_ENTRY_ARRAY, + DO_ARCH_BLOB_EMPTY2, + PROCESS_STUBGEN_ENTRY_ARCH, PROCESS_STUBGEN_ENTRY_ARCH_INIT); + assert(next(_blob_cursor) == BlobId::NUM_BLOBIDS, "should have exhausted all blob ids!"); + assert(next(_stub_cursor) == StubId::NUM_STUBIDS, "should have exhausted all stub ids!"); + assert(next(_entry_cursor) == EntryId::NUM_ENTRYIDS, "should have exhausted all entry ids!"); +#ifdef ASSERT + // run further sanity checks + verify_stub_tables(); +#endif // ASSERT +} + +#undef PROCESS_SHARED_BLOB +#undef PROCESS_C1_BLOB +#undef PROCESS_C2_BLOB +#undef PROCESS_C2_STUB +#undef PROCESS_C2_JVMTI_STUB +#undef PROCESS_STUBGEN_BLOB +#undef PROCESS_STUBGEN_STUB +#undef PROCESS_STUBGEN_ENTRY +#undef PROCESS_STUBGEN_ENTRY_INIT +#undef PROCESS_STUBGEN_ENTRY_ARRAY +#undef PROCESS_STUBGEN_ENTRY_ARCH +#undef PROCESS_STUBGEN_ENTRY_ARCH_INIT + +#ifdef ASSERT + +void StubInfo::verify_stub_tables() { + // exercise the traversal and interconversion APIs + const int NUM_STUBGROUPS = static_cast(StubGroup::NUM_STUBGROUPS); + StubGroup groups[NUM_STUBGROUPS] = { + StubGroup::SHARED, + StubGroup::C1, + StubGroup::C2, + StubGroup::STUBGEN }; + + // check that the statically defined blob, stub and entry counts + // match the computed totals + assert(blob_count(StubGroup::SHARED) == StubInfo::SHARED_STUB_COUNT, + "miscounted number of shared blobs %d vs %d", + blob_count(StubGroup::SHARED), StubInfo::SHARED_STUB_COUNT); + + assert(stub_count(StubGroup::SHARED) == StubInfo::SHARED_STUB_COUNT, + "miscounted number of shared stubs %d vs %d", + stub_count(StubGroup::SHARED), StubInfo::SHARED_STUB_COUNT); + + assert(entry_count(StubGroup::SHARED) == StubInfo::SHARED_ENTRY_COUNT, + "miscounted number of shared entries %d vs %d", + entry_count(StubGroup::SHARED), StubInfo::SHARED_ENTRY_COUNT); + + assert(blob_count(StubGroup::C1) == StubInfo::C1_STUB_COUNT, + "miscounted number of c1 blobs %d vs %d", + blob_count(StubGroup::C1), StubInfo::C1_STUB_COUNT); + + assert(stub_count(StubGroup::C1) == StubInfo::C1_STUB_COUNT, + "miscounted number of c1 stubs %d vs %d", + stub_count(StubGroup::C1), StubInfo::C1_STUB_COUNT); + + assert(entry_count(StubGroup::C1) == StubInfo::C1_STUB_COUNT, + "miscounted number of c1 entries %d vs %d", + entry_count(StubGroup::C1), StubInfo::C1_STUB_COUNT); + + assert(blob_count(StubGroup::C2) == StubInfo::C2_STUB_COUNT, + "miscounted number of c2 blobs %d vs %d", + blob_count(StubGroup::C2), StubInfo::C2_STUB_COUNT); + + assert(stub_count(StubGroup::C2) == StubInfo::C2_STUB_COUNT, + "miscounted number of c2 stubs %d vs %d", + stub_count(StubGroup::C2), StubInfo::C2_STUB_COUNT); + + assert(entry_count(StubGroup::C2) == StubInfo::C2_STUB_COUNT, + "miscounted number of c2 entries %d vs %d", + entry_count(StubGroup::C2), StubInfo::C2_STUB_COUNT); + + assert(blob_count(StubGroup::STUBGEN) == StubInfo::STUBGEN_BLOB_COUNT, + "miscounted number of stubgen blobs %d vs %d", + blob_count(StubGroup::STUBGEN), StubInfo::STUBGEN_STUB_COUNT); + + assert(stub_count(StubGroup::STUBGEN) == StubInfo::STUBGEN_STUB_COUNT, + "miscounted number of stubgen stubs %d vs %d", + stub_count(StubGroup::STUBGEN), StubInfo::STUBGEN_STUB_COUNT); + + assert(entry_count(StubGroup::STUBGEN) == StubInfo::STUBGEN_ENTRY_COUNT, + "miscounted number of stubgen entries %d vs %d", + entry_count(StubGroup::STUBGEN), StubInfo::STUBGEN_ENTRY_COUNT); + + // 1) check that the per-group blob counts add up + for (int gidx = 0; gidx < NUM_STUBGROUPS ; gidx++) { + StubGroup group = groups[gidx]; + BlobId blob = blob_base(group); + int group_blob_total = blob_count(group); + while (blob != BlobId::NO_BLOBID) { + // predecrement total + group_blob_total--; + assert(group_blob_total > 0 || blob == blob_max(group), "must be!"); + assert(stubgroup(blob) == group, "iterated out of group %s to blob %s", name(group), name(blob)); + blob = next_in_group(group, blob); + } + assert(group_blob_total == 0, "must be!"); + } + + // 2) check that the per-group and per-blob stub counts add up + for (int gidx = 0; gidx < NUM_STUBGROUPS; gidx++) { + StubGroup group = groups[gidx]; + BlobId blob = blob_base(group); + StubId group_stub = stub_base(group); + int group_stub_total = stub_count(group); + while (blob != BlobId::NO_BLOBID) { + StubId stub = stub_base(blob); + int stub_total = stub_count(blob); + while (stub != StubId::NO_STUBID) { + // iterations via group and blob should proceed in parallel + assert(stub == group_stub, "must be!"); + // predecrement totals + group_stub_total--; + stub_total--; + assert(stub_total > 0 || stub == stub_max(blob), "must be!"); + assert(group_stub_total > 0 || stub == stub_max(group), "must be!"); + assert(stubgroup(stub) == group, "iterated out of group %s to stub %s", name(group), name(stub)); + stub = next_in_blob(blob, stub); + group_stub = next(group_stub); + } + assert(stub_total == 0, "must be!"); + blob = next_in_group(group, blob); + } + assert(group_stub_total == 0, "must be!"); + } + + // 3) check that the per-group, per-blob and per-stub entry counts add up + for (int gidx = 0; gidx < NUM_STUBGROUPS; gidx++) { + StubGroup group = groups[gidx]; + BlobId blob = blob_base(group); + StubId group_stub = stub_base(group); + EntryId group_entry = entry_base(group); + int group_entry_total = entry_count(group); + while (blob != BlobId::NO_BLOBID) { + StubId stub = stub_base(blob); + while (stub != StubId::NO_STUBID) { + EntryId entry = entry_base(stub); + int entry_total = entry_count(stub); + while (entry != EntryId::NO_ENTRYID) { + // iterations via group and blob should proceed in parallel + assert(entry == group_entry, "must be!"); + // predecrement totals + group_entry_total--; + entry_total--; + assert(entry_total > 0 || entry == entry_max(stub), "must be!"); + assert(group_entry_total > 0 || entry == entry_max(group), "must be!"); + assert(stubgroup(entry) == group, "iterated out of group %s to entry %s", name(group), name(entry)); + entry = next_in_stub(stub, entry); + group_entry = next(group_entry); + } + assert(entry_total == 0, "must be!"); + stub = next_in_blob(blob, stub); + group_stub = next(group_stub); + } + blob = next_in_group(group, blob); + } + assert(group_entry_total == 0, "must be!"); + } +} + +#endif // ASSERT + +// info support + +void StubInfo::dump_group_table(LogStream& ls) { + ls.print_cr("STUB GROUP TABLE"); + for (int i = 0; i < GROUP_TABLE_SIZE; i++) { + GroupDetails& g = _group_table[i]; + ls.print_cr("%1d: %-8s", i, g._name); + if (g._base == g._max) { + // some groups don't have a blob + if (g._base == BlobId::NO_BLOBID) { + ls.print_cr(" blobs: %s(%d)", + "no_blobs", + static_cast(g._base)); + } else { + ls.print_cr(" blobs: %s(%d)", + blob_details(g._base)._name, + static_cast(g._base)); + } + } else { + ls.print_cr(" blobs: %s(%d) ... %s(%d)", + blob_details(g._base)._name, + static_cast(g._base), + blob_details(g._max)._name, + static_cast(g._max)); + } + } +} + +void StubInfo::dump_blob_table(LogStream& ls) { + ls.print_cr("BLOB TABLE"); + for (int i = 0; i < BLOB_TABLE_SIZE; i++) { + BlobDetails& b = _blob_table[i]; + ls.print_cr("%-3d: %s", i, b._name); + if (b._base == b._max) { + // some blobs don't have a stub + if (b._base == StubId::NO_STUBID) { + ls.print_cr(" stubs: %s(%d)", + "no_stubs", + static_cast(b._base)); + } else { + ls.print_cr(" stubs: %s(%d)", + stub_details(b._base)._name, + static_cast(b._base)); + } + } else { + ls.print_cr(" stubs: %s(%d) ... %s(%d)", + stub_details(b._base)._name, + static_cast(b._base), + stub_details(b._max)._name, + static_cast(b._max)); + } + } +} + +void StubInfo::dump_stub_table(LogStream& ls) { + ls.print_cr("STUB TABLE"); + for (int i = 0; i < STUB_TABLE_SIZE; i++) { + StubDetails& s = _stub_table[i]; + ls.print_cr("%-3d: %s %s", i, s._name, + (s._is_entry_array ? "array" : "")); + ls.print_cr(" blob: %d", static_cast(s._blob)); + if (s._base == s._max) { + // some stubs don't have an entry + if (s._base == EntryId::NO_ENTRYID) { + ls.print_cr(" entries: %s(%d)", + "no_entry", + static_cast(s._base)); + } else { + ls.print_cr(" entries: %s(%d)", + entry_details(s._base)._name, + static_cast(s._base)); + } + } else { + ls.print_cr(" entries: %s(%d) ... %s(%d)", + entry_details(s._base)._name, + static_cast(s._base), + entry_details(s._max)._name, + static_cast(s._max)); + } + } +} + +void StubInfo::dump_entry_table(LogStream& ls) { + ls.print_cr("ENTRY TABLE"); + for (int i = 0; i < ENTRY_TABLE_SIZE; i++) { + EntryDetails& e = _entry_table[i]; + ls.print_cr("%-3d: %s", i, e._name); + if (e._array_base != EntryId::NO_ENTRYID) { + ls.print_cr(" array base: %d", static_cast(e._array_base)); + } + ls.print_cr(" stub: %d", static_cast(e._stub)); + } +} + +void StubInfo::dump_tables(LogStream& ls) { + dump_group_table(ls); + ls.print_cr(""); + dump_blob_table(ls); + ls.print_cr(""); + dump_stub_table(ls); + ls.print_cr(""); + dump_entry_table(ls); +} + +// Global Group/Blob/Stub/Entry Id Hierarchy Traversal: + +// traverse up + +StubGroup StubInfo::stubgroup(EntryId id) { + // delegate + return stubgroup(stub(id)); +} + +StubGroup StubInfo::stubgroup(BlobId id) { + return blob_details(id)._group; +} + +StubGroup StubInfo::stubgroup(StubId id) { + // delegate + return stubgroup(blob(id)); +} + +StubId StubInfo::stub(EntryId id) { + return entry_details(id)._stub; +} + +BlobId StubInfo::blob(EntryId id) { + // delegate + return blob(stub(id)); +} + +BlobId StubInfo::blob(StubId id) { + return stub_details(id)._blob; +} + +// traverse down + +BlobId StubInfo::blob_base(StubGroup stub_group) { + return group_details(stub_group)._base; +} + +BlobId StubInfo::blob_max(StubGroup stub_group) { + return group_details(stub_group)._max; +} + +int StubInfo::blob_count(StubGroup stub_group) { + return span(blob_max(stub_group), blob_base(stub_group)); +} + +StubId StubInfo::stub_base(StubGroup stub_group) { + BlobId base = blob_base(stub_group); + return (base == BlobId::NO_BLOBID ? StubId::NO_STUBID : stub_base(base)); +} + +StubId StubInfo::stub_max(StubGroup stub_group) { + BlobId base = blob_max(stub_group); + return (base == BlobId::NO_BLOBID ? StubId::NO_STUBID : stub_max(base)); +} + +int StubInfo::stub_count(StubGroup stub_group) { + return span(stub_max(stub_group), stub_base(stub_group)); +} + +EntryId StubInfo::entry_base(StubGroup stub_group) { + return group_details(stub_group)._entry_base; +} + +EntryId StubInfo::entry_max(StubGroup stub_group) { + return group_details(stub_group)._entry_max; +} + +int StubInfo::entry_count(StubGroup stub_group) { + return span(entry_max(stub_group), entry_base(stub_group)); +} + +StubId StubInfo::stub_base(BlobId id) { + return blob_details(id)._base; +} + +StubId StubInfo::stub_max(BlobId id) { + return blob_details(id)._max; +} + +int StubInfo::stub_count(BlobId id) { + return span(stub_max(id), stub_base(id)); +} + +EntryId StubInfo::entry_base(StubId id) { + return stub_details(id)._base; +} + +EntryId StubInfo::entry_max(StubId id) { + return stub_details(id)._max; +} + +int StubInfo::entry_count(StubId id) { + return span(entry_max(id), entry_base(id)); +} + +EntryId StubInfo::entry_base(BlobId id) { + return blob_details(id)._entry_base; +} + +EntryId StubInfo::entry_max(BlobId id) { + return blob_details(id)._entry_max; +} + +int StubInfo::entry_count(BlobId id) { + return span(entry_base(id), entry_max(id)); +} + +// Global <-> Local Id Management: + +// private helpers + +bool StubInfo::has_group(BlobId id, StubGroup group) { + return stubgroup(id) == group; +} + +bool StubInfo::has_group(StubId id, StubGroup group) { + return stubgroup(id) == group; +} + +bool StubInfo::has_group(EntryId id, StubGroup group) { + return stubgroup(id) == group; +} + +// Convert a blob, entry or stub id to a unique, zero-based offset in +// the range of blob/stub/entry ids for a given stub group. + +int StubInfo::local_offset(StubGroup group, BlobId id) { + assert(has_group(id, group), "id %s is not a %s blob!", name(id), name(group)); + BlobId base = blob_base(group); + int s = span(id, base); + assert(s >= 1, "must be"); + return s - 1; +} + +int StubInfo::local_offset(StubGroup group, StubId id) { + assert(has_group(id, group), "id %s is not a %s stub!", name(id), name(group)); + StubId base = stub_base(group); + int s = span(id, base); + assert(s >= 1, "must be"); + return s - 1; +} + +int StubInfo::local_offset(StubGroup group, EntryId id) { + assert(has_group(id, group), "id %s is not a %s entry!", name(id), name(group)); + EntryId base = entry_base(group); + int s = span(id, base); + assert(s >= 1, "must be"); + return s - 1; +} + +// public API + +// check that a stub belongs to an expected stub group + +bool StubInfo::is_shared(StubId id) { + return has_group(id, StubGroup::SHARED); +} + +bool StubInfo::is_c1(StubId id) { + return has_group(id, StubGroup::C1); +} + +bool StubInfo::is_c2(StubId id) { + return has_group(id, StubGroup::C2); +} + +bool StubInfo::is_stubgen(StubId id) { + return has_group(id, StubGroup::STUBGEN); +} + +// check that a stub belongs to an expected stub group + +bool StubInfo::is_shared(BlobId id) { + return has_group(id, StubGroup::SHARED); +} + +bool StubInfo::is_c1(BlobId id) { + return has_group(id, StubGroup::C1); +} + +bool StubInfo::is_c2(BlobId id) { + return has_group(id, StubGroup::C2); +} + +bool StubInfo::is_stubgen(BlobId id) { + return has_group(id, StubGroup::STUBGEN); +} + +// Convert a stub id to a unique, zero-based offset in the range of +// stub ids for a given stub group. + +int StubInfo::shared_offset(StubId id) { + return local_offset(StubGroup::SHARED, id); +} + +int StubInfo::c1_offset(StubId id) { + return local_offset(StubGroup::C1, id); +} + +int StubInfo::c2_offset(StubId id) { + return local_offset(StubGroup::C2, id); +} + +int StubInfo::stubgen_offset(StubId id) { + return local_offset(StubGroup::STUBGEN, id); +} + +// initialization function called to populate blob. stub and entry +// tables. this must be called before any stubs are generated +void initialize_stub_info() { + ResourceMark rm; + StubInfo::populate_stub_tables(); + + LogTarget(Debug, stubs) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + StubInfo::dump_tables(ls); + } +} diff --git a/src/hotspot/share/runtime/stubInfo.hpp b/src/hotspot/share/runtime/stubInfo.hpp new file mode 100644 index 00000000000..eaea07f7e6c --- /dev/null +++ b/src/hotspot/share/runtime/stubInfo.hpp @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Red Hat, Inc. 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. + * + */ + +#ifndef SHARE_RUNTIME_STUBINFO_HPP +#define SHARE_RUNTIME_STUBINFO_HPP + +#include "logging/logStream.hpp" +#include "runtime/stubDeclarations.hpp" + +// class StubInfo records details of the global stubgroup, blob, stub +// and entry hierarchy and provides APIs that +// +// 1) allow relationships between blobs, stubs and their entries to be +// identified. +// +// 2) Support conversion from a global blob/stub/entry id to a +// corresponding, unique, group-local blob/stub/entry offset from the +// first blob/stub/entry in the same stubgroup + +// We have four distinct stub groups, each of which includes multiple +// blobs, stubs and entries. + +enum class StubGroup : int { + SHARED, + C1, + C2, + STUBGEN, + NUM_STUBGROUPS +}; + +// Generated code elements are used to implement the following enums: +// +// Global and Stub Group Local Blob/Stub/Entry Enumerations: +// +// The following enums uniquely list every generated blob, stub and +// entry across all four stub groups. +// +// enum StubId; // unique id for every stub in the above groups +// enum BlobId; // unique id for every blob in the above groups +// enum EntryId; // unique id for every entry in the above groups +// +// +// Management APIs for these enums are defined in class StubInfo. The +// API methods rely on a small amount of code and data genertaed from +// the blob, stub and entry declarations. +// +// Global Group/Blob/Stub/Entry Id Hierarchy Traversal: +// +// traverse up +// +// StubGroup StubInfo::stubgroup(EntryId); +// StubGroup StubInfo::stubgroup(BlobId); +// StubGroup StubInfo::stubgroup(StubId); +// +// StubId StubInfo::stub(EntryId); +// BlobId StubInfo::blob(EntryId); +// BlobId StubInfo::blob(StubId); +// +// traverse down +// +// BlobId StubInfo::blob_base(StubGroup) +// BlobId StubInfo::blob_max(StubGroup) +// int StubInfo::blob_count(StubGroup) +// +// StubId StubInfo::stub_base(StubGroup) +// StubId StubInfo::stub_max(StubGroup) +// int StubInfo::stub_count(StubGroup) +// +// EntryId StubInfo::entry_base(StubGroup) +// EntryId StubInfo::entry_max(StubGroup) +// int StubInfo::entry_count(StubGroup) +// +// StubId StubInfo::stub_base(BlobId); +// StubId StubInfo::stub_max(BlobId); +// int StubInfo::stub_count(BlobId); +// +// EntryId StubInfo::entry_base(StubId); +// EntryId StubInfo::entry_max(StubId); +// int StubInfo::entry_count(StubId); +// +// EntryId StubInfo::entry_base(BlobId); +// EntryId StubInfo::entry_max(BlobId); +// int StubInfo::entry_count(BlobId); +// +// +// Global <-> Local Id Management: +// +// check that a stub belongs to an expected stub group +// +// bool StubInfo::is_shared(StubId id); +// bool StubInfo::is_c1(StubId id); +// bool StubInfo::is_c2(StubId id); +// bool StubInfo::is_stubgen(StubId id); +// +// Convert a stub id to a unique, zero-based offset in the range of +// stub ids for a given stub group. +// +// int StubInfo::shared_offset(StubId id); +// int StubInfo::c1_offset(StubId id); +// int StubInfo::c2_offset(StubId id); +// int StubInfo::stubgen_offset(StubId id); +// +// Convert a blob id to a unique, zero-based offset in the range of +// blob ids for a given stub group. we only need this for stubgen +// blobs as for all other stub groups the stub indices and blob +// indices are identical. +// +// int StubInfo::stubgen_offset(BlobId id); +// +// Convert an entry id to a unique, zero-based offset in the range +// of entry ids for a given stub group. we only need this for shared +// and stubgen blobs as for all other stub groups the stub indices +// and entry indices are identical. +// +// int StubInfo::shared_offset(EntryId id); +// int StubInfo::stubgen_offset(EntryId id); +// +// n.b. invalid interconversions from a global id to the wrong type of +// group id are caught by asserts + + +// Generate global blob, stub and entry enums from blob, stubs and +// entry declarations + +// Global enumeration for all blobs +// +// n.b. the stubgroup is included in tag because the same name may be +// reused across groups (e.g. c1 and c2 both use new_instance) +// +// enum BlobId { +// shared_deopt_id, +// . . . +// c1_unwind_exception_id, +// . . . +// c2_uncommon_trap_id, +// . . . +// stubgen_initial_id, +// . . . +// NUM_BLOBIDS, +// }; + + +#define SHARED_DECLARE_TAG(name, type) JOIN3(shared, name, id) , +#define C1_DECLARE_TAG(name) JOIN3(c1, name, id) , +#define C2_DECLARE_TAG1(name) JOIN3(c2, name, id) , +#define C2_DECLARE_TAG2(name, _1) JOIN3(c2, name, id) , +#define C2_DECLARE_TAG4(name, _1, _2, _3) JOIN3(c2, name, id) , +#define STUBGEN_DECLARE_TAG(name) JOIN3(stubgen, name, id) , + +enum class BlobId : int { + NO_BLOBID = -1, + // declare an enum tag for each shared runtime blob + SHARED_STUBS_DO(SHARED_DECLARE_TAG) + // declare an enum tag for each c1 runtime blob + C1_STUBS_DO(C1_DECLARE_TAG) + // declare an enum tag for each opto runtime blob or stub + C2_STUBS_DO(C2_DECLARE_TAG2, + C2_DECLARE_TAG4, + C2_DECLARE_TAG1) + // declare an enum tag for each stubgen blob + STUBGEN_BLOBS_DO(STUBGEN_DECLARE_TAG) + NUM_BLOBIDS +}; + +#undef SHARED_DECLARE_TAG +#undef C1_DECLARE_TAG +#undef C2_DECLARE_TAG1 +#undef C2_DECLARE_TAG2 +#undef C2_DECLARE_TAG4 +#undef STUBGEN_DECLARE_TAG + +// Global enumeration for all stubs +// +// n.b. the stubgroup is included in tag because the same name may be +// reused across groups (e.g. c1 and c2 both use new_instance). For +// stubgen stubs the blob name is omitted from the tag because all +// stub names may not be reused scross different stubgen blobs. +// +// enum StubId { +// shared_deopt_id, +// . . . +// c1_unwind_exception_id, +// . . . +// c2_uncommon_trap_id, +// . . . +// stubgen_call_stub_id, +// stubgen_forward_exception_id, +// . . . +// NUM_BLOBIDS, +// }; +// + +#define SHARED_DECLARE_TAG(name, type) JOIN3(shared, name, id) , +#define C1_DECLARE_TAG(name) JOIN3(c1, name, id) , +#define C2_DECLARE_TAG1(name) JOIN3(c2, name, id) , +#define C2_DECLARE_TAG2(name, _1) JOIN3(c2, name, id) , +#define C2_DECLARE_TAG4(name, _1, _2, _3) JOIN3(c2, name, id) , +#define STUBGEN_DECLARE_TAG(blob, name) JOIN3(stubgen, name, id) , + +enum class StubId : int { + NO_STUBID = -1, + // declare an enum tag for each shared runtime blob + SHARED_STUBS_DO(SHARED_DECLARE_TAG) + // declare an enum tag for each c1 runtime blob + C1_STUBS_DO(C1_DECLARE_TAG) + // declare an enum tag for each opto runtime blob or stub + C2_STUBS_DO(C2_DECLARE_TAG2, + C2_DECLARE_TAG4, + C2_DECLARE_TAG1) + // declare an enum tag for each stubgen runtime stub + STUBGEN_STUBS_DO(STUBGEN_DECLARE_TAG) + NUM_STUBIDS +}; + +#undef SHARED_DECLARE_TAG +#undef C1_DECLARE_TAG +#undef C2_DECLARE_TAG1 +#undef C2_DECLARE_TAG2 +#undef C2_DECLARE_TAG4 +#undef STUBGEN_DECLARE_TAG + + +// +// Global enumeration for all entries +// +// n.b. the stubgroup is included in tag because the same name may be +// reused across groups (e.g. c1 and c2 both use new_instance) +// +// enum EntryId : int { +// NO_ENTRYID = -1, +// shared_deopt_id, +// shared_deopt_max = +// shared_deopt_id + DeoptimzationBlob::NUM_ENTRIES -1, +// . . . +// c1_unwind_exception_id, +// . . . +// c2_uncommon_trap_id, +// . . . +// stubgen_call_stub_id, +// stubgen_call_stub_return_address_id, +// stubgen_forward_exception_id, +// . . . +// stubgen_aarch64_large_array_equals_id, +// . . . +// stubgen_lookup_secondary_supers_table_stubs_id, +// stubgen_lookup_secondary_supers_table_stubs_max = +// stubgen_lookup_secondary_supers_table_stubs_id + +// Klass::SECONDARY_SUPERS_TABLE_SIZE, +// . . . +// NUM_ENTRYIDS, +// }; +// +// - global id tags include a stub group prefix because some of the +// stub names are used in more than one group (e.g. new_instance, +// forward_exception). arch specific stubgen stubs also include the +// arch name in the tag. +// +// - for shared stub entries we only need to allocate a single enum +// tag for most blobs since they have only one entry. However, we need +// to bump up the index by an extra 3 (or 5 with JVMCI included) when +// we are generating the deoptimization blob because it has 4 +// (respectively, 6) entries. So, in that case we allocate a single +// enum tag identifying the index of the first entry and a max tag +// identifying the index of the last entry +// +// - for stubgen stubs which employ an array of entries we allocate a +// single enum tag identifying the index of the first entry and a max +// tag identifying the index of the last entry e.g. for +// lookup_secondary_supers_table we generate +// +// . . . +// stubgen_lookup_secondary_supers_table_stubs_id, +// stubgen_lookup_secondary_supers_table_stubs_max = stubgen_lookup_secondary_supers_table_stubs_id + Klass::SECONDARY_SUPERS_TABLE_SIZE, +// . . . +// + +// macro to declare tags for shared entries with a base id for the +// first (and usually only) entry and a max id that identifies the +// last (usually same as first) entry in the blob, ensuring the entry +// for the next stub has the correct index. + +#define SHARED_DECLARE_TAG(name, type) \ + JOIN3(shared, name, id), \ + JOIN3(shared, name, max) = JOIN3(shared, name, id) + \ + type ::ENTRY_COUNT - 1, \ + +// macros to declare a tag for a C1 generated blob or a C2 generated +// blob, stub or JVMTI stub all of which have a single unique entry + +#define C1_DECLARE_TAG(name) \ + JOIN3(c1, name, id), \ + +#define C2_DECLARE_BLOB_TAG(name, type) \ + JOIN3(c2, name, id), \ + +#define C2_DECLARE_STUB_TAG(name, fancy_jump, pass_tls, return_pc) \ + JOIN3(c2, name, id), \ + +#define C2_DECLARE_JVMTI_STUB_TAG(name) \ + JOIN3(c2, name, id), \ + +// macros to declare a tag for a StubGen normal entry or initialized +// entry + +#define STUBGEN_DECLARE_TAG(blob_name, stub_name, \ + field_name, getter_name) \ + JOIN3(stubgen, field_name, id), \ + +#define STUBGEN_DECLARE_INIT_TAG(blob_name, stub_name, \ + field_name, getter_name, \ + init_function) \ + JOIN3(stubgen, field_name, id), \ + +// macro to declare a tag for a StubGen entry array. this macro +// declares a base id for the first entry then a max id that +// identifies the last entry in the array, ensuring the entry for the +// next stub has the correct index. + +#define STUBGEN_DECLARE_ARRAY_TAG(blob_name, stub_name, \ + field_name, getter_name, \ + count) \ + JOIN3(stubgen, field_name, id), \ + JOIN3(stubgen, field_name, max) = JOIN3(stubgen, field_name, id) + \ + count - 1, \ + +// macros to declare a tag for StubGen arch entries + +#define STUBGEN_DECLARE_ARCH_TAG(arch_name, blob_name, stub_name, \ + field_name, getter_name) \ + JOIN4(stubgen, arch_name, field_name, id), \ + +#define STUBGEN_DECLARE_ARCH_INIT_TAG(arch_name, blob_name, stub_name, \ + field_name, getter_name, \ + init_function) \ + JOIN4(stubgen, arch_name, field_name, id), \ + +// the above macros are enough to declare the enum + +enum class EntryId : int { + NO_ENTRYID = -1, + // declare an enum tag for each shared runtime blob + SHARED_STUBS_DO(SHARED_DECLARE_TAG) + // declare an enum tag for each c1 runtime blob + C1_STUBS_DO(C1_DECLARE_TAG) + // declare an enum tag for each opto runtime blob or stub + C2_STUBS_DO(C2_DECLARE_BLOB_TAG, + C2_DECLARE_STUB_TAG, + C2_DECLARE_JVMTI_STUB_TAG) + // declare an enum tag for each stubgen entry or, in the case of an + // array of entries for the first and last entries. + STUBGEN_ALL_ENTRIES_DO(STUBGEN_DECLARE_TAG, + STUBGEN_DECLARE_INIT_TAG, + STUBGEN_DECLARE_ARRAY_TAG, + STUBGEN_DECLARE_ARCH_TAG, + STUBGEN_DECLARE_ARCH_INIT_TAG) + NUM_ENTRYIDS +}; + +#undef SHARED_DECLARE_TAG +#undef C1_DECLARE_TAG +#undef C2_DECLARE_BLOB_TAG +#undef C2_DECLARE_STUB_TAG +#undef C2_DECLARE_JVMTI_STUB_TAG +#undef STUBGEN_DECLARE_TAG +#undef STUBGEN_DECLARE_INIT_TAG +#undef STUBGEN_DECLARE_ARRAY_TAG +#undef STUBGEN_DECLARE_ARCH_TAG +#undef STUBGEN_DECLARE_ARCH_INIT_TAG + +// we need static init expressions for blob, stub and entry counts in +// each stubgroup + +#define SHARED_STUB_COUNT_INITIALIZER \ + 0 SHARED_STUBS_DO(COUNT2) + +#define SHARED_ENTRY_COUNT_INITIALIZER \ + 0 SHARED_STUBS_DO(SHARED_COUNT2) + +#define C1_STUB_COUNT_INITIALIZER \ + 0 C1_STUBS_DO(COUNT1) + +#define C2_STUB_COUNT_INITIALIZER \ + 0 C2_STUBS_DO(COUNT2, COUNT4, COUNT1) + +#define STUBGEN_BLOB_COUNT_INITIALIZER \ + 0 STUBGEN_BLOBS_DO(COUNT1) + +#define STUBGEN_STUB_COUNT_INITIALIZER \ + 0 STUBGEN_STUBS_DO(COUNT2) + +#define STUBGEN_ENTRY_COUNT_INITIALIZER \ + 0 STUBGEN_ALL_ENTRIES_DO(COUNT4, COUNT5, \ + STUBGEN_COUNT5, \ + COUNT5, COUNT6) + +// Declare management class StubInfo + +class StubInfo: AllStatic { +private: + // element types for tables recording stubgroup, blob, stub and + // entry properties and relationships + + // map each stubgroup to its initial and final blobs + struct GroupDetails { + BlobId _base; // first blob id belonging to stub group + BlobId _max; // last blob id belonging to stub group + // some stubs have no entries so we have to explicitly track the + // first and last entry associated with the group rather than + // deriving it from the first and last blob/stub pair + EntryId _entry_base; // first entry id belonging to stub + EntryId _entry_max; // last entry id belonging to stub + const char* _name; // name of stubgroup + }; + + // a blob table element enables the stub group of a guven blob to be + // identified and all stubs within the blob to be identified + // + // invariant: the number of stubs in a blob must be 1 unless the + // blob belongs to the StubGen stub group + + struct BlobDetails { + StubGroup _group; // stub group to which blob belongs + StubId _base; // first stub id belonging to blob + StubId _max; // last stub id belonging to blob + // some stubs have no entries so we have to explicitly track the + // first and last entry associated with the blob rather than + // deriving it from the first and last stub + EntryId _entry_base; // first entry id belonging to stub + EntryId _entry_max; // last entry id belonging to stub + const char* _name; // name of blob + }; + + // a stub table element enables the blob of a given stub to be + // identified and all entries within the stub to be identified + // + // invariant: the number of entries in a blob must be 1 unless the + // blob belongs to the StubGen group or the Shared stub group + + struct StubDetails { + BlobId _blob; // blob to which stub belongs + EntryId _base; // first entry id belonging to stub + EntryId _max; // last entry id belonging to stub + bool _is_entry_array; // true iff stub has array of entries + const char* _name; // name of stub + }; + + // a stub table element enables the blob of a given stub to be + // identified and all entries within the stub to be identified + // + // invariant: the number of entries in a blob must be 1 unless the + // blob belongs to the StubGen group or the Shared stub group + + struct EntryDetails { + StubId _stub; // stub to which the entry belongs + EntryId _array_base; // base entry id for entry array stubs + const char* _name; // name of stub + }; + + // tables are sized and indexed using the global ids + static const int GROUP_TABLE_SIZE = static_cast(StubGroup::NUM_STUBGROUPS); + static const int BLOB_TABLE_SIZE = static_cast(BlobId::NUM_BLOBIDS); + static const int STUB_TABLE_SIZE = static_cast(StubId::NUM_STUBIDS); + static const int ENTRY_TABLE_SIZE = static_cast(EntryId::NUM_ENTRYIDS); + + static struct GroupDetails _group_table[GROUP_TABLE_SIZE]; + static struct BlobDetails _blob_table[BLOB_TABLE_SIZE]; + static struct StubDetails _stub_table[STUB_TABLE_SIZE]; + static struct EntryDetails _entry_table[ENTRY_TABLE_SIZE]; + + // helpers to access table elements using enums as indices + static struct GroupDetails& group_details(StubGroup g); + static struct BlobDetails& blob_details(BlobId b); + static struct StubDetails& stub_details(StubId s); + static struct EntryDetails& entry_details(EntryId e); + + // helpers for counting entries/stubs in a given stub/blob + + static int span(EntryId second, EntryId first); + static int span(StubId second, StubId first); + static int span(BlobId second, BlobId first); + + // helper for testing whether a blob, stub or entry lies in a + // specific stubgroup + static bool has_group(BlobId id, StubGroup group); + static bool has_group(StubId id, StubGroup group); + static bool has_group(EntryId id, StubGroup group); + + // helpers for computing blob, stub or entry offsets within + // a specific stub group + + static int local_offset(StubGroup group, BlobId id); + static int local_offset(StubGroup group, StubId id); + static int local_offset(StubGroup group, EntryId id); + + // implementation of methods used to populate the stubgroup, blob, + // stub and entry tables + static void process_shared_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry, + EntryId declaredMax); + static void process_c1_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry); + static void process_c2_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry); + static void process_stubgen_blob(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob); + static void process_stubgen_stub(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub); + static void process_stubgen_entry(StubGroup& group_cursor, + BlobId& blob_cursor, + StubId& stub_cursor, + EntryId& entry_cursor, + const char* name, + BlobId declaredBlob, + StubId declaredStub, + EntryId declaredEntry, + int arrayCount); + + static void dump_group_table(LogStream& ls); + static void dump_blob_table(LogStream& ls); + static void dump_stub_table(LogStream& ls); + static void dump_entry_table(LogStream& ls); + + static void verify_stub_tables(); +public: + + // Define statically sized counts for blobs, stubs and entries in + // each stub group. n.b. we omit cases where the blob or entry count + // equals the stub count. + static const int SHARED_STUB_COUNT = SHARED_STUB_COUNT_INITIALIZER; + static const int SHARED_ENTRY_COUNT = SHARED_ENTRY_COUNT_INITIALIZER; + + static const int C1_STUB_COUNT = C1_STUB_COUNT_INITIALIZER; + + static const int C2_STUB_COUNT = C2_STUB_COUNT_INITIALIZER; + + static const int STUBGEN_STUB_COUNT = STUBGEN_STUB_COUNT_INITIALIZER; + static const int STUBGEN_BLOB_COUNT = STUBGEN_BLOB_COUNT_INITIALIZER; + static const int STUBGEN_ENTRY_COUNT = STUBGEN_ENTRY_COUNT_INITIALIZER; + + // init method called from a static initializer + static void populate_stub_tables(); + // for logging + static void dump_tables(LogStream& ls); + + // helpers to step through blob, stub or entry enum sequences. + // input id may be NO_BLOB/STUB/ENTRYID. returned id may be + // NUM_BLOB/STUB/ENTRYIDs + static BlobId next(BlobId id); + static StubId next(StubId id); + static EntryId next(EntryId id); + + // helpers to step through blob/stub/entry enum sequence within + // (respectively) the enclosing group/blob/stub. returned id will be + // a valid blob/stub/entry id or NO_BLOB/STUB/ENTRYID if the + // group/blob/stub contains no more stubs/entries. + static BlobId next_in_group(StubGroup stub_group, BlobId blob_id); + static StubId next_in_blob(BlobId blob_id, StubId stub_id); + static EntryId next_in_stub(StubId stub_id, EntryId entry_id); + +#ifdef ASSERT + // helpers to check sequencing of blobs stubs and entries + static bool is_next(BlobId second, BlobId first); + static bool is_next(StubId second, StubId first); + static bool is_next(EntryId second, EntryId first); +#endif // ASSERT + + // name retrieval + static const char* name(StubGroup stub_group); + static const char* name(BlobId id); + static const char* name(StubId id); + static const char* name(EntryId id); + + // Global Group/Blob/Stub/Entry Id Hierarchy Traversal: + + // traverse up + + static StubGroup stubgroup(EntryId id); + static StubGroup stubgroup(BlobId id); + static StubGroup stubgroup(StubId id); + + static StubId stub(EntryId id); + static BlobId blob(EntryId id); + static BlobId blob(StubId id); + + // traverse down + + static BlobId blob_base(StubGroup stub_group); + static BlobId blob_max(StubGroup stub_group); + static int blob_count(StubGroup stub_group); + + static StubId stub_base(StubGroup stub_group); + static StubId stub_max(StubGroup stub_group); + static int stub_count(StubGroup stub_group); + + static EntryId entry_base(StubGroup stub_group); + static EntryId entry_max(StubGroup stub_group); + static int entry_count(StubGroup stub_group); + + static StubId stub_base(BlobId id); + static StubId stub_max(BlobId id); + static int stub_count(BlobId id); + + static EntryId entry_base(BlobId id); + static EntryId entry_max(BlobId id); + static int entry_count(BlobId id); + + static EntryId entry_base(StubId id); + static EntryId entry_max(StubId id); + static int entry_count(StubId id); + + // Global <-> Local Id Management: + + // check that a blob/stub belongs to an expected stub group + + static bool is_shared(StubId id); + static bool is_c1(StubId id); + static bool is_c2(StubId id); + static bool is_stubgen(StubId id); + + static bool is_shared(BlobId id); + static bool is_c1(BlobId id); + static bool is_c2(BlobId id); + static bool is_stubgen(BlobId id); + + // Convert a stub id to a unique, zero-based offset in the range of + // stub ids for a given stub group. + + static int shared_offset(StubId id); + static int c1_offset(StubId id); + static int c2_offset(StubId id); + static int stubgen_offset(StubId id); +}; + + +#endif // SHARE_RUNTIME_STUBINFO_HPP diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index c2d570abad0..bbfdb223ae8 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -48,134 +48,54 @@ address UnsafeMemoryAccess::_common_exit_stub_pc = nullptr; // Implementation of StubRoutines - for a description of how to // declare new blobs, stubs and entries , see stubDefinitions.hpp. -// define arrays to hold stub and blob names - -// use a template to generate the initializer for the blob names array - -#define DEFINE_BLOB_NAME(blob_name) \ - # blob_name, - -const char* StubRoutines::_blob_names[StubGenBlobId::NUM_BLOBIDS] = { - STUBGEN_BLOBS_DO(DEFINE_BLOB_NAME) -}; - -#undef DEFINE_BLOB_NAME - -#define DEFINE_STUB_NAME(blob_name, stub_name) \ - # stub_name , \ - -// use a template to generate the initializer for the stub names array -const char* StubRoutines::_stub_names[StubGenStubId::NUM_STUBIDS] = { - STUBGEN_STUBS_DO(DEFINE_STUB_NAME) -}; - -#undef DEFINE_STUB_NAME - // Define fields used to store blobs -#define DEFINE_BLOB_FIELD(blob_name) \ +#define DEFINE_STUBGEN_BLOB_FIELD(blob_name) \ BufferBlob* StubRoutines:: STUBGEN_BLOB_FIELD_NAME(blob_name) = nullptr; -STUBGEN_BLOBS_DO(DEFINE_BLOB_FIELD) +STUBGEN_BLOBS_DO(DEFINE_STUBGEN_BLOB_FIELD) -#undef DEFINE_BLOB_FIELD +#undef DEFINE_STUBGEN_BLOB_FIELD -// Define fields used to store stub entries +// Define fields used to store stubgen stub entries -#define DEFINE_ENTRY_FIELD(blob_name, stub_name, field_name, getter_name) \ +#define DEFINE_STUBGEN_ENTRY_FIELD(blob_name, stub_name, field_name, getter_name) \ address StubRoutines:: STUB_FIELD_NAME(field_name) = nullptr; -#define DEFINE_ENTRY_FIELD_INIT(blob_name, stub_name, field_name, getter_name, init_function) \ +#define DEFINE_STUBGEN_ENTRY_FIELD_INIT(blob_name, stub_name, field_name, getter_name, init_function) \ address StubRoutines:: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function); -#define DEFINE_ENTRY_FIELD_ARRAY(blob_name, stub_name, field_name, getter_name, count) \ +#define DEFINE_STUBGEN_ENTRY_FIELD_ARRAY(blob_name, stub_name, field_name, getter_name, count) \ address StubRoutines:: STUB_FIELD_NAME(field_name)[count] = { nullptr }; -STUBGEN_ENTRIES_DO(DEFINE_ENTRY_FIELD, DEFINE_ENTRY_FIELD_INIT, DEFINE_ENTRY_FIELD_ARRAY) +STUBGEN_ENTRIES_DO(DEFINE_STUBGEN_ENTRY_FIELD, DEFINE_STUBGEN_ENTRY_FIELD_INIT, DEFINE_STUBGEN_ENTRY_FIELD_ARRAY) -#undef DEFINE_ENTRY_FIELD_ARRAY -#undef DEFINE_ENTRY_FIELD_INIT -#undef DEFINE_ENTRY_FIELD +#undef DEFINE_STUBGEN_ENTRY_FIELD_ARRAY +#undef DEFINE_STUBGEN_ENTRY_FIELD_INIT +#undef DEFINE_STUBGEN_ENTRY_FIELD jint StubRoutines::_verify_oop_count = 0; address StubRoutines::_string_indexof_array[4] = { nullptr }; -const char* StubRoutines::get_blob_name(StubGenBlobId id) { - assert(0 <= id && id < StubGenBlobId::NUM_BLOBIDS, "invalid blob id"); - return _blob_names[id]; +const char* StubRoutines::get_blob_name(BlobId id) { + assert(StubInfo::is_stubgen(id), "not a stubgen blob %s", StubInfo::name(id)); + return StubInfo::name(id); } -const char* StubRoutines::get_stub_name(StubGenStubId id) { - assert(0 <= id && id < StubGenStubId::NUM_STUBIDS, "invalid stub id"); - return _stub_names[id]; +const char* StubRoutines::get_stub_name(StubId id) { + assert(StubInfo::is_stubgen(id), "not a stubgen stub %s", StubInfo::name(id)); + return StubInfo::name(id); } #ifdef ASSERT +// translate a stub id to an associated blob id while checking that it +// is a stubgen stub -// array holding start and end indices for stub ids associated with a -// given blob. Given a blob with id (StubGenBlobId) blob_id for any -// stub with id (StubGenStubId) stub_id declared within the blob: -// _blob_offsets[blob_id] <= stub_id < _blob_offsets[blob_id+1] - -static int _blob_limits[StubGenBlobId::NUM_BLOBIDS + 1]; - -// macro used to compute blob limits -#define BLOB_COUNT(blob_name) \ - counter += StubGenStubId_ ## blob_name :: NUM_STUBIDS_ ## blob_name; \ - _blob_limits[++index] = counter; \ - -// macro that checks stubs are associated with the correct blobs -#define STUB_VERIFY(blob_name, stub_name) \ - localStubId = (int) (StubGenStubId_ ## blob_name :: blob_name ## _ ## stub_name ## _id); \ - globalStubId = (int) (StubGenStubId:: stub_name ## _id); \ - blobId = (int) (StubGenBlobId:: blob_name ## _id); \ - assert((globalStubId >= _blob_limits[blobId] && \ - globalStubId < _blob_limits[blobId+1]), \ - "stub " # stub_name " uses incorrect blob name " # blob_name); \ - assert(globalStubId == _blob_limits[blobId] + localStubId, \ - "stub " # stub_name " id found at wrong offset!"); \ - -bool verifyStubIds() { - // first compute the blob limits - int counter = 0; - int index = 0; - // populate offsets table with cumulative total of local enum counts - STUBGEN_BLOBS_DO(BLOB_COUNT); - - // ensure 1) global stub ids lie in the range of the associated blob - // and 2) each blob's base + local stub id == global stub id - int globalStubId, blobId, localStubId; - STUBGEN_STUBS_DO(STUB_VERIFY); - return true; -} - -#undef BLOB_COUNT -#undef STUB_VERIFY - -// ensure we verify the blob ids when this compile unit is first entered -bool _verified_stub_ids = verifyStubIds(); - - -// macro used by stub to blob translation - -#define BLOB_CHECK_OFFSET(blob_name) \ - if (id < _blob_limits[((int)blobId) + 1]) { return blobId; } \ - blobId = StubGenBlobId:: blob_name ## _id; \ - -// translate a global stub id to an associated blob id based on the -// computed blob limits - -StubGenBlobId StubRoutines::stub_to_blob(StubGenStubId stubId) { - int id = (int)stubId; - assert(id > ((int)StubGenStubId::NO_STUBID) && id < ((int)StubGenStubId::NUM_STUBIDS), "stub id out of range!"); - // start with no blob to catch stub id == -1 - StubGenBlobId blobId = StubGenBlobId::NO_BLOBID; - STUBGEN_BLOBS_DO(BLOB_CHECK_OFFSET); - // if we reach here we should have the last blob id - assert(blobId == StubGenBlobId::NUM_BLOBIDS - 1, "unexpected blob id"); - return blobId; +BlobId StubRoutines::stub_to_blob(StubId id) { + assert(StubInfo::is_stubgen(id), "not a stubgen stub %s", StubInfo::name(id)); + return StubInfo::blob(id); } #endif // ASSERT @@ -187,7 +107,7 @@ address StubRoutines::_store_inline_type_fields_to_buf = nullptr; // Initialization -extern void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id); // only interface to generators +extern void StubGenerator_generate(CodeBuffer* code, BlobId blob_id); // only interface to generators void UnsafeMemoryAccess::create_table(int max_size) { UnsafeMemoryAccess::_table = new UnsafeMemoryAccess[max_size]; @@ -217,11 +137,12 @@ address UnsafeMemoryAccess::page_error_continue_pc(address pc) { } -static BufferBlob* initialize_stubs(StubGenBlobId blob_id, +static BufferBlob* initialize_stubs(BlobId blob_id, int code_size, int max_aligned_stubs, const char* timer_msg, const char* buffer_name, const char* assert_msg) { + assert(StubInfo::is_stubgen(blob_id), "not a stubgen blob %s", StubInfo::name(blob_id)); ResourceMark rm; if (code_size == 0) { LogTarget(Info, stubs) lt; @@ -257,11 +178,11 @@ static BufferBlob* initialize_stubs(StubGenBlobId blob_id, #define DEFINE_BLOB_INIT_METHOD(blob_name) \ void StubRoutines::initialize_ ## blob_name ## _stubs() { \ if (STUBGEN_BLOB_FIELD_NAME(blob_name) == nullptr) { \ - StubGenBlobId blob_id = StubGenBlobId:: STUB_ID_NAME(blob_name); \ + BlobId blob_id = BlobId:: JOIN3(stubgen, blob_name, id); \ int size = _ ## blob_name ## _code_size; \ int max_aligned_size = 10; \ const char* timer_msg = "StubRoutines generation " # blob_name " stubs"; \ - const char* name = "StubRoutines (" # blob_name "stubs)"; \ + const char* name = "StubRoutines (" # blob_name " stubs)"; \ const char* assert_msg = "_" # blob_name "_code_size"; \ STUBGEN_BLOB_FIELD_NAME(blob_name) = \ initialize_stubs(blob_id, size, max_aligned_size, timer_msg, \ @@ -276,9 +197,9 @@ STUBGEN_BLOBS_DO(DEFINE_BLOB_INIT_METHOD) #define DEFINE_BLOB_INIT_FUNCTION(blob_name) \ -void blob_name ## _stubs_init() { \ - StubRoutines::initialize_ ## blob_name ## _stubs(); \ -} + void blob_name ## _stubs_init() { \ + StubRoutines::initialize_ ## blob_name ## _stubs(); \ + } STUBGEN_BLOBS_DO(DEFINE_BLOB_INIT_FUNCTION) @@ -288,7 +209,7 @@ STUBGEN_BLOBS_DO(DEFINE_BLOB_INIT_FUNCTION) * we generate the underlying driver method but this wrapper is needed * to perform special handling depending on where the compiler init * gets called from. it ought to be possible to remove this at some - * point and have adeterminate ordered init. + * point and have a determinate ordered init. */ void compiler_stubs_init(bool in_compiler_thread) { @@ -306,7 +227,6 @@ void compiler_stubs_init(bool in_compiler_thread) { } } - // // Default versions of arraycopy functions // diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp index ca8c669fdf8..2242b7f09a9 100644 --- a/src/hotspot/share/runtime/stubRoutines.hpp +++ b/src/hotspot/share/runtime/stubRoutines.hpp @@ -31,7 +31,7 @@ #include "runtime/frame.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/stubCodeGenerator.hpp" -#include "runtime/stubDeclarations.hpp" +#include "runtime/stubInfo.hpp" #include "runtime/threadWXSetters.inline.hpp" #include "utilities/macros.hpp" @@ -151,51 +151,6 @@ class UnsafeMemoryAccessMark : public StackObj { ~UnsafeMemoryAccessMark(); }; -// declare stubgen blob id enum - -#define BLOB_ENUM_DECLARE(blob_name) \ - STUB_ID_NAME(blob_name), - -enum StubGenBlobId : int { - NO_BLOBID = -1, - STUBGEN_BLOBS_DO(BLOB_ENUM_DECLARE) - NUM_BLOBIDS -}; - -#undef BLOB_ENUM_DECLARE - -// declare blob local stub id enums - -#define BLOB_LOCAL_ENUM_START(blob_name) \ - enum StubGenStubId_ ## blob_name { \ - NO_STUBID_ ## blob_name = -1, - -#define BLOB_LOCAL_ENUM_END(blob_name) \ - NUM_STUBIDS_ ## blob_name \ - }; - -#define BLOB_LOCAL_STUB_ENUM_DECLARE(blob_name, stub_name) \ - blob_name ## _ ## stub_name ## _id, - -STUBGEN_BLOBS_STUBS_DO(BLOB_LOCAL_ENUM_START, BLOB_LOCAL_ENUM_END, BLOB_LOCAL_STUB_ENUM_DECLARE) - -#undef BLOB_LOCAL_ENUM_START -#undef BLOB_LOCAL_ENUM_END -#undef BLOB_LOCAL_STUB_ENUM_DECLARE - -// declare global stub id enum - -#define STUB_ENUM_DECLARE(blob_name, stub_name) \ - STUB_ID_NAME(stub_name) , - -enum StubGenStubId : int { - NO_STUBID = -1, - STUBGEN_STUBS_DO(STUB_ENUM_DECLARE) - NUM_STUBIDS -}; - -#undef STUB_ENUM_DECLARE - class StubRoutines: AllStatic { public: @@ -208,17 +163,8 @@ class StubRoutines: AllStatic { #include CPU_HEADER(stubRoutines) -// declare blob and stub name storage and associated lookup methods - -private: - static bool _inited_names; - static const char* _blob_names[StubGenBlobId::NUM_BLOBIDS]; - static const char* _stub_names[StubGenStubId::NUM_STUBIDS]; - -public: - static bool init_names(); - static const char* get_blob_name(StubGenBlobId id); - static const char* get_stub_name(StubGenStubId id); + static const char* get_blob_name(BlobId id); + static const char* get_stub_name(StubId id); // declare blob fields @@ -332,8 +278,7 @@ class StubRoutines: AllStatic { #undef DEFINE_BLOB_GETTER #ifdef ASSERT - // provide a translation from stub id to its associated blob id - static StubGenBlobId stub_to_blob(StubGenStubId stubId); + static BlobId stub_to_blob(StubId id); #endif // Debugging diff --git a/src/hotspot/share/runtime/suspendResumeManager.cpp b/src/hotspot/share/runtime/suspendResumeManager.cpp index fd14f73f553..2e75d763cb3 100644 --- a/src/hotspot/share/runtime/suspendResumeManager.cpp +++ b/src/hotspot/share/runtime/suspendResumeManager.cpp @@ -35,9 +35,9 @@ // This is the closure that prevents a suspended JavaThread from // escaping the suspend request. -class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure { +class ThreadSelfSuspensionHandshakeClosure : public AsyncHandshakeClosure { public: - ThreadSelfSuspensionHandshake() : AsyncHandshakeClosure("ThreadSelfSuspensionHandshake") {} + ThreadSelfSuspensionHandshakeClosure() : AsyncHandshakeClosure("ThreadSelfSuspensionHandshakeClosure") {} void do_thread(Thread* thr) { JavaThread* current = JavaThread::cast(thr); assert(current == Thread::current(), "Must be self executed."); @@ -52,11 +52,11 @@ class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure { }; // This is the closure that synchronously honors the suspend request. -class SuspendThreadHandshake : public HandshakeClosure { +class SuspendThreadHandshakeClosure : public HandshakeClosure { bool _register_vthread_SR; bool _did_suspend; public: - SuspendThreadHandshake(bool register_vthread_SR) : HandshakeClosure("SuspendThread"), + SuspendThreadHandshakeClosure(bool register_vthread_SR) : HandshakeClosure("SuspendThread"), _register_vthread_SR(register_vthread_SR), _did_suspend(false) { } void do_thread(Thread* thr) { @@ -93,7 +93,7 @@ bool SuspendResumeManager::suspend(bool register_vthread_SR) { do_owner_suspend(); return true; } else { - SuspendThreadHandshake st(register_vthread_SR); + SuspendThreadHandshakeClosure st(register_vthread_SR); Handshake::execute(&st, _target); return st.did_suspend(); } @@ -150,7 +150,7 @@ bool SuspendResumeManager::suspend_with_handshake(bool register_vthread_SR) { set_suspended(true, register_vthread_SR); set_async_suspend_handshake(true); log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended, arming ThreadSuspension", p2i(_target)); - ThreadSelfSuspensionHandshake* ts = new ThreadSelfSuspensionHandshake(); + ThreadSelfSuspensionHandshakeClosure* ts = new ThreadSelfSuspensionHandshakeClosure(); Handshake::execute(ts, _target); return true; } diff --git a/src/hotspot/share/runtime/suspendResumeManager.hpp b/src/hotspot/share/runtime/suspendResumeManager.hpp index fed3b34055e..01735cb3bf8 100644 --- a/src/hotspot/share/runtime/suspendResumeManager.hpp +++ b/src/hotspot/share/runtime/suspendResumeManager.hpp @@ -25,12 +25,12 @@ #ifndef SHARE_RUNTIME_SUSPENDRESUMEMANAGER_HPP #define SHARE_RUNTIME_SUSPENDRESUMEMANAGER_HPP -class SuspendThreadHandshake; -class ThreadSelfSuspensionHandshake; +class SuspendThreadHandshakeClosure; +class ThreadSelfSuspensionHandshakeClosure; class SuspendResumeManager { - friend SuspendThreadHandshake; - friend ThreadSelfSuspensionHandshake; + friend SuspendThreadHandshakeClosure; + friend ThreadSelfSuspensionHandshakeClosure; friend JavaThread; JavaThread* _target; diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 91108e1956a..cd7326bfd2b 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1713,12 +1713,12 @@ size_t ObjectSynchronizer::deflate_monitor_list(ObjectMonitorDeflationSafepointe return deflated_count; } -class HandshakeForDeflation : public HandshakeClosure { +class DeflationHandshakeClosure : public HandshakeClosure { public: - HandshakeForDeflation() : HandshakeClosure("HandshakeForDeflation") {} + DeflationHandshakeClosure() : HandshakeClosure("DeflationHandshakeClosure") {} void do_thread(Thread* thread) { - log_trace(monitorinflation)("HandshakeForDeflation::do_thread: thread=" + log_trace(monitorinflation)("DeflationHandshakeClosure::do_thread: thread=" INTPTR_FORMAT, p2i(thread)); if (thread->is_Java_thread()) { // Clear OM cache @@ -1883,8 +1883,8 @@ size_t ObjectSynchronizer::deflate_idle_monitors() { // A JavaThread needs to handshake in order to safely free the // ObjectMonitors that were deflated in this cycle. - HandshakeForDeflation hfd_hc; - Handshake::execute(&hfd_hc); + DeflationHandshakeClosure dhc; + Handshake::execute(&dhc); // Also, we sync and desync GC threads around the handshake, so that they can // safely read the mark-word and look-through to the object-monitor, without // being afraid that the object-monitor is going away. diff --git a/src/hotspot/share/runtime/threadSMR.cpp b/src/hotspot/share/runtime/threadSMR.cpp index bcfd950ee39..631a7ed8d79 100644 --- a/src/hotspot/share/runtime/threadSMR.cpp +++ b/src/hotspot/share/runtime/threadSMR.cpp @@ -1168,9 +1168,10 @@ void ThreadsSMRSupport::print_info_on(const Thread* thread, outputStream* st) { // The count is only interesting if we have a _threads_list_ptr. st->print(", _nested_threads_hazard_ptr_cnt=%u", thread->_nested_threads_hazard_ptr_cnt); } - if (SafepointSynchronize::is_at_safepoint() || Thread::current() == thread) { - // It is only safe to walk the list if we're at a safepoint or the - // calling thread is walking its own list. + if ((SafepointSynchronize::is_at_safepoint() && thread->is_Java_thread()) || + Thread::current() == thread) { + // It is only safe to walk the list if we're at a safepoint and processing a JavaThread, + // or the calling thread is walking its own list. SafeThreadsListPtr* current = thread->_threads_list_ptr; if (current != nullptr) { // Skip the top nesting level as it is always printed above. diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 3c8c883ea25..c68434a0cc9 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -44,6 +44,7 @@ #include "gc/shared/vmStructs_gc.hpp" #include "interpreter/bytecodes.hpp" #include "interpreter/interpreter.hpp" +#include "jfr/recorder/service/jfrRecorderThread.hpp" #include "logging/logAsyncWriter.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" @@ -1032,6 +1033,7 @@ declare_type(TrainingReplayThread, JavaThread) \ declare_type(StringDedupThread, JavaThread) \ declare_type(AttachListenerThread, JavaThread) \ + declare_type(JfrRecorderThread, JavaThread) \ DEBUG_ONLY(COMPILER2_OR_JVMCI_PRESENT( \ declare_type(DeoptimizeObjectsALotThread, JavaThread))) \ declare_toplevel_type(OSThread) \ diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index 0ff5e5d227b..1f8265484f1 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -24,6 +24,7 @@ #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/vmThreadCpuTimeScope.inline.hpp" #include "jfr/jfrEvents.hpp" #include "jfr/support/jfrThreadId.hpp" #include "logging/log.hpp" @@ -275,31 +276,25 @@ void VMThread::evaluate_operation(VM_Operation* op) { { PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time()); HOTSPOT_VMOPS_BEGIN( - (char *) op->name(), strlen(op->name()), + (char*) op->name(), strlen(op->name()), op->evaluate_at_safepoint() ? 0 : 1); EventExecuteVMOperation event; + VMThreadCPUTimeScope CPUTimeScope(this, op->is_gc_operation()); op->evaluate(); if (event.should_commit()) { post_vm_operation_event(&event, op); } HOTSPOT_VMOPS_END( - (char *) op->name(), strlen(op->name()), + (char*) op->name(), strlen(op->name()), op->evaluate_at_safepoint() ? 0 : 1); } - - if (UsePerfData && os::is_thread_cpu_time_supported()) { - assert(Thread::current() == this, "Must be called from VM thread"); - // Update vm_thread_cpu_time after each VM operation. - ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::vm); - tttc.do_thread(this); - } } -class HandshakeALotClosure : public HandshakeClosure { +class ALotOfHandshakeClosure : public HandshakeClosure { public: - HandshakeALotClosure() : HandshakeClosure("HandshakeALot") {} + ALotOfHandshakeClosure() : HandshakeClosure("ALotOfHandshakeClosure") {} void do_thread(Thread* thread) { #ifdef ASSERT JavaThread::cast(thread)->verify_states_for_handshake(); @@ -453,8 +448,8 @@ void VMThread::wait_for_operation() { if (handshake_or_safepoint_alot()) { if (HandshakeALot) { MutexUnlocker mul(VMOperation_lock); - HandshakeALotClosure hal_cl; - Handshake::execute(&hal_cl); + ALotOfHandshakeClosure aohc; + Handshake::execute(&aohc); } // When we unlocked above someone might have setup a new op. if (_next_vm_operation != nullptr) { diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index 8e0c955bff8..f30b0c170a6 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -1124,7 +1124,7 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, // jdk.internal.vm.ThreadSnapshot support #if INCLUDE_JVMTI -class GetThreadSnapshotClosure: public HandshakeClosure { +class GetThreadSnapshotHandshakeClosure: public HandshakeClosure { private: static OopStorage* oop_storage() { assert(_thread_service_storage != nullptr, "sanity"); @@ -1180,14 +1180,14 @@ class GetThreadSnapshotClosure: public HandshakeClosure { GrowableArray* _locks; Blocker _blocker; - GetThreadSnapshotClosure(Handle thread_h, JavaThread* java_thread): - HandshakeClosure("GetThreadSnapshotClosure"), + GetThreadSnapshotHandshakeClosure(Handle thread_h, JavaThread* java_thread): + HandshakeClosure("GetThreadSnapshotHandshakeClosure"), _thread_h(thread_h), _java_thread(java_thread), _frame_count(0), _methods(nullptr), _bcis(nullptr), _thread_status(), _thread_name(nullptr), _locks(nullptr), _blocker() { } - virtual ~GetThreadSnapshotClosure() { + virtual ~GetThreadSnapshotHandshakeClosure() { delete _methods; delete _bcis; _thread_name.release(oop_storage()); @@ -1439,7 +1439,17 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); - Handle thread_h(THREAD, JNIHandles::resolve(jthread)); + + JavaThread* java_thread = nullptr; + oop thread_oop; + bool has_javathread = tlh.cv_internal_thread_to_JavaThread(jthread, &java_thread, &thread_oop); + assert((has_javathread && thread_oop != nullptr) || !has_javathread, "Missing Thread oop"); + Handle thread_h(THREAD, thread_oop); + bool is_virtual = java_lang_VirtualThread::is_instance(thread_h()); // Deals with null + + if (!has_javathread && !is_virtual) { + return nullptr; // thread terminated so not of interest + } // wrapper to auto delete JvmtiVTMSTransitionDisabler class TransitionDisabler { @@ -1460,8 +1470,6 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) { } } transition_disabler; - JavaThread* java_thread = nullptr; - bool is_virtual = java_lang_VirtualThread::is_instance(thread_h()); Handle carrier_thread; if (is_virtual) { // 1st need to disable mount/unmount transitions @@ -1476,7 +1484,7 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) { } // Handshake with target - GetThreadSnapshotClosure cl(thread_h, java_thread); + GetThreadSnapshotHandshakeClosure cl(thread_h, java_thread); if (java_thread == nullptr) { // unmounted vthread, execute on the current thread cl.do_thread(nullptr); @@ -1508,7 +1516,7 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) { if (cl._locks != nullptr && cl._locks->length() > 0) { locks = oopFactory::new_objArray_handle(lock_klass, cl._locks->length(), CHECK_NULL); for (int n = 0; n < cl._locks->length(); n++) { - GetThreadSnapshotClosure::OwnedLock* lock_info = cl._locks->adr_at(n); + GetThreadSnapshotHandshakeClosure::OwnedLock* lock_info = cl._locks->adr_at(n); Handle lock = jdk_internal_vm_ThreadLock::create(lock_klass, lock_info->_frame_depth, lock_info->_type, lock_info->_obj, CHECK_NULL); diff --git a/src/hotspot/share/utilities/deferred.hpp b/src/hotspot/share/utilities/deferredStatic.hpp similarity index 61% rename from src/hotspot/share/utilities/deferred.hpp rename to src/hotspot/share/utilities/deferredStatic.hpp index a12ca571fe6..43d72d2af41 100644 --- a/src/hotspot/share/utilities/deferred.hpp +++ b/src/hotspot/share/utilities/deferredStatic.hpp @@ -22,17 +22,29 @@ * */ -#ifndef SHARE_UTILITIES_STABLEVALUE_HPP -#define SHARE_UTILITIES_STABLEVALUE_HPP +#ifndef SHARE_UTILITIES_DEFERREDSTATIC_HPP +#define SHARE_UTILITIES_DEFERREDSTATIC_HPP -#include "globalDefinitions.hpp" +#include "utilities/globalDefinitions.hpp" + +#include #include -// The purpose of this class is to defer initialization of a T to a later point in time, -// and then to never deallocate it. This is mainly useful for deferring the initialization of -// static fields in classes, in order to avoid "Static Initialization Order Fiasco". +// The purpose of this class is to provide control over the initialization +// time for an object of type T with static storage duration. An instance of +// this class provides storage for an object, sized and aligned for T. The +// object must be explicitly initialized before use. This avoids problems +// resulting from the unspecified initialization time and ordering between +// different objects that comes from using undeferred objects (the so-called +// "Static Initialization Order Fiasco). +// +// Once initialized, the object is never destroyed. This avoids similar issues +// with the timing and ordering of destruction on normal program exit. +// +// T must not be a reference type. T may be cv-qualified; accessors will +// return a correspondingly cv-qualified reference to the object. template -class Deferred { +class DeferredStatic { union { T _t; }; @@ -40,14 +52,14 @@ class Deferred { DEBUG_ONLY(bool _initialized); public: - NONCOPYABLE(Deferred); + NONCOPYABLE(DeferredStatic); - Deferred() + DeferredStatic() DEBUG_ONLY(: _initialized(false)) { // Do not construct value, on purpose. } - ~Deferred() { + ~DeferredStatic() { // Do not destruct value, on purpose. } @@ -56,27 +68,14 @@ class Deferred { return &_t; } - const T* get() const { - assert(_initialized, "must be initialized before access"); - return &_t; - } - T& operator*() { return *get(); } - const T& operator*() const { - return *get(); - } - T* operator->() { return get(); } - const T* operator->() const { - return get(); - } - template void initialize(Ts&... args) { assert(!_initialized, "Double initialization forbidden"); @@ -86,4 +85,4 @@ class Deferred { } }; -#endif // SHARE_UTILITIES_STABLEVALUE_HPP +#endif // SHARE_UTILITIES_DEFERREDSTATIC_HPP diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index c48b33b1e1f..fd1a2930034 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -114,15 +114,17 @@ bool Exceptions::special_exception(JavaThread* thread, const char* file, int lin #endif // ASSERT if (h_exception.is_null() && !thread->can_call_java()) { - ResourceMark rm(thread); - const char* exc_value = h_name != nullptr ? h_name->as_C_string() : "null"; - log_info(exceptions)("Thread cannot call Java so instead of throwing exception <%.*s%s%.*s> (" PTR_FORMAT ") \n" - "at [%s, line %d]\nfor thread " PTR_FORMAT ",\n" - "throwing pre-allocated exception: %s", - MAX_LEN, exc_value, message ? ": " : "", - MAX_LEN, message ? message : "", - p2i(h_exception()), file, line, p2i(thread), - Universe::vm_exception()->print_value_string()); + if (log_is_enabled(Info, exceptions)) { + ResourceMark rm(thread); + const char* exc_value = h_name != nullptr ? h_name->as_C_string() : "null"; + log_info(exceptions)("Thread cannot call Java so instead of throwing exception <%.*s%s%.*s> (" PTR_FORMAT ") \n" + "at [%s, line %d]\nfor thread " PTR_FORMAT ",\n" + "throwing pre-allocated exception: %s", + MAX_LEN, exc_value, message ? ": " : "", + MAX_LEN, message ? message : "", + p2i(h_exception()), file, line, p2i(thread), + Universe::vm_exception()->print_value_string()); + } // We do not care what kind of exception we get for a thread which // is compiling. We just install a dummy exception object thread->set_pending_exception(Universe::vm_exception(), file, line); @@ -152,6 +154,9 @@ void Exceptions::_throw(JavaThread* thread, const char* file, int line, Handle h message ? ": " : "", MAX_LEN, message ? message : "", p2i(h_exception()), file, line, p2i(thread)); + if (log_is_enabled(Info, exceptions, stacktrace)) { + log_exception_stacktrace(h_exception); + } // for AbortVMOnException flag Exceptions::debug_check_abort(h_exception, message); @@ -609,3 +614,42 @@ void Exceptions::log_exception(Handle exception, const char* message) { MAX_LEN, message); } } + +// This is called from InterpreterRuntime::exception_handler_for_exception(), which is the only +// easy way to be notified in the VM that an _athrow bytecode has been executed. (The alternative +// would be to add hooks into the interpreter and compiler, for all platforms ...). +// +// Unfortunately, InterpreterRuntime::exception_handler_for_exception() is called for every level +// of the Java stack when looking for an exception handler. To avoid excessive output, +// we print the stack only when the bci points to an _athrow bytecode. +// +// NOTE: exceptions that are NOT thrown by _athrow are handled by Exceptions::special_exception() +// and Exceptions::_throw()). +void Exceptions::log_exception_stacktrace(Handle exception, methodHandle method, int bci) { + if (!method->is_native() && (Bytecodes::Code) *method->bcp_from(bci) == Bytecodes::_athrow) { + // TODO: try to find a way to avoid repeated stacktraces when an exception gets re-thrown + // by a finally block + log_exception_stacktrace(exception); + } +} + +// This should be called only from a live Java thread. +void Exceptions::log_exception_stacktrace(Handle exception) { + LogStreamHandle(Info, exceptions, stacktrace) st; + ResourceMark rm; + const char* detail_message = java_lang_Throwable::message_as_utf8(exception()); + if (detail_message != nullptr) { + st.print_cr("Exception <%.*s: %.*s>", + MAX_LEN, exception->print_value_string(), + MAX_LEN, detail_message); + } else { + st.print_cr("Exception <%.*s>", + MAX_LEN, exception->print_value_string()); + } + JavaThread* t = JavaThread::current(); + if (t->has_last_Java_frame()) { + t->print_active_stack_on(&st); + } else { + st.print_cr("(Cannot print stracktrace)"); + } +} diff --git a/src/hotspot/share/utilities/exceptions.hpp b/src/hotspot/share/utilities/exceptions.hpp index b6b6265b1bb..f0c2e9fff10 100644 --- a/src/hotspot/share/utilities/exceptions.hpp +++ b/src/hotspot/share/utilities/exceptions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -190,6 +190,8 @@ class Exceptions { // for logging exceptions static void log_exception(Handle exception, const char* message); + static void log_exception_stacktrace(Handle exception); + static void log_exception_stacktrace(Handle exception, methodHandle method, int bci); }; diff --git a/src/hotspot/share/utilities/globalDefinitions.cpp b/src/hotspot/share/utilities/globalDefinitions.cpp index 0765f781ada..29720b1ecf7 100644 --- a/src/hotspot/share/utilities/globalDefinitions.cpp +++ b/src/hotspot/share/utilities/globalDefinitions.cpp @@ -56,6 +56,8 @@ int LogMinObjAlignmentInBytes = -1; // Oop encoding heap max uint64_t OopEncodingHeapMax = 0; +const int LockingMode = LM_LIGHTWEIGHT; + // Something to help porters sleep at night #ifdef ASSERT diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 22e8fbade6e..d4f6fcefb72 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -1022,6 +1022,8 @@ enum LockingMode { LM_LIGHTWEIGHT = 2 }; +extern const int LockingMode; + //---------------------------------------------------------------------------------------------------- // Special constants for debugging diff --git a/src/hotspot/share/utilities/packedTable.hpp b/src/hotspot/share/utilities/packedTable.hpp index ed08a2b4c21..1266c65cbf1 100644 --- a/src/hotspot/share/utilities/packedTable.hpp +++ b/src/hotspot/share/utilities/packedTable.hpp @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_UTILITIES_PACKEDTABLE_HPP +#define SHARE_UTILITIES_PACKEDTABLE_HPP + #include "oops/array.hpp" #include "utilities/globalDefinitions.hpp" @@ -121,3 +124,5 @@ class PackedTableLookup: public PackedTableBase { } } }; + +#endif // SHARE_UTILITIES_PACKEDTABLE_HPP diff --git a/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java b/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java index 5c5c7a1865a..fabd2086fa5 100644 --- a/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java +++ b/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013 SAP SE. All rights reserved. + * Copyright (c) 2013, 2025 SAP SE. 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 @@ -52,6 +52,15 @@ AixFileStore getFileStore(UnixPath path) throws IOException { return new AixFileStore(path); } + private static boolean supportsUserDefinedFileAttributeView(UnixPath file) { + try { + FileStore store = new AixFileStore(file); + return store.supportsFileAttributeView(UserDefinedFileAttributeView.class); + } catch (IOException e) { + return false; + } + } + @Override @SuppressWarnings("unchecked") public V getFileAttributeView(Path obj, @@ -59,8 +68,10 @@ public V getFileAttributeView(Path obj, LinkOption... options) { if (type == UserDefinedFileAttributeView.class) { - return (V) new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), - Util.followLinks(options)); + UnixPath file = UnixPath.toUnixPath(obj); + return supportsUserDefinedFileAttributeView(file) ? + (V) new AixUserDefinedFileAttributeView(file, Util.followLinks(options)) + : null; } return super.getFileAttributeView(obj, type, options); } @@ -71,8 +82,10 @@ public DynamicFileAttributeView getFileAttributeView(Path obj, LinkOption... options) { if (name.equals("user")) { - return new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), - Util.followLinks(options)); + UnixPath file = UnixPath.toUnixPath(obj); + return supportsUserDefinedFileAttributeView(file) ? + new AixUserDefinedFileAttributeView(file, Util.followLinks(options)) + : null; } return super.getFileAttributeView(obj, name, options); } diff --git a/src/java.base/macosx/native/libjava/java_props_macosx.c b/src/java.base/macosx/native/libjava/java_props_macosx.c index 07bc2be9d54..6656bf04efc 100644 --- a/src/java.base/macosx/native/libjava/java_props_macosx.c +++ b/src/java.base/macosx/native/libjava/java_props_macosx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -23,6 +23,7 @@ * questions. */ +#include #include #include #include @@ -229,33 +230,50 @@ void setOSNameAndVersion(java_props_t *sprops) { NSString *nsVerStr = NULL; char* osVersionCStr = NULL; NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion]; - // Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x) - // or explicitly requesting version compatibility - if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) || - (getenv("SYSTEM_VERSION_COMPAT") != NULL)) { - if (osVer.patchVersion == 0) { // Omit trailing ".0" + // Some macOS versions require special handling. For example, + // when the NSOperatingSystemVersion reports 10.16 as the version + // then it should be treated as 11. Similarly, when it reports 16.0 + // as the version then it should be treated as 26. + // If the SYSTEM_VERSION_COMPAT environment variable (a macOS construct) + // is set to 1, then we don't do any special handling for any versions + // and just literally use the value that NSOperatingSystemVersion reports. + const char* envVal = getenv("SYSTEM_VERSION_COMPAT"); + const bool versionCompatEnabled = envVal != NULL + && strncmp(envVal, "1", 1) == 0; + const bool requiresSpecialHandling = + ((long) osVer.majorVersion == 10 && (long) osVer.minorVersion >= 16) + || ((long) osVer.majorVersion == 16 && (long) osVer.minorVersion >= 0); + if (!requiresSpecialHandling || versionCompatEnabled) { + // no special handling - just use the version reported + // by NSOperatingSystemVersion + if (osVer.patchVersion == 0) { + // Omit trailing ".0" nsVerStr = [NSString stringWithFormat:@"%ld.%ld", (long)osVer.majorVersion, (long)osVer.minorVersion]; } else { nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", - (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; + (long)osVer.majorVersion, (long)osVer.minorVersion, + (long)osVer.patchVersion]; } } else { - // Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT - // AKA 11+ Read the *real* ProductVersion from the hidden link to avoid SYSTEM_VERSION_COMPAT - // If not found, fallback below to the SystemVersion.plist - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : - @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; + // Requires special handling. We ignore the version reported + // by the NSOperatingSystemVersion API and instead read the + // *real* ProductVersion from + // /System/Library/CoreServices/.SystemVersionPlatform.plist. + // If not found there, then as a last resort we fallback to + // /System/Library/CoreServices/SystemVersion.plist + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey : @"ProductVersion"]; + nsVerStr = [version objectForKey: @"ProductVersion"]; } } - // Fallback to reading the SystemVersion.plist + // Last resort - fallback to reading the SystemVersion.plist if (nsVerStr == NULL) { - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : - @"/System/Library/CoreServices/SystemVersion.plist"]; + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey : @"ProductVersion"]; + nsVerStr = [version objectForKey: @"ProductVersion"]; } } diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 9c9fbc837db..468d138657b 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -1134,8 +1134,14 @@ public File[] listFiles() { if (ss == null) return null; int n = ss.length; File[] fs = new File[n]; - for (int i = 0; i < n; i++) { - fs[i] = new File(ss[i], this); + if (path.isEmpty()) { + for (int i = 0; i < n; i++) { + fs[i] = new File(ss[i]); + } + } else { + for (int i = 0; i < n; i++) { + fs[i] = new File(ss[i], this); + } } return fs; } diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index 339030e022c..a7aa3ea358b 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -1030,17 +1030,32 @@ public final double readDouble() throws IOException { */ public final String readLine() throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + long bytesRead = 0; + long start = FileReadEvent.timestamp(); + try { + String result = implReadLine(); + bytesRead = result == null ? 0 : result.length(); + return result; + } finally { + FileReadEvent.offer(start, path, bytesRead); + } + } + return implReadLine(); + } + + private final String implReadLine() throws IOException { StringBuilder input = new StringBuilder(); int c = -1; boolean eol = false; while (!eol) { - switch (c = read()) { + switch (c = read0()) { case -1, '\n' -> eol = true; case '\r' -> { eol = true; long cur = getFilePointer(); - if ((read()) != '\n') { + if ((read0()) != '\n') { seek(cur); } } diff --git a/src/java.base/share/classes/java/io/Reader.java b/src/java.base/share/classes/java/io/Reader.java index af5ac9f68ec..9656d140023 100644 --- a/src/java.base/share/classes/java/io/Reader.java +++ b/src/java.base/share/classes/java/io/Reader.java @@ -27,8 +27,11 @@ import java.nio.CharBuffer; import java.nio.ReadOnlyBufferException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; +import jdk.internal.util.ArraysSupport; /** * Abstract class for reading character streams. The only methods that a @@ -397,16 +400,6 @@ public int read(char[] cbuf) throws IOException { */ public abstract int read(char[] cbuf, int off, int len) throws IOException; - private String readAllCharsAsString() throws IOException { - StringBuilder result = new StringBuilder(); - char[] cbuf = new char[TRANSFER_BUFFER_SIZE]; - int nread; - while ((nread = read(cbuf, 0, cbuf.length)) != -1) { - result.append(cbuf, 0, nread); - } - return result.toString(); - } - /** * Reads all remaining characters as lines of text. This method blocks until * all remaining characters have been read and end of stream is detected, @@ -457,7 +450,57 @@ private String readAllCharsAsString() throws IOException { * @since 25 */ public List readAllLines() throws IOException { - return readAllCharsAsString().lines().toList(); + List lines = new ArrayList<>(); + char[] cb = new char[1024]; + + int start = 0; + int pos = 0; + int limit = 0; + boolean skipLF = false; + int n; + while ((n = read(cb, pos, cb.length - pos)) != -1) { + limit = pos + n; + while (pos < limit) { + if (skipLF) { + if (cb[pos] == '\n') { + pos++; + start++; + } + skipLF = false; + } + while (pos < limit) { + char c = cb[pos++]; + if (c == '\n' || c == '\r') { + lines.add(new String(cb, start, pos - 1 - start)); + skipLF = (c == '\r'); + start = pos; + break; + } + } + if (pos == limit) { + int len = limit - start; + if (len >= cb.length/2) { + // allocate larger buffer and copy chars to beginning + int newLength = ArraysSupport.newLength(cb.length, + TRANSFER_BUFFER_SIZE, cb.length); + char[] tmp = new char[newLength]; + System.arraycopy(cb, start, tmp, 0, len); + cb = tmp; + } else if (start != 0 && len != 0) { + // move fragment to beginning of buffer + System.arraycopy(cb, start, cb, 0, len); + } + pos = limit = len; + start = 0; + break; + } + } + } + // add a string if EOS terminates the last line + if (limit > start) + lines.add(new String(cb, start, limit - start)); + + return Collections.unmodifiableList(lines); } /** @@ -499,7 +542,13 @@ public List readAllLines() throws IOException { * @since 25 */ public String readAllAsString() throws IOException { - return readAllCharsAsString(); + StringBuilder result = new StringBuilder(); + char[] cbuf = new char[TRANSFER_BUFFER_SIZE]; + int nread; + while ((nread = read(cbuf, 0, cbuf.length)) != -1) { + result.append(cbuf, 0, nread); + } + return result.toString(); } /** Maximum skip-buffer size */ diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 98cf4ea433a..493498bad13 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -118,11 +118,9 @@ * fixed-width 16-bit entities. The Unicode Standard has since been * changed to allow for characters whose representation requires more * than 16 bits. The range of legal code points is now - * U+0000 to U+10FFFF, known as Unicode scalar value. - * (Refer to the - * definition of the U+n notation in the Unicode - * Standard.) + * U+0000 to U+10FFFF, known as + * + * Unicode scalar value. * *

The set of characters from U+0000 to U+FFFF is * sometimes referred to as the Basic Multilingual Plane (BMP). @@ -182,7 +180,7 @@ * * * - * @spec https://www.unicode.org/reports/tr27 Unicode 3.1.0 + * @spec https://www.unicode.org/reports/tr44 Unicode Character Database * @author Lee Boynton * @author Guy Steele * @author Akira Tanaka diff --git a/src/java.base/share/classes/java/lang/Process.java b/src/java.base/share/classes/java/lang/Process.java index 3e4837d2e02..0a55343926f 100644 --- a/src/java.base/share/classes/java/lang/Process.java +++ b/src/java.base/share/classes/java/lang/Process.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -41,7 +41,7 @@ /** * {@code Process} provides control of native processes started by - * ProcessBuilder.start and Runtime.exec. + * {@code ProcessBuilder.start} and {@code Runtime.exec}. * The class provides methods for performing input from the process, performing * output to the process, waiting for the process to complete, * checking the exit status of the process, and destroying (killing) @@ -78,10 +78,6 @@ * process I/O can also be redirected * using methods of the {@link ProcessBuilder} class. * - *

The process is not killed when there are no more references to - * the {@code Process} object, but rather the process - * continues executing asynchronously. - * *

There is no requirement that the process represented by a {@code * Process} object execute asynchronously or concurrently with respect * to the Java process that owns the {@code Process} object. @@ -98,6 +94,49 @@ * Delegating to the underlying Process or ProcessHandle is typically * easiest and most efficient. * + *

Resource Usage

+ * {@linkplain ProcessBuilder#start() Starting a process} uses resources in both the invoking process and the invoked + * process and for the communication streams between them. + * The resources to control the process and for communication between the processes are retained + * until there are no longer any references to the Process or the input, error, and output streams + * or readers, or they have been closed. + * + *

The process is not killed when there are no more references to the {@code Process} object, + * but rather the process continues executing asynchronously. + * The process implementation closes file descriptors and handles for streams + * that are no longer referenced to prevent leaking operating system resources. + * Processes that have terminated or been terminated are monitored and their resources released. + * + *

Streams should be {@code closed} when they are no longer needed, to avoid delaying + * releasing the operating system resources. + * {@code Try-with-resources} can be used to open and close the streams. + *

For example, to capture the output of a program known to produce some output and then exit: + * {@snippet lang = "java" : + * List capture(List args) throws Exception { + * ProcessBuilder pb = new ProcessBuilder(args); + * Process process = pb.start(); + * try (BufferedReader in = process.inputReader()) { + * List captured = in.readAllLines(); + * int status = process.waitFor(); + * if (status != 0) { + * throw new RuntimeException("Process %d: %s failed with %d" + * .formatted(process.pid(), args, status)); + * } + * return captured; + * } + * } + * } + *

Stream resources (file descriptor or handle) are always paired; one in the invoking process + * and the other end of that connection in the invoked process. + * Closing a stream at either end terminates communication but does not have any direct effect + * on the other Process. The closing of the stream typically results in the other process exiting. + * + *

{@linkplain #destroy Destroying a process} signals the operating system to terminate the process. + * It is up to the operating system to clean up and release the resources of that process. + * Typically, file descriptors and handles are closed. When they are closed, any connections to + * other processes are terminated and file descriptors and handles in the invoking process signal + * end-of-file or closed. Usually, that is seen as an end-of-file or an exception. + * * @since 1.0 */ public abstract class Process { @@ -127,6 +166,9 @@ public Process() {} * then this method will return a * null output stream. * + *

The output stream should be {@linkplain OutputStream#close closed} + * when it is no longer needed. + * * @apiNote * When writing to both {@link #getOutputStream()} and either {@link #outputWriter()} * or {@link #outputWriter(Charset)}, {@link BufferedWriter#flush BufferedWriter.flush} @@ -159,9 +201,15 @@ public Process() {} * then the input stream returned by this method will receive the * merged standard output and the standard error of the process. * + *

The input stream should be {@linkplain InputStream#close closed} + * when it is no longer needed. + * * @apiNote - * Use {@link #getInputStream()} and {@link #inputReader()} with extreme care. - * The {@code BufferedReader} may have buffered input from the input stream. + * Use either this method or an {@linkplain #inputReader() input reader} + * but not both on the same {@code Process}. + * The input reader consumes and buffers bytes from the input stream. + * Bytes read from the input stream would not be seen by the reader and + * buffer contents are unpredictable. * * @implNote * Implementation note: It is a good idea for the returned @@ -185,9 +233,15 @@ public Process() {} * then this method will return a * null input stream. * + *

The error stream should be {@linkplain InputStream#close closed} + * when it is no longer needed. + * * @apiNote - * Use {@link #getErrorStream()} and {@link #errorReader()} with extreme care. - * The {@code BufferedReader} may have buffered input from the error stream. + * Use either this method or an {@linkplain #errorReader() error reader} + * but not both on the same {@code Process}. + * The error reader consumes and buffers bytes from the error stream. + * Bytes read from the error stream would not be seen by the reader and the + * buffer contents are unpredictable. * * @implNote * Implementation note: It is a good idea for the returned @@ -208,6 +262,16 @@ public Process() {} * If the {@code native.encoding} is not a valid charset name or not supported * the {@link Charset#defaultCharset()} is used. * + *

The reader should be {@linkplain BufferedReader#close closed} + * when it is no longer needed. + * + * @apiNote + * Use either this method or the {@linkplain #getInputStream input stream} + * but not both on the same {@code Process}. + * The input reader consumes and buffers bytes from the input stream. + * Bytes read from the input stream would not be seen by the reader and the + * buffer contents are unpredictable. + * * @return a {@link BufferedReader BufferedReader} using the * {@code native.encoding} if supported, otherwise, the * {@link Charset#defaultCharset()} @@ -238,6 +302,9 @@ public final BufferedReader inputReader() { * then the {@code InputStreamReader} will be reading from a * null input stream. * + *

The reader should be {@linkplain BufferedReader#close closed} + * when it is no longer needed. + * *

Otherwise, if the standard error of the process has been redirected using * {@link ProcessBuilder#redirectErrorStream(boolean) * ProcessBuilder.redirectErrorStream} then the input reader returned by @@ -245,9 +312,11 @@ public final BufferedReader inputReader() { * of the process. * * @apiNote - * Using both {@link #getInputStream} and {@link #inputReader(Charset)} has - * unpredictable behavior since the buffered reader reads ahead from the - * input stream. + * Use either this method or the {@linkplain #getInputStream input stream} + * but not both on the same {@code Process}. + * The input reader consumes and buffers bytes from the input stream. + * Bytes read from the input stream would not be seen by the reader and the + * buffer contents are unpredictable. * *

When the process has terminated, and the standard input has not been redirected, * reading of the bytes available from the underlying stream is on a best effort basis and @@ -283,6 +352,16 @@ public final BufferedReader inputReader(Charset charset) { * If the {@code native.encoding} is not a valid charset name or not supported * the {@link Charset#defaultCharset()} is used. * + *

The error reader should be {@linkplain BufferedReader#close closed} + * when it is no longer needed. + * + * @apiNote + * Use either this method or the {@linkplain #getErrorStream error stream} + * but not both on the same {@code Process}. + * The error reader consumes and buffers bytes from the error stream. + * Bytes read from the error stream would not be seen by the reader and the + * buffer contents are unpredictable. + * * @return a {@link BufferedReader BufferedReader} using the * {@code native.encoding} if supported, otherwise, the * {@link Charset#defaultCharset()} @@ -314,10 +393,15 @@ public final BufferedReader errorReader() { * then the {@code InputStreamReader} will be reading from a * null input stream. * + *

The error reader should be {@linkplain BufferedReader#close closed} + * when it is no longer needed. + * * @apiNote - * Using both {@link #getErrorStream} and {@link #errorReader(Charset)} has - * unpredictable behavior since the buffered reader reads ahead from the - * error stream. + * Use either this method or the {@linkplain #getErrorStream error stream} + * but not both on the same {@code Process}. + * The error reader consumes and buffers bytes from the error stream. + * Bytes read from the error stream would not be seen by the reader and the + * buffer contents are unpredictable. * *

When the process has terminated, and the standard error has not been redirected, * reading of the bytes available from the underlying stream is on a best effort basis and @@ -346,7 +430,7 @@ public final BufferedReader errorReader(Charset charset) { /** * Returns a {@code BufferedWriter} connected to the normal input of the process * using the native encoding. - * Writes text to a character-output stream, buffering characters so as to provide + * Writes text to a character-output stream, buffering characters to provide * for the efficient writing of single characters, arrays, and strings. * *

This method delegates to {@link #outputWriter(Charset)} using the @@ -354,6 +438,9 @@ public final BufferedReader errorReader(Charset charset) { * If the {@code native.encoding} is not a valid charset name or not supported * the {@link Charset#defaultCharset()} is used. * + *

The output writer should be {@linkplain BufferedWriter#close closed} + * when it is no longer needed. + * * @return a {@code BufferedWriter} to the standard input of the process using the charset * for the {@code native.encoding} system property * @since 17 @@ -365,7 +452,7 @@ public final BufferedWriter outputWriter() { /** * Returns a {@code BufferedWriter} connected to the normal input of the process * using a Charset. - * Writes text to a character-output stream, buffering characters so as to provide + * Writes text to a character-output stream, buffering characters to provide * for the efficient writing of single characters, arrays, and strings. * *

Characters written by the writer are encoded to bytes using {@link OutputStreamWriter} @@ -383,6 +470,9 @@ public final BufferedWriter outputWriter() { * ProcessBuilder.redirectInput} then the {@code OutputStreamWriter} writes to a * null output stream. * + *

The output writer should be {@linkplain BufferedWriter#close closed} + * when it is no longer needed. + * * @apiNote * A {@linkplain BufferedWriter} writes characters, arrays of characters, and strings. * Wrapping the {@link BufferedWriter} with a {@link PrintWriter} provides @@ -674,11 +764,12 @@ public long pid() { * free the current thread and block only if and when the value is needed. *
* For example, launching a process to compare two files and get a boolean if they are identical: - *

 {@code   Process p = new ProcessBuilder("cmp", "f1", "f2").start();
-     *    Future identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
-     *    ...
-     *    if (identical.get()) { ... }
-     * }
+ * {@snippet lang = "java" : + * Process p = new ProcessBuilder("cmp", "f1", "f2").start(); + * Future identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0); + * ... + * if (identical.get()) { ... } + * } * * @implSpec * This implementation executes {@link #waitFor()} in a separate thread @@ -695,11 +786,11 @@ public long pid() { * External implementations should override this method and provide * a more efficient implementation. For example, to delegate to the underlying * process, it can do the following: - *
{@code
+     * {@snippet lang = "java" :
      *    public CompletableFuture onExit() {
      *       return delegate.onExit().thenApply(p -> this);
      *    }
-     * }
+ * } * @apiNote * The process may be observed to have terminated with {@link #isAlive} * before the ComputableFuture is completed and dependent actions are invoked. diff --git a/src/java.base/share/classes/java/lang/ProcessBuilder.java b/src/java.base/share/classes/java/lang/ProcessBuilder.java index 9cb5848bdff..d461818eedf 100644 --- a/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -150,30 +150,33 @@ *

Starting a new process which uses the default working directory * and environment is easy: * - *

 {@code
+ * {@snippet lang = "java" :
+
  * Process p = new ProcessBuilder("myCommand", "myArg").start();
- * }
+ * } + * *

Here is an example that starts a process with a modified working * directory and environment, and redirects standard output and error * to be appended to a log file: * - *

 {@code
- * ProcessBuilder pb =
- *   new ProcessBuilder("myCommand", "myArg1", "myArg2");
- * Map env = pb.environment();
- * env.put("VAR1", "myValue");
- * env.remove("OTHERVAR");
- * env.put("VAR2", env.get("VAR1") + "suffix");
- * pb.directory(new File("myDir"));
- * File log = new File("log");
- * pb.redirectErrorStream(true);
- * pb.redirectOutput(Redirect.appendTo(log));
- * Process p = pb.start();
- * assert pb.redirectInput() == Redirect.PIPE;
- * assert pb.redirectOutput().file() == log;
- * assert p.getInputStream().read() == -1;
- * }
+ * {@snippet lang = "java": + * ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); + * Map env = pb.environment(); + * env.put("VAR1", "myValue"); + * env.remove("OTHERVAR"); + * env.put("VAR2", env.get("VAR1") + "suffix"); + * + * pb.directory(new File("myDir")); + * File log = new File("log"); + * pb.redirectErrorStream(true); + * pb.redirectOutput(Redirect.appendTo(log)); + * + * Process p = pb.start(); + * assert pb.redirectInput() == Redirect.PIPE; + * assert pb.redirectOutput().file() == log; + * assert p.getInputStream().read() == -1; + * } * *

To start a process with an explicit set of environment * variables, first call {@link java.util.Map#clear() Map.clear()} @@ -506,10 +509,10 @@ public enum Type { * This is the default handling of subprocess standard I/O. * *

It will always be true that - *

 {@code
-         * Redirect.PIPE.file() == null &&
-         * Redirect.PIPE.type() == Redirect.Type.PIPE
-         * }
+ * {@snippet lang = "java" : + * Redirect.PIPE.file() == null && + * Redirect.PIPE.type() == Redirect.Type.PIPE + * } */ public static final Redirect PIPE = new Redirect() { public Type type() { return Type.PIPE; } @@ -521,10 +524,10 @@ public enum Type { * behavior of most operating system command interpreters (shells). * *

It will always be true that - *

 {@code
-         * Redirect.INHERIT.file() == null &&
-         * Redirect.INHERIT.type() == Redirect.Type.INHERIT
-         * }
+ * {@snippet lang = "java" : + * Redirect.INHERIT.file() == null && + * Redirect.INHERIT.type() == Redirect.Type.INHERIT + * } */ public static final Redirect INHERIT = new Redirect() { public Type type() { return Type.INHERIT; } @@ -537,11 +540,10 @@ public enum Type { * an operating system specific "null file". * *

It will always be true that - *

 {@code
-         * Redirect.DISCARD.file() is the filename appropriate for the operating system
-         * and may be null &&
-         * Redirect.DISCARD.type() == Redirect.Type.WRITE
-         * }
+ * {@snippet lang = "java" : + * Redirect.DISCARD.file() != null && // is the filename appropriate for the operating system + * Redirect.DISCARD.type() == Redirect.Type.WRITE; + * } * @since 9 */ public static final Redirect DISCARD = new Redirect() { @@ -572,10 +574,10 @@ boolean append() { * Returns a redirect to read from the specified file. * *

It will always be true that - *

 {@code
-         * Redirect.from(file).file() == file &&
-         * Redirect.from(file).type() == Redirect.Type.READ
-         * }
+ * {@snippet lang = "java" : + * Redirect.from(file).file() == file && + * Redirect.from(file).type() == Redirect.Type.READ + * } * * @param file The {@code File} for the {@code Redirect}. * @return a redirect to read from the specified file @@ -598,10 +600,10 @@ public String toString() { * its previous contents will be discarded. * *

It will always be true that - *

 {@code
-         * Redirect.to(file).file() == file &&
-         * Redirect.to(file).type() == Redirect.Type.WRITE
-         * }
+ * {@snippet lang = "java" : + * Redirect.to(file).file() == file && + * Redirect.to(file).type() == Redirect.Type.WRITE + * } * * @param file The {@code File} for the {@code Redirect}. * @return a redirect to write to the specified file @@ -628,10 +630,10 @@ public String toString() { * system-dependent and therefore unspecified. * *

It will always be true that - *

 {@code
-         * Redirect.appendTo(file).file() == file &&
-         * Redirect.appendTo(file).type() == Redirect.Type.APPEND
-         * }
+ * {@snippet lang = "java" : + * Redirect.appendTo(file).file() == file && + * Redirect.appendTo(file).type() == Redirect.Type.APPEND + * } * * @param file The {@code File} for the {@code Redirect}. * @return a redirect to append to the specified file @@ -914,15 +916,15 @@ public Redirect redirectError() { * to be the same as those of the current Java process. * *

This is a convenience method. An invocation of the form - *

 {@code
-     * pb.inheritIO()
-     * }
+ * {@snippet lang = "java" : + * pb.inheritIO() + * } * behaves in exactly the same way as the invocation - *
 {@code
-     * pb.redirectInput(Redirect.INHERIT)
-     *   .redirectOutput(Redirect.INHERIT)
-     *   .redirectError(Redirect.INHERIT)
-     * }
+ * {@snippet lang = "java" : + * pb.redirectInput(Redirect.INHERIT) + * .redirectOutput(Redirect.INHERIT) + * .redirectError(Redirect.INHERIT) + * } * * This gives behavior equivalent to most operating system * command interpreters, or the standard C library function @@ -1176,22 +1178,21 @@ private Process start(Redirect[] redirects) throws IOException { * @apiNote * For example to count the unique imports for all the files in a file hierarchy * on a Unix compatible platform: - *
{@code
-     * String directory = "/home/duke/src";
-     * ProcessBuilder[] builders = {
+     * {@snippet lang = "java" :
+     *     String directory = "/home/duke/src";
+     *     ProcessBuilder[] builders = {
      *              new ProcessBuilder("find", directory, "-type", "f"),
      *              new ProcessBuilder("xargs", "grep", "-h", "^import "),
      *              new ProcessBuilder("awk", "{print $2;}"),
      *              new ProcessBuilder("sort", "-u")};
-     * List processes = ProcessBuilder.startPipeline(
-     *         Arrays.asList(builders));
-     * Process last = processes.get(processes.size()-1);
-     * try (InputStream is = last.getInputStream();
+     *     List processes = ProcessBuilder.startPipeline( Arrays.asList(builders));
+     *     Process last = processes.get(processes.size() - 1);
+     *     try (InputStream is = last.getInputStream();
      *         Reader isr = new InputStreamReader(is);
      *         BufferedReader r = new BufferedReader(isr)) {
-     *     long count = r.lines().count();
+     *         long count = r.lines().count();
+     *     }
      * }
-     * }
* * @param builders a List of ProcessBuilders * @return a {@code List}es started from the corresponding diff --git a/src/java.base/share/classes/java/lang/ScopedValue.java b/src/java.base/share/classes/java/lang/ScopedValue.java index 206c81d5238..57c6ca29a1e 100644 --- a/src/java.base/share/classes/java/lang/ScopedValue.java +++ b/src/java.base/share/classes/java/lang/ScopedValue.java @@ -26,17 +26,19 @@ package java.lang; +import java.lang.ref.Reference; import java.util.NoSuchElementException; import java.util.Objects; -import java.lang.ref.Reference; -import java.util.concurrent.StructuredTaskScope; import java.util.concurrent.StructureViolationException; +import java.util.concurrent.StructuredTaskScope; +import java.util.function.IntSupplier; import java.util.function.Supplier; import jdk.internal.access.JavaUtilConcurrentTLRAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.vm.ScopedValueContainer; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Hidden; -import jdk.internal.vm.ScopedValueContainer; +import jdk.internal.vm.annotation.Stable; /** * A value that may be safely and efficiently shared to methods without using method @@ -244,6 +246,9 @@ public final class ScopedValue { @Override public int hashCode() { return hash; } + @Stable + static IntSupplier hashGenerator; + /** * An immutable map from {@code ScopedValue} to values. * @@ -526,7 +531,8 @@ public static Carrier where(ScopedValue key, T value) { } private ScopedValue() { - this.hash = generateKey(); + IntSupplier nextHash = hashGenerator; + this.hash = nextHash != null ? nextHash.getAsInt() : generateKey(); } /** @@ -552,11 +558,11 @@ public T get() { // This code should perhaps be in class Cache. We do it // here because the generated code is small and fast and // we really want it to be inlined in the caller. - int n = (hash & Cache.SLOT_MASK) * 2; + int n = (hash & Cache.Constants.SLOT_MASK) * 2; if (objects[n] == this) { return (T)objects[n + 1]; } - n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2; + n = ((hash >>> Cache.INDEX_BITS) & Cache.Constants.SLOT_MASK) * 2; if (objects[n] == this) { return (T)objects[n + 1]; } @@ -580,11 +586,11 @@ private T slowGet() { public boolean isBound() { Object[] objects = scopedValueCache(); if (objects != null) { - int n = (hash & Cache.SLOT_MASK) * 2; + int n = (hash & Cache.Constants.SLOT_MASK) * 2; if (objects[n] == this) { return true; } - n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2; + n = ((hash >>> Cache.INDEX_BITS) & Cache.Constants.SLOT_MASK) * 2; if (objects[n] == this) { return true; } @@ -688,17 +694,17 @@ private static Snapshot scopedValueBindings() { private static int nextKey = 0xf0f0_f0f0; - // A Marsaglia xor-shift generator used to generate hashes. This one has full period, so - // it generates 2**32 - 1 hashes before it repeats. We're going to use the lowest n bits - // and the next n bits as cache indexes, so we make sure that those indexes map - // to different slots in the cache. + // A Marsaglia xor-shift generator used to generate hashes. This one has + // full period, so it generates 2**32 - 1 hashes before it repeats. We're + // going to use the lowest n bits and the next n bits as cache indexes, so + // we make sure that those indexes map to different slots in the cache. private static synchronized int generateKey() { int x = nextKey; do { x ^= x >>> 12; x ^= x << 9; x ^= x >>> 23; - } while (Cache.primarySlot(x) == Cache.secondarySlot(x)); + } while (((Cache.primaryIndex(x) ^ Cache.secondaryIndex(x)) & 1) == 0); return (nextKey = x); } @@ -709,7 +715,7 @@ private static synchronized int generateKey() { * @return the bitmask */ int bitmask() { - return (1 << Cache.primaryIndex(this)) | (1 << (Cache.secondaryIndex(this) + Cache.TABLE_SIZE)); + return (1 << Cache.primaryIndex(hash)) | (1 << (Cache.secondaryIndex(hash) + Cache.TABLE_SIZE)); } // Return true iff bitmask, considered as a set of bits, contains all @@ -727,57 +733,100 @@ private static final class Cache { static final int TABLE_MASK = TABLE_SIZE - 1; static final int PRIMARY_MASK = (1 << TABLE_SIZE) - 1; - // The number of elements in the cache array, and a bit mask used to - // select elements from it. - private static final int CACHE_TABLE_SIZE, SLOT_MASK; - // The largest cache we allow. Must be a power of 2 and greater than - // or equal to 2. - private static final int MAX_CACHE_SIZE = 16; - - static { - final String propertyName = "java.lang.ScopedValue.cacheSize"; - var sizeString = System.getProperty(propertyName, "16"); - var cacheSize = Integer.valueOf(sizeString); - if (cacheSize < 2 || cacheSize > MAX_CACHE_SIZE) { - cacheSize = MAX_CACHE_SIZE; - System.err.println(propertyName + " is out of range: is " + sizeString); - } - if ((cacheSize & (cacheSize - 1)) != 0) { // a power of 2 - cacheSize = MAX_CACHE_SIZE; - System.err.println(propertyName + " must be an integer power of 2: is " + sizeString); + + // This class serves to defer initialization of some values until they + // are needed. In particular, we must not invoke System.getProperty + // early in the JDK boot process, because that leads to a circular class + // initialization dependency. + // + // In more detail: + // + // The size of the cache depends on System.getProperty. Generating the + // hash of an instance of ScopedValue depends on ThreadLocalRandom. + // + // Invoking either of these early in the JDK boot process will cause + // startup to fail with an unrecoverable circular dependency. + // + // To break these cycles we allow scoped values to be created (but not + // used) without invoking either System.getProperty or + // ThreadLocalRandom. To do this we defer querying System.getProperty + // until the first reference to CACHE_TABLE_SIZE, and we define a local + // hash generator which is used until CACHE_TABLE_SIZE is initialized. + + private static class Constants { + // The number of elements in the cache array, and a bit mask used to + // select elements from it. + private static final int CACHE_TABLE_SIZE, SLOT_MASK; + // The largest cache we allow. Must be a power of 2 and greater than + // or equal to 2. + private static final int MAX_CACHE_SIZE = 16; + + private static final JavaUtilConcurrentTLRAccess THREAD_LOCAL_RANDOM_ACCESS + = SharedSecrets.getJavaUtilConcurrentTLRAccess(); + + static { + final String propertyName = "java.lang.ScopedValue.cacheSize"; + var sizeString = System.getProperty(propertyName, "16"); + var cacheSize = Integer.valueOf(sizeString); + if (cacheSize < 2 || cacheSize > MAX_CACHE_SIZE) { + cacheSize = MAX_CACHE_SIZE; + System.err.println(propertyName + " is out of range: is " + sizeString); + } + if ((cacheSize & (cacheSize - 1)) != 0) { // a power of 2 + cacheSize = MAX_CACHE_SIZE; + System.err.println(propertyName + " must be an integer power of 2: is " + sizeString); + } + CACHE_TABLE_SIZE = cacheSize; + SLOT_MASK = cacheSize - 1; + + // hashGenerator is set here (in class Constants rather than + // in global scope) in order not to initialize + // j.u.c.ThreadLocalRandom early in the JDK boot process. + // After this static initialization, new instances of + // ScopedValue will be initialized by a thread-local random + // generator. + hashGenerator = new IntSupplier() { + @Override + public int getAsInt() { + int x; + do { + x = THREAD_LOCAL_RANDOM_ACCESS + .nextSecondaryThreadLocalRandomSeed(); + } while (Cache.primarySlot(x) == Cache.secondarySlot(x)); + return x; + } + }; } - CACHE_TABLE_SIZE = cacheSize; - SLOT_MASK = cacheSize - 1; } - static int primaryIndex(ScopedValue key) { - return key.hash & TABLE_MASK; + static int primaryIndex(int hash) { + return hash & Cache.TABLE_MASK; } - static int secondaryIndex(ScopedValue key) { - return (key.hash >> INDEX_BITS) & TABLE_MASK; + static int secondaryIndex(int hash) { + return (hash >> INDEX_BITS) & Cache.TABLE_MASK; } private static int primarySlot(ScopedValue key) { - return key.hashCode() & SLOT_MASK; + return key.hashCode() & Constants.SLOT_MASK; } private static int secondarySlot(ScopedValue key) { - return (key.hash >> INDEX_BITS) & SLOT_MASK; + return (key.hash >> INDEX_BITS) & Constants.SLOT_MASK; } static int primarySlot(int hash) { - return hash & SLOT_MASK; + return hash & Constants.SLOT_MASK; } static int secondarySlot(int hash) { - return (hash >> INDEX_BITS) & SLOT_MASK; + return (hash >> INDEX_BITS) & Constants.SLOT_MASK; } static void put(ScopedValue key, Object value) { Object[] theCache = scopedValueCache(); if (theCache == null) { - theCache = new Object[CACHE_TABLE_SIZE * 2]; + theCache = new Object[Constants.CACHE_TABLE_SIZE * 2]; setScopedValueCache(theCache); } // Update the cache to replace one entry with the value we just looked up. @@ -813,26 +862,23 @@ private static void setKey(Object[] objs, int n, Object key) { objs[n * 2] = key; } - private static final JavaUtilConcurrentTLRAccess THREAD_LOCAL_RANDOM_ACCESS - = SharedSecrets.getJavaUtilConcurrentTLRAccess(); - // Return either true or false, at pseudo-random, with a bias towards true. // This chooses either the primary or secondary cache slot, but the // primary slot is approximately twice as likely to be chosen as the // secondary one. private static boolean chooseVictim() { - int r = THREAD_LOCAL_RANDOM_ACCESS.nextSecondaryThreadLocalRandomSeed(); + int r = Constants.THREAD_LOCAL_RANDOM_ACCESS.nextSecondaryThreadLocalRandomSeed(); return (r & 15) >= 5; } // Null a set of cache entries, indicated by the 1-bits given static void invalidate(int toClearBits) { - toClearBits = (toClearBits >>> TABLE_SIZE) | (toClearBits & PRIMARY_MASK); + toClearBits = ((toClearBits >>> Cache.TABLE_SIZE) | toClearBits) & PRIMARY_MASK; Object[] objects; if ((objects = scopedValueCache()) != null) { for (int bits = toClearBits; bits != 0; ) { int index = Integer.numberOfTrailingZeros(bits); - setKeyAndObjectAt(objects, index & SLOT_MASK, null, null); + setKeyAndObjectAt(objects, index & Constants.SLOT_MASK, null, null); bits &= ~1 << index; } } diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 52af7dfd503..eac8a1355b7 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -553,135 +553,125 @@ public String(byte[] bytes, int offset, int length, Charset charset) { * disambiguate it against other similar methods of this class. */ private String(Charset charset, byte[] bytes, int offset, int length) { + String str; if (length == 0) { - this.value = "".value; - this.coder = "".coder; + str = ""; } else if (charset == UTF_8.INSTANCE) { - if (COMPACT_STRINGS) { - int dp = StringCoding.countPositives(bytes, offset, length); - if (dp == length) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - return; + str = utf8(bytes, offset, length); + } else if (charset == ISO_8859_1.INSTANCE) { + str = iso88591(bytes, offset, length); + } else if (charset == US_ASCII.INSTANCE) { + str = ascii(bytes, offset, length); + } else { + str = decode(charset, bytes, offset, length); + } + this(str); + } + + private static String utf8(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS) { + int dp = StringCoding.countPositives(bytes, offset, length); + if (dp == length) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); + } + // Decode with a stable copy, to be the result if the decoded length is the same + byte[] latin1 = Arrays.copyOfRange(bytes, offset, offset + length); + int sp = dp; // first dp bytes are already in the copy + while (sp < length) { + int b1 = latin1[sp++]; + if (b1 >= 0) { + latin1[dp++] = (byte) b1; + continue; } - // Decode with a stable copy, to be the result if the decoded length is the same - byte[] latin1 = Arrays.copyOfRange(bytes, offset, offset + length); - int sp = dp; // first dp bytes are already in the copy - while (sp < length) { - int b1 = latin1[sp++]; - if (b1 >= 0) { - latin1[dp++] = (byte)b1; + if ((b1 & 0xfe) == 0xc2 && sp < length) { // b1 either 0xc2 or 0xc3 + int b2 = latin1[sp]; + if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 + latin1[dp++] = (byte) decode2(b1, b2); + sp++; continue; } - if ((b1 & 0xfe) == 0xc2 && sp < length) { // b1 either 0xc2 or 0xc3 - int b2 = latin1[sp]; - if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 - latin1[dp++] = (byte)decode2(b1, b2); - sp++; - continue; - } - } - // anything not a latin1, including the REPL - // we have to go with the utf16 - sp--; - break; - } - if (sp == length) { - if (dp != latin1.length) { - latin1 = Arrays.copyOf(latin1, dp); - } - this.value = latin1; - this.coder = LATIN1; - return; - } - byte[] utf16 = StringUTF16.newBytesFor(length); - StringLatin1.inflate(latin1, 0, utf16, 0, dp); - dp = decodeUTF8_UTF16(latin1, sp, length, utf16, dp, true); - if (dp != length) { - utf16 = Arrays.copyOf(utf16, dp << 1); } - this.value = utf16; - this.coder = UTF16; - } else { // !COMPACT_STRINGS - byte[] dst = StringUTF16.newBytesFor(length); - int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); - if (dp != length) { - dst = Arrays.copyOf(dst, dp << 1); + // anything not a latin1, including the REPL + // we have to go with the utf16 + sp--; + break; + } + if (sp == length) { + if (dp != latin1.length) { + latin1 = Arrays.copyOf(latin1, dp); } - this.value = dst; - this.coder = UTF16; + return new String(latin1, LATIN1); } - } else if (charset == ISO_8859_1.INSTANCE) { - if (COMPACT_STRINGS) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - } else { - this.value = StringLatin1.inflate(bytes, offset, length); - this.coder = UTF16; + byte[] utf16 = StringUTF16.newBytesFor(length); + StringLatin1.inflate(latin1, 0, utf16, 0, dp); + dp = decodeUTF8_UTF16(latin1, sp, length, utf16, dp, true); + if (dp != length) { + utf16 = Arrays.copyOf(utf16, dp << 1); } - } else if (charset == US_ASCII.INSTANCE) { - if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - } else { - byte[] dst = StringUTF16.newBytesFor(length); - int dp = 0; - while (dp < length) { - int b = bytes[offset++]; - StringUTF16.putChar(dst, dp++, (b >= 0) ? (char) b : REPL); - } - this.value = dst; - this.coder = UTF16; + return new String(utf16, UTF16); + } else { // !COMPACT_STRINGS + byte[] dst = StringUTF16.newBytesFor(length); + int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); + if (dp != length) { + dst = Arrays.copyOf(dst, dp << 1); } + return new String(dst, UTF16); + } + } + + private static String iso88591(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); } else { - // (1)We never cache the "external" cs, the only benefit of creating - // an additional StringDe/Encoder object to wrap it is to share the - // de/encode() method. These SD/E objects are short-lived, the young-gen - // gc should be able to take care of them well. But the best approach - // is still not to generate them if not really necessary. - // (2)The defensive copy of the input byte/char[] has a big performance - // impact, as well as the outgoing result byte/char[]. Need to do the - // optimization check of (sm==null && classLoader0==null) for both. - CharsetDecoder cd = charset.newDecoder(); - // ArrayDecoder fastpaths - if (cd instanceof ArrayDecoder ad) { - // ascii - if (ad.isASCIICompatible() && !StringCoding.hasNegatives(bytes, offset, length)) { - if (COMPACT_STRINGS) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - return; - } - this.value = StringLatin1.inflate(bytes, offset, length); - this.coder = UTF16; - return; - } + return new String(StringLatin1.inflate(bytes, offset, length), UTF16); + } + } + + private static String ascii(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); + } else { + byte[] dst = StringUTF16.newBytesFor(length); + int dp = 0; + while (dp < length) { + int b = bytes[offset++]; + StringUTF16.putChar(dst, dp++, (b >= 0) ? (char) b : REPL); + } + return new String(dst, UTF16); + } + } + private static String decode(Charset charset, byte[] bytes, int offset, int length) { + // (1)We never cache the "external" cs, the only benefit of creating + // an additional StringDe/Encoder object to wrap it is to share the + // de/encode() method. These SD/E objects are short-lived, the young-gen + // gc should be able to take care of them well. But the best approach + // is still not to generate them if not really necessary. + // (2)The defensive copy of the input byte/char[] has a big performance + // impact, as well as the outgoing result byte/char[]. Need to do the + // optimization check of (sm==null && classLoader0==null) for both. + CharsetDecoder cd = charset.newDecoder(); + // ArrayDecoder fastpaths + if (cd instanceof ArrayDecoder ad) { + // ascii + if (ad.isASCIICompatible() && !StringCoding.hasNegatives(bytes, offset, length)) { + return iso88591(bytes, offset, length); + } else { // fastpath for always Latin1 decodable single byte if (COMPACT_STRINGS && ad.isLatin1Decodable()) { byte[] dst = new byte[length]; ad.decodeToLatin1(bytes, offset, length, dst); - this.value = dst; - this.coder = LATIN1; - return; - } - - int en = scale(length, cd.maxCharsPerByte()); - cd.onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - char[] ca = new char[en]; - int clen = ad.decode(bytes, offset, length, ca); - if (COMPACT_STRINGS) { - byte[] val = StringUTF16.compress(ca, 0, clen);; - this.coder = StringUTF16.coderFromArrayLen(val, clen); - this.value = val; - return; + return new String(dst, LATIN1); + } else { + int en = scale(length, cd.maxCharsPerByte()); + cd.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + char[] ca = new char[en]; + int clen = ad.decode(bytes, offset, length, ca); + return new String(ca, 0, clen, null); } - coder = UTF16; - value = StringUTF16.toBytes(ca, 0, clen); - return; } - + } else { // decode using CharsetDecoder int en = scale(length, cd.maxCharsPerByte()); cd.onMalformedInput(CodingErrorAction.REPLACE) @@ -694,14 +684,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) { // Substitution is enabled, so this shouldn't happen throw new Error(x); } - if (COMPACT_STRINGS) { - byte[] val = StringUTF16.compress(ca, 0, caLen); - this.coder = StringUTF16.coderFromArrayLen(val, caLen); - this.value = val; - return; - } - coder = UTF16; - value = StringUTF16.toBytes(ca, 0, caLen); + return new String(ca, 0, caLen, null); } } diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 6b1751476f7..e640700c2e9 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -132,6 +132,7 @@ public sealed interface CodeBuilder * values require two slots. * * @param paramNo the index of the parameter + * @throws IndexOutOfBoundsException if the parameter index is out of bounds */ int parameterSlot(int paramNo); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index 6b75126a90f..4b443929158 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -540,7 +540,7 @@ default ConstantValueEntry constantValueEntry(ConstantDesc c) { if (c instanceof Long l) return longEntry(l); if (c instanceof Float f) return floatEntry(f); if (c instanceof Double d) return doubleEntry(d); - throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); + throw new IllegalArgumentException("Illegal type: " + c.getClass()); // implicit null check } /** @@ -559,7 +559,8 @@ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { if (c instanceof MethodTypeDesc mtd) return methodTypeEntry(mtd); if (c instanceof DirectMethodHandleDesc dmhd) return methodHandleEntry(dmhd); if (c instanceof DynamicConstantDesc dcd) return constantDynamicEntry(dcd); - throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); + // Shouldn't reach here + throw new IllegalArgumentException("Illegal type: " + c.getClass()); // implicit null check } /** diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index 89718cff1f7..f531ec0ee86 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -25,12 +25,10 @@ package java.lang.ref; -import jdk.internal.misc.Unsafe; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.access.JavaLangRefAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.ref.Cleaner; import java.util.Objects; @@ -209,11 +207,6 @@ private static class ReferenceHandler extends Thread { } public void run() { - // pre-load and initialize Cleaner class so that we don't - // get into trouble later in the run loop if there's - // memory shortage while loading/initializing it lazily. - Unsafe.getUnsafe().ensureClassInitialized(Cleaner.class); - while (true) { processPendingReferences(); } @@ -263,18 +256,7 @@ private static void processPendingReferences() { Reference ref = pendingList; pendingList = ref.discovered; ref.discovered = null; - - if (ref instanceof Cleaner) { - ((Cleaner)ref).clean(); - // Notify any waiters that progress has been made. - // This improves latency for nio.Bits waiters, which - // are the only important ones. - synchronized (processPendingLock) { - processPendingLock.notifyAll(); - } - } else { - ref.enqueueFromPending(); - } + ref.enqueueFromPending(); } // Notify any waiters of completion of current round. synchronized (processPendingLock) { diff --git a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java index 8cce10e007f..7fbbfb7136b 100644 --- a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java +++ b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java @@ -392,7 +392,7 @@ public enum ClassFileFormatVersion { // the implementation of latest() must be updated too. /// The preview features of Valhalla. - /// @since 25 + /// @since 26 CURRENT_PREVIEW_FEATURES(ClassFile.latestMajorVersion()); private final int major; diff --git a/src/java.base/share/classes/java/nio/Bits.java b/src/java.base/share/classes/java/nio/Bits.java index a9a22d6079e..07dd6a91890 100644 --- a/src/java.base/share/classes/java/nio/Bits.java +++ b/src/java.base/share/classes/java/nio/Bits.java @@ -101,8 +101,15 @@ static boolean unaligned() { // increasing delay before throwing OutOfMemoryError: // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) // which means that OOME will be thrown after 0.5 s of trying + private static final long INITIAL_SLEEP = 1; private static final int MAX_SLEEPS = 9; + private static final Object RESERVE_SLOWPATH_LOCK = new Object(); + + // Token for detecting whether some other thread has done a GC since the + // last time the checking thread went around the retry-with-GC loop. + private static int RESERVE_GC_EPOCH = 0; // Never negative. + // These methods should be called whenever direct memory is allocated or // freed. They allow the user to control the amount of direct memory // which a process may access. All sizes are specified in bytes. @@ -118,29 +125,45 @@ static void reserveMemory(long size, long cap) { return; } - final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); + // Don't completely discard interruptions. Instead, record them and + // reapply when we're done here (whether successfully or OOME). boolean interrupted = false; try { - - // Retry allocation until success or there are no more - // references (including Cleaners that might free direct - // buffer memory) to process and allocation still fails. - boolean refprocActive; - do { + // Keep trying to reserve until either succeed or there is no + // further cleaning available from prior GCs. If the latter then + // GC to hopefully find more cleaning to do. Once a thread GCs it + // drops to the later retry with backoff loop. + for (int cleanedEpoch = -1; true; ) { + synchronized (RESERVE_SLOWPATH_LOCK) { + // Test if cleaning for prior GCs (from here) is complete. + // If so, GC to produce more cleaning work, and change + // the token to inform other threads that there may be + // more cleaning work to do. This is done under the lock + // to close a race. We could have multiple threads pass + // the test "simultaneously", resulting in back-to-back + // GCs. For a STW GC the window is small, but for a + // concurrent GC it's quite large. If a thread were to + // somehow be stuck trying to take the lock while enough + // other threads succeeded for the epoch to wrap, it just + // does an excess GC. + if (RESERVE_GC_EPOCH == cleanedEpoch) { + // Increment with overflow to 0, so the value can + // never equal the initial/reset cleanedEpoch value. + RESERVE_GC_EPOCH = Integer.max(0, RESERVE_GC_EPOCH + 1); + System.gc(); + break; + } + cleanedEpoch = RESERVE_GC_EPOCH; + } try { - refprocActive = jlra.waitForReferenceProcessing(); + if (tryReserveOrClean(size, cap)) { + return; + } } catch (InterruptedException e) { - // Defer interrupts and keep trying. interrupted = true; - refprocActive = true; - } - if (tryReserveMemory(size, cap)) { - return; + cleanedEpoch = -1; // Reset when incomplete. } - } while (refprocActive); - - // trigger VM's Reference processing - System.gc(); + } // A retry loop with exponential back-off delays. // Sometimes it would suffice to give up once reference @@ -151,40 +174,53 @@ static void reserveMemory(long size, long cap) { // DirectBufferAllocTest to (usually) succeed, while // without it that test likely fails. Since failure here // ends in OOME, there's no need to hurry. - long sleepTime = 1; - int sleeps = 0; - while (true) { - if (tryReserveMemory(size, cap)) { - return; - } - if (sleeps >= MAX_SLEEPS) { - break; - } + for (int sleeps = 0; true; ) { try { - if (!jlra.waitForReferenceProcessing()) { - Thread.sleep(sleepTime); - sleepTime <<= 1; - sleeps++; + if (tryReserveOrClean(size, cap)) { + return; + } else if (sleeps < MAX_SLEEPS) { + Thread.sleep(INITIAL_SLEEP << sleeps); + ++sleeps; // Only increment if sleep completed. + } else { + throw new OutOfMemoryError + ("Cannot reserve " + + size + " bytes of direct buffer memory (allocated: " + + RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")"); } } catch (InterruptedException e) { interrupted = true; } } - // no luck - throw new OutOfMemoryError - ("Cannot reserve " - + size + " bytes of direct buffer memory (allocated: " - + RESERVED_MEMORY.get() + ", limit: " + MAX_MEMORY +")"); - } finally { + // Reapply any deferred interruption. if (interrupted) { - // don't swallow interrupts Thread.currentThread().interrupt(); } } } + // Try to reserve memory, or failing that, try to make progress on + // cleaning. Returns true if successfully reserved memory, false if + // failed and ran out of cleaning work. + private static boolean tryReserveOrClean(long size, long cap) + throws InterruptedException + { + JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); + boolean progressing = true; + while (true) { + if (tryReserveMemory(size, cap)) { + return true; + } else if (BufferCleaner.tryCleaning()) { + progressing = true; + } else if (!progressing) { + return false; + } else { + progressing = jlra.waitForReferenceProcessing(); + } + } + } + private static boolean tryReserveMemory(long size, long cap) { // -XX:MaxDirectMemorySize limits the total capacity rather than the diff --git a/src/java.base/share/classes/java/nio/BufferCleaner.java b/src/java.base/share/classes/java/nio/BufferCleaner.java new file mode 100644 index 00000000000..ddacecbcf63 --- /dev/null +++ b/src/java.base/share/classes/java/nio/BufferCleaner.java @@ -0,0 +1,269 @@ +/* + * 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. + */ + +package java.nio; + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.util.Objects; +import sun.nio.Cleaner; + +/** + * BufferCleaner supports PhantomReference-based management of native memory + * referred to by Direct-XXX-Buffers. Unreferenced DBBs may be garbage + * collected, deactivating the associated PRefs and making them available for + * cleanup here. + * + * There is a configured limit to the amount of memory that may be allocated + * by DBBs. When that limit is reached, the allocator may invoke the garbage + * collector directly to attempt to trigger cleaning here, hopefully + * permitting the allocation to complete. Only if that doesn't free sufficient + * memory does the allocation fail. See java.nio.Bits::reserveMemory() for + * details. + * + * One of the requirements for that approach is having a way to determine that + * deactivated cleaners have been cleaned. java.lang.ref.Cleaner doesn't + * provide such a mechanism, and adding such a mechanism to that class to + * satisfy this unique requirement was deemed undesirable. Instead, this class + * uses the underlying primitives (PhantomReferences, ReferenceQueues) to + * provide the functionality needed for DBB management. + */ +class BufferCleaner { + private static final class PhantomCleaner + extends PhantomReference + implements Cleaner + { + private final Runnable action; + // Position in the CleanerList. + CleanerList.Node node; + int index; + + public PhantomCleaner(Object obj, Runnable action) { + super(obj, queue); + this.action = action; + } + + @Override + public void clean() { + if (cleanerList.remove(this)) { + // If being cleaned explicitly by application, rather than via + // reference processing by BufferCleaner, clear the referent so + // reference processing is disabled for this object. + clear(); + try { + action.run(); + } catch (Throwable x) { + // Long-standing behavior: when cleaning fails, VM exits. + if (System.err != null) { + new Error("nio Cleaner terminated abnormally", x).printStackTrace(); + } + System.exit(1); + } + } + } + } + + // Cribbed from jdk.internal.ref.CleanerImpl. + static final class CleanerList { + /** + * Capacity for a single node in the list. + * This balances memory overheads vs locality vs GC walking costs. + */ + static final int NODE_CAPACITY = 4096; + + /** + * Head node. This is the only node where PhantomCleanabls are + * added to or removed from. This is the only node with variable size, + * all other nodes linked from the head are always at full capacity. + */ + private Node head; + + /** + * Cached node instance to provide better behavior near NODE_CAPACITY + * threshold: if list size flips around NODE_CAPACITY, it would reuse + * the cached node instead of wasting and re-allocating a new node all + * the time. + */ + private Node cache; + + public CleanerList() { + this.head = new Node(); + } + + /** + * Insert this PhantomCleaner in the list. + */ + public synchronized void insert(PhantomCleaner phc) { + if (head.size == NODE_CAPACITY) { + // Head node is full, insert new one. + // If possible, pick a pre-allocated node from cache. + Node newHead; + if (cache != null) { + newHead = cache; + cache = null; + } else { + newHead = new Node(); + } + newHead.next = head; + head = newHead; + } + assert head.size < NODE_CAPACITY; + + // Put the incoming object in head node and record indexes. + final int lastIndex = head.size; + phc.node = head; + phc.index = lastIndex; + head.arr[lastIndex] = phc; + head.size++; + } + + /** + * Remove this PhantomCleaner from the list. + * + * @return true if Cleaner was removed or false if not because + * it had already been removed before + */ + public synchronized boolean remove(PhantomCleaner phc) { + if (phc.node == null) { + // Not in the list. + return false; + } + assert phc.node.arr[phc.index] == phc; + + // Replace with another element from the head node, as long + // as it is not the same element. This keeps all non-head + // nodes at full capacity. + final int lastIndex = head.size - 1; + assert lastIndex >= 0; + if (head != phc.node || (phc.index != lastIndex)) { + PhantomCleaner mover = head.arr[lastIndex]; + mover.node = phc.node; + mover.index = phc.index; + phc.node.arr[phc.index] = mover; + } + + // Now we can unlink the removed element. + phc.node = null; + + // Remove the last element from the head node. + head.arr[lastIndex] = null; + head.size--; + + // If head node becomes empty after this, and there are + // nodes that follow it, replace the head node with another + // full one. If needed, stash the now free node in cache. + if (head.size == 0 && head.next != null) { + Node newHead = head.next; + if (cache == null) { + cache = head; + cache.next = null; + } + head = newHead; + } + + return true; + } + + /** + * Segment node. + */ + static class Node { + // Array of tracked cleaners, and the amount of elements in it. + final PhantomCleaner[] arr = new PhantomCleaner[NODE_CAPACITY]; + int size; + + // Linked list structure. + Node next; + } + } + + private static final class CleaningThread extends Thread { + public CleaningThread() {} + + @Override + public void run() { + while (true) { + try { + Cleaner c = (Cleaner) queue.remove(); + c.clean(); + } catch (InterruptedException e) { + // Ignore InterruptedException in cleaner thread. + } + } + } + } + + /** + * Try to do some cleaning. Takes a cleaner from the queue and executes it. + * + * @return true if a cleaner was found and executed, false if there + * weren't any cleaners in the queue. + */ + public static boolean tryCleaning() { + Cleaner c = (Cleaner) queue.poll(); + if (c == null) { + return false; + } else { + c.clean(); + return true; + } + } + + private static final CleanerList cleanerList = new CleanerList(); + private static final ReferenceQueue queue = new ReferenceQueue(); + private static CleaningThread cleaningThread = null; + + private static void startCleaningThreadIfNeeded() { + synchronized (cleanerList) { + if (cleaningThread != null) { + return; + } + cleaningThread = new CleaningThread(); + } + cleaningThread.setDaemon(true); + cleaningThread.start(); + } + + private BufferCleaner() {} + + /** + * Construct a new Cleaner for obj, with the associated action. + * + * @param obj object to track. + * @param action cleanup action for obj. + * @return associated cleaner. + * + */ + public static Cleaner register(Object obj, Runnable action) { + Objects.requireNonNull(obj, "obj"); + Objects.requireNonNull(action, "action"); + startCleaningThreadIfNeeded(); + PhantomCleaner cleaner = new PhantomCleaner(obj, action); + cleanerList.insert(cleaner); + Reference.reachabilityFence(obj); + return cleaner; + } +} diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 12bc0103d1b..8bd943f4e67 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -30,6 +30,7 @@ package java.nio; import java.io.FileDescriptor; import java.lang.foreign.MemorySegment; import java.lang.ref.Reference; +import java.nio.BufferCleaner; import java.util.Objects; import jdk.internal.foreign.AbstractMemorySegmentImpl; import jdk.internal.foreign.MemorySessionImpl; @@ -37,7 +38,7 @@ import jdk.internal.foreign.SegmentFactories; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.misc.ScopedMemoryAccess.ScopedAccessError; import jdk.internal.misc.VM; -import jdk.internal.ref.Cleaner; +import sun.nio.Cleaner; import sun.nio.ch.DirectBuffer; @@ -122,7 +123,7 @@ class Direct$Type$Buffer$RW$$BO$ address = base; } try { - cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); + cleaner = BufferCleaner.register(this, new Deallocator(base, size, cap)); } catch (Throwable t) { // Prevent leak if the Deallocator or Cleaner fail for any reason UNSAFE.freeMemory(base); @@ -197,7 +198,7 @@ class Direct$Type$Buffer$RW$$BO$ #if[rw] super(-1, 0, cap, cap, fd, isSync, segment); address = addr; - cleaner = Cleaner.create(this, unmapper); + cleaner = (unmapper == null) ? null : BufferCleaner.register(this, unmapper); att = null; #else[rw] super(cap, addr, fd, unmapper, isSync, segment); diff --git a/src/java.base/share/classes/java/nio/X-Buffer.java.template b/src/java.base/share/classes/java/nio/X-Buffer.java.template index 283f5534597..c43004cc0ac 100644 --- a/src/java.base/share/classes/java/nio/X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template @@ -1897,21 +1897,31 @@ public abstract sealed class $Type$Buffer #if[char] /** - * Absolute bulk get method. + * Relative bulk get method. * *

This method transfers {@code srcEnd-srcBegin} characters from this - * buffer into the given array, starting at index {@code srcBegin} in this - * buffer and at offset {@code dstBegin} in the array. The position of this - * buffer is unchanged. + * buffer into the given array, starting at index + * {@code position() + srcBegin} in this buffer and at offset + * {@code dstBegin} in the array. The position of this buffer is unchanged. + * + *

An invocation of this method behaves exactly the same was as the + * invocation + * + * {@snippet lang=java : + * get(position() + srcBegin, dst, dstBegin, srcEnd - srcBegin) + * } * * @param srcBegin - * The index in this buffer from which the first character will be - * read; must be non-negative and less than {@code limit()} + * The index in this buffer, relative to the current position, + * of the first character to + * read; must be non-negative and less than + * {@code limit() - position()} * * @param srcEnd - * The index in this buffer directly before the last character to - * read; must be non-negative and less or equal than {@code limit()} - * and must be greater or equal than {@code srcBegin} + * The index in this buffer, relative to the current position, + * after the last character to read; + * must be greater than or equal to {@code srcBegin} and less than + * or equal to {@code limit() - position()} * * @param dst * The destination array @@ -1924,14 +1934,16 @@ public abstract sealed class $Type$Buffer * If the preconditions on the {@code srcBegin}, {@code srcEnd}, * and {@code dstBegin} parameters do not hold * - * @implSpec This method is equivalent to - * {@code get(srcBegin, dst, dstBegin, srcEnd - srcBegin)}. - * * @since 25 */ @Override public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { - get(srcBegin, dst, dstBegin, srcEnd - srcBegin); + // Check [srcBegin,srcEnd) is a subset of [0,limit()-position) + int pos = position(); + int lim = limit(); + Objects.checkFromToIndex(srcBegin, srcEnd, lim - pos); + + get(pos + srcBegin, dst, dstBegin, srcEnd - srcBegin); } /** diff --git a/src/java.base/share/classes/java/security/SecureRandom.java b/src/java.base/share/classes/java/security/SecureRandom.java index e53341be9da..53fdd3070d8 100644 --- a/src/java.base/share/classes/java/security/SecureRandom.java +++ b/src/java.base/share/classes/java/security/SecureRandom.java @@ -25,6 +25,7 @@ package java.security; +import jdk.internal.util.ByteArray; import sun.security.jca.GetInstance; import sun.security.jca.GetInstance.Instance; import sun.security.jca.Providers; @@ -837,6 +838,16 @@ protected final int next(int numBits) { return next >>> (numBytes*8 - numBits); } + /** + * {@inheritDoc} + */ + @Override + public long nextLong() { + byte[] b = new byte[8]; + nextBytes(b); // Calls engineNextBytes internally + return ByteArray.getLong(b, 0); + } + /** * Returns the given number of seed bytes, computed using the seed * generation algorithm that this class uses to seed itself. This diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 9059d196861..eb69d1dfc2f 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -561,8 +561,8 @@ * RFC 4647: Matching of Language Tags * @spec https://www.rfc-editor.org/info/rfc5646 * RFC 5646: Tags for Identifying Languages - * @spec https://unicode.org/reports/tr35/ - * Unicode Locale Data Markup Language + * @spec https://www.unicode.org/reports/tr35 + * Unicode Locale Data Markup Language (LDML) * @see Builder * @see ResourceBundle * @see java.text.Format @@ -1687,14 +1687,14 @@ private String computeLanguageTag() { * {@return a case folded IETF BCP 47 language tag} * *

This method formats a language tag into one with case convention - * that adheres to section 2.1.1. Formatting of Language Tags of RFC5646. + * that adheres to section 2.1.1. Formatting of Language Tags of RFC 5646. * This format is defined as: All subtags, including extension and private * use subtags, use lowercase letters with two exceptions: two-letter * and four-letter subtags that neither appear at the start of the tag * nor occur after singletons. Such two-letter subtags are all * uppercase (as in the tags "en-CA-x-ca" or "sgn-BE-FR") and four- * letter subtags are titlecase (as in the tag "az-Latn-x-latn"). As - * legacy tags, (defined as "grandfathered" in RFC5646) are not always well-formed, this method + * legacy tags, (defined as "grandfathered" in RFC 5646) are not always well-formed, this method * will simply case fold a legacy tag to match the exact case convention * for the particular tag specified in the respective * {@link ##legacy_tags Legacy tags} table. @@ -1720,15 +1720,15 @@ private String computeLanguageTag() { *

As the formatting of the case convention is dependent on the * positioning of certain subtags, callers of this method should ensure * that the language tag is well-formed, (conforming to section 2.1. Syntax - * of RFC5646). + * of RFC 5646). * * @param languageTag the IETF BCP 47 language tag. * @throws IllformedLocaleException if {@code languageTag} is not well-formed * @throws NullPointerException if {@code languageTag} is {@code null} * @spec https://www.rfc-editor.org/rfc/rfc5646.html#section-2.1 - * RFC5646 2.1. Syntax + * RFC 5646: 2.1. Syntax * @spec https://www.rfc-editor.org/rfc/rfc5646#section-2.1.1 - * RFC5646 2.1.1. Formatting of Language Tags + * RFC 5646: 2.1.1. Formatting of Language Tags * @since 21 */ public static String caseFoldLanguageTag(String languageTag) { diff --git a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java index 0d26607591d..c249f630163 100644 --- a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java @@ -44,16 +44,16 @@ import java.util.Objects; /** - * Provides default implementations of {@link ExecutorService} - * execution methods. This class implements the {@code submit}, - * {@code invokeAny} and {@code invokeAll} methods using a - * {@link RunnableFuture} returned by {@code newTaskFor}, which defaults - * to the {@link FutureTask} class provided in this package. For example, - * the implementation of {@code submit(Runnable)} creates an - * associated {@code RunnableFuture} that is executed and - * returned. Subclasses may override the {@code newTaskFor} methods - * to return {@code RunnableFuture} implementations other than - * {@code FutureTask}. + * Provides default implementations of {@link ExecutorService} methods + * other than {@link Executor#execute}. This class implements the {@code + * submit}, {@code invokeAny} and {@code invokeAll} methods using a + * {@link RunnableFuture} returned by {@code newTaskFor}, which + * defaults to the {@link FutureTask} class provided in this package. + * For example, the implementation of {@code submit(Runnable)} creates + * an associated {@code RunnableFuture} that is executed and + * returned. Subclasses may override the {@code newTaskFor} methods to + * return {@code RunnableFuture} implementations other than {@code + * FutureTask}. * *

Extension example. Here is a sketch of a class * that customizes {@link ThreadPoolExecutor} to use diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 6ff31c61049..b4368842865 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -43,7 +43,7 @@ /** * A stage of a possibly asynchronous computation, that performs an * action or computes a value when another CompletionStage completes. - * A stage completes upon termination of its computation, but this may + * A stage completes upon termination of its computation, which may * in turn trigger other dependent stages. The functionality defined * in this interface takes only a few basic forms, which expand out to * a larger set of methods to capture a range of usage styles: @@ -97,18 +97,25 @@ * In all other cases, if a stage's computation terminates abruptly * with an (unchecked) exception or error, then all dependent stages * requiring its completion complete exceptionally as well, with a - * {@link CompletionException} holding the exception as its cause. If - * a stage is dependent on both of two stages, and both - * complete exceptionally, then the CompletionException may correspond - * to either one of these exceptions. If a stage is dependent on - * either of two others, and only one of them completes - * exceptionally, no guarantees are made about whether the dependent - * stage completes normally or exceptionally. In the case of method - * {@code whenComplete}, when the supplied action itself encounters an - * exception, then the stage completes exceptionally with this - * exception unless the source stage also completed exceptionally, in - * which case the exceptional completion from the source stage is - * given preference and propagated to the dependent stage. + * {@link CompletionException} holding the exception as its + * cause. This convention distinguishes exceptions in an action itself + * from those it depends on. If they are to be handled in the same + * way, instead catch {@link RuntimeException} (possibly inspecting + * the exception's {@code getCause()}). If a stage is dependent on + * both of two stages, and both complete exceptionally, then + * the CompletionException may correspond to either one of these + * exceptions. If a stage is dependent on either of two + * others, and only one of them completes exceptionally, no guarantees + * are made about whether the dependent stage completes normally or + * exceptionally. In the case of method {@code whenComplete}, when the + * supplied action itself encounters an exception, then the stage + * completes exceptionally with that exception unless the source stage + * also completed exceptionally, in which case the exceptional + * completion from the source stage is given preference and propagated + * to the dependent stage. Applications are encouraged to maintain + * these conventions, avoiding unnecessary nesting when rethrowing, as + * in {@code throw (ex instanceof CompletionException) ? ex : new + * CompletionException(ex)}. * * * @@ -137,7 +144,7 @@ * } * }} * - *

This interface does not define methods for initially creating, + *

The {@code CompletionStage} interface does not define methods for initially creating, * forcibly completing normally or exceptionally, probing completion * status or results, or awaiting completion of a stage. * Implementations of CompletionStage may provide means of achieving @@ -145,6 +152,13 @@ * enables interoperability among different implementations of this * interface by providing a common conversion type. * + *

Memory consistency effects: Actions in a thread prior to the + * submission of a computation producing a {@code CompletionStage} happen-before + * that computation begins. And actions taken by {@code + * CompletionStage x} happen-before actions of any dependent + * stage subsequent to {@code x}'s completion. + * * @param the type of values the stage produces or consumes * * @author Doug Lea @@ -153,8 +167,8 @@ public interface CompletionStage { /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied function. * *

This method is analogous to @@ -172,9 +186,9 @@ public interface CompletionStage { public CompletionStage thenApply(Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -189,8 +203,8 @@ public interface CompletionStage { (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -207,8 +221,8 @@ public interface CompletionStage { Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -221,9 +235,9 @@ public interface CompletionStage { public CompletionStage thenAccept(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -236,8 +250,8 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -251,7 +265,7 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -264,8 +278,8 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRun(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, executes the given action using this stage's default + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, executes the given action using {@code this} stage's default * asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules @@ -278,7 +292,7 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRunAsync(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action using the supplied Executor. * * See the {@link CompletionStage} documentation for rules @@ -293,7 +307,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied function. * @@ -312,8 +326,8 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied function. * @@ -332,7 +346,7 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied function. @@ -354,7 +368,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied action. * @@ -372,8 +386,8 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied action. * @@ -391,7 +405,7 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied action. @@ -412,7 +426,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -426,9 +440,9 @@ public CompletionStage thenRunAsync(Runnable action, public CompletionStage runAfterBoth(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -442,7 +456,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action * using the supplied executor. * @@ -459,7 +473,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied function. * @@ -477,8 +491,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied function. * @@ -496,7 +510,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied function. @@ -517,7 +531,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied action. * @@ -534,8 +548,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied action. * @@ -552,7 +566,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied action. @@ -572,7 +586,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -587,9 +601,9 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -604,7 +618,7 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action * using the supplied executor. * @@ -626,10 +640,10 @@ public CompletionStage runAfterEither(CompletionStage other, * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -652,13 +666,13 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function, - * executed using this stage's default asynchronous execution + * executed using {@code this} stage's default asynchronous execution * facility. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -679,10 +693,10 @@ public CompletionStage runAfterEither(CompletionStage other, * value as the CompletionStage returned by the given function, * executed using the supplied Executor. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned by {@code this} method is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -701,13 +715,13 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed with {@code this} stage's * result and exception as arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -719,14 +733,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed using this stage's - * default asynchronous execution facility, with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed using {@code this} stage's + * default asynchronous execution facility, with {@code this} stage's * result and exception as arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -738,14 +752,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * either normally or exceptionally, is executed using the - * supplied executor, with this stage's result and exception as + * supplied executor, with {@code this} stage's result and exception as * arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -760,22 +774,22 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action when this stage completes. + * {@code this} stage, that executes the given action when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked + *

When {@code this} stage is complete, the given action is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments. The returned + * {@code null} if none) of {@code this} stage as arguments. The returned * stage is completed when the action returns. * *

Unlike method {@link #handle handle}, - * this method is not designed to translate completion outcomes, + * method {@code whenComplete} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: if this stage completed + * if it does, the following rules apply: if {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -785,23 +799,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using this stage's - * default asynchronous execution facility when this stage completes. + * {@code this} stage, that executes the given action using {@code this} stage's + * default asynchronous execution facility when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked with the + *

When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

Unlike method {@link #handleAsync(BiFunction) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -811,23 +825,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using the supplied - * Executor when this stage completes. + * {@code this} stage, that executes the given action using the supplied + * Executor when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked with the + *

When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

Unlike method {@link #handleAsync(BiFunction,Executor) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @param executor the executor to use for asynchronous execution @@ -838,14 +852,14 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage */ @@ -853,10 +867,10 @@ public CompletionStage runAfterEither(CompletionStage other, (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function, using this stage's default - * asynchronous execution facility. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function, using {@code this} stage's default + * asynchronous execution facility. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * @@ -865,7 +879,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage * @since 12 @@ -879,10 +893,10 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the * argument to the supplied function, using the supplied Executor. - * Otherwise, if this stage completes normally, then the returned + * Otherwise, if {@code this} stage completes normally, then the returned * stage also completes normally with the same value. * * @implSpec The default implementation invokes {@link #handle}, @@ -890,7 +904,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage @@ -905,16 +919,16 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception. + * function applied to {@code this} stage's exception. * * @implSpec The default implementation invokes {@link #handle}, * invoking the given function on exception, then {@link * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -927,9 +941,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using this stage's + * function applied to {@code this} stage's exception, using {@code this} stage's * default asynchronous execution facility. * * @implSpec The default implementation invokes {@link #handle}, @@ -937,7 +951,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -951,9 +965,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using the + * function applied to {@code this} stage's exception, using the * supplied Executor. * * @implSpec The default implementation invokes {@link #handle}, @@ -961,7 +975,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage * @since 12 @@ -978,9 +992,9 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a {@link CompletableFuture} maintaining the same - * completion properties as this stage. If this stage is already a - * CompletableFuture, this method may return this stage itself. - * Otherwise, invocation of this method may be equivalent in + * completion properties as {@code this} stage. If {@code this} stage is already a + * CompletableFuture, method {@code toCompletableFuture} may return {@code this} stage itself. + * Otherwise, invocation may be equivalent in * effect to {@code thenApply(x -> x)}, but returning an instance * of type {@code CompletableFuture}. * diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index e417abd6c40..acbb306301e 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -148,7 +148,7 @@ *

Like {@link Hashtable} but unlike {@link HashMap}, this class * does not allow {@code null} to be used as a key or value. * - *

ConcurrentHashMaps support a set of sequential and parallel bulk + *

ConcurrentHashMaps support a set of sequential and parallel bulk * operations that, unlike most {@link Stream} methods, are designed * to be safely, and often sensibly, applied even with maps that are * being concurrently updated by other threads; for example, when @@ -3699,7 +3699,7 @@ final int batchFor(long b) { } /** - * Performs the given action for each (key, value). + * Performs the given {@linkplain ##Bulk bulk} action for each (key, value). * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -3715,7 +3715,7 @@ public void forEach(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each (key, value). * * @param parallelismThreshold the (estimated) number of elements @@ -3738,7 +3738,7 @@ public void forEach(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from applying the given {@linkplain ##Bulk bulk} search * function on each (key, value), or null if none. Upon * success, further element processing is suppressed and the * results of any other parallel invocations of the search @@ -3762,7 +3762,7 @@ public U search(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, or null if none. * @@ -3788,7 +3788,7 @@ public U reduce(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3814,7 +3814,7 @@ public double reduceToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3840,7 +3840,7 @@ public long reduceToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3866,7 +3866,7 @@ public int reduceToInt(long parallelismThreshold, } /** - * Performs the given action for each key. + * Performs the given {@linkplain ##Bulk bulk} action for each key. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -3882,7 +3882,7 @@ public void forEachKey(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each key. * * @param parallelismThreshold the (estimated) number of elements @@ -3905,7 +3905,7 @@ public void forEachKey(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from applying the given {@linkplain ##Bulk bulk} search * function on each key, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -3929,7 +3929,7 @@ public U searchKeys(long parallelismThreshold, } /** - * Returns the result of accumulating all keys using the given + * Returns the result of {@linkplain ##Bulk bulk} accumulating all keys using the given * reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -3948,7 +3948,7 @@ public K reduceKeys(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, or * null if none. * @@ -3974,7 +3974,7 @@ public U reduceKeys(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4000,7 +4000,7 @@ public double reduceKeysToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4026,7 +4026,7 @@ public long reduceKeysToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4052,7 +4052,7 @@ public int reduceKeysToInt(long parallelismThreshold, } /** - * Performs the given action for each value. + * Performs the given {@linkplain ##Bulk bulk} action for each value. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -4069,7 +4069,7 @@ public void forEachValue(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each value. * * @param parallelismThreshold the (estimated) number of elements @@ -4092,7 +4092,7 @@ public void forEachValue(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from {@linkplain ##Bulk bulk} applying the given search * function on each value, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -4116,7 +4116,7 @@ public U searchValues(long parallelismThreshold, } /** - * Returns the result of accumulating all values using the + * Returns the result of {@linkplain ##Bulk bulk} accumulating all values using the * given reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -4134,7 +4134,7 @@ public V reduceValues(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, or * null if none. * @@ -4160,7 +4160,7 @@ public U reduceValues(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4186,7 +4186,7 @@ public double reduceValuesToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4212,7 +4212,7 @@ public long reduceValuesToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4238,7 +4238,7 @@ public int reduceValuesToInt(long parallelismThreshold, } /** - * Performs the given action for each entry. + * Performs the given {@linkplain ##Bulk bulk} action for each entry. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -4253,7 +4253,7 @@ public void forEachEntry(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each entry. * * @param parallelismThreshold the (estimated) number of elements @@ -4276,7 +4276,7 @@ public void forEachEntry(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from {@linkplain ##Bulk bulk} applying the given search * function on each entry, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -4300,7 +4300,7 @@ public U searchEntries(long parallelismThreshold, } /** - * Returns the result of accumulating all entries using the + * Returns the result of {@linkplain ##Bulk bulk} accumulating all entries using the * given reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -4318,7 +4318,7 @@ public Map.Entry reduceEntries(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * or null if none. * @@ -4344,7 +4344,7 @@ public U reduceEntries(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * @@ -4370,7 +4370,7 @@ public double reduceEntriesToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * @@ -4396,7 +4396,7 @@ public long reduceEntriesToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * diff --git a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java index 87e498d9c24..ca78c254624 100644 --- a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java +++ b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java @@ -44,7 +44,10 @@ * useful in programs involving a fixed sized party of threads that * must occasionally wait for each other. The barrier is called * cyclic because it can be re-used after the waiting threads - * are released. + * are released. If you need support for variable numbers of parties + * per cycle, alternate actions on exceptions, termination control, + * contention control, or status monitoring, use the more flexible + * {@link Phaser} class. * *

A {@code CyclicBarrier} supports an optional {@link Runnable} command * that is run once per barrier point, after the last thread in the party diff --git a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java index 0d4acf8913e..f899b56b288 100644 --- a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java @@ -56,7 +56,9 @@ * *

Method {@code submit} extends base method {@link * Executor#execute(Runnable)} by creating and returning a {@link Future} - * that can be used to cancel execution and/or wait for completion. + * that can be used to cancel execution and/or wait for completion; + * also reporting exceptions that would otherwise be uncaught + * using method {@code execute}. * Methods {@code invokeAny} and {@code invokeAll} perform the most * commonly useful forms of bulk execution, executing a collection of * tasks and then waiting for at least one, or all, to diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index ba7c2e1efee..ef3d6348010 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -306,7 +306,7 @@ public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFa } /** - * Creates a thread pool that can schedule commands to run after a + * Creates a fixed-size thread pool that can schedule commands to run after a * given delay, or to execute periodically. * @param corePoolSize the number of threads to keep in the pool, * even if they are idle @@ -318,7 +318,7 @@ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) } /** - * Creates a thread pool that can schedule commands to run after a + * Creates a fixed-size thread pool that can schedule commands to run after a * given delay, or to execute periodically. * @param corePoolSize the number of threads to keep in the pool, * even if they are idle diff --git a/src/java.base/share/classes/java/util/concurrent/Flow.java b/src/java.base/share/classes/java/util/concurrent/Flow.java index 1aefaea43b0..16b2ba5e9d8 100644 --- a/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -60,7 +60,8 @@ * TRUE} item to a single subscriber. Because the subscriber receives * only a single item, this class does not use buffering and ordering * control required in most implementations (for example {@link - * SubmissionPublisher}). + * SubmissionPublisher}), and omits some error processing needed to + * fully conform to the Reactive Streams specification. * *

 {@code
  * class OneShotPublisher implements Publisher {
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index a7821921bc9..482fe3cf801 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -140,7 +140,7 @@
  * tasks, as well as method {@link #submitWithTimeout} to cancel tasks
  * that take too long. The scheduled functions or actions may create
  * and invoke other {@linkplain ForkJoinTask ForkJoinTasks}. Delayed
- * actions become enabled and behave as ordinary submitted
+ * actions become enabled for execution and behave as ordinary submitted
  * tasks when their delays elapse.  Scheduling methods return
  * {@linkplain ForkJoinTask ForkJoinTasks} that implement the {@link
  * ScheduledFuture} interface. Resource exhaustion encountered after
@@ -153,7 +153,7 @@
  * to disable all delayed tasks upon shutdown, and method {@link
  * #shutdownNow} may be used to instead unconditionally initiate pool
  * termination. Monitoring methods such as {@link #getQueuedTaskCount}
- * do not include scheduled tasks that are not yet enabled to execute,
+ * do not include scheduled tasks that are not yet enabled for execution,
  * which are reported separately by method {@link
  * #getDelayedTaskCount}.
  *
@@ -3505,7 +3505,7 @@ final  ScheduledForkJoinTask scheduleDelayedTask(ScheduledForkJoinTask
     }
 
     /**
-     * Submits a one-shot task that becomes enabled after the given
+     * Submits a one-shot task that becomes enabled for execution after the given
      * delay.  At that point it will execute unless explicitly
      * cancelled, or fail to execute (eventually reporting
      * cancellation) when encountering resource exhaustion, or the
@@ -3533,7 +3533,7 @@ public ScheduledFuture schedule(Runnable command,
     }
 
     /**
-     * Submits a value-returning one-shot task that becomes enabled
+     * Submits a value-returning one-shot task that becomes enabled for execution
      * after the given delay. At that point it will execute unless
      * explicitly cancelled, or fail to execute (eventually reporting
      * cancellation) when encountering resource exhaustion, or the
@@ -3562,7 +3562,7 @@ public  ScheduledFuture schedule(Callable callable,
     }
 
     /**
-     * Submits a periodic action that becomes enabled first after the
+     * Submits a periodic action that becomes enabled for execution first after the
      * given initial delay, and subsequently with the given period;
      * that is, executions will commence after
      * {@code initialDelay}, then {@code initialDelay + period}, then
@@ -3616,7 +3616,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command,
     }
 
     /**
-     * Submits a periodic action that becomes enabled first after the
+     * Submits a periodic action that becomes enabled for execution first after the
      * given initial delay, and subsequently with the given delay
      * between the termination of one execution and the commencement of
      * the next.
diff --git a/src/java.base/share/classes/java/util/concurrent/Future.java b/src/java.base/share/classes/java/util/concurrent/Future.java
index c6f3036c2d2..2ac837d7270 100644
--- a/src/java.base/share/classes/java/util/concurrent/Future.java
+++ b/src/java.base/share/classes/java/util/concurrent/Future.java
@@ -50,6 +50,26 @@
  * declare types of the form {@code Future} and
  * return {@code null} as a result of the underlying task.
  *
+ * 

Cancellation of a Future need not abruptly terminate its + * computation. Method {@code cancel} causes {@code isCancelled()} to + * return {@code true} unless already {@code isDone()}; in either case + * {@code isDone()} subsequently reports {@code true}. This suppresses + * execution by an {@link ExecutorService} if not already started. + * There are several options for suppressing unnecessary computation + * or unblocking a running Future that will not generate a + * result. When task bodies are simple and short, no special attention + * is warranted. Computational methods in Future-aware code bodies + * (for example {@link ForkJoinTask}, {@link FutureTask}) may inspect + * their own {@code isDone()} status before or while engaging in + * expensive computations. In blocking I/O or communication contexts, + * the optional {@code mayInterruptIfRunning} argument of {@code + * cancel} may be used to support conventions that tasks should + * unblock and exit when {@link Thread#interrupted}, whether checked + * inside a task body or as a response to an {@link + * InterruptedException}. It is still preferable to additionally + * check {@code isDone()} status when possible to avoid unintended + * effects of other uses of {@link Thread#interrupt}. + * *

Sample Usage (Note that the following classes are all * made-up.) * diff --git a/src/java.base/share/classes/java/util/concurrent/FutureTask.java b/src/java.base/share/classes/java/util/concurrent/FutureTask.java index b905e71aeef..2ec97629105 100644 --- a/src/java.base/share/classes/java/util/concurrent/FutureTask.java +++ b/src/java.base/share/classes/java/util/concurrent/FutureTask.java @@ -285,7 +285,9 @@ protected void done() { } * this future has already been set or has been cancelled. * *

This method is invoked internally by the {@link #run} method - * upon successful completion of the computation. + * upon successful completion of the computation. Invocation in + * other contexts has undefined effects. Any override of this + * method in subclasses should include {@code super.set(v)}. * * @param v the value */ diff --git a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java index b6b088ae7cd..8585cfe1082 100644 --- a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java @@ -47,8 +47,9 @@ */ public interface RunnableFuture extends Runnable, Future { /** - * Sets this Future to the result of its computation - * unless it has been cancelled. + * Sets this Future to the result of its computation unless it has + * been cancelled (or has already been invoked, in which case + * effects are undefined). */ void run(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java index 4d63ffae4bb..034d98687c2 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java @@ -40,10 +40,12 @@ * delay, or to execute periodically. * *

The {@code schedule} methods create tasks with various delays - * and return a task object that can be used to cancel or check - * execution. The {@code scheduleAtFixedRate} and - * {@code scheduleWithFixedDelay} methods create and execute tasks - * that run periodically until cancelled. + * and return {@link ScheduledFuture} objects that can be used to cancel or check + * execution. When delays elapse, tasks are enabled for execution and + * behave in accord with other {@link ExecutorService} tasks, except + * that {@code scheduleAtFixedRate} and {@code scheduleWithFixedDelay} + * methods create and execute tasks that run periodically until + * cancelled. * *

Commands submitted using the {@link Executor#execute(Runnable)} * and {@link ExecutorService} {@code submit} methods are scheduled @@ -91,7 +93,7 @@ public interface ScheduledExecutorService extends ExecutorService { /** - * Submits a one-shot task that becomes enabled after the given delay. + * Submits a one-shot task that becomes enabled for execution after the given delay. * * @param command the task to execute * @param delay the time from now to delay execution @@ -107,7 +109,7 @@ public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); /** - * Submits a value-returning one-shot task that becomes enabled + * Submits a value-returning one-shot task that becomes enabled for execution * after the given delay. * * @param callable the function to execute @@ -123,7 +125,7 @@ public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -167,7 +169,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 94f40ccf6f5..23398aeae28 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -57,7 +57,7 @@ * capabilities of {@link ThreadPoolExecutor} (which this class * extends) are required. * - *

Delayed tasks execute no sooner than they are enabled, but + *

Delayed tasks execute no sooner than they are enabled for execution, but * without any real-time guarantees about when, after they are * enabled, they will commence. Tasks scheduled for exactly the same * execution time are enabled in first-in-first-out (FIFO) order of @@ -568,7 +568,7 @@ public ScheduledFuture schedule(Callable callable, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -621,7 +621,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 3a8f3746637..f793d2bcabd 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -162,8 +162,8 @@ * (this.subscription = subscription).request(1); * } * public void onNext(S item) { - * subscription.request(1); * submit(function.apply(item)); + * subscription.request(1); * } * public void onError(Throwable ex) { closeExceptionally(ex); } * public void onComplete() { close(); } @@ -602,9 +602,11 @@ public int offer(T item, long timeout, TimeUnit unit, /** * Unless already closed, issues {@link * Flow.Subscriber#onComplete() onComplete} signals to current - * subscribers, and disallows subsequent attempts to publish. - * Upon return, this method does NOT guarantee that all - * subscribers have yet completed. + * subscribers, and disallows subsequent attempts to publish. To + * ensure uniform ordering among subscribers, this method may + * await completion of in-progress offers. Upon return, this + * method does NOT guarantee that all subscribers have + * yet completed. */ public void close() { ReentrantLock lock = this.lock; diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index f02aa9f5931..d116fb9b22b 100644 --- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -398,6 +398,8 @@ else if (s == MICRO_SCALE) * @param obj the object to wait on * @param timeout the maximum time to wait. If less than * or equal to zero, do not wait at all. + * @throws IllegalMonitorStateException if the current thread is not + * the owner of the object's monitor. * @throws InterruptedException if interrupted while waiting */ public void timedWait(Object obj, long timeout) diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index e01b3ec7d50..f947eb4f7db 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile int} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile int} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 57722f33371..b31a8edf53a 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile long} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile long} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 1c0c6d0afd0..e3ca4830d5a 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -46,11 +46,12 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile} reference fields of designated - * classes. This class is designed for use in atomic data structures - * in which several reference fields of the same node are - * independently subject to atomic updates. For example, a tree node - * might be declared as + * designated non-static {@code volatile} reference fields of + * designated classes, providing a subset of the functionality of + * class {@link VarHandle} that should be used instead. This class + * may be used in atomic data structures in which several reference + * fields of the same node are independently subject to atomic + * updates. For example, a tree node might be declared as * *

 {@code
  * class Node {
@@ -68,6 +69,26 @@
  *   // ... and so on
  * }}
* + * However, it is preferable to use {@link VarHandle}: + *
 {@code
+ * import java.lang.invoke.VarHandle;
+ * import java.lang.invoke.MethodHandles;
+ * class Node {
+ *  private volatile Node left, right;
+ *  private static final VarHandle LEFT, RIGHT;
+ *  Node getLeft() { return left; }
+ *  boolean compareAndSetLeft(Node expect, Node update) {
+ *    return LEFT.compareAndSet(this, expect, update);
+ *  }
+ *  // ... and so on
+ *  static { try {
+ *    MethodHandles.Lookup l = MethodHandles.lookup();
+ *    LEFT  = l.findVarHandle(Node.class, "left", Node.class);
+ *    RIGHT = l.findVarHandle(Node.class, "right", Node.class);
+ *   } catch (ReflectiveOperationException e) {
+ *     throw new ExceptionInInitializerError(e);
+ * }}}}
+ * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. * Because this class cannot ensure that all uses of the field diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index 3e0b293380f..536996fd273 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -97,6 +97,10 @@ * perform reads under read locks. If a reader tries to acquire the * write lock it will never succeed. * + *

Note: If you do not rely on reentrancy, you may find that {@link + * StampedLock} offers better performance, as in: {@code ReadWriteLock + * lock = new StampedLock().asReadWriteLock()}. + * *

  • Lock downgrading *

    Reentrancy also allows downgrading from the write lock to a read lock, * by acquiring the write lock, then the read lock and then releasing the @@ -734,11 +738,13 @@ protected ReadLock(ReentrantReadWriteLock lock) { * Acquires the read lock. * *

    Acquires the read lock if the write lock is not held by - * another thread and returns immediately. + * any thread and returns immediately. * - *

    If the write lock is held by another thread then - * the current thread becomes disabled for thread scheduling - * purposes and lies dormant until the read lock has been acquired. + *

    If the write lock is held by any thread or the fairness + * policy prohibits acquisition of the read lock at this time, + * then the current thread becomes disabled for thread + * scheduling purposes and lies dormant until the read lock + * has been acquired. */ public void lock() { sync.acquireShared(1); @@ -749,11 +755,13 @@ public void lock() { * {@linkplain Thread#interrupt interrupted}. * *

    Acquires the read lock if the write lock is not held - * by another thread and returns immediately. + * by any thread and returns immediately. * - *

    If the write lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of two things happens: + *

    If the write lock is held by any thread or the fairness + * policy prohibits acquisition of the read lock at this time, + * then the current thread becomes disabled for thread + * scheduling purposes and lies dormant until one of two + * things happens: * *

      * @@ -794,7 +802,7 @@ public void lockInterruptibly() throws InterruptedException { * another thread at the time of invocation. * *

      Acquires the read lock if the write lock is not held by - * another thread and returns immediately with the value + * any thread and returns immediately with the value * {@code true}. Even when this lock has been set to use a * fair ordering policy, a call to {@code tryLock()} * will immediately acquire the read lock if it is @@ -806,7 +814,7 @@ public void lockInterruptibly() throws InterruptedException { * tryLock(0, TimeUnit.SECONDS)} which is almost equivalent * (it also detects interruption). * - *

      If the write lock is held by another thread then + *

      If the write lock is held by any thread then * this method will return immediately with the value * {@code false}. * diff --git a/src/java.base/share/classes/java/util/concurrent/package-info.java b/src/java.base/share/classes/java/util/concurrent/package-info.java index dd0c8f79bc0..f237017799d 100644 --- a/src/java.base/share/classes/java/util/concurrent/package-info.java +++ b/src/java.base/share/classes/java/util/concurrent/package-info.java @@ -222,7 +222,9 @@ *

    • they are guaranteed to traverse elements as they existed upon * construction exactly once, and may (but are not guaranteed to) * reflect any modifications subsequent to construction. - *
    + *
  • These properties extend to other iteration-based + * operations. In particular, {@link Object#equals} is almost never + * useful unless both collections are known to be quiescent. * *

    Memory Consistency Properties

    * diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index b7f03c1b0af..2908370acd5 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -44,6 +44,7 @@ import java.util.stream.StreamSupport; import jdk.internal.util.ArraysSupport; +import jdk.internal.util.regex.CaseFolding; import jdk.internal.util.regex.Grapheme; /** @@ -2915,6 +2916,8 @@ private CharPredicate bitsOrSingle(BitClass bits, int ch) { toLowerCase(u+212a) ==> u+006B (6)AngstromSign u+212b toLowerCase(u+212b) ==> u+00e5 + (7) Latin Capital Letter Sharp S u+1e0e, was added in version 5.1 + toLowerCase(u+1e9e) ==> u+00df */ if (ch < 256 && !(has(CASE_INSENSITIVE) && has(UNICODE_CASE) && @@ -2922,7 +2925,11 @@ private CharPredicate bitsOrSingle(BitClass bits, int ch) { ch == 0x49 || ch == 0x69 || //I and i ch == 0x53 || ch == 0x73 || //S and s ch == 0x4b || ch == 0x6b || //K and k - ch == 0xc5 || ch == 0xe5))) { //A+ring + ch == 0xc5 || ch == 0xe5 || //A+ring + // need to force single() to use SingleU specifically for u+00df. + // u+00df <-> u+1e9e, see https://codepoints.net/U+00DF. + // Character.toUpperCase('u+00df') still returns u+00df for now. + ch == 0xdf))) { // Shape S bits.add(ch, flags0); return null; } @@ -2939,7 +2946,7 @@ private CharPredicate single(final int ch) { upper = Character.toUpperCase(ch); lower = Character.toLowerCase(upper); // Unicode case insensitive matches - if (upper != lower) + if (upper != lower || ch == 0xDF) return SingleU(lower); } else if (ASCII.isAscii(ch)) { lower = ASCII.toLower(ch); @@ -4154,7 +4161,7 @@ boolean match(Matcher matcher, int i, CharSequence seq) { if (predicate.is(ch0)) return next.match(matcher, j, seq); } else { - while (i + n < j) { + while (i + n <= j) { String nfc = Normalizer.normalize( seq.toString().substring(i, j), Normalizer.Form.NFC); if (nfc.codePointCount(0, nfc.length()) == 1) { @@ -4163,13 +4170,10 @@ boolean match(Matcher matcher, int i, CharSequence seq) { return true; } } - ch0 = Character.codePointBefore(seq, j); j -= Character.charCount(ch0); } } - if (j < matcher.to) - return false; } else { matcher.hitEnd = true; } @@ -5963,12 +5967,29 @@ static CharPredicate CIRange(int lower, int upper) { } static CharPredicate CIRangeU(int lower, int upper) { + int[] closingCharacters = CaseFolding.getClassRangeClosingCharacters(lower, upper); + if (closingCharacters.length == 0) { + return ch -> { + if (inRange(lower, ch, upper)) + return true; + int up = Character.toUpperCase(ch); + return (inRange(lower, up, upper) || + inRange(lower, Character.toLowerCase(up), upper)); + }; + } return ch -> { if (inRange(lower, ch, upper)) return true; int up = Character.toUpperCase(ch); - return inRange(lower, up, upper) || - inRange(lower, Character.toLowerCase(up), upper); + int lo = Character.toLowerCase(up); + if (inRange(lower, up, upper) || + inRange(lower, lo, upper)) + return true; + for (int cp : closingCharacters) { + if (up == cp || lo == cp) + return true; + } + return false; }; } diff --git a/src/java.base/share/classes/javax/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java index e729a984811..22dc66127e2 100644 --- a/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/src/java.base/share/classes/javax/crypto/Cipher.java @@ -316,19 +316,22 @@ private Cipher(CipherSpi firstSpi, Service firstService, private static final String SHA512TRUNCATED = "SHA512/2"; + // Parse the specified cipher transformation for algorithm and the + // optional mode and padding. If the transformation contains only + // algorithm, then only algorithm is returned. Otherwise, the + // transformation must contain all 3 and they must be non-empty. private static String[] tokenizeTransformation(String transformation) throws NoSuchAlgorithmException { if (transformation == null) { throw new NoSuchAlgorithmException("No transformation given"); } /* - * array containing the components of a cipher transformation: + * Components of a cipher transformation: * - * index 0: algorithm component (e.g., AES) - * index 1: feedback component (e.g., CFB) - * index 2: padding component (e.g., PKCS5Padding) + * 1) algorithm component (e.g., AES) + * 2) feedback component (e.g., CFB) - optional + * 3) padding component (e.g., PKCS5Padding) - optional */ - String[] parts = { "", "", "" }; // check if the transformation contains algorithms with "/" in their // name which can cause the parsing logic to go wrong @@ -337,27 +340,35 @@ private static String[] tokenizeTransformation(String transformation) int startIdx = (sha512Idx == -1 ? 0 : sha512Idx + SHA512TRUNCATED.length()); int endIdx = transformation.indexOf('/', startIdx); - if (endIdx == -1) { - // algorithm - parts[0] = transformation.trim(); + + boolean algorithmOnly = (endIdx == -1); + String algo = (algorithmOnly ? transformation.trim() : + transformation.substring(0, endIdx).trim()); + if (algo.isEmpty()) { + throw new NoSuchAlgorithmException("Invalid transformation: " + + "algorithm not specified-" + + transformation); + } + if (algorithmOnly) { // done + return new String[] { algo }; } else { - // algorithm/mode/padding - parts[0] = transformation.substring(0, endIdx).trim(); + // continue parsing mode and padding startIdx = endIdx+1; endIdx = transformation.indexOf('/', startIdx); if (endIdx == -1) { throw new NoSuchAlgorithmException("Invalid transformation" + " format:" + transformation); } - parts[1] = transformation.substring(startIdx, endIdx).trim(); - parts[2] = transformation.substring(endIdx+1).trim(); - } - if (parts[0].isEmpty()) { - throw new NoSuchAlgorithmException("Invalid transformation: " + - "algorithm not specified-" + String mode = transformation.substring(startIdx, endIdx).trim(); + String padding = transformation.substring(endIdx+1).trim(); + // ensure mode and padding are specified + if (mode.isEmpty() || padding.isEmpty()) { + throw new NoSuchAlgorithmException("Invalid transformation: " + + "missing mode and/or padding-" + transformation); + } + return new String[] { algo, mode, padding }; } - return parts; } // Provider attribute name for supported chaining mode @@ -453,28 +464,17 @@ private static List getTransforms(String transformation) throws NoSuchAlgorithmException { String[] parts = tokenizeTransformation(transformation); - String alg = parts[0]; - String mode = (parts[1].length() == 0 ? null : parts[1]); - String pad = (parts[2].length() == 0 ? null : parts[2]); - - if ((mode == null) && (pad == null)) { + if (parts.length == 1) { // Algorithm only - Transform tr = new Transform(alg, "", null, null); - return Collections.singletonList(tr); + return List.of(new Transform(parts[0], "", null, null)); } else { - // Algorithm w/ at least mode or padding or both - List list = new ArrayList<>(4); - if ((mode != null) && (pad != null)) { - list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); - } - if (mode != null) { - list.add(new Transform(alg, "/" + mode, null, pad)); - } - if (pad != null) { - list.add(new Transform(alg, "//" + pad, mode, null)); - } - list.add(new Transform(alg, "", mode, pad)); - return list; + // Algorithm w/ both mode and padding + return List.of( + new Transform(parts[0], "/" + parts[1] + "/" + parts[2], + null, null), + new Transform(parts[0], "/" + parts[1], null, parts[2]), + new Transform(parts[0], "//" + parts[2], parts[1], null), + new Transform(parts[0], "", parts[1], parts[2])); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java index f93e90723ea..f683e259d3d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java @@ -442,6 +442,7 @@ public void writeIndex(PoolEntry entry) { writeU2(cpIndex(entry)); } + // Null checks entry public void writeIndex(int bytecode, PoolEntry entry) { writeU1U2(bytecode, cpIndex(entry)); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index e86847af710..32b26d54d6d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -207,7 +207,6 @@ private void writeExceptionHandlers(BufWriterImpl buf, int pos) { } else { buf.writeU2U2U2(startPc, endPc, handlerPc); buf.writeIndexOrZero(h.catchTypeEntry()); - handlersSize++; } } if (handlersSize < handlers.size()) @@ -563,8 +562,8 @@ private void writeLongLabelOffset(int instructionPc, Label label) { } private void writeShortJump(int bytecode, Label target) { + int targetBci = labelToBci(target); // implicit null check int instructionPc = curPc(); - int targetBci = labelToBci(target); // algebraic union of jump | (instructionPc, target), distinguished by null == target. int jumpOrInstructionPc; @@ -587,6 +586,7 @@ private void writeShortJump(int bytecode, Label target) { } private void writeLongJump(int bytecode, Label target) { + Objects.requireNonNull(target); // before any write int instructionPc = curPc(); bytecodesBufWriter.writeU1(bytecode); writeLongLabelOffset(instructionPc, target); @@ -634,6 +634,17 @@ private void writeParsedLongLabel(int jumpOrInstructionPc, Label nullOrTarget) { } public void writeLookupSwitch(Label defaultTarget, List cases) { + cases = new ArrayList<>(cases); // cases may be untrusted + for (var each : cases) { + Objects.requireNonNull(each); // single null case may exist + } + cases.sort(new Comparator<>() { + @Override + public int compare(SwitchCase c1, SwitchCase c2) { + return Integer.compare(c1.caseValue(), c2.caseValue()); + } + }); + // validation end int instructionPc = curPc(); bytecodesBufWriter.writeU1(LOOKUPSWITCH); int pad = 4 - (curPc() % 4); @@ -641,13 +652,6 @@ public void writeLookupSwitch(Label defaultTarget, List cases) { bytecodesBufWriter.skip(pad); // padding content can be anything writeLongLabelOffset(instructionPc, defaultTarget); bytecodesBufWriter.writeInt(cases.size()); - cases = new ArrayList<>(cases); - cases.sort(new Comparator<>() { - @Override - public int compare(SwitchCase c1, SwitchCase c2) { - return Integer.compare(c1.caseValue(), c2.caseValue()); - } - }); for (var c : cases) { bytecodesBufWriter.writeInt(c.caseValue()); var target = c.target(); @@ -656,6 +660,11 @@ public int compare(SwitchCase c1, SwitchCase c2) { } public void writeTableSwitch(int low, int high, Label defaultTarget, List cases) { + var caseMap = new HashMap(cases.size()); // cases may be untrusted + for (var c : cases) { + caseMap.put(c.caseValue(), c.target()); + } + // validation end int instructionPc = curPc(); bytecodesBufWriter.writeU1(TABLESWITCH); int pad = 4 - (curPc() % 4); @@ -663,10 +672,6 @@ public void writeTableSwitch(int low, int high, Label defaultTarget, List(cases.size()); - for (var c : cases) { - caseMap.put(c.caseValue(), c.target()); - } for (long l = low; l<=high; l++) { var target = caseMap.getOrDefault((int)l, defaultTarget); writeLongLabelOffset(instructionPc, target); @@ -945,6 +950,7 @@ public CodeBuilder invoke(Opcode opcode, MemberRefEntry ref) { int slots = Util.parameterSlots(Util.methodTypeSymbol(ref.type())) + 1; writeInvokeInterface(opcode, (InterfaceMethodRefEntry) ref, slots); } else { + Util.checkKind(opcode, Opcode.Kind.INVOKE); writeInvokeNormal(opcode, ref); } return this; @@ -976,7 +982,8 @@ public CodeBuilder getfield(ClassDesc owner, String name, ClassDesc type) { @Override public CodeBuilder fieldAccess(Opcode opcode, FieldRefEntry ref) { - bytecodesBufWriter.writeIndex(opcode.bytecode(), ref); + Util.checkKind(opcode, Opcode.Kind.FIELD_ACCESS); + writeFieldAccess(opcode, ref); return this; } @@ -994,6 +1001,7 @@ public CodeBuilder arrayStore(TypeKind tk) { @Override public CodeBuilder branch(Opcode op, Label target) { + Util.checkKind(op, Opcode.Kind.BRANCH); writeBranch(op, target); return this; } @@ -1657,6 +1665,8 @@ public CodeBuilder ixor() { @Override public CodeBuilder lookupswitch(Label defaultTarget, List cases) { + Objects.requireNonNull(defaultTarget); + // check cases when we sort them writeLookupSwitch(defaultTarget, cases); return this; } @@ -1816,6 +1826,7 @@ public CodeBuilder monitorexit() { @Override public CodeBuilder multianewarray(ClassEntry array, int dims) { + BytecodeHelpers.validateMultiArrayDimensions(dims); writeNewMultidimensionalArray(dims, array); return this; } @@ -1862,6 +1873,8 @@ public CodeBuilder swap() { @Override public CodeBuilder tableswitch(int low, int high, Label defaultTarget, List cases) { + Objects.requireNonNull(defaultTarget); + // check cases when we write them writeTableSwitch(low, high, defaultTarget, cases); return this; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java index 0775d800127..225b58176b0 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -44,12 +44,11 @@ import static java.lang.constant.ConstantDescs.CLASS_INIT_NAME; import static java.lang.constant.ConstantDescs.INIT_NAME; -/** - * ParserVerifier performs selected checks of the class file format according to - * {@jvms 4.8 Format Checking} - * - * @see hotspot/share/classfile/classFileParser.cpp - */ +/// ParserVerifier performs selected checks of the class file format according to +/// {@jvms 4.8 Format Checking}. +/// +/// From `classFileParser.cpp`. +/// public record ParserVerifier(ClassModel classModel) { List verify() { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationBytecodes.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationBytecodes.java index a7d97c7ea37..8bd964650d3 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationBytecodes.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationBytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,10 +29,7 @@ import static jdk.internal.classfile.impl.RawBytecodeHelper.*; import static jdk.internal.classfile.impl.verifier.VerificationSignature.BasicType.*; -/** - * @see hotspot/share/interpreter/bytecodes.hpp - * @see hotspot/share/interpreter/bytecodes.cpp - */ +/// From `bytecodes.cpp`. final class VerificationBytecodes { static final int _breakpoint = 202, diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java index 13aac2c92c6..07a3de21cc1 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -26,10 +26,7 @@ import java.util.Arrays; -/** - * @see hotspot/share/classfile/stackMapFrame.hpp - * @see hotspot/share/classfile/stackMapFrame.cpp - */ +/// From `stackMapFrame.cpp`. class VerificationFrame { public static final int FLAG_THIS_UNINIT = 0x01; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationSignature.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationSignature.java index 9fa4a377852..4c0b21b6a37 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationSignature.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,6 +24,7 @@ */ package jdk.internal.classfile.impl.verifier; +/// Relevant parts from `signatures.cpp`, such as `SignatureStream`. final class VerificationSignature { enum BasicType { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java index d5447d74316..783f52832fe 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java @@ -24,19 +24,19 @@ */ package jdk.internal.classfile.impl.verifier; +import java.util.ArrayList; +import java.util.List; + import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Object; import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Uninitialized; import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_UninitializedThis; -/** - * @see hotspot/share/classfile/stackMapTable.hpp - * @see hotspot/share/classfile/stackMapTable.cpp - */ +/// From `stackMapTable.cpp`. class VerificationTable { private final int _code_length; private final int _frame_count; - private final VerificationFrame[] _frame_array; + private final List _frame_array; private final VerifierImpl _verifier; int get_frame_count() { @@ -44,7 +44,7 @@ int get_frame_count() { } int get_offset(int index) { - return _frame_array[index].offset(); + return _frame_array.get(index).offset(); } static class StackMapStream { @@ -76,32 +76,28 @@ boolean at_end() { } } - VerificationTable(byte[] stackmap_data, VerificationFrame init_frame, int max_locals, int max_stack, byte[] code_data, int code_len, + VerificationTable(StackMapReader reader, VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl v) { _verifier = v; - var reader = new StackMapReader(stackmap_data, code_data, code_len, cp, v); - _code_length = code_len; - _frame_count = reader.get_frame_count(); - _frame_array = new VerificationFrame[_frame_count]; + _code_length = reader.code_length(); + int _frame_count = reader.get_frame_count(); + _frame_array = new ArrayList<>(_frame_count); if (_frame_count > 0) { - VerificationFrame pre_frame = init_frame; - for (int i = 0; i < _frame_count; i++) { - VerificationFrame frame = reader.next(pre_frame, i == 0, max_locals, max_stack); - _frame_array[i] = frame; - int offset = frame.offset(); - if (offset >= code_len || code_data[offset] == 0) { - _verifier.verifyError("StackMapTable error: bad offset"); + while (!reader.at_end()) { + VerificationFrame frame = reader.next(); + if (frame != null) { + _frame_array.add(frame); } - pre_frame = frame; } } reader.check_end(); + this._frame_count = _frame_array.size(); } int get_index_from_offset(int offset) { int i = 0; for (; i < _frame_count; i++) { - if (_frame_array[i].offset() == offset) { + if (_frame_array.get(i).offset() == offset) { return i; } } @@ -117,7 +113,7 @@ boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boo if (frame_index < 0 || frame_index >= _frame_count) { _verifier.verifyError(String.format("Expecting a stackmap frame at branch target %d", target)); } - VerificationFrame stackmap_frame = _frame_array[frame_index]; + VerificationFrame stackmap_frame = _frame_array.get(frame_index); boolean result = true; if (match) { result = frame.is_assignable_to(stackmap_frame); @@ -151,6 +147,10 @@ static class StackMapReader { private final byte[] _code_data; private final int _code_length; private final int _frame_count; + private int _parsed_frame_count; + private VerificationFrame _prev_frame; + char _max_locals, _max_stack; + boolean _first; void check_verification_type_array_size(int size, int max_size) { if (size < 0 || size > max_size) { @@ -169,25 +169,73 @@ public int get_frame_count() { return _frame_count; } + public VerificationFrame prev_frame() { + return _prev_frame; + } + + public byte[] code_data() { + return _code_data; + } + + public int code_length() { + return _code_length; + } + + public boolean at_end() { + return _stream.at_end(); + } + + public VerificationFrame next() { + _parsed_frame_count++; + check_size(); + VerificationFrame frame = next_helper(); + if (frame != null) { + check_offset(frame); + _prev_frame = frame; + } + return frame; + } + public void check_end() { - if (!_stream.at_end()) { - _verifier.classError("wrong attribute size"); + if (_frame_count != _parsed_frame_count) { + _verifier.verifyError("wrong attribute size"); } } private final VerifierImpl _verifier; - public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len, VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl context) { + public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len, + VerificationFrame init_frame, char max_locals, char max_stack, + VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl context) { this._verifier = context; _stream = new StackMapStream(stackmapData, _verifier); + _code_data = code_data; + _code_length = code_len; + _parsed_frame_count = 0; + _prev_frame = init_frame; + _max_locals = max_locals; + _max_stack = max_stack; + _first = true; if (stackmapData != null) { + _cp = cp; _frame_count = _stream.get_u2(); } else { + _cp = null; _frame_count = 0; } - _code_data = code_data; - _code_length = code_len; - _cp = cp; + } + + void check_offset(VerificationFrame frame) { + int offset = frame.offset(); + if (offset >= _code_length || _code_data[offset] == 0) { + _verifier.verifyError("StackMapTable error: bad offset"); + } + } + + void check_size() { + if (_frame_count < _parsed_frame_count) { + _verifier.verifyError("wrong attribute size"); + } } int chop(VerificationType[] locals, int length, int chops) { @@ -234,36 +282,37 @@ VerificationType parse_verification_type(int[] flags) { return VerificationType.bogus_type; } - public VerificationFrame next(VerificationFrame pre_frame, boolean first, int max_locals, int max_stack) { + VerificationFrame next_helper() { VerificationFrame frame; int offset; VerificationType[] locals = null; int frame_type = _stream.get_u1(); if (frame_type < 64) { - if (first) { + if (_first) { offset = frame_type; - if (pre_frame.locals_size() > 0) { - locals = new VerificationType[pre_frame.locals_size()]; + if (_prev_frame.locals_size() > 0) { + locals = new VerificationType[_prev_frame.locals_size()]; } } else { - offset = pre_frame.offset() + frame_type + 1; - locals = pre_frame.locals(); + offset = _prev_frame.offset() + frame_type + 1; + locals = _prev_frame.locals(); } - frame = new VerificationFrame(offset, pre_frame.flags(), pre_frame.locals_size(), 0, max_locals, max_stack, locals, null, _verifier); - if (first && locals != null) { - frame.copy_locals(pre_frame); + frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _verifier); + if (_first && locals != null) { + frame.copy_locals(_prev_frame); } + _first = false; return frame; } if (frame_type < 128) { - if (first) { + if (_first) { offset = frame_type - 64; - if (pre_frame.locals_size() > 0) { - locals = new VerificationType[pre_frame.locals_size()]; + if (_prev_frame.locals_size() > 0) { + locals = new VerificationType[_prev_frame.locals_size()]; } } else { - offset = pre_frame.offset() + frame_type - 63; - locals = pre_frame.locals(); + offset = _prev_frame.offset() + frame_type - 63; + locals = _prev_frame.locals(); } VerificationType[] stack = new VerificationType[2]; int stack_size = 1; @@ -272,11 +321,12 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma stack[1] = stack[0].to_category2_2nd(_verifier); stack_size = 2; } - check_verification_type_array_size(stack_size, max_stack); - frame = new VerificationFrame(offset, pre_frame.flags(), pre_frame.locals_size(), stack_size, max_locals, max_stack, locals, stack, _verifier); - if (first && locals != null) { - frame.copy_locals(pre_frame); + check_verification_type_array_size(stack_size, _max_stack); + frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier); + if (_first && locals != null) { + frame.copy_locals(_prev_frame); } + _first = false; return frame; } int offset_delta = _stream.get_u2(); @@ -284,14 +334,14 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma _verifier.classError("reserved frame type"); } if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { - if (first) { + if (_first) { offset = offset_delta; - if (pre_frame.locals_size() > 0) { - locals = new VerificationType[pre_frame.locals_size()]; + if (_prev_frame.locals_size() > 0) { + locals = new VerificationType[_prev_frame.locals_size()]; } } else { - offset = pre_frame.offset() + offset_delta + 1; - locals = pre_frame.locals(); + offset = _prev_frame.offset() + offset_delta + 1; + locals = _prev_frame.locals(); } VerificationType[] stack = new VerificationType[2]; int stack_size = 1; @@ -300,22 +350,23 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma stack[1] = stack[0].to_category2_2nd(_verifier); stack_size = 2; } - check_verification_type_array_size(stack_size, max_stack); - frame = new VerificationFrame(offset, pre_frame.flags(), pre_frame.locals_size(), stack_size, max_locals, max_stack, locals, stack, _verifier); - if (first && locals != null) { - frame.copy_locals(pre_frame); + check_verification_type_array_size(stack_size, _max_stack); + frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier); + if (_first && locals != null) { + frame.copy_locals(_prev_frame); } + _first = false; return frame; } if (frame_type <= SAME_EXTENDED) { - locals = pre_frame.locals(); - int length = pre_frame.locals_size(); + locals = _prev_frame.locals(); + int length = _prev_frame.locals_size(); int chops = SAME_EXTENDED - frame_type; int new_length = length; - int flags = pre_frame.flags(); + int flags = _prev_frame.flags(); if (chops != 0) { new_length = chop(locals, length, chops); - check_verification_type_array_size(new_length, max_locals); + check_verification_type_array_size(new_length, _max_locals); flags = 0; for (int i=0; i 0) { locals = new VerificationType[new_length]; @@ -332,24 +383,25 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma locals = null; } } else { - offset = pre_frame.offset() + offset_delta + 1; + offset = _prev_frame.offset() + offset_delta + 1; } - frame = new VerificationFrame(offset, flags, new_length, 0, max_locals, max_stack, locals, null, _verifier); - if (first && locals != null) { - frame.copy_locals(pre_frame); + frame = new VerificationFrame(offset, flags, new_length, 0, _max_locals, _max_stack, locals, null, _verifier); + if (_first && locals != null) { + frame.copy_locals(_prev_frame); } + _first = false; return frame; } else if (frame_type < SAME_EXTENDED + 4) { int appends = frame_type - SAME_EXTENDED; - int real_length = pre_frame.locals_size(); + int real_length = _prev_frame.locals_size(); int new_length = real_length + appends*2; locals = new VerificationType[new_length]; - VerificationType[] pre_locals = pre_frame.locals(); + VerificationType[] pre_locals = _prev_frame.locals(); int i; - for (i=0; ihotspot/share/classfile/verificationType.hpp - * @see hotspot/share/classfile/verificationType.cpp - */ +/// From `verificationType.cpp`. class VerificationType { private static final int BitsPerByte = 8; @@ -332,7 +329,7 @@ private boolean _is_assignable_from(VerificationType from, VerifierImpl context) return from.is_integer(); default: if (is_reference() && from.is_reference()) { - return is_reference_assignable_from(from, context); + return is_reference_assignable_from(from, context, null); } else { return false; } @@ -379,18 +376,25 @@ static VerificationType from_tag(int tag, VerifierImpl context) { } } - boolean resolve_and_check_assignability(ClassHierarchyImpl assignResolver, String name, String from_name, boolean from_is_array, boolean from_is_object) { + boolean resolve_and_check_assignability(ClassHierarchyImpl assignResolver, String target_name, String from_name, + boolean from_is_array, boolean from_is_object, boolean[] target_is_interface) { //let's delegate assignability to SPI - var desc = Util.toClassDesc(name); - if (assignResolver.isInterface(desc)) { - return !from_is_array || "java/lang/Cloneable".equals(name) || "java/io/Serializable".equals(name); + var targetClass = Util.toClassDesc(target_name); + boolean isInterface = assignResolver.isInterface(targetClass); + + if (target_is_interface != null) { + target_is_interface[0] = isInterface; + } + + if (isInterface) { + return !from_is_array || "java/lang/Cloneable".equals(target_name) || "java/io/Serializable".equals(target_name); } else if (from_is_object) { - return assignResolver.isAssignableFrom(desc, Util.toClassDesc(from_name)); + return assignResolver.isAssignableFrom(targetClass, Util.toClassDesc(from_name)); } return false; } - boolean is_reference_assignable_from(VerificationType from, VerifierImpl context) { + boolean is_reference_assignable_from(VerificationType from, VerifierImpl context, boolean[] target_is_interface) { ClassHierarchyImpl clsTree = context.class_hierarchy(); if (from.is_null()) { return true; @@ -402,7 +406,7 @@ boolean is_reference_assignable_from(VerificationType from, VerifierImpl context if (VerifierImpl.java_lang_Object.equals(name())) { return true; } - return resolve_and_check_assignability(clsTree, name(), from.name(), from.is_array(), from.is_object()); + return resolve_and_check_assignability(clsTree, name(), from.name(), from.is_array(), from.is_object(), target_is_interface); } else if (is_array() && from.is_array()) { VerificationType comp_this = get_component(context); VerificationType comp_from = from.get_component(context); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java index 4c2104c5a78..dc0a26fbbc7 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -42,16 +42,12 @@ import static jdk.internal.classfile.impl.verifier.VerificationSignature.BasicType.T_BOOLEAN; import static jdk.internal.classfile.impl.verifier.VerificationSignature.BasicType.T_LONG; -/** - * VerifierImpl performs selected checks and verifications of the class file - * format according to {@jvms 4.8 Format Checking}, - * {@jvms 4.9 Constraints on Java Virtual Machine code}, - * {@jvms 4.10 Verification of class Files} and {@jvms 6.5 Instructions} - * - * @see java.base/share/native/include/classfile_constants.h.template - * @see hotspot/share/classfile/verifier.hpp - * @see hotspot/share/classfile/verifier.cpp - */ +/// VerifierImpl performs selected checks and verifications of the class file +/// format according to {@jvms 4.8 Format Checking}, +/// {@jvms 4.9 Constraints on Java Virtual Machine code}, +/// {@jvms 4.10 Verification of class Files} and {@jvms 6.5 Instructions} +/// +/// From `verifier.cpp`. public final class VerifierImpl { static final int JVM_CONSTANT_Utf8 = 1, @@ -142,11 +138,8 @@ public static List verify(ClassModel classModel, ClassHierarchyReso } public static boolean is_eligible_for_verification(VerificationWrapper klass) { - String name = klass.thisClassName(); - return !java_lang_Object.equals(name) && - !java_lang_Class.equals(name) && - !java_lang_String.equals(name) && - !java_lang_Throwable.equals(name); + // 8330606 Not applicable here + return true; } static List inference_verify(VerificationWrapper klass) { @@ -323,7 +316,9 @@ void verify_method(VerificationWrapper.MethodWrapper m) { verify_exception_handler_table(code_length, code_data, ex_minmax); verify_local_variable_table(code_length, code_data); - VerificationTable stackmap_table = new VerificationTable(stackmap_data, current_frame, max_locals, max_stack, code_data, code_length, cp, this); + var reader = new VerificationTable.StackMapReader(stackmap_data, code_data, code_length, current_frame, + (char) max_locals, (char) max_stack, cp, this); + VerificationTable stackmap_table = new VerificationTable(reader, cp, this); var bcs = code.start(); boolean no_control_flow = false; @@ -1052,13 +1047,11 @@ void verify_method(VerificationWrapper.MethodWrapper m) { no_control_flow = false; break; case IF_ACMPEQ : case IF_ACMPNE : - current_frame.pop_stack( - VerificationType.reference_check); + current_frame.pop_stack(object_type()); // fall through case IFNULL : case IFNONNULL : - current_frame.pop_stack( - VerificationType.reference_check); + current_frame.pop_stack(object_type()); target = bcs.dest(); stackmap_table.check_jump_target (current_frame, target); @@ -1270,6 +1263,7 @@ void verify_exception_handler_table(int code_length, byte[] code_data, int[] min if (catch_type_index != 0) { VerificationType catch_type = cp_index_to_type(catch_type_index, cp); VerificationType throwable = VerificationType.reference_type(java_lang_Throwable); + // 8267118 Not applicable here boolean is_subclass = throwable.is_assignable_from(catch_type, this); if (!is_subclass) { verifyError(String.format("Catch type is not a subclass of Throwable in exception handler %d", handler_pc)); @@ -1353,7 +1347,7 @@ void verify_cp_index(int bci, ConstantPoolWrapper cp, int index) { void verify_cp_type(int bci, int index, ConstantPoolWrapper cp, int types) { verify_cp_index(bci, cp, index); int tag = cp.tagAt(index); - if ((types & (1 << tag))== 0) { + if (tag > JVM_CONSTANT_ExternalMax || (types & (1 << tag))== 0) { verifyError(String.format("Illegal type at constant pool entry %d", index)); } } @@ -1432,10 +1426,11 @@ void verify_switch(RawBytecodeHelper bcs, int code_length, byte[] code_data, Ver if (low > high) { verifyError("low must be less than or equal to high in tableswitch"); } - keys = high - low + 1; - if (keys < 0) { + long keys64 = ((long) high - low) + 1; + if (keys64 > 65535) { // Max code length verifyError("too many keys in tableswitch"); } + keys = (int) keys64; delta = 1; } else { // Make sure that the lookupswitch items are sorted @@ -1492,6 +1487,7 @@ void verify_field_instructions(RawBytecodeHelper bcs, VerificationFrame current_ case GETFIELD -> { stack_object_type = current_frame.pop_stack( target_class_type); + // 8270398 Not applicable here for (int i = 0; i < n; i++) { current_frame.push_stack(field_type[i]); } @@ -1643,12 +1639,29 @@ boolean verify_invoke_instructions(RawBytecodeHelper bcs, int code_length, Verif && !is_same_or_direct_interface(current_class(), current_type(), ref_class_type) && !ref_class_type.equals(VerificationType.reference_type( current_class().superclassName()))) { - boolean have_imr_indirect = cp.tagAt(index) == JVM_CONSTANT_InterfaceMethodref; - boolean subtype = ref_class_type.is_assignable_from(current_type(), this); - if (!subtype) { + + // We know it is not current class, direct superinterface or immediate superclass. That means it + // could be: + // - a totally unrelated class or interface + // - an indirect superinterface + // - an indirect superclass (including Object) + // We use the assignability test to see if it is a superclass, or else an interface, and keep track + // of the latter. Note that subtype can be true if we are dealing with an interface that is not actually + // implemented as assignability treats all interfaces as Object. + + boolean[] is_interface = {false}; // This can only be set true if the assignability check will return true + // and we loaded the class. For any other "true" returns (e.g. same class + // or Object) we either can't get here (same class already excluded above) + // or we know it is not an interface (i.e. Object). + boolean subtype = ref_class_type.is_reference_assignable_from(current_type(), this, is_interface); + if (!subtype) { // Totally unrelated class verifyError("Bad invokespecial instruction: current class isn't assignable to reference class."); - } else if (have_imr_indirect) { - verifyError("Bad invokespecial instruction: interface method reference is in an indirect superinterface."); + } else { + // Indirect superclass (including Object), indirect interface, or unrelated interface. + // Any interface use is an error. + if (is_interface[0]) { + verifyError("Bad invokespecial instruction: interface method to invoke is not in a direct superinterface."); + } } } @@ -1817,7 +1830,7 @@ void verify_iinc(int index, VerificationFrame current_frame) { void verify_return_value(VerificationType return_type, VerificationType type, int bci, VerificationFrame current_frame) { if (return_type.is_bogus()) { - verifyError("Method expects a return value"); + verifyError("Method does not expect a return value"); } boolean match = return_type.is_assignable_from(type, this); if (!match) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md new file mode 100644 index 00000000000..1899f7b86a3 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/verifier.md @@ -0,0 +1,20 @@ +The Class-File Verifier +=== +The Class-File API provides a verifier, a debug utility that reports as many +verification errors as possible in a class file. + +Currently, the verifier closely follows the C++ code that implements the hotspot +verifier. However, there are a few differences: +- The Class-File API verifier tries to collect as many errors as possible, while + the hotspot verifier fails fast. +- The hotspot verifier has access to other classes and can check access control; + the Class-File API verifier cannot. + +Thus, this verifier cannot serve as a complete implementation of the verifier +specified in the JVMS because it has no access to other class files or loaded +classes. However, it is still in our interest to make this verifier up to date: +for example, this should not fail upon encountering new language features, and +should at best include all new checks hotspot has as long as the required +information are accessible to the Class-File API. + +Last sync: jdk-26+5, July 3rd 2025 diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java index f63665119e2..49c914465ed 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -30,6 +30,23 @@ import java.util.Objects; /** + * Defines the header and version information for jimage files. + * + *

    Version number changes must be synced in a single change across all code + * which reads/writes jimage files, and code which tries to open a jimage file + * with an unexpected version should fail. + * + *

    Known jimage file code which needs updating on version change: + *

      + *
    • src/java.base/share/native/libjimage/imageFile.hpp + *
    + * + *

    Version history: + *

      + *
    • {@code 1.0}: Original version. + *
    • {@code 1.1}: Change package entry flags to support preview mode. + *
    + * * @implNote This class needs to maintain JDK 8 source compatibility. * * It is used internally in the JDK to implement jimage/jrtfs access, @@ -39,7 +56,7 @@ public final class ImageHeader { public static final int MAGIC = 0xCAFEDADA; public static final int MAJOR_VERSION = 1; - public static final int MINOR_VERSION = 0; + public static final int MINOR_VERSION = 1; private static final int HEADER_SLOTS = 7; private final int magic; diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java index f31c7291927..42f532c6ae2 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -27,6 +27,7 @@ import java.nio.ByteBuffer; import java.util.Objects; +import java.util.function.Predicate; /** * @implNote This class needs to maintain JDK 8 source compatibility. @@ -44,7 +45,82 @@ public class ImageLocation { public static final int ATTRIBUTE_OFFSET = 5; public static final int ATTRIBUTE_COMPRESSED = 6; public static final int ATTRIBUTE_UNCOMPRESSED = 7; - public static final int ATTRIBUTE_COUNT = 8; + public static final int ATTRIBUTE_PREVIEW_FLAGS = 8; + public static final int ATTRIBUTE_COUNT = 9; + + // Flag masks for the ATTRIBUTE_PREVIEW_FLAGS attribute. Defined so + // that zero is the overwhelmingly common case for normal resources. + + /** + * Set on a "normal" (non-preview) location if a preview version + * of it exists in the same module (can apply to both resources + * and directories in the {@code /modules/xxx/...} namespace). + */ + public static final int FLAGS_HAS_PREVIEW_VERSION = 0x1; + /** + * Set on all preview locations in the {@code /modules/xxx/...} namespace. + */ + public static final int FLAGS_IS_PREVIEW_VERSION = 0x2; + /** + * Set on a preview location if no normal (non-preview) version + * of it exists in the same module (can apply to both resources + * and directories in the {@code /modules/xxx/...} namespace). + */ + public static final int FLAGS_IS_PREVIEW_ONLY = 0x4; + /** + * This flag identifies the unique {@code "/packages"} location, and + * is used to determine the {@link LocationType} without additional + * string comparison. + */ + public static final int FLAGS_IS_PACKAGE_ROOT = 0x8; + + // Also used in ImageReader. + static final String MODULES_PREFIX = "/modules"; + static final String PACKAGES_PREFIX = "/packages"; + static final String PREVIEW_INFIX = "/META-INF/preview"; + + /** + * Helper function to calculate preview flags (ATTRIBUTE_PREVIEW_FLAGS). + * + *

    Since preview flags are calculated separately for resource nodes and + * directory nodes (in two quite different places) it's useful to have a + * common helper. + * + * @param name the jimage name of the resource or directory. + * @param hasEntry a predicate for jimage names returning whether an entry + * is present. + * @return flags for the ATTRIBUTE_PREVIEW_FLAGS attribute. + */ + public static int getFlags(String name, Predicate hasEntry) { + if (name.startsWith(PACKAGES_PREFIX + "/")) { + throw new IllegalArgumentException("Package sub-directory flags handled separately: " + name); + } + String start = name.startsWith(MODULES_PREFIX + "/") ? MODULES_PREFIX + "/" : "/"; + int idx = name.indexOf('/', start.length()); + if (idx == -1) { + // Special case for "/packages" root, but otherwise, no flags. + return name.equals(PACKAGES_PREFIX) ? FLAGS_IS_PACKAGE_ROOT : 0; + } + String prefix = name.substring(0, idx); + String suffix = name.substring(idx); + if (suffix.startsWith(PREVIEW_INFIX + "/")) { + // Preview resources/directories. + String nonPreviewName = prefix + suffix.substring(PREVIEW_INFIX.length()); + return FLAGS_IS_PREVIEW_VERSION + | (hasEntry.test(nonPreviewName) ? 0 : FLAGS_IS_PREVIEW_ONLY); + } else if (!suffix.startsWith("/META-INF/")) { + // Non-preview resources/directories. + String previewName = prefix + PREVIEW_INFIX + suffix; + return hasEntry.test(previewName) ? FLAGS_HAS_PREVIEW_VERSION : 0; + } else { + // Edge case for things META-INF/module-info.class etc. + return 0; + } + } + + public enum LocationType { + RESOURCE, MODULES_ROOT, MODULES_DIR, PACKAGES_ROOT, PACKAGES_DIR; + } protected final long[] attributes; @@ -285,6 +361,10 @@ public int getExtensionOffset() { return (int)getAttribute(ATTRIBUTE_EXTENSION); } + public int getFlags() { + return (int) getAttribute(ATTRIBUTE_PREVIEW_FLAGS); + } + public String getFullName() { return getFullName(false); } @@ -294,7 +374,7 @@ public String getFullName(boolean modulesPrefix) { if (getModuleOffset() != 0) { if (modulesPrefix) { - builder.append("/modules"); + builder.append(MODULES_PREFIX); } builder.append('/'); @@ -317,36 +397,6 @@ public String getFullName(boolean modulesPrefix) { return builder.toString(); } - String buildName(boolean includeModule, boolean includeParent, - boolean includeName) { - StringBuilder builder = new StringBuilder(); - - if (includeModule && getModuleOffset() != 0) { - builder.append("/modules/"); - builder.append(getModule()); - } - - if (includeParent && getParentOffset() != 0) { - builder.append('/'); - builder.append(getParent()); - } - - if (includeName) { - if (includeModule || includeParent) { - builder.append('/'); - } - - builder.append(getBase()); - - if (getExtensionOffset() != 0) { - builder.append('.'); - builder.append(getExtension()); - } - } - - return builder.toString(); - } - public long getContentOffset() { return getAttribute(ATTRIBUTE_OFFSET); } @@ -359,6 +409,42 @@ public long getUncompressedSize() { return getAttribute(ATTRIBUTE_UNCOMPRESSED); } + // Fast (zero allocation) type determination for locations. + public LocationType getType() { + switch (getModuleOffset()) { + case ImageStrings.MODULES_STRING_OFFSET: + // Locations in /modules/... namespace are directory entries. + return LocationType.MODULES_DIR; + case ImageStrings.PACKAGES_STRING_OFFSET: + // Locations in /packages/... namespace are always 2-level + // "/packages/xxx" directories. + return LocationType.PACKAGES_DIR; + case ImageStrings.EMPTY_STRING_OFFSET: + // Only 2 choices, either the "/modules" or "/packages" root. + assert isRootDir() : "Invalid root directory: " + getFullName(); + return (getFlags() & FLAGS_IS_PACKAGE_ROOT) != 0 + ? LocationType.PACKAGES_ROOT + : LocationType.MODULES_ROOT; + default: + // Anything else is // and references a resource. + return LocationType.RESOURCE; + } + } + + private boolean isRootDir() { + if (getModuleOffset() == 0 && getParentOffset() == 0) { + String name = getFullName(); + return name.equals(MODULES_PREFIX) || name.equals(PACKAGES_PREFIX); + } + return false; + } + + @Override + public String toString() { + // Cannot use String.format() (too early in startup for locale code). + return "ImageLocation[name='" + getFullName() + "', type=" + getType() + ", flags=" + getFlags() + "]"; + } + static ImageLocation readFrom(BasicImageReader reader, int offset) { Objects.requireNonNull(reader); long[] attributes = reader.getAttributes(offset); diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index f12c39f3e81..00811da2f05 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -24,27 +24,66 @@ */ package jdk.internal.jimage; +import jdk.internal.jimage.ImageLocation.LocationType; + import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.nio.file.Files; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.function.Consumer; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static jdk.internal.jimage.ImageLocation.FLAGS_HAS_PREVIEW_VERSION; +import static jdk.internal.jimage.ImageLocation.FLAGS_IS_PREVIEW_ONLY; +import static jdk.internal.jimage.ImageLocation.LocationType.MODULES_DIR; +import static jdk.internal.jimage.ImageLocation.LocationType.MODULES_ROOT; +import static jdk.internal.jimage.ImageLocation.LocationType.PACKAGES_DIR; +import static jdk.internal.jimage.ImageLocation.LocationType.RESOURCE; +import static jdk.internal.jimage.ImageLocation.MODULES_PREFIX; +import static jdk.internal.jimage.ImageLocation.PACKAGES_PREFIX; +import static jdk.internal.jimage.ImageLocation.PREVIEW_INFIX; /** + * A view over the entries of a jimage file with a unified namespace suitable + * for file system use. The jimage entries (resources, module and package + * information) are mapped into a unified hierarchy of named nodes, which serve + * as the underlying structure for {@code JrtFileSystem} and other utilities. + * + *

    Entries in jimage are expressed as one of three {@link Node} types; + * resource nodes, directory nodes and link nodes. + * + *

    When remapping jimage entries, jimage location names (e.g. {@code + * "/java.base/java/lang/Integer.class"}) are prefixed with {@code "/modules"} + * to form the names of resource nodes. This aligns with the naming of module + * entries in jimage (e.g. "/modules/java.base/java/lang"), which appear as + * directory nodes in {@code ImageReader}. + * + *

    Package entries (e.g. {@code "/packages/java.lang"} appear as directory + * nodes containing link nodes, which resolve back to the root directory of the + * module in which that package exists (e.g. {@code "/modules/java.base"}). + * Unlike other nodes, the jimage file does not contain explicit entries for + * link nodes, and their existence is derived only from the contents of the + * parent directory. + * + *

    While similar to {@code BasicImageReader}, this class is not a conceptual + * subtype of it, and deliberately hides types such as {@code ImageLocation} to + * give a focused API based only on nodes. + * * @implNote This class needs to maintain JDK 8 source compatibility. * * It is used internally in the JDK to implement jimage/jrtfs access, @@ -60,15 +99,27 @@ private ImageReader(SharedImageReader reader) { this.reader = reader; } - public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { - Objects.requireNonNull(imagePath); - Objects.requireNonNull(byteOrder); - - return SharedImageReader.open(imagePath, byteOrder); + /** + * Opens an image reader for a jimage file at the specified path. + * + * @param imagePath file system path of the jimage file. + * @param mode whether to return preview resources. + */ + public static ImageReader open(Path imagePath, PreviewMode mode) throws IOException { + return open(imagePath, ByteOrder.nativeOrder(), mode); } - public static ImageReader open(Path imagePath) throws IOException { - return open(imagePath, ByteOrder.nativeOrder()); + /** + * Opens an image reader for a jimage file at the specified path. + * + * @param imagePath file system path of the jimage file. + * @param byteOrder the byte-order to be used when reading the jimage file. + * @param mode controls whether preview resources are visible. + */ + public static ImageReader open(Path imagePath, ByteOrder byteOrder, PreviewMode mode) throws IOException { + Objects.requireNonNull(imagePath); + Objects.requireNonNull(byteOrder); + return SharedImageReader.open(imagePath, byteOrder, mode.resolve()); } @Override @@ -92,156 +143,276 @@ private void requireOpen() { } } - // directory management interface - public Directory getRootDirectory() throws IOException { - ensureOpen(); - return reader.getRootDirectory(); - } - - + /** + * Finds the node with the given name. + * + * @param name a node name of the form {@code "/modules//...} or + * {@code "/packages//...}. + * @return a node representing a resource, directory or symbolic link. + */ public Node findNode(String name) throws IOException { ensureOpen(); return reader.findNode(name); } - public byte[] getResource(Node node) throws IOException { + /** + * Returns a resource node in the given module, or null if no resource of + * that name exists. + * + *

    This is equivalent to: + *

    {@code
    +     * findNode("/modules/" + moduleName + "/" + resourcePath)
    +     * }
    + * but more performant, and returns {@code null} for directories. + * + * @param moduleName The module name of the requested resource. + * @param resourcePath Trailing module-relative resource path, not starting + * with {@code '/'}. + */ + public Node findResourceNode(String moduleName, String resourcePath) + throws IOException { ensureOpen(); - return reader.getResource(node); + return reader.findResourceNode(moduleName, resourcePath); } - public byte[] getResource(Resource rs) throws IOException { + /** + * Returns whether a resource exists in the given module. + * + *

    This is equivalent to: + *

    {@code
    +     * findResourceNode(moduleName, resourcePath) != null
    +     * }
    + * but more performant, and will not create or cache new nodes. + * + * @param moduleName The module name of the resource being tested for. + * @param resourcePath Trailing module-relative resource path, not starting + * with {@code '/'}. + */ + public boolean containsResource(String moduleName, String resourcePath) + throws IOException { ensureOpen(); - return reader.getResource(rs); + return reader.containsResource(moduleName, resourcePath); } - public ImageHeader getHeader() { - requireOpen(); - return reader.getHeader(); + /** + * Returns a copy of the content of a resource node. The buffer returned by + * this method is not cached by the node, and each call returns a new array + * instance. + * + * @throws IOException if the content cannot be returned (including if the + * given node is not a resource node). + */ + public byte[] getResource(Node node) throws IOException { + ensureOpen(); + return reader.getResource(node); } + /** + * Releases a (possibly cached) {@link ByteBuffer} obtained via + * {@link #getResourceBuffer(Node)}. + * + *

    Note that no testing is performed to check whether the buffer about + * to be released actually came from a call to {@code getResourceBuffer()}. + */ public static void releaseByteBuffer(ByteBuffer buffer) { BasicImageReader.releaseByteBuffer(buffer); } - public String getName() { - requireOpen(); - return reader.getName(); - } - - public ByteOrder getByteOrder() { - requireOpen(); - return reader.getByteOrder(); - } - - public Path getImagePath() { + /** + * Returns the content of a resource node in a possibly cached byte buffer. + * Callers of this method must call {@link #releaseByteBuffer(ByteBuffer)} + * when they are finished with it. + */ + public ByteBuffer getResourceBuffer(Node node) { requireOpen(); - return reader.getImagePath(); - } - - public ImageStringsReader getStrings() { - requireOpen(); - return reader.getStrings(); - } - - public ImageLocation findLocation(String mn, String rn) { - requireOpen(); - return reader.findLocation(mn, rn); - } - - public boolean verifyLocation(String mn, String rn) { - requireOpen(); - return reader.verifyLocation(mn, rn); + if (!node.isResource()) { + throw new IllegalArgumentException("Not a resource node: " + node); + } + return reader.getResourceBuffer(node.getLocation()); } - public ImageLocation findLocation(String name) { - requireOpen(); - return reader.findLocation(name); - } + private static final class SharedImageReader extends BasicImageReader { + // There are >30,000 nodes in a complete jimage tree, and even relatively + // common tasks (e.g. starting up javac) load somewhere in the region of + // 1000 classes. Thus, an initial capacity of 2000 is a reasonable guess. + private static final int INITIAL_NODE_CACHE_CAPACITY = 2000; + + static final class ReaderKey { + private final Path imagePath; + private final boolean previewMode; + + public ReaderKey(Path imagePath, boolean previewMode) { + this.imagePath = imagePath; + this.previewMode = previewMode; + } - public String[] getEntryNames() { - requireOpen(); - return reader.getEntryNames(); - } + @Override + public boolean equals(Object obj) { + // No pattern variables here (Java 8 compatible source). + if (obj instanceof ReaderKey) { + ReaderKey other = (ReaderKey) obj; + return this.imagePath.equals(other.imagePath) && this.previewMode == other.previewMode; + } + return false; + } - public String[] getModuleNames() { - requireOpen(); - int off = "/modules/".length(); - return reader.findNode("/modules") - .getChildren() - .stream() - .map(Node::getNameString) - .map(s -> s.substring(off, s.length())) - .toArray(String[]::new); - } + @Override + public int hashCode() { + return imagePath.hashCode() ^ Boolean.hashCode(previewMode); + } + } - public long[] getAttributes(int offset) { - requireOpen(); - return reader.getAttributes(offset); - } + private static final Map OPEN_FILES = new HashMap<>(); - public String getString(int offset) { - requireOpen(); - return reader.getString(offset); - } + // List of openers for this shared image. + private final Set openers = new HashSet<>(); - public byte[] getResource(String name) { - requireOpen(); - return reader.getResource(name); - } + // Attributes of the jimage file. The jimage file does not contain + // attributes for the individual resources (yet). We use attributes + // of the jimage file itself (creation, modification, access times). + private final BasicFileAttributes imageFileAttributes; - public byte[] getResource(ImageLocation loc) { - requireOpen(); - return reader.getResource(loc); - } + // Cache of all user visible nodes, guarded by synchronizing 'this' instance. + private final Map nodes; - public ByteBuffer getResourceBuffer(ImageLocation loc) { - requireOpen(); - return reader.getResourceBuffer(loc); - } + // Preview mode support. + private final boolean previewMode; + // A relativized mapping from non-preview name to directories containing + // preview-only nodes. This is used to add preview-only content to + // directories as they are completed. + private final HashMap previewDirectoriesToMerge; - public InputStream getResourceStream(ImageLocation loc) { - requireOpen(); - return reader.getResourceStream(loc); - } - - private static final class SharedImageReader extends BasicImageReader { - static final int SIZE_OF_OFFSET = Integer.BYTES; + private SharedImageReader(Path imagePath, ByteOrder byteOrder, boolean previewMode) throws IOException { + super(imagePath, byteOrder); + this.imageFileAttributes = Files.readAttributes(imagePath, BasicFileAttributes.class); + this.nodes = new HashMap<>(INITIAL_NODE_CACHE_CAPACITY); + this.previewMode = previewMode; - static final Map OPEN_FILES = new HashMap<>(); + // Node creation is very lazy, so we can just make the top-level directories + // now without the risk of triggering the building of lots of other nodes. + Directory packages = ensureCached(newDirectory(PACKAGES_PREFIX)); + Directory modules = ensureCached(newDirectory(MODULES_PREFIX)); - // List of openers for this shared image. - final Set openers; + Directory root = newDirectory("/"); + root.setChildren(Arrays.asList(packages, modules)); + ensureCached(root); - // attributes of the .jimage file. jimage file does not contain - // attributes for the individual resources (yet). We use attributes - // of the jimage file itself (creation, modification, access times). - // Iniitalized lazily, see {@link #imageFileAttributes()}. - BasicFileAttributes imageFileAttributes; + // By scanning the /packages directory information early we can determine + // which module/package pairs have preview resources, and build the (small) + // set of preview nodes early. This also ensures that preview-only entries + // in the /packages directory are not present in non-preview mode. + this.previewDirectoriesToMerge = previewMode ? new HashMap<>() : null; + packages.setChildren(processPackagesDirectory(previewMode)); + } - // directory management implementation - final HashMap nodes; - volatile Directory rootDir; + /** + * Process {@code "/packages/xxx"} entries to build the child nodes for the + * root {@code "/packages"} node. Preview-only entries will be skipped if + * {@code previewMode == false}. + * + *

    If {@code previewMode == true}, this method also populates the {@link + * #previewDirectoriesToMerge} map with any preview-only nodes, to be merged + * into directories as they are completed. It also caches preview resources + * and preview-only directories for direct lookup. + */ + private ArrayList processPackagesDirectory(boolean previewMode) { + ImageLocation pkgRoot = findLocation(PACKAGES_PREFIX); + assert pkgRoot != null : "Invalid jimage file"; + IntBuffer offsets = getOffsetBuffer(pkgRoot); + ArrayList pkgDirs = new ArrayList<>(offsets.capacity()); + // Package path to module map, sorted in reverse order so that + // longer child paths get processed first. + Map> previewPackagesToModules = + new TreeMap<>(Comparator.reverseOrder()); + for (int i = 0; i < offsets.capacity(); i++) { + ImageLocation pkgDir = getLocation(offsets.get(i)); + int flags = pkgDir.getFlags(); + // A package subdirectory is "preview only" if all the modules + // it references have that package marked as preview only. + // Skipping these entries avoids empty package subdirectories. + if (previewMode || (flags & FLAGS_IS_PREVIEW_ONLY) == 0) { + pkgDirs.add(ensureCached(newDirectory(pkgDir.getFullName()))); + } + if (!previewMode || (flags & FLAGS_HAS_PREVIEW_VERSION) == 0) { + continue; + } + // Only do this in preview mode for the small set of packages with + // preview versions (the number of preview entries should be small). + List moduleNames = new ArrayList<>(); + ModuleReference.readNameOffsets(getOffsetBuffer(pkgDir), /*normal*/ false, /*preview*/ true) + .forEachRemaining(n -> moduleNames.add(getString(n))); + previewPackagesToModules.put(pkgDir.getBase().replace('.', '/'), moduleNames); + } + // Reverse sorted map means child directories are processed first. + previewPackagesToModules.forEach((pkgPath, modules) -> + modules.forEach(modName -> processPreviewDir(MODULES_PREFIX + "/" + modName, pkgPath))); + // We might have skipped some preview-only package entries. + pkgDirs.trimToSize(); + return pkgDirs; + } + + void processPreviewDir(String namePrefix, String pkgPath) { + String previewDirName = namePrefix + PREVIEW_INFIX + "/" + pkgPath; + ImageLocation previewLoc = findLocation(previewDirName); + assert previewLoc != null : "Missing preview directory location: " + previewDirName; + String nonPreviewDirName = namePrefix + "/" + pkgPath; + List previewOnlyChildren = createChildNodes(previewLoc, 0, childLoc -> { + String baseName = getBaseName(childLoc); + String nonPreviewChildName = nonPreviewDirName + "/" + baseName; + boolean isPreviewOnly = (childLoc.getFlags() & FLAGS_IS_PREVIEW_ONLY) != 0; + LocationType type = childLoc.getType(); + if (type == RESOURCE) { + // Preview resources are cached to override non-preview versions. + Node childNode = ensureCached(newResource(nonPreviewChildName, childLoc)); + return isPreviewOnly ? childNode : null; + } else { + // Child directories are not cached here (they are either cached + // already or have been added to previewDirectoriesToMerge). + assert type == MODULES_DIR : "Invalid location type: " + childLoc; + Node childNode = nodes.get(nonPreviewChildName); + assert isPreviewOnly == (childNode != null) : + "Inconsistent child node: " + nonPreviewChildName; + return childNode; + } + }); + Directory previewDir = newDirectory(nonPreviewDirName); + previewDir.setChildren(previewOnlyChildren); + if ((previewLoc.getFlags() & FLAGS_IS_PREVIEW_ONLY) != 0) { + // If we are preview-only, our children are also preview-only, so + // this directory is a complete hierarchy and should be cached. + assert !previewOnlyChildren.isEmpty() : "Invalid empty preview-only directory: " + nonPreviewDirName; + ensureCached(previewDir); + } else if (!previewOnlyChildren.isEmpty()) { + // A partial directory containing extra preview-only nodes + // to be merged when the non-preview directory is completed. + previewDirectoriesToMerge.put(nonPreviewDirName, previewDir); + } + } - Directory packagesDir; - Directory modulesDir; + // Adds a node to the cache, ensuring that no matching entry already existed. + private T ensureCached(T node) { + Node existingNode = nodes.put(node.getName(), node); + assert existingNode == null : "Unexpected node already cached for: " + node; + return node; + } - private SharedImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { - super(imagePath, byteOrder); - this.openers = new HashSet<>(); - this.nodes = new HashMap<>(); + // As above but ignores null. + private T ensureCachedIfNonNull(T node) { + return node != null ? ensureCached(node) : null; } - public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + private static ImageReader open(Path imagePath, ByteOrder byteOrder, boolean previewMode) throws IOException { Objects.requireNonNull(imagePath); Objects.requireNonNull(byteOrder); synchronized (OPEN_FILES) { - SharedImageReader reader = OPEN_FILES.get(imagePath); + ReaderKey key = new ReaderKey(imagePath, previewMode); + SharedImageReader reader = OPEN_FILES.get(key); if (reader == null) { // Will fail with an IOException if wrong byteOrder. - reader = new SharedImageReader(imagePath, byteOrder); - OPEN_FILES.put(imagePath, reader); + reader = new SharedImageReader(imagePath, byteOrder, previewMode); + OPEN_FILES.put(key, reader); } else if (reader.getByteOrder() != byteOrder) { throw new IOException("\"" + reader.getName() + "\" is not an image file"); } @@ -264,457 +435,490 @@ public void close(ImageReader image) throws IOException { if (openers.isEmpty()) { close(); nodes.clear(); - rootDir = null; - if (!OPEN_FILES.remove(this.getImagePath(), this)) { + if (!OPEN_FILES.remove(new ReaderKey(getImagePath(), previewMode), this)) { throw new IOException("image file not found in open list"); } } } } - void addOpener(ImageReader reader) { - synchronized (OPEN_FILES) { - openers.add(reader); + /** + * Returns a node with the given name, or null if no resource or directory of + * that name exists. + * + *

    Note that there is no reentrant calling back to this method from within + * the node handling code. + * + * @param name an absolute, {@code /}-separated path string, prefixed with either + * "/modules" or "/packages". + */ + synchronized Node findNode(String name) { + // Root directories "/", "/modules" and "/packages", as well + // as all "/packages/xxx" subdirectories are already cached. + Node node = nodes.get(name); + if (node == null) { + if (name.startsWith(MODULES_PREFIX + "/")) { + node = buildAndCacheModulesNode(name); + } else if (name.startsWith(PACKAGES_PREFIX + "/")) { + node = buildAndCacheLinkNode(name); + } + } else if (!node.isCompleted()) { + // Only directories can be incomplete. + assert node instanceof Directory : "Invalid incomplete node: " + node; + completeDirectory((Directory) node); } + assert node == null || node.isCompleted() : "Incomplete node: " + node; + return node; } - boolean removeOpener(ImageReader reader) { - synchronized (OPEN_FILES) { - return openers.remove(reader); + /** + * Returns a resource node in the given module, or null if no resource of + * that name exists. + * + *

    Note that there is no reentrant calling back to this method from within + * the node handling code. + */ + Node findResourceNode(String moduleName, String resourcePath) { + // Unlike findNode(), this method makes only one lookup in the + // underlying jimage, but can only reliably return resource nodes. + if (moduleName.indexOf('/') >= 0) { + throw new IllegalArgumentException("invalid module name: " + moduleName); + } + String nodeName = MODULES_PREFIX + "/" + moduleName + "/" + resourcePath; + // Synchronize as tightly as possible to reduce locking contention. + synchronized (this) { + Node node = nodes.get(nodeName); + if (node == null) { + ImageLocation loc = findLocation(moduleName, resourcePath); + if (loc != null && loc.getType() == RESOURCE) { + node = newResource(nodeName, loc); + nodes.put(node.getName(), node); + } + return node; + } else { + return node.isResource() ? node : null; + } } } - // directory management interface - Directory getRootDirectory() { - return buildRootDirectory(); + /** + * Returns whether a resource exists in the given module. + * + *

    This method is expected to be called frequently for resources + * which do not exist in the given module (e.g. as part of classpath + * search). As such, it skips checking the nodes cache if possible, and + * only checks for an entry in the jimage file, as this is faster if the + * resource is not present. This also means it doesn't need + * synchronization most of the time. + */ + boolean containsResource(String moduleName, String resourcePath) { + if (moduleName.indexOf('/') >= 0) { + throw new IllegalArgumentException("invalid module name: " + moduleName); + } + // In preview mode, preview-only resources are eagerly added to the + // cache, so we must check that first. + if (previewMode) { + String nodeName = MODULES_PREFIX + "/" + moduleName + "/" + resourcePath; + // Synchronize as tightly as possible to reduce locking contention. + synchronized (this) { + Node node = nodes.get(nodeName); + if (node != null) { + return node.isResource(); + } + } + } + ImageLocation loc = findLocation(moduleName, resourcePath); + return loc != null && loc.getType() == RESOURCE; } /** - * Lazily build a node from a name. + * Builds a node in the "/modules/..." namespace. + * + *

    Called by {@link #findNode(String)} if a {@code /modules/...} node + * is not present in the cache. */ - synchronized Node buildNode(String name) { - Node n; - boolean isPackages = name.startsWith("/packages"); - boolean isModules = !isPackages && name.startsWith("/modules"); - - if (!(isModules || isPackages)) { + private Node buildAndCacheModulesNode(String name) { + assert name.startsWith(MODULES_PREFIX + "/") : "Invalid module node name: " + name; + if (isPreviewName(name)) { return null; } - + // Returns null for non-directory resources, since the jimage name does not + // start with "/modules" (e.g. "/java.base/java/lang/Object.class"). ImageLocation loc = findLocation(name); - - if (loc != null) { // A sub tree node - if (isPackages) { - n = handlePackages(name, loc); - } else { // modules sub tree - n = handleModulesSubTree(name, loc); - } - } else { // Asking for a resource? /modules/java.base/java/lang/Object.class - if (isModules) { - n = handleResource(name); - } else { - // Possibly ask for /packages/java.lang/java.base - // although /packages/java.base not created - n = handleModuleLink(name); - } + if (loc != null) { + assert name.equals(loc.getFullName()) : "Mismatched location for directory: " + name; + assert loc.getType() == MODULES_DIR : "Invalid modules directory: " + name; + return ensureCached(completeModuleDirectory(newDirectory(name), loc)); } - return n; + // Now try the non-prefixed resource name, but be careful to avoid false + // positives for names like "/modules/modules/xxx" which could return a + // location of a directory entry. + loc = findLocation(name.substring(MODULES_PREFIX.length())); + return ensureCachedIfNonNull( + loc != null && loc.getType() == RESOURCE ? newResource(name, loc) : null); } - synchronized Directory buildRootDirectory() { - Directory root = rootDir; // volatile read - if (root != null) { - return root; - } - - root = newDirectory(null, "/"); - root.setIsRootDir(); - - // /packages dir - packagesDir = newDirectory(root, "/packages"); - packagesDir.setIsPackagesDir(); - - // /modules dir - modulesDir = newDirectory(root, "/modules"); - modulesDir.setIsModulesDir(); - - root.setCompleted(true); - return rootDir = root; + /** + * Returns whether a directory name in the "/modules/" directory could be referencing + * the "META-INF" directory". + */ + private boolean isMetaInf(Directory dir) { + String name = dir.getName(); + int pathStart = name.indexOf('/', MODULES_PREFIX.length() + 1); + return name.length() == pathStart + "/META-INF".length() + && name.endsWith("/META-INF"); } /** - * To visit sub tree resources. + * Returns whether a node name in the "/modules/" directory could be referencing + * a preview resource or directory under "META-INF/preview". */ - interface LocationVisitor { - void visit(ImageLocation loc); + private boolean isPreviewName(String name) { + int pathStart = name.indexOf('/', MODULES_PREFIX.length() + 1); + int previewEnd = pathStart + PREVIEW_INFIX.length(); + return pathStart > 0 + && name.regionMatches(pathStart, PREVIEW_INFIX, 0, PREVIEW_INFIX.length()) + && (name.length() == previewEnd || name.charAt(previewEnd) == '/'); } - void visitLocation(ImageLocation loc, LocationVisitor visitor) { - byte[] offsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(offsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { - int offset = intBuffer.get(i); - ImageLocation pkgLoc = getLocation(offset); - visitor.visit(pkgLoc); - } + private String getBaseName(ImageLocation loc) { + // Matches logic in ImageLocation#getFullName() regarding extensions. + String trailingParts = loc.getBase() + + ((loc.getExtensionOffset() != 0) ? "." + loc.getExtension() : ""); + return trailingParts.substring(trailingParts.lastIndexOf('/') + 1); } - void visitPackageLocation(ImageLocation loc) { - // Retrieve package name - String pkgName = getBaseExt(loc); - // Content is array of offsets in Strings table - byte[] stringsOffsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - // For each module, create a link node. - for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { - // skip empty state, useless. - intBuffer.get(i); - i++; - int offset = intBuffer.get(i); - String moduleName = getString(offset); - Node targetNode = findNode("/modules/" + moduleName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); + /** + * Builds a link node of the form "/packages/xxx/yyy". + * + *

    Called by {@link #findNode(String)} if a {@code /packages/...} + * node is not present in the cache (the name is not trusted). + */ + private Node buildAndCacheLinkNode(String name) { + // There are only locations for "/packages" or "/packages/xxx" + // directories, but not the symbolic links below them (links are + // derived from the name information in the parent directory). + int packageStart = PACKAGES_PREFIX.length() + 1; + int packageEnd = name.indexOf('/', packageStart); + // We already built the 2-level "/packages/xxx" directories, + // so if this is a 2-level name, it cannot reference a node. + if (packageEnd >= 0) { + String dirName = name.substring(0, packageEnd); + // If no parent exists here, the name cannot be valid. + Directory parent = (Directory) nodes.get(dirName); + if (parent != null) { + if (!parent.isCompleted()) { + // This caches all child links of the parent directory. + completePackageSubdirectory(parent, findLocation(dirName)); + } + return nodes.get(name); } } + return null; } - Node handlePackages(String name, ImageLocation loc) { - long size = loc.getUncompressedSize(); - Node n = null; - // Only possibilities are /packages, /packages/package/module - if (name.equals("/packages")) { - visitLocation(loc, (childloc) -> { - findNode(childloc.getFullName()); - }); - packagesDir.setCompleted(true); - n = packagesDir; + /** Completes a directory by ensuring its child list is populated correctly. */ + private void completeDirectory(Directory dir) { + String name = dir.getName(); + // Since the node exists, we can assert that its name starts with + // either "/modules" or "/packages", making differentiation easy. + // It also means that the name is valid, so it must yield a location. + assert name.startsWith(MODULES_PREFIX) || name.startsWith(PACKAGES_PREFIX); + ImageLocation loc = findLocation(name); + assert loc != null && name.equals(loc.getFullName()) : "Invalid location for name: " + name; + LocationType type = loc.getType(); + if (type == MODULES_DIR || type == MODULES_ROOT) { + completeModuleDirectory(dir, loc); } else { - if (size != 0) { // children are offsets to module in StringsTable - String pkgName = getBaseExt(loc); - Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); - visitPackageLocation(loc); - pkgDir.setCompleted(true); - n = pkgDir; - } else { // Link to module - String pkgName = loc.getParent(); - String modName = getBaseExt(loc); - Node targetNode = findNode("/modules/" + modName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); - n = linkNode; - } - } + assert type == PACKAGES_DIR : "Invalid location type: " + loc; + completePackageSubdirectory(dir, loc); } - return n; - } - - // Asking for /packages/package/module although - // /packages// not yet created, need to create it - // prior to return the link to module node. - Node handleModuleLink(String name) { - // eg: unresolved /packages/package/module - // Build /packages/package node - Node ret = null; - String radical = "/packages/"; - String path = name; - if (path.startsWith(radical)) { - int start = radical.length(); - int pkgEnd = path.indexOf('/', start); - if (pkgEnd != -1) { - String pkg = path.substring(start, pkgEnd); - String pkgPath = radical + pkg; - Node n = findNode(pkgPath); - // If not found means that this is a symbolic link such as: - // /packages/java.util/java.base/java/util/Vector.class - // and will be done by a retry of the filesystem - for (Node child : n.getChildren()) { - if (child.name.equals(name)) { - ret = child; - break; - } - } - } - } - return ret; - } - - Node handleModulesSubTree(String name, ImageLocation loc) { - Node n; - assert (name.equals(loc.getFullName())); - Directory dir = makeDirectories(name); - visitLocation(loc, (childloc) -> { - String path = childloc.getFullName(); - if (path.startsWith("/modules")) { // a package - makeDirectories(path); - } else { // a resource - makeDirectories(childloc.buildName(true, true, false)); - // if we have already created a resource for this name previously, then don't - // recreate it - if (!nodes.containsKey(childloc.getFullName(true))) { - newResource(dir, childloc); - } + assert dir.isCompleted() : "Directory must be complete by now: " + dir; + } + + /** Completes a modules directory by setting the list of child nodes. */ + private Directory completeModuleDirectory(Directory dir, ImageLocation loc) { + assert dir.getName().equals(loc.getFullName()) : "Mismatched location for directory: " + dir; + List previewOnlyNodes = getPreviewNodesToMerge(dir); + // We hide preview names from direct lookup, but must also prevent + // the preview directory from appearing in any META-INF directories. + boolean parentIsMetaInfDir = isMetaInf(dir); + List children = createChildNodes(loc, previewOnlyNodes.size(), childLoc -> { + LocationType type = childLoc.getType(); + if (type == MODULES_DIR) { + String name = childLoc.getFullName(); + return parentIsMetaInfDir && name.endsWith("/preview") + ? null + : nodes.computeIfAbsent(name, this::newDirectory); + } else { + assert type == RESOURCE : "Invalid location type: " + loc; + // Add "/modules" prefix to image location paths to get node names. + String resourceName = childLoc.getFullName(true); + return nodes.computeIfAbsent(resourceName, n -> newResource(n, childLoc)); } }); - dir.setCompleted(true); - n = dir; - return n; - } - - Node handleResource(String name) { - Node n = null; - if (!name.startsWith("/modules/")) { - return null; - } - // Make sure that the thing that follows "/modules/" is a module name. - int moduleEndIndex = name.indexOf('/', "/modules/".length()); - if (moduleEndIndex == -1) { - return null; - } - ImageLocation moduleLoc = findLocation(name.substring(0, moduleEndIndex)); - if (moduleLoc == null || moduleLoc.getModuleOffset() == 0) { - return null; - } - - String locationPath = name.substring("/modules".length()); - ImageLocation resourceLoc = findLocation(locationPath); - if (resourceLoc != null) { - Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); - Resource res = newResource(dir, resourceLoc); - n = res; - } - return n; - } - - String getBaseExt(ImageLocation loc) { - String base = loc.getBase(); - String ext = loc.getExtension(); - if (ext != null && !ext.isEmpty()) { - base = base + "." + ext; - } - return base; + children.addAll(previewOnlyNodes); + dir.setChildren(children); + return dir; } - synchronized Node findNode(String name) { - buildRootDirectory(); - Node n = nodes.get(name); - if (n == null || !n.isCompleted()) { - n = buildNode(name); + /** Completes a package directory by setting the list of child nodes. */ + private void completePackageSubdirectory(Directory dir, ImageLocation loc) { + assert dir.getName().equals(loc.getFullName()) : "Mismatched location for directory: " + dir; + assert !dir.isCompleted() : "Directory already completed: " + dir; + assert loc.getType() == PACKAGES_DIR : "Invalid location type: " + loc.getType(); + + // In non-preview mode we might skip a very small number of preview-only + // entries, but it's not worth "right-sizing" the array for that. + IntBuffer offsets = getOffsetBuffer(loc); + List children = new ArrayList<>(offsets.capacity() / 2); + ModuleReference.readNameOffsets(offsets, /*normal*/ true, previewMode) + .forEachRemaining(n -> { + String modName = getString(n); + Node link = newLinkNode(dir.getName() + "/" + modName, MODULES_PREFIX + "/" + modName); + children.add(ensureCached(link)); + }); + // If the parent directory exists, there must be at least one child node. + assert !children.isEmpty() : "Invalid empty package directory: " + dir; + dir.setChildren(children); + } + + /** Returns the list of child preview nodes to be merged into the given directory. */ + List getPreviewNodesToMerge(Directory dir) { + if (previewDirectoriesToMerge != null) { + Directory mergeDir = previewDirectoriesToMerge.get(dir.getName()); + if (mergeDir != null) { + return mergeDir.children; + } } - return n; + return Collections.emptyList(); } /** - * Returns the file attributes of the image file. + * Creates the list of child nodes for a modules {@code Directory} from + * its parent location. + * + *

    The {@code getChildFn} may return existing cached nodes rather + * than creating them, and if newly created nodes are to be cached, + * it is the job of {@code getChildFn}, or the caller of this method, + * to do that. + * + * @param loc a location relating to a "/modules" directory. + * @param extraNodesCount a known number of preview-only child nodes + * which will be merged onto the end of the returned list later. + * @param getChildFn a function to return a node for each child location + * (or null to skip putting anything in the list). + * @return the list of the non-null child nodes, returned by + * {@code getChildFn}, in the order of the locations entries. */ - BasicFileAttributes imageFileAttributes() { - BasicFileAttributes attrs = imageFileAttributes; - if (attrs == null) { - try { - Path file = getImagePath(); - attrs = Files.readAttributes(file, BasicFileAttributes.class); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); + private List createChildNodes(ImageLocation loc, int extraNodesCount, Function getChildFn) { + LocationType type = loc.getType(); + assert type == MODULES_DIR || type == MODULES_ROOT : "Invalid location type: " + loc; + IntBuffer offsets = getOffsetBuffer(loc); + int childCount = offsets.capacity(); + List children = new ArrayList<>(childCount + extraNodesCount); + for (int i = 0; i < childCount; i++) { + Node childNode = getChildFn.apply(getLocation(offsets.get(i))); + if (childNode != null) { + children.add(childNode); } - imageFileAttributes = attrs; } - return attrs; - } - - Directory newDirectory(Directory parent, String name) { - Directory dir = Directory.create(parent, name, imageFileAttributes()); - nodes.put(dir.getName(), dir); - return dir; + return children; } - Resource newResource(Directory parent, ImageLocation loc) { - Resource res = Resource.create(parent, loc, imageFileAttributes()); - nodes.put(res.getName(), res); - return res; + /** Helper to extract the integer offset buffer from a directory location. */ + private IntBuffer getOffsetBuffer(ImageLocation dir) { + assert dir.getType() != RESOURCE : "Not a directory: " + dir.getFullName(); + byte[] offsets = getResource(dir); + ByteBuffer buffer = ByteBuffer.wrap(offsets); + buffer.order(getByteOrder()); + return buffer.asIntBuffer(); } - LinkNode newLinkNode(Directory dir, String name, Node link) { - LinkNode linkNode = LinkNode.create(dir, name, link); - nodes.put(linkNode.getName(), linkNode); - return linkNode; + /** + * Creates an "incomplete" directory node with no child nodes set. + * Directories need to be "completed" before they are returned by + * {@link #findNode(String)}. + */ + private Directory newDirectory(String name) { + return new Directory(name, imageFileAttributes); } - Directory makeDirectories(String parent) { - Directory last = rootDir; - for (int offset = parent.indexOf('/', 1); - offset != -1; - offset = parent.indexOf('/', offset + 1)) { - String dir = parent.substring(0, offset); - last = makeDirectory(dir, last); - } - return makeDirectory(parent, last); - + /** + * Creates a new resource from an image location. This is the only case + * where the image location name does not match the requested node name. + * In image files, resource locations are NOT prefixed by {@code /modules}. + */ + private Resource newResource(String name, ImageLocation loc) { + return new Resource(name, loc, imageFileAttributes); } - Directory makeDirectory(String dir, Directory last) { - Directory nextDir = (Directory) nodes.get(dir); - if (nextDir == null) { - nextDir = newDirectory(last, dir); - } - return nextDir; + /** + * Creates a new link node pointing at the given target name. + * + *

    Note that target node is resolved each time {@code resolve()} is called, + * so if a link node is retained after its reader is closed, it will fail. + */ + private LinkNode newLinkNode(String name, String targetName) { + return new LinkNode(name, () -> findNode(targetName), imageFileAttributes); } - byte[] getResource(Node node) throws IOException { + /** Returns the content of a resource node. */ + private byte[] getResource(Node node) throws IOException { + // We could have been given a non-resource node here. if (node.isResource()) { return super.getResource(node.getLocation()); } throw new IOException("Not a resource: " + node); } - - byte[] getResource(Resource rs) throws IOException { - return super.getResource(rs.getLocation()); - } } - // jimage file does not store directory structure. We build nodes - // using the "path" strings found in the jimage file. - // Node can be a directory or a resource + /** + * A directory, resource or symbolic link. + * + *

    Node Equality

    + * + * Nodes are identified solely by their name, and it is not valid to attempt + * to compare nodes from different reader instances. Different readers may + * produce nodes with the same names, but different contents. + * + *

    Furthermore, since a {@link ImageReader} provides "perfect" caching of + * nodes, equality of nodes from the same reader is equivalent to instance + * identity. + */ public abstract static class Node { - private static final int ROOT_DIR = 0b0000_0000_0000_0001; - private static final int PACKAGES_DIR = 0b0000_0000_0000_0010; - private static final int MODULES_DIR = 0b0000_0000_0000_0100; - - private int flags; private final String name; private final BasicFileAttributes fileAttrs; - private boolean completed; - - protected Node(String name, BasicFileAttributes fileAttrs) { - this.name = Objects.requireNonNull(name); - this.fileAttrs = Objects.requireNonNull(fileAttrs); - } /** - * A node is completed when all its direct children have been built. + * Creates an abstract {@code Node}, which is either a resource, directory + * or symbolic link. * - * @return + *

    This constructor is only non-private so it can be used by the + * {@code ExplodedImage} class, and must not be used otherwise. */ - public boolean isCompleted() { - return completed; - } - - public void setCompleted(boolean completed) { - this.completed = completed; - } - - public final void setIsRootDir() { - flags |= ROOT_DIR; - } - - public final boolean isRootDir() { - return (flags & ROOT_DIR) != 0; - } - - public final void setIsPackagesDir() { - flags |= PACKAGES_DIR; - } - - public final boolean isPackagesDir() { - return (flags & PACKAGES_DIR) != 0; + protected Node(String name, BasicFileAttributes fileAttrs) { + this.name = Objects.requireNonNull(name); + this.fileAttrs = Objects.requireNonNull(fileAttrs); } - public final void setIsModulesDir() { - flags |= MODULES_DIR; + // A node is completed when all its direct children have been built. + // As such, non-directory nodes are always complete. + boolean isCompleted() { + return true; } - public final boolean isModulesDir() { - return (flags & MODULES_DIR) != 0; + // Only resources can return a location. + ImageLocation getLocation() { + throw new IllegalStateException("not a resource: " + getName()); } + /** + * Returns the name of this node (e.g. {@code + * "/modules/java.base/java/lang/Object.class"} or {@code + * "/packages/java.lang"}). + * + *

    Note that for resource nodes this is NOT the underlying jimage + * resource name (it is prefixed with {@code "/modules"}). + */ public final String getName() { return name; } + /** + * Returns file attributes for this node. The value returned may be the + * same for all nodes, and should not be relied upon for accuracy. + */ public final BasicFileAttributes getFileAttributes() { return fileAttrs; } - // resolve this Node (if this is a soft link, get underlying Node) + /** + * Resolves a symbolic link to its target node. If this code is not a + * symbolic link, then it resolves to itself. + */ public final Node resolveLink() { return resolveLink(false); } + /** + * Resolves a symbolic link to its target node. If this code is not a + * symbolic link, then it resolves to itself. + */ public Node resolveLink(boolean recursive) { return this; } - // is this a soft link Node? + /** Returns whether this node is a symbolic link. */ public boolean isLink() { return false; } + /** + * Returns whether this node is a directory. Directory nodes can have + * {@link #getChildNames()} invoked to get the fully qualified names + * of any child nodes. + */ public boolean isDirectory() { return false; } - public List getChildren() { - throw new IllegalArgumentException("not a directory: " + getNameString()); - } - + /** + * Returns whether this node is a resource. Resource nodes can have + * their contents obtained via {@link ImageReader#getResource(Node)} + * or {@link ImageReader#getResourceBuffer(Node)}. + */ public boolean isResource() { return false; } - public ImageLocation getLocation() { - throw new IllegalArgumentException("not a resource: " + getNameString()); + /** + * Returns the fully qualified names of any child nodes for a directory. + * + *

    By default, this method throws {@link IllegalStateException} and + * is overridden for directories. + */ + public Stream getChildNames() { + throw new IllegalStateException("not a directory: " + getName()); } + /** + * Returns the uncompressed size of this node's content. If this node is + * not a resource, this method returns zero. + */ public long size() { return 0L; } + /** + * Returns the compressed size of this node's content. If this node is + * not a resource, this method returns zero. + */ public long compressedSize() { return 0L; } + /** + * Returns the extension string of a resource node. If this node is not + * a resource, this method returns null. + */ public String extension() { return null; } - public long contentOffset() { - return 0L; - } - - public final FileTime creationTime() { - return fileAttrs.creationTime(); - } - - public final FileTime lastAccessTime() { - return fileAttrs.lastAccessTime(); - } - - public final FileTime lastModifiedTime() { - return fileAttrs.lastModifiedTime(); - } - - public final String getNameString() { - return name; - } - @Override public final String toString() { - return getNameString(); + return getName(); } + /** See Node Equality. */ @Override public final int hashCode() { return name.hashCode(); } + /** See Node Equality. */ @Override public final boolean equals(Object other) { if (this == other) { @@ -729,21 +933,40 @@ public final boolean equals(Object other) { } } - // directory node - directory has full path name without '/' at end. - static final class Directory extends Node { - private final List children; + /** + * Directory node (referenced from a full path, without a trailing '/'). + * + *

    Directory nodes have two distinct states: + *

      + *
    • Incomplete: The child list has not been set. + *
    • Complete: The child list has been set. + *
    + * + *

    When a directory node is returned by {@link ImageReader#findNode(String)} + * it is always complete, but this DOES NOT mean that its child nodes are + * complete yet. + * + *

    To avoid users being able to access incomplete child nodes, the + * {@code Node} API offers only a way to obtain child node names, forcing + * callers to invoke {@code findNode()} if they need to access the child + * node itself. + * + *

    This approach allows directories to be implemented lazily with respect + * to child nodes, while retaining efficiency when child nodes are accessed + * (since any incomplete nodes will be created and placed in the node cache + * when the parent was first returned to the user). + */ + private static final class Directory extends Node { + // Monotonic reference, will be set to the unmodifiable child list exactly once. + private List children = null; private Directory(String name, BasicFileAttributes fileAttrs) { super(name, fileAttrs); - children = new ArrayList<>(); } - static Directory create(Directory parent, String name, BasicFileAttributes fileAttrs) { - Directory d = new Directory(name, fileAttrs); - if (parent != null) { - parent.addChild(d); - } - return d; + @Override + boolean isCompleted() { + return children != null; } @Override @@ -752,46 +975,42 @@ public boolean isDirectory() { } @Override - public List getChildren() { - return Collections.unmodifiableList(children); - } - - void addChild(Node node) { - assert !children.contains(node) : "Child " + node + " already added"; - children.add(node); + public Stream getChildNames() { + if (children != null) { + return children.stream().map(Node::getName); + } + throw new IllegalStateException("Cannot get child nodes of an incomplete directory: " + getName()); } - public void walk(Consumer consumer) { - consumer.accept(this); - for (Node child : children) { - if (child.isDirectory()) { - ((Directory)child).walk(consumer); - } else { - consumer.accept(child); - } - } + private void setChildren(List children) { + assert this.children == null : this + ": Cannot set child nodes twice!"; + this.children = Collections.unmodifiableList(children); } } - // "resource" is .class or any other resource (compressed/uncompressed) in a jimage. - // full path of the resource is the "name" of the resource. - static class Resource extends Node { + /** + * Resource node (e.g. a ".class" entry, or any other data resource). + * + *

    Resources are leaf nodes referencing an underlying image location. They + * are lightweight, and do not cache their contents. + * + *

    Unlike directories (where the node name matches the jimage path for the + * corresponding {@code ImageLocation}), resource node names are NOT the same + * as the corresponding jimage path. The difference is that node names for + * resources are prefixed with "/modules", which is missing from the + * equivalent jimage path. + */ + private static class Resource extends Node { private final ImageLocation loc; - private Resource(ImageLocation loc, BasicFileAttributes fileAttrs) { - super(loc.getFullName(true), fileAttrs); + private Resource(String name, ImageLocation loc, BasicFileAttributes fileAttrs) { + super(name, fileAttrs); this.loc = loc; } - static Resource create(Directory parent, ImageLocation loc, BasicFileAttributes fileAttrs) { - Resource rs = new Resource(loc, fileAttrs); - parent.addChild(rs); - return rs; - } - @Override - public boolean isCompleted() { - return true; + ImageLocation getLocation() { + return loc; } @Override @@ -799,11 +1018,6 @@ public boolean isResource() { return true; } - @Override - public ImageLocation getLocation() { - return loc; - } - @Override public long size() { return loc.getUncompressedSize(); @@ -818,36 +1032,29 @@ public long compressedSize() { public String extension() { return loc.getExtension(); } - - @Override - public long contentOffset() { - return loc.getContentOffset(); - } } - // represents a soft link to another Node - static class LinkNode extends Node { - private final Node link; - - private LinkNode(String name, Node link) { - super(name, link.getFileAttributes()); + /** + * Link node (a symbolic link to a top-level modules directory). + * + *

    Link nodes resolve their target by invoking a given supplier, and do + * not cache the result. Since nodes are cached by the {@code ImageReader}, + * this means that only the first call to {@link #resolveLink(boolean)} + * could do any significant work. + */ + private static class LinkNode extends Node { + private final Supplier link; + + private LinkNode(String name, Supplier link, BasicFileAttributes fileAttrs) { + super(name, fileAttrs); this.link = link; } - static LinkNode create(Directory parent, String name, Node link) { - LinkNode ln = new LinkNode(name, link); - parent.addChild(ln); - return ln; - } - - @Override - public boolean isCompleted() { - return true; - } - @Override public Node resolveLink(boolean recursive) { - return (recursive && link instanceof LinkNode) ? ((LinkNode)link).resolveLink(true) : link; + // No need to use or propagate the recursive flag, since the target + // cannot possibly be a link node (links only point to directories). + return link.get(); } @Override diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java b/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java index eea62e444de..d9a6755d0cc 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -33,6 +33,19 @@ * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ public interface ImageStrings { + // String offset constants are useful for efficient classification + // of location entries without string comparison. These may change + // between jimage versions (they are checked during initialization). + + /** Fixed offset for the empty string in the strings table. */ + int EMPTY_STRING_OFFSET = 0; + /** Fixed offset for the string "class" in the strings table. */ + int CLASS_STRING_OFFSET = 1; + /** Fixed offset for the string "modules" in the strings table. */ + int MODULES_STRING_OFFSET = 7; + /** Fixed offset for the string "packages" in the strings table. */ + int PACKAGES_STRING_OFFSET = 15; + String get(int offset); int add(final String string); diff --git a/src/java.base/share/classes/jdk/internal/jimage/ModuleReference.java b/src/java.base/share/classes/jdk/internal/jimage/ModuleReference.java new file mode 100644 index 00000000000..6a28fd10c87 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/jimage/ModuleReference.java @@ -0,0 +1,265 @@ +/* + * 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. + */ + +package jdk.internal.jimage; + +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * Represents the module entries stored in the buffer of {@code "/packages/xxx"} + * image locations (package subdirectories). These entries use flags which are + * similar to, but distinct from, the {@link ImageLocation} flags, so + * encapsulating them here helps avoid confusion. + * + * @implNote This class needs to maintain JDK 8 source compatibility. + * + * It is used internally in the JDK to implement jimage/jrtfs access, + * but also compiled and delivered as part of the jrtfs.jar to support access + * to the jimage file provided by the shipped JDK by tools running on JDK 8. + */ +public final class ModuleReference implements Comparable { + // The following flags are designed to be additive (hence "has-resources" + // rather than "is-empty", even though "isEmpty()" is whats in the API). + // API methods like "isEmpty()" and "hasPreviewVersion()" are designed to + // match the semantics of ImageLocation flags to avoid having business + // logic need to reason about two different flag regimes. + + /** If set, the associated module has resources (in normal or preview mode). */ + private static final int FLAGS_HAS_CONTENT = 0x1; + /** If set, this package exists in non-preview mode. */ + private static final int FLAGS_HAS_NORMAL_VERSION = 0x2; + /** If set, this package exists in preview mode. */ + private static final int FLAGS_HAS_PREVIEW_VERSION = 0x4; + + /** + * References are ordered with preview versions first which permits early + * exit when processing preview entries (it's reversed because the default + * order for a boolean is {@code false < true}). + */ + private static final Comparator PREVIEW_FIRST = + Comparator.comparing(ModuleReference::hasPreviewVersion).reversed() + .thenComparing(ModuleReference::name); + + /** Creates a reference for an empty package (one without content in). */ + public static ModuleReference forEmptyPackage(String moduleName, boolean isPreview) { + return new ModuleReference(moduleName, previewFlag(isPreview)); + } + + /** Creates a reference for a preview only module. */ + public static ModuleReference forResource(String moduleName, boolean isPreview) { + return new ModuleReference(moduleName, FLAGS_HAS_CONTENT | previewFlag(isPreview)); + } + + private static int previewFlag(boolean isPreview) { + return isPreview ? FLAGS_HAS_PREVIEW_VERSION : FLAGS_HAS_NORMAL_VERSION; + } + + /** Merges two references for the same module (combining their flags). */ + public ModuleReference merge(ModuleReference other) { + if (!name.equals(other.name)) { + throw new IllegalArgumentException("Cannot merge " + other + " with " + this); + } + // Because flags are additive, we can just OR them here. + return new ModuleReference(name, flags | other.flags); + } + + private final String name; + private final int flags; + + private ModuleReference(String moduleName, int flags) { + this.name = Objects.requireNonNull(moduleName); + this.flags = flags; + } + + /** Returns the module name of this reference. */ + public String name() { + return name; + } + + /** + * Returns whether the package associated with this reference contains + * resources in this reference's module. + * + *

    An invariant of the module system is that while a package may exist + * under many modules, it is only non-empty in one. + */ + public boolean hasContent() { + return ((flags & FLAGS_HAS_CONTENT) != 0); + } + + /** + * Returns whether the package associated with this reference has a preview + * version (empty or otherwise) in this reference's module. + */ + public boolean hasPreviewVersion() { + return (flags & FLAGS_HAS_PREVIEW_VERSION) != 0; + } + + /** Returns whether this reference exists only in preview mode. */ + public boolean isPreviewOnly() { + return !hasNormalVersion(flags); + } + + private static boolean hasNormalVersion(int flags) { + return (flags & FLAGS_HAS_NORMAL_VERSION) != 0; + } + + @Override + public int compareTo(ModuleReference rhs) { + return PREVIEW_FIRST.compare(this, rhs); + } + + @Override + public String toString() { + return "ModuleReference{ module=" + name + ", flags=" + flags + " }"; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ModuleReference)) { + return false; + } + ModuleReference other = (ModuleReference) obj; + return name.equals(other.name) && flags == other.flags; + } + + @Override + public int hashCode() { + return Objects.hash(name, flags); + } + + /** + * Reads the content buffer of a package subdirectory to return a sequence + * of module name offsets in the jimage. + * + * @param buffer the content buffer of an {@link ImageLocation} with type + * {@link ImageLocation.LocationType#PACKAGES_DIR PACKAGES_DIR}. + * @param includeNormal whether to include name offsets for modules present + * in normal (non-preview) mode. + * @param includePreview whether to include name offsets for modules present + * in preview mode. + * @return an iterator of module name offsets. + */ + public static Iterator readNameOffsets( + IntBuffer buffer, boolean includeNormal, boolean includePreview) { + int bufferSize = buffer.capacity(); + if (bufferSize == 0 || (bufferSize & 0x1) != 0) { + throw new IllegalArgumentException("Invalid buffer size"); + } + int testFlags = (includeNormal ? FLAGS_HAS_NORMAL_VERSION : 0) + + (includePreview ? FLAGS_HAS_PREVIEW_VERSION : 0); + if (testFlags == 0) { + throw new IllegalArgumentException("Invalid flags"); + } + + return new Iterator() { + private int idx = nextIdx(0); + + int nextIdx(int idx) { + for (; idx < bufferSize; idx += 2) { + // If any of the test flags are set, include this entry. + if ((buffer.get(idx) & testFlags) != 0) { + return idx; + } else if (!includeNormal) { + // Preview entries are first in the offset buffer, so we + // can exit early (by returning the end index) if we are + // only iterating preview entries, and have run out. + break; + } + } + return bufferSize; + } + + @Override + public boolean hasNext() { + return idx < bufferSize; + } + + @Override + public Integer next() { + if (idx < bufferSize) { + int nameOffset = buffer.get(idx + 1); + idx = nextIdx(idx + 2); + return nameOffset; + } + throw new NoSuchElementException(); + } + }; + } + + /** + * Writes a list of module references to a given buffer. The given references + * list is checked carefully to ensure the written buffer will be valid. + * + *

    Entries are written in order, taking two integer slots per entry as + * {@code [, ]}. + * + * @param refs the references to write, correctly ordered. + * @param buffer destination buffer. + * @param nameEncoder encoder for module names. + * @throws IllegalArgumentException in the references are invalid in any way. + */ + public static void write( + List refs, IntBuffer buffer, Function nameEncoder) { + if (refs.isEmpty()) { + throw new IllegalArgumentException("References list must be non-empty"); + } + int expectedCapacity = 2 * refs.size(); + if (buffer.capacity() != expectedCapacity) { + throw new IllegalArgumentException( + "Invalid buffer capacity: expected " + expectedCapacity + ", got " + buffer.capacity()); + } + // This catches exact duplicates in the list. + refs.stream().reduce((lhs, rhs) -> { + if (lhs.compareTo(rhs) >= 0) { + throw new IllegalArgumentException("References must be strictly ordered: " + refs); + } + return rhs; + }); + // Distinct references can have the same name (but we don't allow this). + if (refs.stream().map(ModuleReference::name).distinct().count() != refs.size()) { + throw new IllegalArgumentException("Reference names must be unique: " + refs); + } + if (refs.stream().filter(ModuleReference::hasContent).count() > 1) { + throw new IllegalArgumentException("At most one reference can have content: " + refs); + } + for (ModuleReference modRef : refs) { + buffer.put(modRef.flags); + buffer.put(nameEncoder.apply(modRef.name)); + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java b/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java new file mode 100644 index 00000000000..e6e54de0f2a --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java @@ -0,0 +1,88 @@ +/* + * 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. + */ +package jdk.internal.jimage; + +import java.lang.reflect.InvocationTargetException; + +/** + * Specifies the preview mode used to open a jimage file via {@link ImageReader}. + * + * @implNote This class needs to maintain JDK 8 source compatibility. + * + * It is used internally in the JDK to implement jimage/jrtfs access, + * but also compiled and delivered as part of the jrtfs.jar to support access + * to the jimage file provided by the shipped JDK by tools running on JDK 8. + * */ +public enum PreviewMode { + /** + * Preview mode is disabled. No preview classes or resources will be available + * in this mode. + */ + DISABLED() { + @Override + boolean resolve() { + return false; + } + }, + /** + * Preview mode is enabled. If preview classes or resources exist in the jimage file, + * they will be made available. + */ + ENABLED() { + @Override + boolean resolve() { + return true; + } + }, + /** + * The preview mode of the current run-time, typically determined by the + * {@code --enable-preview} flag. + */ + FOR_RUNTIME() { + @Override + boolean resolve() { + // We want to call jdk.internal.misc.PreviewFeatures.isEnabled(), but + // is not available in older JREs, so we must look to it reflectively. + Class clazz; + try { + clazz = Class.forName("jdk.internal.misc.PreviewFeatures"); + } catch (ClassNotFoundException e) { + // It is valid and expected that the class might not exist (JDK-8). + return false; + } + try { + return (Boolean) clazz.getDeclaredMethod("isEnabled").invoke(null); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + // But if the class exists, the method must exist and be callable. + throw new ExceptionInInitializerError(e); + } + } + }; + + /** + * Resolves whether preview mode should be enabled for an {@link ImageReader}. + */ + abstract boolean resolve(); +} diff --git a/src/java.base/share/classes/jdk/internal/jimage/SystemImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/SystemImageReader.java new file mode 100644 index 00000000000..38bf786e533 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/jimage/SystemImageReader.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, 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. + */ + +package jdk.internal.jimage; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; + +/** + * Static holder class for singleton {@link ImageReader} instance. + * + * @implNote This class needs to maintain JDK 8 source compatibility. + * + * It is used internally in the JDK to implement jimage/jrtfs access, + * but also compiled and delivered as part of the jrtfs.jar to support access + * to the jimage file provided by the shipped JDK by tools running on JDK 8. + */ +public class SystemImageReader { + private static final ImageReader SYSTEM_IMAGE_READER; + + static { + String javaHome = System.getProperty("java.home"); + FileSystem fs; + if (SystemImageReader.class.getClassLoader() == null) { + try { + fs = (FileSystem) Class.forName("sun.nio.fs.DefaultFileSystemProvider") + .getMethod("theFileSystem") + .invoke(null); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } else { + fs = FileSystems.getDefault(); + } + try { + SYSTEM_IMAGE_READER = ImageReader.open(fs.getPath(javaHome, "lib", "modules"), PreviewMode.FOR_RUNTIME); + } catch (IOException e) { + throw new ExceptionInInitializerError(e); + } + } + + /** + * Returns the singleton {@code ImageReader} to read the image file in this + * run-time image. The returned instance must not be closed. + * + * @throws UncheckedIOException if an I/O error occurs + */ + public static ImageReader get() { + return SYSTEM_IMAGE_READER; + } + + private SystemImageReader() {} +} diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/ExplodedImage.java b/src/java.base/share/classes/jdk/internal/jrtfs/ExplodedImage.java index e2c17f8ca25..4fe6612a8ed 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/ExplodedImage.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/ExplodedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -27,17 +27,15 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; import java.nio.file.FileSystemException; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Stream; import jdk.internal.jimage.ImageReader.Node; @@ -56,16 +54,15 @@ class ExplodedImage extends SystemImage { private static final String MODULES = "/modules/"; private static final String PACKAGES = "/packages/"; - private static final int PACKAGES_LEN = PACKAGES.length(); - private final FileSystem defaultFS; + private final Path modulesDir; private final String separator; - private final Map nodes = Collections.synchronizedMap(new HashMap<>()); + private final Map nodes = new HashMap<>(); private final BasicFileAttributes modulesDirAttrs; ExplodedImage(Path modulesDir) throws IOException { - defaultFS = FileSystems.getDefault(); - String str = defaultFS.getSeparator(); + this.modulesDir = modulesDir; + String str = modulesDir.getFileSystem().getSeparator(); separator = str.equals("/") ? null : str; modulesDirAttrs = Files.readAttributes(modulesDir, BasicFileAttributes.class); initNodes(); @@ -79,21 +76,26 @@ private final class PathNode extends Node { private PathNode link; private List children; - PathNode(String name, Path path, BasicFileAttributes attrs) { // path + private PathNode(String name, Path path, BasicFileAttributes attrs) { // path super(name, attrs); this.path = path; } - PathNode(String name, Node link) { // link + private PathNode(String name, Node link) { // link super(name, link.getFileAttributes()); this.link = (PathNode)link; } - PathNode(String name, List children) { // dir + private PathNode(String name, List children) { // dir super(name, modulesDirAttrs); this.children = children; } + @Override + public boolean isResource() { + return link == null && !getFileAttributes().isDirectory(); + } + @Override public boolean isDirectory() { return children != null || @@ -112,21 +114,21 @@ public PathNode resolveLink(boolean recursive) { return recursive && link.isLink() ? link.resolveLink(true) : link; } - byte[] getContent() throws IOException { + private byte[] getContent() throws IOException { if (!getFileAttributes().isRegularFile()) throw new FileSystemException(getName() + " is not file"); return Files.readAllBytes(path); } @Override - public List getChildren() { + public Stream getChildNames() { if (!isDirectory()) - throw new IllegalArgumentException("not a directory: " + getNameString()); + throw new IllegalArgumentException("not a directory: " + getName()); if (children == null) { List list = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(path)) { for (Path p : stream) { - p = explodedModulesDir.relativize(p); + p = modulesDir.relativize(p); String pName = MODULES + nativeSlashToFrontSlash(p.toString()); Node node = findNode(pName); if (node != null) { // findNode may choose to hide certain files! @@ -138,7 +140,7 @@ public List getChildren() { } children = list; } - return children; + return children.stream().map(Node::getName); } @Override @@ -152,7 +154,7 @@ public long size() { } @Override - public void close() throws IOException { + public synchronized void close() throws IOException { nodes.clear(); } @@ -161,74 +163,78 @@ public byte[] getResource(Node node) throws IOException { return ((PathNode)node).getContent(); } - // find Node for the given Path @Override - public synchronized Node findNode(String str) { - Node node = findModulesNode(str); + public synchronized Node findNode(String name) { + PathNode node = nodes.get(name); if (node != null) { return node; } - // lazily created for paths like /packages///xyz - // For example /packages/java.lang/java.base/java/lang/ - if (str.startsWith(PACKAGES)) { - // pkgEndIdx marks end of part - int pkgEndIdx = str.indexOf('/', PACKAGES_LEN); - if (pkgEndIdx != -1) { - // modEndIdx marks end of part - int modEndIdx = str.indexOf('/', pkgEndIdx + 1); - if (modEndIdx != -1) { - // make sure we have such module link! - // ie., /packages// is valid - Node linkNode = nodes.get(str.substring(0, modEndIdx)); - if (linkNode == null || !linkNode.isLink()) { - return null; - } - // map to "/modules/zyz" path and return that node - // For example, "/modules/java.base/java/lang" for - // "/packages/java.lang/java.base/java/lang". - String mod = MODULES + str.substring(pkgEndIdx + 1); - return findModulesNode(mod); - } - } + // If null, this was not the name of "/modules/..." node, and since all + // "/packages/..." nodes were created and cached in advance, the name + // cannot reference a valid node. + Path path = underlyingModulesPath(name); + if (path == null) { + return null; } - return null; + // This can still return null for hidden files. + return createModulesNode(name, path); } - // find a Node for a path that starts like "/modules/..." - Node findModulesNode(String str) { - PathNode node = nodes.get(str); - if (node != null) { - return node; - } - // lazily created "/modules/xyz/abc/" Node - // This is mapped to default file system path "/xyz/abc" - Path p = underlyingPath(str); - if (p != null) { - try { - BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class); - if (attrs.isRegularFile()) { - Path f = p.getFileName(); - if (f.toString().startsWith("_the.")) - return null; + /** + * Lazily creates and caches a {@code Node} for the given "/modules/..." name + * and corresponding path to a file or directory. + * + * @param name a resource or directory node name, of the form "/modules/...". + * @param path the path of a file for a resource or directory. + * @return the newly created and cached node, or {@code null} if the given + * path references a file which must be hidden in the node hierarchy. + */ + private Node createModulesNode(String name, Path path) { + assert !nodes.containsKey(name) : "Node must not already exist: " + name; + assert isNonEmptyModulesPath(name) : "Invalid modules name: " + name; + + try { + // We only know if we're creating a resource of directory when we + // look up file attributes, and we only do that once. Thus, we can + // only reject "marker files" here, rather than by inspecting the + // given name string, since it doesn't apply to directories. + BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); + if (attrs.isRegularFile()) { + Path f = path.getFileName(); + if (f.toString().startsWith("_the.")) { + return null; } - node = new PathNode(str, p, attrs); - nodes.put(str, node); - return node; - } catch (IOException x) { - // does not exists or unable to determine + } else if (!attrs.isDirectory()) { + return null; } + PathNode node = new PathNode(name, path, attrs); + nodes.put(name, node); + return node; + } catch (IOException x) { + // Since the path reference a file, any errors should not be ignored. + throw new UncheckedIOException(x); } - return null; } - Path underlyingPath(String str) { - if (str.startsWith(MODULES)) { - str = frontSlashToNativeSlash(str.substring("/modules".length())); - return defaultFS.getPath(explodedModulesDir.toString(), str); + /** + * Returns the expected file path for name in the "/modules/..." namespace, + * or {@code null} if the name is not in the "/modules/..." namespace or the + * path does not reference a file. + */ + private Path underlyingModulesPath(String name) { + if (isNonEmptyModulesPath(name)) { + Path path = modulesDir.resolve(frontSlashToNativeSlash(name.substring(MODULES.length()))); + return Files.exists(path) ? path : null; } return null; } + private static boolean isNonEmptyModulesPath(String name) { + // Don't just check the prefix, there must be something after it too + // (otherwise you end up with an empty string after trimming). + return name.startsWith(MODULES) && name.length() > MODULES.length(); + } + // convert "/" to platform path separator private String frontSlashToNativeSlash(String str) { return separator == null ? str : str.replace("/", separator); @@ -249,24 +255,21 @@ private void initNodes() throws IOException { // same package prefix may exist in multiple modules. This Map // is filled by walking "jdk modules" directory recursively! Map> packageToModules = new HashMap<>(); - try (DirectoryStream stream = Files.newDirectoryStream(explodedModulesDir)) { + try (DirectoryStream stream = Files.newDirectoryStream(modulesDir)) { for (Path module : stream) { if (Files.isDirectory(module)) { String moduleName = module.getFileName().toString(); // make sure "/modules/" is created - findModulesNode(MODULES + moduleName); + Objects.requireNonNull(createModulesNode(MODULES + moduleName, module)); try (Stream contentsStream = Files.walk(module)) { contentsStream.filter(Files::isDirectory).forEach((p) -> { p = module.relativize(p); String pkgName = slashesToDots(p.toString()); // skip META-INF and empty strings if (!pkgName.isEmpty() && !pkgName.startsWith("META-INF")) { - List moduleNames = packageToModules.get(pkgName); - if (moduleNames == null) { - moduleNames = new ArrayList<>(); - packageToModules.put(pkgName, moduleNames); - } - moduleNames.add(moduleName); + packageToModules + .computeIfAbsent(pkgName, k -> new ArrayList<>()) + .add(moduleName); } }); } @@ -275,8 +278,8 @@ private void initNodes() throws IOException { } // create "/modules" directory // "nodes" map contains only /modules/ nodes only so far and so add all as children of /modules - PathNode modulesDir = new PathNode("/modules", new ArrayList<>(nodes.values())); - nodes.put(modulesDir.getName(), modulesDir); + PathNode modulesRootNode = new PathNode("/modules", new ArrayList<>(nodes.values())); + nodes.put(modulesRootNode.getName(), modulesRootNode); // create children under "/packages" List packagesChildren = new ArrayList<>(packageToModules.size()); @@ -285,7 +288,7 @@ private void initNodes() throws IOException { List moduleNameList = entry.getValue(); List moduleLinkNodes = new ArrayList<>(moduleNameList.size()); for (String moduleName : moduleNameList) { - Node moduleNode = findModulesNode(MODULES + moduleName); + Node moduleNode = Objects.requireNonNull(nodes.get(MODULES + moduleName)); PathNode linkNode = new PathNode(PACKAGES + pkgName + "/" + moduleName, moduleNode); nodes.put(linkNode.getName(), linkNode); moduleLinkNodes.add(linkNode); @@ -295,13 +298,13 @@ private void initNodes() throws IOException { packagesChildren.add(pkgDir); } // "/packages" dir - PathNode packagesDir = new PathNode("/packages", packagesChildren); - nodes.put(packagesDir.getName(), packagesDir); + PathNode packagesRootNode = new PathNode("/packages", packagesChildren); + nodes.put(packagesRootNode.getName(), packagesRootNode); // finally "/" dir! List rootChildren = new ArrayList<>(); - rootChildren.add(packagesDir); - rootChildren.add(modulesDir); + rootChildren.add(packagesRootNode); + rootChildren.add(modulesRootNode); PathNode root = new PathNode("/", rootChildren); nodes.put(root.getName(), root); } diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java index f0804b58c1c..e1eb1115260 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -49,7 +49,7 @@ final class JrtFileAttributes implements BasicFileAttributes { //-------- basic attributes -------- @Override public FileTime creationTime() { - return node.creationTime(); + return node.getFileAttributes().creationTime(); } @Override @@ -69,12 +69,12 @@ public boolean isRegularFile() { @Override public FileTime lastAccessTime() { - return node.lastAccessTime(); + return node.getFileAttributes().lastAccessTime(); } @Override public FileTime lastModifiedTime() { - return node.lastModifiedTime(); + return node.getFileAttributes().lastModifiedTime(); } @Override diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java index 9a8d9d22dfa..4d739d1e200 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -54,17 +54,15 @@ import java.nio.file.attribute.FileTime; import java.nio.file.attribute.UserPrincipalLookupService; import java.nio.file.spi.FileSystemProvider; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; import jdk.internal.jimage.ImageReader.Node; -import static java.util.stream.Collectors.toList; +import jdk.internal.jimage.PreviewMode; /** * jrt file system implementation built on System jimage files. @@ -83,13 +81,34 @@ class JrtFileSystem extends FileSystem { private volatile boolean isClosable; private SystemImage image; - JrtFileSystem(JrtFileSystemProvider provider, Map env) - throws IOException - { + /** + * Special constructor for the singleton system jrt file system. This creates + * a non-closable instance, and should only be called once by {@link + * JrtFileSystemProvider}. + * + * @param provider the provider opening the file system. + */ + JrtFileSystem(JrtFileSystemProvider provider) + throws IOException { this.provider = provider; - this.image = SystemImage.open(); // open image file + this.image = SystemImage.open(PreviewMode.FOR_RUNTIME); // open image file this.isOpen = true; - this.isClosable = env != null; + // Only the system singleton jrt file system is "unclosable". + this.isClosable = false; + } + + /** + * Creates a new, non-system, instance of the jrt file system. + * + * @param provider the provider opening the file system. + * @param mode controls whether preview resources are visible. + */ + JrtFileSystem(JrtFileSystemProvider provider, PreviewMode mode) + throws IOException { + this.provider = provider; + this.image = SystemImage.open(mode); // open image file + this.isOpen = true; + this.isClosable = true; } // FileSystem method implementations @@ -225,19 +244,19 @@ Iterator iteratorOf(JrtPath path, DirectoryStream.Filter fil throw new NotDirectoryException(path.getName()); } if (filter == null) { - return node.getChildren() - .stream() - .map(child -> (Path)(path.resolve(new JrtPath(this, child.getNameString()).getFileName()))) - .iterator(); + return node.getChildNames() + .map(child -> (Path) (path.resolve(new JrtPath(this, child).getFileName()))) + .iterator(); } - return node.getChildren() - .stream() - .map(child -> (Path)(path.resolve(new JrtPath(this, child.getNameString()).getFileName()))) - .filter(p -> { try { return filter.accept(p); - } catch (IOException x) {} - return false; - }) - .iterator(); + return node.getChildNames() + .map(child -> (Path) (path.resolve(new JrtPath(this, child).getFileName()))) + .filter(p -> { + try { + return filter.accept(p); + } catch (IOException x) {} + return false; + }) + .iterator(); } // returns the content of the file resource specified by the path diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java index 9ee620f4137..5721aa7411e 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java @@ -24,6 +24,8 @@ */ package jdk.internal.jrtfs; +import jdk.internal.jimage.PreviewMode; + import java.io.*; import java.net.MalformedURLException; import java.net.URL; @@ -44,7 +46,7 @@ /** * File system provider for jrt file systems. Conditionally creates jrt fs on - * .jimage file or exploded modules directory of underlying JDK. + * a jimage file, or exploded modules directory of underlying JDK. * * @implNote This class needs to maintain JDK 8 source compatibility. * @@ -107,8 +109,22 @@ public FileSystem newFileSystem(URI uri, Map env) if (env.containsKey("java.home")) { return newFileSystem((String)env.get("java.home"), uri, env); } else { - return new JrtFileSystem(this, env); + return new JrtFileSystem(this, parsePreviewMode(env.get("previewMode"))); + } + } + + // Currently this does not support specifying "for runtime", because it is + // expected that callers creating non-standard image readers will not be + // using them to read resources for the current runtime (they would just + // use "jrt:" URLs if they were doing that). + private static PreviewMode parsePreviewMode(Object envValue) { + if (envValue instanceof Boolean && (Boolean) envValue) { + return PreviewMode.ENABLED; + } else if (envValue instanceof String && Boolean.parseBoolean((String) envValue)) { + return PreviewMode.ENABLED; } + // Default (unspecified/null or bad parameter) is to not use preview mode. + return PreviewMode.DISABLED; } private static final String JRT_FS_JAR = "jrt-fs.jar"; @@ -208,7 +224,8 @@ private FileSystem getTheFileSystem() { fs = this.theFileSystem; if (fs == null) { try { - this.theFileSystem = fs = new JrtFileSystem(this, null); + // Special constructor call for singleton instance. + this.theFileSystem = fs = new JrtFileSystem(this); } catch (IOException ioe) { throw new InternalError(ioe); } @@ -226,7 +243,7 @@ public FileSystem getFileSystem(URI uri) { } // Checks that the given file is a JrtPath - static final JrtPath toJrtPath(Path path) { + static JrtPath toJrtPath(Path path) { Objects.requireNonNull(path, "path"); if (!(path instanceof JrtPath)) { throw new ProviderMismatchException(); @@ -257,7 +274,7 @@ public void createDirectory(Path path, FileAttribute... attrs) } @Override - public final void delete(Path path) throws IOException { + public void delete(Path path) throws IOException { toJrtPath(path).delete(); } diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java index 88cdf724e7d..caa915f926f 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java @@ -39,6 +39,7 @@ import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReader.Node; +import jdk.internal.jimage.PreviewMode; /** * @implNote This class needs to maintain JDK 8 source compatibility. @@ -54,11 +55,10 @@ abstract class SystemImage { abstract byte[] getResource(Node node) throws IOException; abstract void close() throws IOException; - static SystemImage open() throws IOException { + static SystemImage open(PreviewMode mode) throws IOException { if (modulesImageExists) { // open a .jimage and build directory structure - final ImageReader image = ImageReader.open(moduleImageFile); - image.getRootDirectory(); + final ImageReader image = ImageReader.open(moduleImageFile, mode); return new SystemImage() { @Override Node findNode(String path) throws IOException { @@ -74,18 +74,21 @@ void close() throws IOException { } }; } + + // TODO: Maybe throw if enablePreview attempted for exploded image? + if (Files.notExists(explodedModulesDir)) throw new FileSystemNotFoundException(explodedModulesDir.toString()); return new ExplodedImage(explodedModulesDir); } - static final String RUNTIME_HOME; + private static final String RUNTIME_HOME; // "modules" jimage file Path - static final Path moduleImageFile; + private static final Path moduleImageFile; // "modules" jimage exists or not? - static final boolean modulesImageExists; + private static final boolean modulesImageExists; // /modules directory Path - static final Path explodedModulesDir; + private static final Path explodedModulesDir; static { PrivilegedAction pa = SystemImage::findHome; diff --git a/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java index 441137db486..2db099e93ed 100644 --- a/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java +++ b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,8 +26,6 @@ package jdk.internal.math; -import java.io.IOException; - import static java.lang.Double.*; import static java.lang.Long.*; import static java.lang.Math.multiplyHigh; @@ -66,44 +64,72 @@ public final class DoubleToDecimal extends ToDecimal { * This is discussed in section 10 of [1]. */ - /* The precision in bits */ static final int P = PRECISION; - /* Exponent width in bits */ - private static final int W = (Double.SIZE - 1) - (P - 1); + /* Exponent width in bits. */ + static final int W = (Double.SIZE - 1) - (P - 1); - /* Minimum value of the exponent: -(2^(W-1)) - P + 3 */ + /* Minimum value of the exponent: -(2^(W-1)) - P + 3. */ static final int Q_MIN = (-1 << (W - 1)) - P + 3; - /* Maximum value of the exponent: 2^(W-1) - P */ + /* Maximum value of the exponent: 2^(W-1) - P. */ static final int Q_MAX = (1 << (W - 1)) - P; - /* 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN */ + /* Minimum value of the significand of a normal value: 2^(P-1). */ + static final long C_MIN = 1L << (P - 1); + + /* Maximum value of the significand of a normal value: 2^P - 1. */ + static final long C_MAX = (1L << P) - 1; + + /* E_MIN = max{e : 10^(e-1) <= MIN_VALUE}. */ static final int E_MIN = -323; - /* 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX */ + /* E_MAX = max{e : 10^(e-1) <= MAX_VALUE}. */ static final int E_MAX = 309; - /* Threshold to detect tiny values, as in section 8.2.1 of [1] */ - static final long C_TINY = 3; + /* + * Let THR_Z = ulp(0.0) / 2 = MIN_VALUE / 2 = 2^(Q_MIN-1). + * THR_Z is the zero threshold. + * Real x rounds to 0 by roundTiesToEven iff |x| <= THR_Z. + * + * E_THR_Z = max{e : 10^e <= THR_Z}. + */ + static final int E_THR_Z = -324; - /* The minimum and maximum k, as in section 8 of [1] */ + /* + * Let THR_I = MAX_VALUE + ulp(MAX_VALUE) / 2 = (2 C_MAX + 1) 2^(Q_MAX-1). + * THR_I is the infinity threshold. + * Real x rounds to infinity by roundTiesToEven iff |x| >= THR_I. + * + * E_THR_I = min{e : THR_I <= 10^(e-1)}. + */ + static final int E_THR_I = 310; + + /* K_MIN = max{k : 10^k <= 2^Q_MIN}. */ static final int K_MIN = -324; + + /* K_MAX = max{k : 10^k <= 2^Q_MAX}. */ static final int K_MAX = 292; - /* H is as in section 8.1 of [1] */ - static final int H = 17; + /* + * Threshold to detect tiny values, as in section 8.2.1 of [1]. + * C_TINY = ceil(2^(-Q_MIN) 10^(K_MIN+1)) + */ + static final long C_TINY = 3; - /* Minimum value of the significand of a normal value: 2^(P-1) */ - private static final long C_MIN = 1L << (P - 1); + /* + * H is as in section 8.1 of [1]. + * H = max{e : 10^(e-2) <= 2^P} + */ + static final int H = 17; - /* Mask to extract the biased exponent */ + /* Mask to extract the biased exponent. */ private static final int BQ_MASK = (1 << W) - 1; - /* Mask to extract the fraction bits */ + /* Mask to extract the fraction bits. */ private static final long T_MASK = (1L << (P - 1)) - 1; - /* Used in rop() */ + /* Used in rop(). */ private static final long MASK_63 = (1L << 63) - 1; /* @@ -169,7 +195,6 @@ public static void split(double v, FormattedFPDecimal fd) { * @param str the String byte array to append to * @param index the index into str * @param v the {@code double} whose rendering is into str. - * @throws IOException If an I/O error occurs */ public int putDecimal(byte[] str, int index, double v) { assert 0 <= index && index <= length(str) - MAX_CHARS : "Trusted caller missed bounds check"; @@ -280,8 +305,8 @@ private int toDecimal(byte[] str, int index, int q, long c, int dk, FormattedFPD int h = q + flog2pow10(-k) + 2; /* g1 and g0 are as in section 9.8.3 of [1], so g = g1 2^63 + g0 */ - long g1 = g1(k); - long g0 = g0(k); + long g1 = g1(-k); + long g0 = g0(-k); long vb = rop(g1, g0, cb << h); long vbl = rop(g1, g0, cbl << h); diff --git a/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java b/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java index 1ca68a000d9..f0ce15db4dd 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,8 +26,6 @@ package jdk.internal.math; -import java.io.IOException; - import static java.lang.Float.*; import static java.lang.Integer.*; import static java.lang.Math.multiplyHigh; @@ -66,44 +64,72 @@ public final class FloatToDecimal extends ToDecimal { * This is discussed in section 10 of [1]. */ - /* The precision in bits */ static final int P = PRECISION; - /* Exponent width in bits */ - private static final int W = (Float.SIZE - 1) - (P - 1); + /* Exponent width in bits. */ + static final int W = (Float.SIZE - 1) - (P - 1); - /* Minimum value of the exponent: -(2^(W-1)) - P + 3 */ + /* Minimum value of the exponent: -(2^(W-1)) - P + 3. */ static final int Q_MIN = (-1 << (W - 1)) - P + 3; - /* Maximum value of the exponent: 2^(W-1) - P */ + /* Maximum value of the exponent: 2^(W-1) - P. */ static final int Q_MAX = (1 << (W - 1)) - P; - /* 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN */ + /* Minimum value of the significand of a normal value: 2^(P-1). */ + static final int C_MIN = 1 << (P - 1); + + /* Maximum value of the significand of a normal value: 2^P - 1. */ + static final int C_MAX = (1 << P) - 1; + + /* E_MIN = max{e : 10^(e-1) <= MIN_VALUE}. */ static final int E_MIN = -44; - /* 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX */ + /* E_MAX = max{e : 10^(e-1) <= MAX_VALUE}. */ static final int E_MAX = 39; - /* Threshold to detect tiny values, as in section 8.2.1 of [1] */ - static final int C_TINY = 8; + /* + * Let THR_Z = ulp(0.0) / 2 = MIN_VALUE / 2 = 2^(Q_MIN-1). + * THR_Z is the zero threshold. + * x is rounded to 0 by roundTiesToEven iff |x| <= THR_Z. + * + * E_THR_Z = max{e : 10^e <= THR_Z}. + */ + static final int E_THR_Z = -46; - /* The minimum and maximum k, as in section 8 of [1] */ + /* + * Let THR_I = MAX_VALUE + ulp(MAX_VALUE) / 2 = (2 C_MAX + 1) 2^(Q_MAX-1). + * THR_I is the infinity threshold. + * x is rounded to infinity by roundTiesToEven iff |x| >= THR_I. + * + * E_THR_I = min{e : THR_I <= 10^(e-1)}. + */ + static final int E_THR_I = 40; + + /* K_MIN = max{k : 10^k <= 2^Q_MIN}. */ static final int K_MIN = -45; + + /* K_MAX = max{k : 10^k <= 2^Q_MAX}. */ static final int K_MAX = 31; - /* H is as in section 8.1 of [1] */ - static final int H = 9; + /* + * Threshold to detect tiny values, as in section 8.2.1 of [1]. + * C_TINY = ceil(2^(-Q_MIN) 10^(K_MIN+1)) + */ + static final int C_TINY = 8; - /* Minimum value of the significand of a normal value: 2^(P-1) */ - private static final int C_MIN = 1 << (P - 1); + /* + * H is as in section 8.1 of [1]. + * H = max{e : 10^(e-2) <= 2^P} + */ + static final int H = 9; - /* Mask to extract the biased exponent */ + /* Mask to extract the biased exponent. */ private static final int BQ_MASK = (1 << W) - 1; - /* Mask to extract the fraction bits */ + /* Mask to extract the fraction bits. */ private static final int T_MASK = (1 << (P - 1)) - 1; - /* Used in rop() */ + /* Used in rop(). */ private static final long MASK_32 = (1L << 32) - 1; /* @@ -142,12 +168,11 @@ public static String toString(float v) { * Appends the rendering of the {@code v} to {@code str}. * *

    The outcome is the same as if {@code v} were first - * {@link #toString(double) rendered} and the resulting string were then + * {@link #toString(float) rendered} and the resulting string were then * * @param str the String byte array to append to * @param index the index into str * @param v the {@code float} whose rendering is into str. - * @throws IOException If an I/O error occurs */ public int putDecimal(byte[] str, int index, float v) { assert 0 <= index && index <= length(str) - MAX_CHARS : "Trusted caller missed bounds check"; @@ -256,7 +281,7 @@ private int toDecimal(byte[] str, int index, int q, int c, int dk) { int h = q + flog2pow10(-k) + 33; /* g is as in the appendix */ - long g = g1(k) + 1; + long g = g1(-k) + 1; int vb = rop(g, cb << h); int vbl = rop(g, cbl << h); diff --git a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java index 6f59338d4c8..81887144ed1 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -1874,26 +1874,19 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { ++i; } - /* - * In some places the idiom - * (ch | 0b10_0000) == lowercase-letter - * is used as a shortcut for - * ch == lowercase-letter || ch == that-same-letter-as-uppercase - * - * Determine whether we are facing a symbolic value or hex notation. - */ + /* Determine whether we are facing a symbolic value or hex notation. */ boolean isDec = true; // decimal input until proven to the contrary if (i < len) { ch = in.charAt(i); if (ch == 'I') { - scanSymbolic(in, i, "Infinity"); + scanSymbolic(in, i, INFINITY_REP); return ssign != '-' ? A2BC_POSITIVE_INFINITY : A2BC_NEGATIVE_INFINITY; } if (ch == 'N') { - scanSymbolic(in, i, "NaN"); + scanSymbolic(in, i, NAN_REP); return A2BC_NOT_A_NUMBER; // ignore sign } - if (ch == '0' && i < len - 1 && (in.charAt(i + 1) | 0b10_0000) == 'x') { + if (ch == '0' && i + 1 < len && toLowerCase(in.charAt(i + 1)) == 'x') { isDec = false; i += 2; } @@ -1931,7 +1924,7 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { /* Scan exponent part, optional for dec, mandatory for hex. */ long ep = 0; // exponent, implicitly 0 boolean hasExp = false; - if (i < len && ((ch = in.charAt(i) | 0b10_0000) == 'e' && isDec + if (i < len && ((ch = toLowerCase(in.charAt(i))) == 'e' && isDec || ch == 'p' && !isDec)) { ++i; @@ -1961,7 +1954,7 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { check(in, isDec | hasExp); /* Skip opt [FfDd]? suffix. */ - if (i < len && (((ch = in.charAt(i) | 0b10_0000)) == 'f' || ch == 'd')) { + if (i < len && ((ch = toLowerCase(in.charAt(i))) == 'f' || ch == 'd')) { ++i; } @@ -2062,21 +2055,21 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { ep += 4L * (n - le); } - int bl = Long.SIZE - Long.numberOfLeadingZeros(c); // bit length + int bl = Long.SIZE - Long.numberOfLeadingZeros(c); // bitlength /* * Let x = c 2^ep, so 2^(ep+bl-1) <= x < 2^(ep+bl) * When ep + bl < Q_MIN then x certainly rounds to zero. - * When ep + bl - 1 > E_MAX then x surely rounds to infinity. + * When ep + bl > QE_MAX then x surely rounds to infinity. */ if (ep < Q_MIN[ix] - bl) { - return buildZero(ix, ssign); + return ssign != '-' ? A2BC_POSITIVE_ZERO : A2BC_NEGATIVE_ZERO; } - if (ep > E_MAX[ix] - bl + 1) { - return buildInfinity(ix, ssign); + if (ep > QE_MAX[ix] - bl) { + return ssign != '-' ? A2BC_POSITIVE_INFINITY : A2BC_NEGATIVE_INFINITY; } int q = (int) ep; // narrowing conversion is safe int shr; // (sh)ift to (r)ight iff shr > 0 - if (q > E_MIN[ix] - bl) { + if (q >= QE_MIN[ix] - bl) { shr = bl - P[ix]; q += shr; } else { @@ -2112,19 +2105,18 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { * For decimal inputs, we copy an appropriate prefix of the input and * rely on another method to do the (sometimes intensive) math conversion. * - * Define e' = n + ep, which leads to - * x = <0 . f_1 ... f_n> 10^e', 10^(e'-1) <= x < 10^e' - * If e' <= EP_MIN then x rounds to zero. - * Similarly, if e' >= EP_MAX then x rounds to infinity. - * (See the comments on the fields for their semantics.) + * Define e = n + ep, which leads to + * x = 0.d_1 ... d_n 10^e, 10^(e-1) <= x < 10^e + * If e <= E_THR_Z then x rounds to zero. + * Similarly, if e >= E_THR_I then x rounds to infinity. * We return immediately in these cases. - * Otherwise, e' fits in an int named e. + * Otherwise, e fits in an int, aptly named e as well. */ - int e = Math.clamp(ep + n, EP_MIN[ix], EP_MAX[ix]); - if (e == EP_MIN[ix]) { // e' <= E_MIN + int e = Math.clamp(ep + n, E_THR_Z[ix], E_THR_I[ix]); + if (e == E_THR_Z[ix]) { // true e <= E_THR_Z return ssign != '-' ? A2BC_POSITIVE_ZERO : A2BC_NEGATIVE_ZERO; } - if (e == EP_MAX[ix]) { // e' >= E_MAX + if (e == E_THR_I[ix]) { // true e >= E_THR_I return ssign != '-' ? A2BC_POSITIVE_INFINITY : A2BC_NEGATIVE_INFINITY; } @@ -2132,8 +2124,10 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { * For further considerations, x also needs to be seen as * x = beta 2^q * with real beta and integer q meeting - * 2^(P-1) <= beta < 2^P and q >= Q_MIN - * 0 < beta < 2^(P-1) and q = Q_MIN + * q >= Q_MIN + * and + * either 2^(P-1) <= beta < 2^P + * or 0 < beta < 2^(P-1) and q = Q_MIN * The (unique) solution is * q = max(floor(log2(x)) - (P-1), Q_MIN), beta = x 2^(-q) * It's usually costly to determine q as here. @@ -2146,10 +2140,10 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { * ql <= q <= qh, and qh - ql <= 4 * Since by now e is relatively small, we can leverage flog2pow10(). * - * When q >= Q_MIN, consider the interval [ 2^(P-1+q), 2^(P+q) ). + * Consider the half-open interval [ 2^(P-1+q), 2^(P+q) ). * It contains all floating-point values of the form * c 2^q, c integer, 2^(P-1) <= c < 2^P (normal values) - * When q = Q_MIN also consider the interval [0, 2^(P-1+q) ) + * When q = Q_MIN also consider the interval half-open [0, 2^(P-1+q) ), * which contains all floating-point values of the form * c 2^q, c integer, 0 <= c < 2^(P-1) (subnormal values and zero) * For these c values, all numbers of the form @@ -2160,14 +2154,15 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { * * First assume ql > 0, so q > 0. * All rounding boundaries (c + 1/2) 2^q are integers. + * * Hence, to correctly round x, it's enough to retain its integer part, * +1 non-zero sticky digit iff the fractional part is non-zero. * (Well, the sticky digit is only needed when the integer part * coincides with a boundary, but that's hard to detect at this stage. * Adding the sticky digit is always safe.) - * If n > e we pass the digits (3 is as good as any other + * If n > e we pass the digits d_1...d_e 3 (3 is as good as any other * non-zero sticky digit) and the exponent e to the conversion routine. - * If n <= e we pass all the digits (no sticky digit, + * If n <= e we pass all the digits d_1...d_n (no sticky digit, * as the fractional part is empty) and the exponent e to the converter. * * Now assume qh <= 0, so q <= 0. @@ -2189,6 +2184,7 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { * Again, since q is not known exactly, we proceed as in the previous * case, with ql as a safe replacement for q. */ + // TODO insert logic for small n: 9 for float, 18 for double int ql = Math.max(MathUtils.flog2pow10(e - 1) - (P[ix] - 1), Q_MIN[ix]); int np = e + Math.max(2 - ql, 1); byte[] digits = new byte[Math.min(n, np)]; @@ -2201,34 +2197,8 @@ static ASCIIToBinaryConverter readJavaFormatString(String in, int ix) { return new ASCIIToBinaryBuffer(ssign == '-', e, digits, digits.length); } - private static PreparedASCIIToBinaryBuffer buildZero(int ix, int ssign) { - /* For now throw on BINARY_16_IX, until Float16 is integrated in java.base. */ - return switch (ix) { - case BINARY_32_IX -> - new PreparedASCIIToBinaryBuffer( - Double.NaN, - ssign != '-' ? 0.0f : -0.0f); - case BINARY_64_IX -> - new PreparedASCIIToBinaryBuffer( - ssign != '-' ? 0.0d : -0.0d, - Float.NaN); - default -> throw new AssertionError("unexpected"); - }; - } - - private static PreparedASCIIToBinaryBuffer buildInfinity(int ix, int ssign) { - /* For now throw on BINARY_16_IX, until Float16 is integrated in java.base. */ - return switch (ix) { - case BINARY_32_IX -> - new PreparedASCIIToBinaryBuffer( - Double.NaN, - ssign != '-' ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY); - case BINARY_64_IX -> - new PreparedASCIIToBinaryBuffer( - ssign != '-' ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY, - Float.NaN); - default -> throw new AssertionError("unexpected"); - }; + private static int toLowerCase(int ch) { + return ch | 0b10_0000; } private static double buildDouble(int ssign, int q, long c) { @@ -2270,12 +2240,12 @@ private static long appendDecDigit(long v, int ch) { private static boolean isDigit(int ch, boolean isDec) { int lch; // lowercase ch return '0' <= ch && ch <= '9' || - !isDec && 'a' <= (lch = ch | 0b10_0000) && lch <= 'f'; + !isDec && 'a' <= (lch = toLowerCase(ch)) && lch <= 'f'; } /* Returns the numeric value of ch, assuming it is a hexdigit. */ private static int digitFor(int ch) { - return ch <= '9' ? ch - '0' : (ch | 0b10_0000) - ('a' - 10); + return ch <= '9' ? ch - '0' : toLowerCase(ch) - ('a' - 10); } /* @@ -2327,25 +2297,24 @@ private static void check(String in, boolean expected) { /* * According to IEEE 754-2019, a finite positive binary floating-point - * of precision P is (uniquely) expressed as + * value of precision P is (uniquely) expressed as * c 2^q * where integers c and q meet * Q_MIN <= q <= Q_MAX - * either 2^(P-1) <= c < 2^P (normal) - * or 0 < c < 2^(P-1) & q = Q_MIN (subnormal) - * c = , d_i in [0, 2) + * either 2^(P-1) <= c < 2^P (normal) + * or 0 < c < 2^(P-1) & q = Q_MIN (subnormal) + * c = b_1...b_P (b_i in [0, 2)) * - * Equivalently, the fp value can be (uniquely) expressed as + * Equivalently, the floating-point value can be (uniquely) expressed as * m 2^ep - * where integer ep and real f meet - * ep = q + P - 1 - * m = c 2^(1-P) + * where integer qe and real f meet + * qe = q + P + * m = c 2^(-P) * Hence, - * E_MIN = Q_MIN + P - 1, E_MAX = Q_MAX + P - 1, - * 1 <= m < 2 (normal) - * m < 1 (subnormal) - * m = - * with a (binary) point between d_0 and d_1 + * QE_MIN = Q_MIN + P, QE_MAX = Q_MAX + P, + * 2^(-1) <= m < 1 (normal) + * m < 2^(-1) (subnormal) + * m = 0.b_1...b_P */ /* @@ -2358,72 +2327,70 @@ private static void check(String in, boolean expected) { // private static final int BINARY_128_IX = 3; // private static final int BINARY_256_IX = 4; - /* The precision of the format. */ @Stable private static final int[] P = { - 11, 24, 53, // 113, 237, + 11, + FloatToDecimal.P, + DoubleToDecimal.P, + // 113, + // 237, }; - /* - * EP_MIN = max{e : 10^e <= MIN_VALUE/2}. - * Note that MIN_VALUE/2 is the 0 threshold. - * Less or equal values round to 0 when using roundTiesToEven. - * Equivalently, EP_MIN = floor(log10(2^(Q_MIN-1))). - */ @Stable - private static final int[] EP_MIN = { - -8, -46, -324, // -4_966, -78_985, + private static final int[] W = { + 5, + FloatToDecimal.W, + DoubleToDecimal.W, +// (1 << 4 + BINARY_128_IX) - P[BINARY_128_IX], +// (1 << 4 + BINARY_256_IX) - P[BINARY_256_IX], }; - /* - * EP_MAX = min{e : MAX_VALUE + ulp(MAX_VALUE)/2 <= 10^(e-1)}. - * Note that MAX_VALUE + ulp(MAX_VALUE)/2 is the infinity threshold. - * Greater or equal values round to infinity when using roundTiesToEven. - * Equivalently, EP_MAX = ceil(log10((2^P - 1/2) 2^Q_MAX)) + 1. - */ + /* Minimum exponent in the m 2^e representation. */ + /* Minimum exponent in the c 2^q representation. */ @Stable - private static final int[] EP_MAX = { - 6, 40, 310, // 4_934, 78_915, + private static final int[] Q_MIN = { + -24, // Float16ToDecimal.Q_MIN, + FloatToDecimal.Q_MIN, + DoubleToDecimal.Q_MIN, +// QE_MIN[BINARY_128_IX] - (P[BINARY_128_IX] - 1), +// QE_MIN[BINARY_256_IX] - (P[BINARY_256_IX] - 1), }; - /* Exponent width. */ @Stable - private static final int[] W = { - (1 << 4 + BINARY_16_IX) - P[BINARY_16_IX], - (1 << 4 + BINARY_32_IX) - P[BINARY_32_IX], - (1 << 4 + BINARY_64_IX) - P[BINARY_64_IX], -// (1 << 4 + BINARY_128_IX) - P[BINARY_128_IX], -// (1 << 4 + BINARY_256_IX) - P[BINARY_256_IX], + private static final int[] QE_MIN = { + Q_MIN[BINARY_16_IX] + P[BINARY_16_IX], + FloatToDecimal.Q_MIN + FloatToDecimal.P, + DoubleToDecimal.Q_MIN + DoubleToDecimal.P, +// Q_MIN[BINARY_128_IX] + P[BINARY_128_IX], +// Q_MIN[BINARY_256_IX] + P[BINARY_256_IX], }; /* Maximum exponent in the m 2^e representation. */ @Stable - private static final int[] E_MAX = { - (1 << W[BINARY_16_IX] - 1) - 1, - (1 << W[BINARY_32_IX] - 1) - 1, - (1 << W[BINARY_64_IX] - 1) - 1, -// (1 << W[BINARY_128_IX] - 1) - 1, -// (1 << W[BINARY_256_IX] - 1) - 1, + private static final int[] QE_MAX = { + 3 - QE_MIN[BINARY_16_IX], + FloatToDecimal.Q_MAX + FloatToDecimal.P, + DoubleToDecimal.Q_MAX + DoubleToDecimal.P, +// 3 - QE_MIN[BINARY_128_IX], +// 3 - QE_MIN[BINARY_256_IX], }; - /* Minimum exponent in the m 2^e representation. */ @Stable - private static final int[] E_MIN = { - 1 - E_MAX[BINARY_16_IX], - 1 - E_MAX[BINARY_32_IX], - 1 - E_MAX[BINARY_64_IX], -// 1 - E_MAX[BINARY_128_IX], -// 1 - E_MAX[BINARY_256_IX], + private static final int[] E_THR_Z = { + -8, + FloatToDecimal.E_THR_Z, + DoubleToDecimal.E_THR_Z, + // -4_966, + // -78_985, }; - /* Minimum exponent in the c 2^q representation. */ @Stable - private static final int[] Q_MIN = { - E_MIN[BINARY_16_IX] - (P[BINARY_16_IX] - 1), - E_MIN[BINARY_32_IX] - (P[BINARY_32_IX] - 1), - E_MIN[BINARY_64_IX] - (P[BINARY_64_IX] - 1), -// E_MIN[BINARY_128_IX] - (P[BINARY_128_IX] - 1), -// E_MIN[BINARY_256_IX] - (P[BINARY_256_IX] - 1), + private static final int[] E_THR_I = { + 6, + FloatToDecimal.E_THR_I, + DoubleToDecimal.E_THR_I, + // 4_934, + // 78_915, }; /* diff --git a/src/java.base/share/classes/jdk/internal/math/MathUtils.java b/src/java.base/share/classes/jdk/internal/math/MathUtils.java index 3c52a244639..0de07f8ed60 100644 --- a/src/java.base/share/classes/jdk/internal/math/MathUtils.java +++ b/src/java.base/share/classes/jdk/internal/math/MathUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -25,6 +25,8 @@ package jdk.internal.math; +import jdk.internal.vm.annotation.Stable; + /** * This class exposes package private utilities for other classes. * Thus, all methods are assumed to be invoked with correct arguments, @@ -34,20 +36,55 @@ final class MathUtils { /* * For full details about this code see the following reference: * - * Giulietti, "The Schubfach way to render doubles", + * [1] Giulietti, "The Schubfach way to render doubles", * https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb */ /* - * The boundaries for k in g0(int) and g1(int). - * K_MIN must be DoubleToDecimal.K_MIN or less. - * K_MAX must be DoubleToDecimal.K_MAX or more. + * N = max{n : 10^n - 1 <= 2^Long.SIZE - 1} + * Every positive integer up to N decimal digits fits in an unsigned long, + * but there are positive integers of N + 1 digits that do not. */ - static final int K_MIN = -324; - static final int K_MAX = 292; + static final int N = 19; - /* Must be DoubleToDecimal.H or more */ - static final int H = 17; + /* + * Given integer e, let 10^e = beta 2^r for the unique integer r and + * real beta meeting + * 2^125 <= beta < 2^126. + * The unique r and beta are + * r = floor(log2(10^e)) - 125, beta = 10^e 2^(-r) + * Let g = floor(beta) + 1. + * Thus, + * (g - 1) 2^r <= 10^e < g 2^r + * Further, let + * g1 = floor(g 2^(-63)), g0 = g - g1 2^63 + * + * For e with GE_MIN <= e <= GE_MAX, the values g1 and g0 are available + * by invoking methods g1(e) and g0(e). + * In addition, r = flog2pow10(e) - 125. + * + * The boundaries GE_MIN, GE_MAX must minimally fit the purposes of the full + * double->decimal and the fast paths of the decimal->double conversions. + * + * For the double->decimal conversion, the interval [GE_MIN, GE_MAX] must + * include the interval [-K_MAX, -K_MIN], where K_MIN and K_MAX are + * discussed in [1]. + * (See DoubleToDecimal.K_MIN and DoubleToDecimal.K_MAX.) + * + * Let x = f 10^ep, where integers f and ep meet 10^(n-1) <= f < 10^n + * (that is, f has n digits) and E_THR_Z < ep + n < E_THR_I. + * (See DoubleToDecimal.E_THR_Z and DoubleToDecimal.E_THR_I.) + * + * The decimal->double fast paths assume n <= N. + * Thus, E_THR_Z - (N - 1) <= ep <= E_THR_I - 2, which means that + * the interval [GE_MIN, GE_MAX] must include the interval + * [E_THR_Z - (N - 1), E_THR_I - 2]. + * That is, + * GE_MIN = min(-K_MAX, E_THR_Z - (N - 1)) + * GE_MAX = max(-K_MIN, E_THR_I - 2) + */ + static final int GE_MIN = -342; + static final int GE_MAX = 324; /* C_10 = floor(log10(2) * 2^Q_10), A_10 = floor(log10(3/4) * 2^Q_10) */ private static final int Q_10 = 41; @@ -59,36 +96,41 @@ final class MathUtils { private static final long C_2 = 913_124_641_741L; private MathUtils() { - throw new RuntimeException("not supposed to be instantiated."); } - /* The first powers of 10. The last entry must be 10^(DoubleToDecimal.H) */ + /* + * The first (unsigned) powers of 10, where the last entry must be 10^N. + * + * @Stable is safe to use, as there are no 0 entries. + */ + @Stable private static final long[] pow10 = { - 1L, - 10L, - 100L, - 1_000L, - 10_000L, - 100_000L, - 1_000_000L, - 10_000_000L, - 100_000_000L, - 1_000_000_000L, - 10_000_000_000L, - 100_000_000_000L, - 1_000_000_000_000L, - 10_000_000_000_000L, - 100_000_000_000_000L, - 1_000_000_000_000_000L, - 10_000_000_000_000_000L, - 100_000_000_000_000_000L, + 1L, + 10L, + 100L, + 1_000L, + 10_000L, + 100_000L, + 1_000_000L, + 10_000_000L, + 100_000_000L, + 1_000_000_000L, + 10_000_000_000L, + 100_000_000_000L, + 1_000_000_000_000L, + 10_000_000_000_000L, + 100_000_000_000_000L, + 1_000_000_000_000_000L, + 10_000_000_000_000_000L, + 100_000_000_000_000_000L, + 1_000_000_000_000_000_000L, + 10 * 1_000_000_000_000_000_000L, }; /** - * Returns 10{@code e}. + * Returns 10{@code e} as an unsigned long. * - * @param e The exponent which must meet - * 0 ≤ {@code e} ≤ {@link #H}. + * @param e The exponent which must meet 0 ≤ {@code e} ≤ {@code N}. * @return 10{@code e}. */ static long pow10(int e) { @@ -96,46 +138,40 @@ static long pow10(int e) { } /** - * Returns the unique integer k such that - * 10k ≤ 2{@code e} - * < 10k+1. + * Returns max{e : 10e ≤ 2{@code q}}. *

    - * The result is correct when |{@code e}| ≤ 6_432_162. - * Otherwise the result is undefined. + * The result is correct when |{@code q}| ≤ 6_432_162. + * Otherwise, the result is undefined. * - * @param e The exponent of 2, which should meet - * |{@code e}| ≤ 6_432_162 for safe results. - * @return ⌊log102{@code e}⌋. + * @param q The exponent of 2, which should meet + * |{@code q}| ≤ 6_432_162 for safe results. + * @return ⌊log102{@code q}⌋. */ - static int flog10pow2(int e) { - return (int) (e * C_10 >> Q_10); + static int flog10pow2(int q) { + return (int) (q * C_10 >> Q_10); } /** - * Returns the unique integer k such that - * 10k ≤ 3/4 · 2{@code e} - * < 10k+1. + * Returns max{e : 10e ≤ 3/4 · 2{@code q}}. *

    * The result is correct when - * -3_606_689 ≤ {@code e} ≤ 3_150_619. - * Otherwise the result is undefined. + * -3_606_689 ≤ {@code q} ≤ 3_150_619. + * Otherwise, the result is undefined. * - * @param e The exponent of 2, which should meet - * -3_606_689 ≤ {@code e} ≤ 3_150_619 for safe results. + * @param q The exponent of 2, which should meet + * -3_606_689 ≤ {@code q} ≤ 3_150_619 for safe results. * @return ⌊log10(3/4 · - * 2{@code e})⌋. + * 2{@code q})⌋. */ - static int flog10threeQuartersPow2(int e) { - return (int) (e * C_10 + A_10 >> Q_10); + static int flog10threeQuartersPow2(int q) { + return (int) (q * C_10 + A_10 >> Q_10); } /** - * Returns the unique integer k such that - * 2k ≤ 10{@code e} - * < 2k+1. + * Returns max{q : 2q ≤ 10{@code e}}. *

    * The result is correct when |{@code e}| ≤ 1_838_394. - * Otherwise the result is undefined. + * Otherwise, the result is undefined. * * @param e The exponent of 10, which should meet * |{@code e}| ≤ 1_838_394 for safe results. @@ -145,669 +181,691 @@ static int flog2pow10(int e) { return (int) (e * C_2 >> Q_2); } - /** - * Let 10-{@code k} = β 2r, - * for the unique pair of integer r and real β meeting - * 2125β < 2126. - * Further, let g = ⌊β⌋ + 1. - * Split g into the higher 63 bits g1 and - * the lower 63 bits g0. Thus, - * g1 = - * ⌊g 2-63⌋ - * and - * g0 = - * g - g1 263. - *

    - * This method returns g1 while - * {@link #g0(int)} returns g0. - *

    - * If needed, the exponent r can be computed as - * r = {@code flog2pow10(-k)} - 125 (see {@link #flog2pow10(int)}). - * - * @param k The exponent of 10, which must meet - * {@link #K_MIN} ≤ {@code e} ≤ {@link #K_MAX}. - * @return g1 as described above. - */ - static long g1(int k) { - return g[k - K_MIN << 1]; + /* See the discussion above for the meaning of g1. */ + static long g1(int e) { + return g[e - GE_MIN << 1]; } - /** - * Returns g0 as described in - * {@link #g1(int)}. - * - * @param k The exponent of 10, which must meet - * {@link #K_MIN} ≤ {@code e} ≤ {@link #K_MAX}. - * @return g0 as described in - * {@link #g1(int)}. - */ - static long g0(int k) { - return g[k - K_MIN << 1 | 1]; + /* See the discussion above for the meaning of g0. */ + static long g0(int e) { + return g[e - GE_MIN << 1 | 1]; } /* - * The precomputed values for g1(int) and g0(int). - * The first entry must be for an exponent of K_MIN or less. - * The last entry must be for an exponent of K_MAX or more. + * The precomputed values for g1 and g0. + * + * @Stable is safe to use, as there are no 0 entries. */ + @Stable private static final long[] g = { - 0x4F0C_EDC9_5A71_8DD4L, 0x5B01_E8B0_9AA0_D1B5L, // -324 - 0x7E7B_160E_F71C_1621L, 0x119C_A780_F767_B5EEL, // -323 - 0x652F_44D8_C5B0_11B4L, 0x0E16_EC67_2C52_F7F2L, // -322 - 0x50F2_9D7A_37C0_0E29L, 0x5812_56B8_F042_5FF5L, // -321 - 0x40C2_1794_F966_71BAL, 0x79A8_4560_C035_1991L, // -320 - 0x679C_F287_F570_B5F7L, 0x75DA_089A_CD21_C281L, // -319 - 0x52E3_F539_9126_F7F9L, 0x44AE_6D48_A41B_0201L, // -318 - 0x424F_F761_40EB_F994L, 0x36F1_F106_E9AF_34CDL, // -317 - 0x6A19_8BCE_CE46_5C20L, 0x57E9_81A4_A918_547BL, // -316 - 0x54E1_3CA5_71D1_E34DL, 0x2CBA_CE1D_5413_76C9L, // -315 - 0x43E7_63B7_8E41_82A4L, 0x23C8_A4E4_4342_C56EL, // -314 - 0x6CA5_6C58_E39C_043AL, 0x060D_D4A0_6B9E_08B0L, // -313 - 0x56EA_BD13_E949_9CFBL, 0x1E71_76E6_BC7E_6D59L, // -312 - 0x4588_9743_2107_B0C8L, 0x7EC1_2BEB_C9FE_BDE1L, // -311 - 0x6F40_F205_01A5_E7A7L, 0x7E01_DFDF_A997_9635L, // -310 - 0x5900_C19D_9AEB_1FB9L, 0x4B34_B319_5479_44F7L, // -309 - 0x4733_CE17_AF22_7FC7L, 0x55C3_C27A_A9FA_9D93L, // -308 - 0x71EC_7CF2_B1D0_CC72L, 0x5606_03F7_765D_C8EAL, // -307 - 0x5B23_9728_8E40_A38EL, 0x7804_CFF9_2B7E_3A55L, // -306 - 0x48E9_45BA_0B66_E93FL, 0x1337_0CC7_55FE_9511L, // -305 - 0x74A8_6F90_123E_41FEL, 0x51F1_AE0B_BCCA_881BL, // -304 - 0x5D53_8C73_41CB_67FEL, 0x74C1_5809_63D5_39AFL, // -303 - 0x4AA9_3D29_016F_8665L, 0x43CD_E007_8310_FAF3L, // -302 - 0x7775_2EA8_024C_0A3CL, 0x0616_333F_381B_2B1EL, // -301 - 0x5F90_F220_01D6_6E96L, 0x3811_C298_F9AF_55B1L, // -300 - 0x4C73_F4E6_67DE_BEDEL, 0x600E_3547_2E25_DE28L, // -299 - 0x7A53_2170_A631_3164L, 0x3349_EED8_49D6_303FL, // -298 - 0x61DC_1AC0_84F4_2783L, 0x42A1_8BE0_3B11_C033L, // -297 - 0x4E49_AF00_6A5C_EC69L, 0x1BB4_6FE6_95A7_CCF5L, // -296 - 0x7D42_B19A_43C7_E0A8L, 0x2C53_E63D_BC3F_AE55L, // -295 - 0x6435_5AE1_CFD3_1A20L, 0x2376_51CA_FCFF_BEAAL, // -294 - 0x502A_AF1B_0CA8_E1B3L, 0x35F8_416F_30CC_9888L, // -293 - 0x4022_25AF_3D53_E7C2L, 0x5E60_3458_F3D6_E06DL, // -292 - 0x669D_0918_621F_D937L, 0x4A33_86F4_B957_CD7BL, // -291 - 0x5217_3A79_E819_7A92L, 0x6E8F_9F2A_2DDF_D796L, // -290 - 0x41AC_2EC7_ECE1_2EDBL, 0x720C_7F54_F17F_DFABL, // -289 - 0x6913_7E0C_AE35_17C6L, 0x1CE0_CBBB_1BFF_CC45L, // -288 - 0x540F_980A_24F7_4638L, 0x171A_3C95_AFFF_D69EL, // -287 - 0x433F_ACD4_EA5F_6B60L, 0x127B_63AA_F333_1218L, // -286 - 0x6B99_1487_DD65_7899L, 0x6A5F_05DE_51EB_5026L, // -285 - 0x5614_106C_B11D_FA14L, 0x5518_D17E_A7EF_7352L, // -284 - 0x44DC_D9F0_8DB1_94DDL, 0x2A7A_4132_1FF2_C2A8L, // -283 - 0x6E2E_2980_E2B5_BAFBL, 0x5D90_6850_331E_043FL, // -282 - 0x5824_EE00_B55E_2F2FL, 0x6473_86A6_8F4B_3699L, // -281 - 0x4683_F19A_2AB1_BF59L, 0x36C2_D21E_D908_F87BL, // -280 - 0x70D3_1C29_DDE9_3228L, 0x579E_1CFE_280E_5A5DL, // -279 - 0x5A42_7CEE_4B20_F4EDL, 0x2C7E_7D98_200B_7B7EL, // -278 - 0x4835_30BE_A280_C3F1L, 0x09FE_CAE0_19A2_C932L, // -277 - 0x7388_4DFD_D0CE_064EL, 0x4331_4499_C29E_0EB6L, // -276 - 0x5C6D_0B31_73D8_050BL, 0x4F5A_9D47_CEE4_D891L, // -275 - 0x49F0_D5C1_2979_9DA2L, 0x72AE_E439_7250_AD41L, // -274 - 0x764E_22CE_A8C2_95D1L, 0x377E_39F5_83B4_4868L, // -273 - 0x5EA4_E8A5_53CE_DE41L, 0x12CB_6191_3629_D387L, // -272 - 0x4BB7_2084_430B_E500L, 0x756F_8140_F821_7605L, // -271 - 0x7925_00D3_9E79_6E67L, 0x6F18_CECE_59CF_233CL, // -270 - 0x60EA_670F_B1FA_BEB9L, 0x3F47_0BD8_47D8_E8FDL, // -269 - 0x4D88_5272_F4C8_9894L, 0x329F_3CAD_0647_20CAL, // -268 - 0x7C0D_50B7_EE0D_C0EDL, 0x3765_2DE1_A3A5_0143L, // -267 - 0x633D_DA2C_BE71_6724L, 0x2C50_F181_4FB7_3436L, // -266 - 0x4F64_AE8A_31F4_5283L, 0x3D0D_8E01_0C92_902BL, // -265 - 0x7F07_7DA9_E986_EA6BL, 0x7B48_E334_E0EA_8045L, // -264 - 0x659F_97BB_2138_BB89L, 0x4907_1C2A_4D88_669DL, // -263 - 0x514C_7962_80FA_2FA1L, 0x20D2_7CEE_A46D_1EE4L, // -262 - 0x4109_FAB5_33FB_594DL, 0x670E_CA58_838A_7F1DL, // -261 - 0x680F_F788_532B_C216L, 0x0B4A_DD5A_6C10_CB62L, // -260 - 0x533F_F939_DC23_01ABL, 0x22A2_4AAE_BCDA_3C4EL, // -259 - 0x4299_942E_49B5_9AEFL, 0x354E_A225_63E1_C9D8L, // -258 - 0x6A8F_537D_42BC_2B18L, 0x554A_9D08_9FCF_A95AL, // -257 - 0x553F_75FD_CEFC_EF46L, 0x776E_E406_E63F_BAAEL, // -256 - 0x4432_C4CB_0BFD_8C38L, 0x5F8B_E99F_1E99_6225L, // -255 - 0x6D1E_07AB_4662_79F4L, 0x3279_75CB_6428_9D08L, // -254 - 0x574B_3955_D1E8_6190L, 0x2861_2B09_1CED_4A6DL, // -253 - 0x45D5_C777_DB20_4E0DL, 0x06B4_226D_B0BD_D524L, // -252 - 0x6FBC_7259_5E9A_167BL, 0x2453_6A49_1AC9_5506L, // -251 - 0x5963_8EAD_E548_11FCL, 0x1D0F_883A_7BD4_4405L, // -250 - 0x4782_D88B_1DD3_4196L, 0x4A72_D361_FCA9_D004L, // -249 - 0x726A_F411_C952_028AL, 0x43EA_EBCF_FAA9_4CD3L, // -248 - 0x5B88_C341_6DDB_353BL, 0x4FEF_230C_C887_70A9L, // -247 - 0x493A_35CD_F17C_2A96L, 0x0CBF_4F3D_6D39_26EEL, // -246 - 0x7529_EFAF_E8C6_AA89L, 0x6132_1862_485B_717CL, // -245 - 0x5DBB_2626_53D2_2207L, 0x675B_46B5_06AF_8DFDL, // -244 - 0x4AFC_1E85_0FDB_4E6CL, 0x52AF_6BC4_0559_3E64L, // -243 - 0x77F9_CA6E_7FC5_4A47L, 0x377F_12D3_3BC1_FD6DL, // -242 - 0x5FFB_0858_6637_6E9FL, 0x45FF_4242_9634_CABDL, // -241 - 0x4CC8_D379_EB5F_8BB2L, 0x6B32_9B68_782A_3BCBL, // -240 - 0x7ADA_EBF6_4565_AC51L, 0x2B84_2BDA_59DD_2C77L, // -239 - 0x6248_BCC5_0451_56A7L, 0x3C69_BCAE_AE4A_89F9L, // -238 - 0x4EA0_9704_0374_4552L, 0x6387_CA25_583B_A194L, // -237 - 0x7DCD_BE6C_D253_A21EL, 0x05A6_103B_C05F_68EDL, // -236 - 0x64A4_9857_0EA9_4E7EL, 0x37B8_0CFC_99E5_ED8AL, // -235 - 0x5083_AD12_7221_0B98L, 0x2C93_3D96_E184_BE08L, // -234 - 0x4069_5741_F4E7_3C79L, 0x7075_CADF_1AD0_9807L, // -233 - 0x670E_F203_2171_FA5CL, 0x4D89_4498_2AE7_59A4L, // -232 - 0x5272_5B35_B45B_2EB0L, 0x3E07_6A13_5585_E150L, // -231 - 0x41F5_15C4_9048_F226L, 0x64D2_BB42_AAD1_810DL, // -230 - 0x6988_22D4_1A0E_503EL, 0x07B7_9204_4482_6815L, // -229 - 0x546C_E8A9_AE71_D9CBL, 0x1FC6_0E69_D068_5344L, // -228 - 0x438A_53BA_F1F4_AE3CL, 0x196B_3EBB_0D20_429DL, // -227 - 0x6C10_85F7_E987_7D2DL, 0x0F11_FDF8_1500_6A94L, // -226 - 0x5673_9E5F_EE05_FDBDL, 0x58DB_3193_4400_5543L, // -225 - 0x4529_4B7F_F19E_6497L, 0x60AF_5ADC_3666_AA9CL, // -224 - 0x6EA8_78CC_B5CA_3A8CL, 0x344B_C493_8A3D_DDC7L, // -223 - 0x5886_C70A_2B08_2ED6L, 0x5D09_6A0F_A1CB_17D2L, // -222 - 0x46D2_38D4_EF39_BF12L, 0x173A_BB3F_B4A2_7975L, // -221 - 0x7150_5AEE_4B8F_981DL, 0x0B91_2B99_2103_F588L, // -220 - 0x5AA6_AF25_093F_ACE4L, 0x0940_EFAD_B403_2AD3L, // -219 - 0x4885_58EA_6DCC_8A50L, 0x0767_2624_9002_88A9L, // -218 - 0x7408_8E43_E2E0_DD4CL, 0x723E_A36D_B337_410EL, // -217 - 0x5CD3_A503_1BE7_1770L, 0x5B65_4F8A_F5C5_CDA5L, // -216 - 0x4A42_EA68_E31F_45F3L, 0x62B7_72D5_916B_0AEBL, // -215 - 0x76D1_770E_3832_0986L, 0x0458_B7BC_1BDE_77DDL, // -214 - 0x5F0D_F8D8_2CF4_D46BL, 0x1D13_C630_164B_9318L, // -213 - 0x4C0B_2D79_BD90_A9EFL, 0x30DC_9E8C_DEA2_DC13L, // -212 - 0x79AB_7BF5_FC1A_A97FL, 0x0160_FDAE_3104_9351L, // -211 - 0x6155_FCC4_C9AE_EDFFL, 0x1AB3_FE24_F403_A90EL, // -210 - 0x4DDE_63D0_A158_BE65L, 0x6229_981D_9002_EDA5L, // -209 - 0x7C97_061A_9BC1_30A2L, 0x69DC_2695_B337_E2A1L, // -208 - 0x63AC_04E2_1634_26E8L, 0x54B0_1EDE_28F9_821BL, // -207 - 0x4FBC_D0B4_DE90_1F20L, 0x43C0_18B1_BA61_34E2L, // -206 - 0x7F94_8121_6419_CB67L, 0x1F99_C11C_5D68_549DL, // -205 - 0x6610_674D_E9AE_3C52L, 0x4C7B_00E3_7DED_107EL, // -204 - 0x51A6_B90B_2158_3042L, 0x09FC_00B5_FE57_4065L, // -203 - 0x4152_2DA2_8113_59CEL, 0x3B30_0091_9845_CD1DL, // -202 - 0x6883_7C37_34EB_C2E3L, 0x784C_CDB5_C06F_AE95L, // -201 - 0x539C_635F_5D89_68B6L, 0x2D0A_3E2B_0059_5877L, // -200 - 0x42E3_82B2_B13A_BA2BL, 0x3DA1_CB55_99E1_1393L, // -199 - 0x6B05_9DEA_B52A_C378L, 0x629C_7888_F634_EC1EL, // -198 - 0x559E_17EE_F755_692DL, 0x3549_FA07_2B5D_89B1L, // -197 - 0x447E_798B_F911_20F1L, 0x1107_FB38_EF7E_07C1L, // -196 - 0x6D97_28DF_F4E8_34B5L, 0x01A6_5EC1_7F30_0C68L, // -195 - 0x57AC_20B3_2A53_5D5DL, 0x4E1E_B234_65C0_09EDL, // -194 - 0x4623_4D5C_21DC_4AB1L, 0x24E5_5B5D_1E33_3B24L, // -193 - 0x7038_7BC6_9C93_AAB5L, 0x216E_F894_FD1E_C506L, // -192 - 0x59C6_C96B_B076_222AL, 0x4DF2_6077_30E5_6A6CL, // -191 - 0x47D2_3ABC_8D2B_4E88L, 0x3E5B_805F_5A51_21F0L, // -190 - 0x72E9_F794_1512_1740L, 0x63C5_9A32_2A1B_697FL, // -189 - 0x5BEE_5FA9_AA74_DF67L, 0x0304_7B5B_54E2_BACCL, // -188 - 0x498B_7FBA_EEC3_E5ECL, 0x0269_FC49_10B5_623DL, // -187 - 0x75AB_FF91_7E06_3CACL, 0x6A43_2D41_B455_69FBL, // -186 - 0x5E23_32DA_CB38_308AL, 0x21CF_5767_C377_87FCL, // -185 - 0x4B4F_5BE2_3C2C_F3A1L, 0x67D9_12B9_692C_6CCAL, // -184 - 0x787E_F969_F9E1_85CFL, 0x595B_5128_A847_1476L, // -183 - 0x6065_9454_C7E7_9E3FL, 0x6115_DA86_ED05_A9F8L, // -182 - 0x4D1E_1043_D31F_B1CCL, 0x4DAB_1538_BD9E_2193L, // -181 - 0x7B63_4D39_51CC_4FADL, 0x62AB_5527_95C9_CF52L, // -180 - 0x62B5_D761_0E3D_0C8BL, 0x0222_AA86_116E_3F75L, // -179 - 0x4EF7_DF80_D830_D6D5L, 0x4E82_2204_DABE_992AL, // -178 - 0x7E59_659A_F381_57BCL, 0x1736_9CD4_9130_F510L, // -177 - 0x6514_5148_C2CD_DFC9L, 0x5F5E_E3DD_40F3_F740L, // -176 - 0x50DD_0DD3_CF0B_196EL, 0x1918_B64A_9A5C_C5CDL, // -175 - 0x40B0_D7DC_A5A2_7ABEL, 0x4746_F83B_AEB0_9E3EL, // -174 - 0x6781_5961_0903_F797L, 0x253E_59F9_1780_FD2FL, // -173 - 0x52CD_E11A_6D9C_C612L, 0x50FE_AE60_DF9A_6426L, // -172 - 0x423E_4DAE_BE17_04DBL, 0x5A65_584D_7FAE_B685L, // -171 - 0x69FD_4917_968B_3AF9L, 0x10A2_26E2_65E4_573BL, // -170 - 0x54CA_A0DF_ABA2_9594L, 0x0D4E_8581_EB1D_1295L, // -169 - 0x43D5_4D7F_BC82_1143L, 0x243E_D134_BC17_4211L, // -168 - 0x6C88_7BFF_9403_4ED2L, 0x06CA_E854_6025_3682L, // -167 - 0x56D3_9666_1002_A574L, 0x6BD5_86A9_E684_2B9BL, // -166 - 0x4576_11EB_4002_1DF7L, 0x0977_9EEE_5203_5616L, // -165 - 0x6F23_4FDE_CCD0_2FF1L, 0x5BF2_97E3_B66B_BCEFL, // -164 - 0x58E9_0CB2_3D73_598EL, 0x165B_ACB6_2B89_63F3L, // -163 - 0x4720_D6F4_FDF5_E13EL, 0x4516_23C4_EFA1_1CC2L, // -162 - 0x71CE_24BB_2FEF_CECAL, 0x3B56_9FA1_7F68_2E03L, // -161 - 0x5B0B_5095_BFF3_0BD5L, 0x15DE_E61A_CC53_5803L, // -160 - 0x48D5_DA11_665C_0977L, 0x2B18_B815_7042_ACCFL, // -159 - 0x7489_5CE8_A3C6_758BL, 0x5E8D_F355_806A_AE18L, // -158 - 0x5D3A_B0BA_1C9E_C46FL, 0x653E_5C44_66BB_BE7AL, // -157 - 0x4A95_5A2E_7D4B_D059L, 0x3765_169D_1EFC_9861L, // -156 - 0x7755_5D17_2EDF_B3C2L, 0x256E_8A94_FE60_F3CFL, // -155 - 0x5F77_7DAC_257F_C301L, 0x6ABE_D543_FEB3_F63FL, // -154 - 0x4C5F_97BC_EACC_9C01L, 0x3BCB_DDCF_FEF6_5E99L, // -153 - 0x7A32_8C61_77AD_C668L, 0x5FAC_9619_97F0_975BL, // -152 - 0x61C2_09E7_92F1_6B86L, 0x7FBD_44E1_465A_12AFL, // -151 - 0x4E34_D4B9_425A_BC6BL, 0x7FCA_9D81_0514_DBBFL, // -150 - 0x7D21_545B_9D5D_FA46L, 0x32DD_C8CE_6E87_C5FFL, // -149 - 0x641A_A9E2_E44B_2E9EL, 0x5BE4_A0A5_2539_6B32L, // -148 - 0x5015_54B5_836F_587EL, 0x7CB6_E6EA_842D_EF5CL, // -147 - 0x4011_1091_35F2_AD32L, 0x3092_5255_368B_25E3L, // -146 - 0x6681_B41B_8984_4850L, 0x4DB6_EA21_F0DE_A304L, // -145 - 0x5201_5CE2_D469_D373L, 0x57C5_881B_2718_826AL, // -144 - 0x419A_B0B5_76BB_0F8FL, 0x5FD1_39AF_527A_01EFL, // -143 - 0x68F7_8122_5791_B27FL, 0x4C81_F5E5_50C3_364AL, // -142 - 0x53F9_341B_7941_5B99L, 0x239B_2B1D_DA35_C508L, // -141 - 0x432D_C349_2DCD_E2E1L, 0x02E2_88E4_AE91_6A6DL, // -140 - 0x6B7C_6BA8_4949_6B01L, 0x516A_74A1_174F_10AEL, // -139 - 0x55FD_22ED_076D_EF34L, 0x4121_F6E7_45D8_DA25L, // -138 - 0x44CA_8257_3924_BF5DL, 0x1A81_9252_9E47_14EBL, // -137 - 0x6E10_D08B_8EA1_322EL, 0x5D9C_1D50_FD3E_87DDL, // -136 - 0x580D_73A2_D880_F4F2L, 0x17B0_1773_FDCB_9FE4L, // -135 - 0x4671_294F_139A_5D8EL, 0x4626_7929_97D6_1984L, // -134 - 0x70B5_0EE4_EC2A_2F4AL, 0x3D0A_5B75_BFBC_F59FL, // -133 - 0x5A2A_7250_BCEE_8C3BL, 0x4A6E_AF91_6630_C47FL, // -132 - 0x4821_F50D_63F2_09C9L, 0x21F2_260D_EB5A_36CCL, // -131 - 0x7369_8815_6CB6_760EL, 0x6983_7016_455D_247AL, // -130 - 0x5C54_6CDD_F091_F80BL, 0x6E02_C011_D117_5062L, // -129 - 0x49DD_23E4_C074_C66FL, 0x719B_CCDB_0DAC_404EL, // -128 - 0x762E_9FD4_6721_3D7FL, 0x68F9_47C4_E2AD_33B0L, // -127 - 0x5E8B_B310_5280_FDFFL, 0x6D94_396A_4EF0_F627L, // -126 - 0x4BA2_F5A6_A867_3199L, 0x3E10_2DEE_A58D_91B9L, // -125 - 0x7904_BC3D_DA3E_B5C2L, 0x3019_E317_6F48_E927L, // -124 - 0x60D0_9697_E1CB_C49BL, 0x4014_B5AC_5907_20ECL, // -123 - 0x4D73_ABAC_B4A3_03AFL, 0x4CDD_5E23_7A6C_1A57L, // -122 - 0x7BEC_45E1_2104_D2B2L, 0x47C8_969F_2A46_908AL, // -121 - 0x6323_6B1A_80D0_A88EL, 0x6CA0_787F_5505_406FL, // -120 - 0x4F4F_88E2_00A6_ED3FL, 0x0A19_F9FF_7737_66BFL, // -119 - 0x7EE5_A7D0_010B_1531L, 0x5CF6_5CCB_F1F2_3DFEL, // -118 - 0x6584_8640_00D5_AA8EL, 0x172B_7D6F_F4C1_CB32L, // -117 - 0x5136_D1CC_CD77_BBA4L, 0x78EF_978C_C3CE_3C28L, // -116 - 0x40F8_A7D7_0AC6_2FB7L, 0x13F2_DFA3_CFD8_3020L, // -115 - 0x67F4_3FBE_77A3_7F8BL, 0x3984_9906_1959_E699L, // -114 - 0x5329_CC98_5FB5_FFA2L, 0x6136_E0D1_ADE1_8548L, // -113 - 0x4287_D6E0_4C91_994FL, 0x00F8_B3DA_F181_376DL, // -112 - 0x6A72_F166_E0E8_F54BL, 0x1B27_862B_1C01_F247L, // -111 - 0x5528_C11F_1A53_F76FL, 0x2F52_D1BC_1667_F506L, // -110 - 0x4420_9A7F_4843_2C59L, 0x0C42_4163_451F_F738L, // -109 - 0x6D00_F732_0D38_46F4L, 0x7A03_9BD2_0833_2526L, // -108 - 0x5733_F8F4_D760_38C3L, 0x7B36_1641_A028_EA85L, // -107 - 0x45C3_2D90_AC4C_FA36L, 0x2F5E_7834_8020_BB9EL, // -106 - 0x6F9E_AF4D_E07B_29F0L, 0x4BCA_59ED_99CD_F8FCL, // -105 - 0x594B_BF71_8062_87F3L, 0x563B_7B24_7B0B_2D96L, // -104 - 0x476F_CC5A_CD1B_9FF6L, 0x11C9_2F50_626F_57ACL, // -103 - 0x724C_7A2A_E1C5_CCBDL, 0x02DB_7EE7_03E5_5912L, // -102 - 0x5B70_61BB_E7D1_7097L, 0x1BE2_CBEC_031D_E0DCL, // -101 - 0x4926_B496_530D_F3ACL, 0x164F_0989_9C17_E716L, // -100 - 0x750A_BA8A_1E7C_B913L, 0x3D4B_4275_C68C_A4F0L, // -99 - 0x5DA2_2ED4_E530_940FL, 0x4AA2_9B91_6BA3_B726L, // -98 - 0x4AE8_2577_1DC0_7672L, 0x6EE8_7C74_561C_9285L, // -97 - 0x77D9_D58B_62CD_8A51L, 0x3173_FA53_BCFA_8408L, // -96 - 0x5FE1_77A2_B571_3B74L, 0x278F_FB76_30C8_69A0L, // -95 - 0x4CB4_5FB5_5DF4_2F90L, 0x1FA6_62C4_F3D3_87B3L, // -94 - 0x7ABA_32BB_C986_B280L, 0x32A3_D13B_1FB8_D91FL, // -93 - 0x622E_8EFC_A138_8ECDL, 0x0EE9_742F_4C93_E0E6L, // -92 - 0x4E8B_A596_E760_723DL, 0x58BA_C359_0A0F_E71EL, // -91 - 0x7DAC_3C24_A567_1D2FL, 0x412A_D228_1019_71C9L, // -90 - 0x6489_C9B6_EAB8_E426L, 0x00EF_0E86_7347_8E3BL, // -89 - 0x506E_3AF8_BBC7_1CEBL, 0x1A58_D86B_8F6C_71C9L, // -88 - 0x4058_2F2D_6305_B0BCL, 0x1513_E056_0C56_C16EL, // -87 - 0x66F3_7EAF_04D5_E793L, 0x3B53_0089_AD57_9BE2L, // -86 - 0x525C_6558_D0AB_1FA9L, 0x15DC_006E_2446_164FL, // -85 - 0x41E3_8447_0D55_B2EDL, 0x5E49_99F1_B69E_783FL, // -84 - 0x696C_06D8_1555_EB15L, 0x7D42_8FE9_2430_C065L, // -83 - 0x5456_6BE0_1111_88DEL, 0x3102_0CBA_835A_3384L, // -82 - 0x4378_564C_DA74_6D7EL, 0x5A68_0A2E_CF7B_5C69L, // -81 - 0x6BF3_BD47_C3ED_7BFDL, 0x770C_DD17_B25E_FA42L, // -80 - 0x565C_976C_9CBD_FCCBL, 0x1270_B0DF_C1E5_9502L, // -79 - 0x4516_DF8A_16FE_63D5L, 0x5B8D_5A4C_9B1E_10CEL, // -78 - 0x6E8A_FF43_57FD_6C89L, 0x127B_C3AD_C4FC_E7B0L, // -77 - 0x586F_329C_4664_56D4L, 0x0EC9_6957_D0CA_52F3L, // -76 - 0x46BF_5BB0_3850_4576L, 0x3F07_8779_73D5_0F29L, // -75 - 0x7132_2C4D_26E6_D58AL, 0x31A5_A58F_1FBB_4B75L, // -74 - 0x5A8E_89D7_5252_446EL, 0x5AEA_EAD8_E62F_6F91L, // -73 - 0x4872_07DF_750E_9D25L, 0x2F22_557A_51BF_8C74L, // -72 - 0x73E9_A632_54E4_2EA2L, 0x1836_EF2A_1C65_AD86L, // -71 - 0x5CBA_EB5B_771C_F21BL, 0x2CF8_BF54_E384_8AD2L, // -70 - 0x4A2F_22AF_927D_8E7CL, 0x23FA_32AA_4F9D_3BDBL, // -69 - 0x76B1_D118_EA62_7D93L, 0x5329_EAAA_18FB_92F8L, // -68 - 0x5EF4_A747_21E8_6476L, 0x0F54_BBBB_472F_A8C6L, // -67 - 0x4BF6_EC38_E7ED_1D2BL, 0x25DD_62FC_38F2_ED6CL, // -66 - 0x798B_138E_3FE1_C845L, 0x22FB_D193_8E51_7BDFL, // -65 - 0x613C_0FA4_FFE7_D36AL, 0x4F2F_DADC_71DA_C97FL, // -64 - 0x4DC9_A61D_9986_42BBL, 0x58F3_157D_27E2_3ACCL, // -63 - 0x7C75_D695_C270_6AC5L, 0x74B8_2261_D969_F7ADL, // -62 - 0x6391_7877_CEC0_556BL, 0x1093_4EB4_ADEE_5FBEL, // -61 - 0x4FA7_9393_0BCD_1122L, 0x4075_D890_8B25_1965L, // -60 - 0x7F72_85B8_12E1_B504L, 0x00BC_8DB4_11D4_F56EL, // -59 - 0x65F5_37C6_7581_5D9CL, 0x66FD_3E29_A7DD_9125L, // -58 - 0x5190_F96B_9134_4AE3L, 0x6BFD_CB54_864A_DA84L, // -57 - 0x4140_C789_40F6_A24FL, 0x6FFE_3C43_9EA2_486AL, // -56 - 0x6867_A5A8_67F1_03B2L, 0x7FFD_2D38_FDD0_73DCL, // -55 - 0x5386_1E20_5327_3628L, 0x6664_242D_97D9_F64AL, // -54 - 0x42D1_B1B3_75B8_F820L, 0x51E9_B68A_DFE1_91D5L, // -53 - 0x6AE9_1C52_55F4_C034L, 0x1CA9_2411_6635_B621L, // -52 - 0x5587_49DB_77F7_0029L, 0x63BA_8341_1E91_5E81L, // -51 - 0x446C_3B15_F992_6687L, 0x6962_029A_7EDA_B201L, // -50 - 0x6D79_F823_28EA_3DA6L, 0x0F03_375D_97C4_5001L, // -49 - 0x5794_C682_8721_CAEBL, 0x259C_2C4A_DFD0_4001L, // -48 - 0x4610_9ECE_D281_6F22L, 0x5149_BD08_B30D_0001L, // -47 - 0x701A_97B1_50CF_1837L, 0x3542_C80D_EB48_0001L, // -46 - 0x59AE_DFC1_0D72_79C5L, 0x7768_A00B_22A0_0001L, // -45 - 0x47BF_1967_3DF5_2E37L, 0x7920_8008_E880_0001L, // -44 - 0x72CB_5BD8_6321_E38CL, 0x5B67_3341_7400_0001L, // -43 - 0x5BD5_E313_8281_82D6L, 0x7C52_8F67_9000_0001L, // -42 - 0x4977_E8DC_6867_9BDFL, 0x16A8_72B9_4000_0001L, // -41 - 0x758C_A7C7_0D72_92FEL, 0x5773_EAC2_0000_0001L, // -40 - 0x5E0A_1FD2_7128_7598L, 0x45F6_5568_0000_0001L, // -39 - 0x4B3B_4CA8_5A86_C47AL, 0x04C5_1120_0000_0001L, // -38 - 0x785E_E10D_5DA4_6D90L, 0x07A1_B500_0000_0001L, // -37 - 0x604B_E73D_E483_8AD9L, 0x52E7_C400_0000_0001L, // -36 - 0x4D09_85CB_1D36_08AEL, 0x0F1F_D000_0000_0001L, // -35 - 0x7B42_6FAB_61F0_0DE3L, 0x31CC_8000_0000_0001L, // -34 - 0x629B_8C89_1B26_7182L, 0x5B0A_0000_0000_0001L, // -33 - 0x4EE2_D6D4_15B8_5ACEL, 0x7C08_0000_0000_0001L, // -32 - 0x7E37_BE20_22C0_914BL, 0x1340_0000_0000_0001L, // -31 - 0x64F9_64E6_8233_A76FL, 0x2900_0000_0000_0001L, // -30 - 0x50C7_83EB_9B5C_85F2L, 0x5400_0000_0000_0001L, // -29 - 0x409F_9CBC_7C4A_04C2L, 0x1000_0000_0000_0001L, // -28 - 0x6765_C793_FA10_079DL, 0x0000_0000_0000_0001L, // -27 - 0x52B7_D2DC_C80C_D2E4L, 0x0000_0000_0000_0001L, // -26 - 0x422C_A8B0_A00A_4250L, 0x0000_0000_0000_0001L, // -25 - 0x69E1_0DE7_6676_D080L, 0x0000_0000_0000_0001L, // -24 - 0x54B4_0B1F_852B_DA00L, 0x0000_0000_0000_0001L, // -23 - 0x43C3_3C19_3756_4800L, 0x0000_0000_0000_0001L, // -22 - 0x6C6B_935B_8BBD_4000L, 0x0000_0000_0000_0001L, // -21 - 0x56BC_75E2_D631_0000L, 0x0000_0000_0000_0001L, // -20 - 0x4563_9182_44F4_0000L, 0x0000_0000_0000_0001L, // -19 - 0x6F05_B59D_3B20_0000L, 0x0000_0000_0000_0001L, // -18 - 0x58D1_5E17_6280_0000L, 0x0000_0000_0000_0001L, // -17 - 0x470D_E4DF_8200_0000L, 0x0000_0000_0000_0001L, // -16 - 0x71AF_D498_D000_0000L, 0x0000_0000_0000_0001L, // -15 - 0x5AF3_107A_4000_0000L, 0x0000_0000_0000_0001L, // -14 - 0x48C2_7395_0000_0000L, 0x0000_0000_0000_0001L, // -13 - 0x746A_5288_0000_0000L, 0x0000_0000_0000_0001L, // -12 - 0x5D21_DBA0_0000_0000L, 0x0000_0000_0000_0001L, // -11 - 0x4A81_7C80_0000_0000L, 0x0000_0000_0000_0001L, // -10 - 0x7735_9400_0000_0000L, 0x0000_0000_0000_0001L, // -9 - 0x5F5E_1000_0000_0000L, 0x0000_0000_0000_0001L, // -8 - 0x4C4B_4000_0000_0000L, 0x0000_0000_0000_0001L, // -7 - 0x7A12_0000_0000_0000L, 0x0000_0000_0000_0001L, // -6 - 0x61A8_0000_0000_0000L, 0x0000_0000_0000_0001L, // -5 - 0x4E20_0000_0000_0000L, 0x0000_0000_0000_0001L, // -4 - 0x7D00_0000_0000_0000L, 0x0000_0000_0000_0001L, // -3 - 0x6400_0000_0000_0000L, 0x0000_0000_0000_0001L, // -2 - 0x5000_0000_0000_0000L, 0x0000_0000_0000_0001L, // -1 - 0x4000_0000_0000_0000L, 0x0000_0000_0000_0001L, // 0 - 0x6666_6666_6666_6666L, 0x3333_3333_3333_3334L, // 1 - 0x51EB_851E_B851_EB85L, 0x0F5C_28F5_C28F_5C29L, // 2 - 0x4189_374B_C6A7_EF9DL, 0x5916_872B_020C_49BBL, // 3 - 0x68DB_8BAC_710C_B295L, 0x74F0_D844_D013_A92BL, // 4 - 0x53E2_D623_8DA3_C211L, 0x43F3_E037_0CDC_8755L, // 5 - 0x431B_DE82_D7B6_34DAL, 0x698F_E692_70B0_6C44L, // 6 - 0x6B5F_CA6A_F2BD_215EL, 0x0F4C_A41D_811A_46D4L, // 7 - 0x55E6_3B88_C230_E77EL, 0x3F70_834A_CDAE_9F10L, // 8 - 0x44B8_2FA0_9B5A_52CBL, 0x4C5A_02A2_3E25_4C0DL, // 9 - 0x6DF3_7F67_5EF6_EADFL, 0x2D5C_D103_96A2_1347L, // 10 - 0x57F5_FF85_E592_557FL, 0x3DE3_DA69_454E_75D3L, // 11 - 0x465E_6604_B7A8_4465L, 0x7E4F_E1ED_D10B_9175L, // 12 - 0x7097_09A1_25DA_0709L, 0x4A19_697C_81AC_1BEFL, // 13 - 0x5A12_6E1A_84AE_6C07L, 0x54E1_2130_67BC_E326L, // 14 - 0x480E_BE7B_9D58_566CL, 0x43E7_4DC0_52FD_8285L, // 15 - 0x734A_CA5F_6226_F0ADL, 0x530B_AF9A_1E62_6A6DL, // 16 - 0x5C3B_D519_1B52_5A24L, 0x426F_BFAE_7EB5_21F1L, // 17 - 0x49C9_7747_490E_AE83L, 0x4EBF_CC8B_9890_E7F4L, // 18 - 0x760F_253E_DB4A_B0D2L, 0x4ACC_7A78_F41B_0CBAL, // 19 - 0x5E72_8432_4908_8D75L, 0x223D_2EC7_29AF_3D62L, // 20 - 0x4B8E_D028_3A6D_3DF7L, 0x34FD_BF05_BAF2_9781L, // 21 - 0x78E4_8040_5D7B_9658L, 0x54C9_31A2_C4B7_58CFL, // 22 - 0x60B6_CD00_4AC9_4513L, 0x5D6D_C14F_03C5_E0A5L, // 23 - 0x4D5F_0A66_A23A_9DA9L, 0x3124_9AA5_9C9E_4D51L, // 24 - 0x7BCB_43D7_69F7_62A8L, 0x4EA0_F76F_60FD_4882L, // 25 - 0x6309_0312_BB2C_4EEDL, 0x254D_92BF_80CA_A068L, // 26 - 0x4F3A_68DB_C8F0_3F24L, 0x1DD7_A899_33D5_4D20L, // 27 - 0x7EC3_DAF9_4180_6506L, 0x62F2_A75B_8622_1500L, // 28 - 0x6569_7BFA_9ACD_1D9FL, 0x025B_B916_04E8_10CDL, // 29 - 0x5121_2FFB_AF0A_7E18L, 0x6849_60DE_6A53_40A4L, // 30 - 0x40E7_5996_25A1_FE7AL, 0x203A_B3E5_21DC_33B6L, // 31 - 0x67D8_8F56_A29C_CA5DL, 0x19F7_863B_6960_52BDL, // 32 - 0x5313_A5DE_E87D_6EB0L, 0x7B2C_6B62_BAB3_7564L, // 33 - 0x4276_1E4B_ED31_255AL, 0x2F56_BC4E_FBC2_C450L, // 34 - 0x6A56_96DF_E1E8_3BC3L, 0x6557_93B1_92D1_3A1AL, // 35 - 0x5512_124C_B4B9_C969L, 0x3779_42F4_7574_2E7BL, // 36 - 0x440E_750A_2A2E_3ABAL, 0x5F94_3590_5DF6_8B96L, // 37 - 0x6CE3_EE76_A9E3_912AL, 0x65B9_EF4D_6324_1289L, // 38 - 0x571C_BEC5_54B6_0DBBL, 0x6AFB_25D7_8283_4207L, // 39 - 0x45B0_989D_DD5E_7163L, 0x08C8_EB12_CECF_6806L, // 40 - 0x6F80_F42F_C897_1BD1L, 0x5ADB_11B7_B14B_D9A3L, // 41 - 0x5933_F68C_A078_E30EL, 0x157C_0E2C_8DD6_47B5L, // 42 - 0x475C_C53D_4D2D_8271L, 0x5DFC_D823_A4AB_6C91L, // 43 - 0x722E_0862_1515_9D82L, 0x632E_269F_6DDF_141BL, // 44 - 0x5B58_06B4_DDAA_E468L, 0x4F58_1EE5_F17F_4349L, // 45 - 0x4913_3890_B155_8386L, 0x72AC_E584_C132_9C3BL, // 46 - 0x74EB_8DB4_4EEF_38D7L, 0x6AAE_3C07_9B84_2D2AL, // 47 - 0x5D89_3E29_D8BF_60ACL, 0x5558_3006_1603_5755L, // 48 - 0x4AD4_31BB_13CC_4D56L, 0x7779_C004_DE69_12ABL, // 49 - 0x77B9_E92B_52E0_7BBEL, 0x258F_99A1_63DB_5111L, // 50 - 0x5FC7_EDBC_424D_2FCBL, 0x37A6_1481_1CAF_740DL, // 51 - 0x4C9F_F163_683D_BFD5L, 0x7951_AA00_E3BF_900BL, // 52 - 0x7A99_8238_A6C9_32EFL, 0x754F_7667_D2CC_19ABL, // 53 - 0x6214_682D_523A_8F26L, 0x2AA5_F853_0F09_AE22L, // 54 - 0x4E76_B9BD_DB62_0C1EL, 0x5551_9375_A5A1_581BL, // 55 - 0x7D8A_C2C9_5F03_4697L, 0x3BB5_B8BC_3C35_59C5L, // 56 - 0x646F_023A_B269_0545L, 0x7C91_6096_9691_149EL, // 57 - 0x5058_CE95_5B87_376BL, 0x16DA_B3AB_ABA7_43B2L, // 58 - 0x4047_0BAA_AF9F_5F88L, 0x78AE_F622_EFB9_02F5L, // 59 - 0x66D8_12AA_B298_98DBL, 0x0DE4_BD04_B2C1_9E54L, // 60 - 0x5246_7555_5BAD_4715L, 0x57EA_30D0_8F01_4B76L, // 61 - 0x41D1_F777_7C8A_9F44L, 0x4654_F3DA_0C01_092CL, // 62 - 0x694F_F258_C744_3207L, 0x23BB_1FC3_4668_0EACL, // 63 - 0x543F_F513_D29C_F4D2L, 0x4FC8_E635_D1EC_D88AL, // 64 - 0x4366_5DA9_754A_5D75L, 0x263A_51C4_A7F0_AD3BL, // 65 - 0x6BD6_FC42_5543_C8BBL, 0x56C3_B607_731A_AEC4L, // 66 - 0x5645_969B_7769_6D62L, 0x789C_919F_8F48_8BD0L, // 67 - 0x4504_787C_5F87_8AB5L, 0x46E3_A7B2_D906_D640L, // 68 - 0x6E6D_8D93_CC0C_1122L, 0x3E39_0C51_5B3E_239AL, // 69 - 0x5857_A476_3CD6_741BL, 0x4B60_D6A7_7C31_B615L, // 70 - 0x46AC_8391_CA45_29AFL, 0x55E7_121F_968E_2B44L, // 71 - 0x7114_05B6_106E_A919L, 0x0971_B698_F0E3_786DL, // 72 - 0x5A76_6AF8_0D25_5414L, 0x078E_2BAD_8D82_C6BDL, // 73 - 0x485E_BBF9_A41D_DCDCL, 0x6C71_BC8A_D79B_D231L, // 74 - 0x73CA_C65C_39C9_6161L, 0x2D82_C744_8C2C_8382L, // 75 - 0x5CA2_3849_C7D4_4DE7L, 0x3E02_3903_A356_CF9BL, // 76 - 0x4A1B_603B_0643_7185L, 0x7E68_2D9C_82AB_D949L, // 77 - 0x7692_3391_A39F_1C09L, 0x4A40_48FA_6AAC_8EDBL, // 78 - 0x5EDB_5C74_82E5_B007L, 0x5500_3A61_EEF0_7249L, // 79 - 0x4BE2_B05D_3584_8CD2L, 0x7733_61E7_F259_F507L, // 80 - 0x796A_B3C8_55A0_E151L, 0x3EB8_9CA6_508F_EE71L, // 81 - 0x6122_296D_114D_810DL, 0x7EFA_16EB_73A6_585BL, // 82 - 0x4DB4_EDF0_DAA4_673EL, 0x3261_ABEF_8FB8_46AFL, // 83 - 0x7C54_AFE7_C43A_3ECAL, 0x1D69_1318_E5F3_A44BL, // 84 - 0x6376_F31F_D02E_98A1L, 0x6454_0F47_1E5C_836FL, // 85 - 0x4F92_5C19_7358_7A1BL, 0x0376_729F_4B7D_35F3L, // 86 - 0x7F50_935B_EBC0_C35EL, 0x38BD_8432_1261_EFEBL, // 87 - 0x65DA_0F7C_BC9A_35E5L, 0x13CA_D028_0EB4_BFEFL, // 88 - 0x517B_3F96_FD48_2B1DL, 0x5CA2_4020_0BC3_CCBFL, // 89 - 0x412F_6612_6439_BC17L, 0x63B5_0019_A303_0A33L, // 90 - 0x684B_D683_D38F_9359L, 0x1F88_0029_04D1_A9EAL, // 91 - 0x536F_DECF_DC72_DC47L, 0x32D3_3354_03DA_EE55L, // 92 - 0x42BF_E573_16C2_49D2L, 0x5BDC_2910_0315_8B77L, // 93 - 0x6ACC_A251_BE03_A951L, 0x12F9_DB4C_D1BC_1258L, // 94 - 0x5570_81DA_FE69_5440L, 0x7594_AF70_A7C9_A847L, // 95 - 0x445A_017B_FEBA_A9CDL, 0x4476_F2C0_863A_ED06L, // 96 - 0x6D5C_CF2C_CAC4_42E2L, 0x3A57_EACD_A391_7B3CL, // 97 - 0x577D_728A_3BD0_3581L, 0x7B79_88A4_82DA_C8FDL, // 98 - 0x45FD_F53B_630C_F79BL, 0x15FA_D3B6_CF15_6D97L, // 99 - 0x6FFC_BB92_3814_BF5EL, 0x565E_1F8A_E4EF_15BEL, // 100 - 0x5996_FC74_F9AA_32B2L, 0x11E4_E608_B725_AAFFL, // 101 - 0x47AB_FD2A_6154_F55BL, 0x27EA_51A0_9284_88CCL, // 102 - 0x72AC_C843_CEEE_555EL, 0x7310_829A_8407_4146L, // 103 - 0x5BBD_6D03_0BF1_DDE5L, 0x4273_9BAE_D005_CDD2L, // 104 - 0x4964_5735_A327_E4B7L, 0x4EC2_E2F2_4004_A4A8L, // 105 - 0x756D_5855_D1D9_6DF2L, 0x4AD1_6B1D_333A_A10CL, // 106 - 0x5DF1_1377_DB14_57F5L, 0x2241_227D_C295_4DA3L, // 107 - 0x4B27_42C6_48DD_132AL, 0x4E9A_81FE_3544_3E1CL, // 108 - 0x783E_D13D_4161_B844L, 0x175D_9CC9_EED3_9694L, // 109 - 0x6032_40FD_CDE7_C69CL, 0x7917_B0A1_8BDC_7876L, // 110 - 0x4CF5_00CB_0B1F_D217L, 0x1412_F3B4_6FE3_9392L, // 111 - 0x7B21_9ADE_7832_E9BEL, 0x5351_85ED_7FD2_85B6L, // 112 - 0x6281_48B1_F9C2_5498L, 0x42A7_9E57_9975_37C5L, // 113 - 0x4ECD_D3C1_949B_76E0L, 0x3552_E512_E12A_9304L, // 114 - 0x7E16_1F9C_20F8_BE33L, 0x6EEB_081E_3510_EB39L, // 115 - 0x64DE_7FB0_1A60_9829L, 0x3F22_6CE4_F740_BC2EL, // 116 - 0x50B1_FFC0_151A_1354L, 0x3281_F0B7_2C33_C9BEL, // 117 - 0x408E_6633_4414_DC43L, 0x4201_8D5F_568F_D498L, // 118 - 0x674A_3D1E_D354_939FL, 0x1CCF_4898_8A7F_BA8DL, // 119 - 0x52A1_CA7F_0F76_DC7FL, 0x30A5_D3AD_3B99_620BL, // 120 - 0x421B_0865_A5F8_B065L, 0x73B7_DC8A_9614_4E6FL, // 121 - 0x69C4_DA3C_3CC1_1A3CL, 0x52BF_C744_2353_B0B1L, // 122 - 0x549D_7B63_63CD_AE96L, 0x7566_3903_4F76_26F4L, // 123 - 0x43B1_2F82_B63E_2545L, 0x4451_C735_D92B_525DL, // 124 - 0x6C4E_B26A_BD30_3BA2L, 0x3A1C_71EF_C1DE_EA2EL, // 125 - 0x56A5_5B88_9759_C94EL, 0x61B0_5B26_34B2_54F2L, // 126 - 0x4551_1606_DF7B_0772L, 0x1AF3_7C1E_908E_AA5BL, // 127 - 0x6EE8_233E_325E_7250L, 0x2B1F_2CFD_B417_76F8L, // 128 - 0x58B9_B5CB_5B7E_C1D9L, 0x6F4C_23FE_29AC_5F2DL, // 129 - 0x46FA_F7D5_E2CB_CE47L, 0x72A3_4FFE_87BD_18F1L, // 130 - 0x7191_8C89_6ADF_B073L, 0x0438_7FFD_A5FB_5B1BL, // 131 - 0x5ADA_D6D4_557F_C05CL, 0x0360_6664_84C9_15AFL, // 132 - 0x48AF_1243_7799_66B0L, 0x02B3_851D_3707_448CL, // 133 - 0x744B_506B_F28F_0AB3L, 0x1DEC_082E_BE72_0746L, // 134 - 0x5D09_0D23_2872_6EF5L, 0x64BC_D358_985B_3905L, // 135 - 0x4A6D_A41C_205B_8BF7L, 0x6A30_A913_AD15_C738L, // 136 - 0x7715_D360_33C5_ACBFL, 0x5D1A_A81F_7B56_0B8CL, // 137 - 0x5F44_A919_C304_8A32L, 0x7DAE_ECE5_FC44_D609L, // 138 - 0x4C36_EDAE_359D_3B5BL, 0x7E25_8A51_969D_7808L, // 139 - 0x79F1_7C49_EF61_F893L, 0x16A2_76E8_F0FB_F33FL, // 140 - 0x618D_FD07_F2B4_C6DCL, 0x121B_9253_F3FC_C299L, // 141 - 0x4E0B_30D3_2890_9F16L, 0x41AF_A843_2997_0214L, // 142 - 0x7CDE_B485_0DB4_31BDL, 0x4F7F_739E_A8F1_9CEDL, // 143 - 0x63E5_5D37_3E29_C164L, 0x3F99_294B_BA5A_E3F1L, // 144 - 0x4FEA_B0F8_FE87_CDE9L, 0x7FAD_BAA2_FB7B_E98DL, // 145 - 0x7FDD_E7F4_CA72_E30FL, 0x7F7C_5DD1_925F_DC15L, // 146 - 0x664B_1FF7_085B_E8D9L, 0x4C63_7E41_41E6_49ABL, // 147 - 0x51D5_B32C_06AF_ED7AL, 0x704F_9834_34B8_3AEFL, // 148 - 0x4177_C289_9EF3_2462L, 0x26A6_135C_F6F9_C8BFL, // 149 - 0x68BF_9DA8_FE51_D3D0L, 0x3DD6_8561_8B29_4132L, // 150 - 0x53CC_7E20_CB74_A973L, 0x4B12_044E_08ED_CDC2L, // 151 - 0x4309_FE80_A2C3_BAC2L, 0x6F41_9D0B_3A57_D7CEL, // 152 - 0x6B43_30CD_D139_2AD1L, 0x3202_94DE_C3BF_BFB0L, // 153 - 0x55CF_5A3E_40FA_88A7L, 0x419B_AA4B_CFCC_995AL, // 154 - 0x44A5_E1CB_672E_D3B9L, 0x1AE2_EEA3_0CA3_ADE1L, // 155 - 0x6DD6_3612_3EB1_52C1L, 0x77D1_7DD1_ADD2_AFCFL, // 156 - 0x57DE_91A8_3227_7567L, 0x7974_64A7_BE42_263FL, // 157 - 0x464B_A7B9_C1B9_2AB9L, 0x4790_5086_31CE_84FFL, // 158 - 0x7079_0C5C_6928_445CL, 0x0C1A_1A70_4FB0_D4CCL, // 159 - 0x59FA_7049_EDB9_D049L, 0x567B_4859_D95A_43D6L, // 160 - 0x47FB_8D07_F161_736EL, 0x11FC_39E1_7AAE_9CABL, // 161 - 0x732C_14D9_8235_857DL, 0x032D_2968_C44A_9445L, // 162 - 0x5C23_43E1_34F7_9DFDL, 0x4F57_5453_D03B_A9D1L, // 163 - 0x49B5_CFE7_5D92_E4CAL, 0x72AC_4376_402F_BB0EL, // 164 - 0x75EF_B30B_C8EB_07ABL, 0x0446_D256_CD19_2B49L, // 165 - 0x5E59_5C09_6D88_D2EFL, 0x1D05_7512_3DAD_BC3AL, // 166 - 0x4B7A_B007_8AD3_DBF2L, 0x4A6A_C40E_97BE_302FL, // 167 - 0x78C4_4CD8_DE1F_C650L, 0x7711_39B0_F2C9_E6B1L, // 168 - 0x609D_0A47_1819_6B73L, 0x78DA_948D_8F07_EBC1L, // 169 - 0x4D4A_6E9F_467A_BC5CL, 0x60AE_DD3E_0C06_5634L, // 170 - 0x7BAA_4A98_70C4_6094L, 0x344A_FB96_79A3_BD20L, // 171 - 0x62EE_A213_8D69_E6DDL, 0x103B_FC78_614F_CA80L, // 172 - 0x4F25_4E76_0ABB_1F17L, 0x2696_6393_810C_A200L, // 173 - 0x7EA2_1723_445E_9825L, 0x2423_D285_9B47_6999L, // 174 - 0x654E_78E9_037E_E01DL, 0x69B6_4204_7C39_2148L, // 175 - 0x510B_93ED_9C65_8017L, 0x6E2B_6803_9694_1AA0L, // 176 - 0x40D6_0FF1_49EA_CCDFL, 0x71BC_5336_1210_154DL, // 177 - 0x67BC_E64E_DCAA_E166L, 0x1C60_8523_5019_BBAEL, // 178 - 0x52FD_850B_E3BB_E784L, 0x7D1A_041C_4014_9625L, // 179 - 0x4264_6A6F_E963_1F9DL, 0x4A7B_367D_0010_781DL, // 180 - 0x6A3A_43E6_4238_3295L, 0x5D91_F0C8_001A_59C8L, // 181 - 0x54FB_6985_01C6_8EDEL, 0x17A7_F3D3_3348_47D4L, // 182 - 0x43FC_546A_67D2_0BE4L, 0x7953_2975_C2A0_3976L, // 183 - 0x6CC6_ED77_0C83_463BL, 0x0EEB_7589_3766_C256L, // 184 - 0x5705_8AC5_A39C_382FL, 0x2589_2AD4_2C52_3512L, // 185 - 0x459E_089E_1C7C_F9BFL, 0x37A0_EF10_2374_F742L, // 186 - 0x6F63_40FC_FA61_8F98L, 0x5901_7E80_38BB_2536L, // 187 - 0x591C_33FD_951A_D946L, 0x7A67_9866_93C8_EA91L, // 188 - 0x4749_C331_4415_7A9FL, 0x151F_AD1E_DCA0_BBA8L, // 189 - 0x720F_9EB5_39BB_F765L, 0x0832_AE97_C767_92A5L, // 190 - 0x5B3F_B22A_9496_5F84L, 0x068E_F213_05EC_7551L, // 191 - 0x48FF_C1BB_AA11_E603L, 0x1ED8_C1A8_D189_F774L, // 192 - 0x74CC_692C_434F_D66BL, 0x4AF4_690E_1C0F_F253L, // 193 - 0x5D70_5423_690C_AB89L, 0x225D_20D8_1673_2843L, // 194 - 0x4AC0_434F_873D_5607L, 0x3517_4D79_AB8F_5369L, // 195 - 0x779A_054C_0B95_5672L, 0x21BE_E25C_45B2_1F0EL, // 196 - 0x5FAE_6AA3_3C77_785BL, 0x3498_B516_9E28_18D8L, // 197 - 0x4C8B_8882_96C5_F9E2L, 0x5D46_F745_4B53_4713L, // 198 - 0x7A78_DA6A_8AD6_5C9DL, 0x7BA4_BED5_4552_0B52L, // 199 - 0x61FA_4855_3BDE_B07EL, 0x2FB6_FF11_0441_A2A8L, // 200 - 0x4E61_D377_6318_8D31L, 0x72F8_CC0D_9D01_4EEDL, // 201 - 0x7D69_5258_9E8D_AEB6L, 0x1E5A_E015_C802_17E1L, // 202 - 0x6454_41E0_7ED7_BEF8L, 0x1848_B344_A001_ACB4L, // 203 - 0x5043_67E6_CBDF_CBF9L, 0x603A_2903_B334_8A2AL, // 204 - 0x4035_ECB8_A319_6FFBL, 0x002E_8736_28F6_D4EEL, // 205 - 0x66BC_ADF4_3828_B32BL, 0x19E4_0B89_DB24_87E3L, // 206 - 0x5230_8B29_C686_F5BCL, 0x14B6_6FA1_7C1D_3983L, // 207 - 0x41C0_6F54_9ED2_5E30L, 0x1091_F2E7_967D_C79CL, // 208 - 0x6933_E554_3150_96B3L, 0x341C_B7D8_F0C9_3F5FL, // 209 - 0x5429_8443_5AA6_DEF5L, 0x767D_5FE0_C0A0_FF80L, // 210 - 0x4354_69CF_7BB8_B25EL, 0x2B97_7FE7_0080_CC66L, // 211 - 0x6BBA_42E5_92C1_1D63L, 0x5F58_CCA4_CD9A_E0A3L, // 212 - 0x562E_9BEA_DBCD_B11CL, 0x4C47_0A1D_7148_B3B6L, // 213 - 0x44F2_1655_7CA4_8DB0L, 0x3D05_A1B1_276D_5C92L, // 214 - 0x6E50_23BB_FAA0_E2B3L, 0x7B3C_35E8_3F15_60E9L, // 215 - 0x5840_1C96_621A_4EF6L, 0x2F63_5E53_65AA_B3EDL, // 216 - 0x4699_B078_4E7B_725EL, 0x591C_4B75_EAEE_F658L, // 217 - 0x70F5_E726_E3F8_B6FDL, 0x74FA_1256_44B1_8A26L, // 218 - 0x5A5E_5285_832D_5F31L, 0x43FB_41DE_9D5A_D4EBL, // 219 - 0x484B_7537_9C24_4C27L, 0x4FFC_34B2_177B_DD89L, // 220 - 0x73AB_EEBF_603A_1372L, 0x4CC6_BAB6_8BF9_6274L, // 221 - 0x5C89_8BCC_4CFB_42C2L, 0x0A38_955E_D661_1B90L, // 222 - 0x4A07_A309_D72F_689BL, 0x21C6_DDE5_784D_AFA7L, // 223 - 0x7672_9E76_2518_A75EL, 0x693E_2FD5_8D49_190BL, // 224 - 0x5EC2_185E_8413_B918L, 0x5431_BFDE_0AA0_E0D5L, // 225 - 0x4BCE_79E5_3676_2DADL, 0x29C1_664B_3BB3_E711L, // 226 - 0x794A_5CA1_F0BD_15E2L, 0x0F9B_D6DE_C5EC_A4E8L, // 227 - 0x6108_4A1B_26FD_AB1BL, 0x2616_457F_04BD_50BAL, // 228 - 0x4DA0_3B48_EBFE_227CL, 0x1E78_3798_D097_73C8L, // 229 - 0x7C33_920E_4663_6A60L, 0x30C0_58F4_80F2_52D9L, // 230 - 0x635C_74D8_384F_884DL, 0x0D66_AD90_6728_4247L, // 231 - 0x4F7D_2A46_9372_D370L, 0x711E_F140_5286_9B6CL, // 232 - 0x7F2E_AA0A_8584_8581L, 0x34FE_4ECD_50D7_5F14L, // 233 - 0x65BE_EE6E_D136_D134L, 0x2A65_0BD7_73DF_7F43L, // 234 - 0x5165_8B8B_DA92_40F6L, 0x551D_A312_C319_329CL, // 235 - 0x411E_093C_AEDB_672BL, 0x5DB1_4F42_35AD_C217L, // 236 - 0x6830_0EC7_7E2B_D845L, 0x7C4E_E536_BC49_368AL, // 237 - 0x5359_A56C_64EF_E037L, 0x7D0B_EA92_303A_9208L, // 238 - 0x42AE_1DF0_50BF_E693L, 0x173C_BBA8_2695_41A0L, // 239 - 0x6AB0_2FE6_E799_70EBL, 0x3EC7_92A6_A422_029AL, // 240 - 0x5559_BFEB_EC7A_C0BCL, 0x3239_421E_E9B4_CEE1L, // 241 - 0x4447_CCBC_BD2F_0096L, 0x5B61_01B2_5490_A581L, // 242 - 0x6D3F_ADFA_C84B_3424L, 0x2BCE_691D_541A_A268L, // 243 - 0x5766_24C8_A03C_29B6L, 0x563E_BA7D_DCE2_1B87L, // 244 - 0x45EB_50A0_8030_215EL, 0x7832_2ECB_171B_4939L, // 245 - 0x6FDE_E767_3380_3564L, 0x59E9_E478_24F8_7527L, // 246 - 0x597F_1F85_C2CC_F783L, 0x6187_E9F9_B72D_2A86L, // 247 - 0x4798_E604_9BD7_2C69L, 0x346C_BB2E_2C24_2205L, // 248 - 0x728E_3CD4_2C8B_7A42L, 0x20AD_F849_E039_D007L, // 249 - 0x5BA4_FD76_8A09_2E9BL, 0x33BE_603B_19C7_D99FL, // 250 - 0x4950_CAC5_3B3A_8BAFL, 0x42FE_B362_7B06_47B3L, // 251 - 0x754E_113B_91F7_45E5L, 0x5197_856A_5E70_72B8L, // 252 - 0x5DD8_0DC9_4192_9E51L, 0x27AC_6ABB_7EC0_5BC6L, // 253 - 0x4B13_3E3A_9ADB_B1DAL, 0x52F0_5562_CBCD_1638L, // 254 - 0x781E_C9F7_5E2C_4FC4L, 0x1E4D_556A_DFAE_89F3L, // 255 - 0x6018_A192_B1BD_0C9CL, 0x7EA4_4455_7FBE_D4C3L, // 256 - 0x4CE0_8142_27CA_707DL, 0x4BB6_9D11_32FF_109CL, // 257 - 0x7B00_CED0_3FAA_4D95L, 0x5F8A_94E8_5198_1A93L, // 258 - 0x6267_0BD9_CC88_3E11L, 0x32D5_43ED_0E13_4875L, // 259 - 0x4EB8_D647_D6D3_64DAL, 0x5BDD_CFF0_D80F_6D2BL, // 260 - 0x7DF4_8A0C_8AEB_D491L, 0x12FC_7FE7_C018_AEABL, // 261 - 0x64C3_A1A3_A256_43A7L, 0x28C9_FFEC_99AD_5889L, // 262 - 0x509C_814F_B511_CFB9L, 0x0707_FFF0_7AF1_13A1L, // 263 - 0x407D_343F_C40E_3FC7L, 0x1F39_998D_2F27_42E7L, // 264 - 0x672E_B9FF_A016_CC71L, 0x7EC2_8F48_4B72_04A4L, // 265 - 0x528B_C7FF_B345_705BL, 0x189B_A5D3_6F8E_6A1DL, // 266 - 0x4209_6CCC_8F6A_C048L, 0x7A16_1E42_BFA5_21B1L, // 267 - 0x69A8_AE14_18AA_CD41L, 0x4356_96D1_32A1_CF81L, // 268 - 0x5486_F1A9_AD55_7101L, 0x1C45_4574_2881_72CEL, // 269 - 0x439F_27BA_F111_2734L, 0x169D_D129_BA01_28A5L, // 270 - 0x6C31_D92B_1B4E_A520L, 0x242F_B50F_9001_DAA1L, // 271 - 0x568E_4755_AF72_1DB3L, 0x368C_90D9_4001_7BB4L, // 272 - 0x453E_9F77_BF8E_7E29L, 0x120A_0D7A_999A_C95DL, // 273 - 0x6ECA_98BF_98E3_FD0EL, 0x5010_1590_F5C4_7561L, // 274 - 0x58A2_13CC_7A4F_FDA5L, 0x2673_4473_F7D0_5DE8L, // 275 - 0x46E8_0FD6_C83F_FE1DL, 0x6B8F_69F6_5FD9_E4B9L, // 276 - 0x7173_4C8A_D9FF_FCFCL, 0x45B2_4323_CC8F_D45CL, // 277 - 0x5AC2_A3A2_47FF_FD96L, 0x6AF5_0283_0A0C_A9E3L, // 278 - 0x489B_B61B_6CCC_CADFL, 0x08C4_0202_6E70_87E9L, // 279 - 0x742C_5692_47AE_1164L, 0x746C_D003_E3E7_3FDBL, // 280 - 0x5CF0_4541_D2F1_A783L, 0x76BD_7336_4FEC_3315L, // 281 - 0x4A59_D101_758E_1F9CL, 0x5EFD_F5C5_0CBC_F5ABL, // 282 - 0x76F6_1B35_88E3_65C7L, 0x4B2F_EFA1_ADFB_22ABL, // 283 - 0x5F2B_48F7_A0B5_EB06L, 0x08F3_261A_F195_B555L, // 284 - 0x4C22_A0C6_1A2B_226BL, 0x20C2_84E2_5ADE_2AABL, // 285 - 0x79D1_013C_F6AB_6A45L, 0x1AD0_D49D_5E30_4444L, // 286 - 0x6174_00FD_9222_BB6AL, 0x48A7_107D_E4F3_69D0L, // 287 - 0x4DF6_6731_41B5_62BBL, 0x53B8_D9FE_50C2_BB0DL, // 288 - 0x7CBD_71E8_6922_3792L, 0x52C1_5CCA_1AD1_2B48L, // 289 - 0x63CA_C186_BA81_C60EL, 0x7567_7D6E_7BDA_8906L, // 290 - 0x4FD5_679E_FB9B_04D8L, 0x5DEC_6458_6315_3A6CL, // 291 - 0x7FBB_D8FE_5F5E_6E27L, 0x497A_3A27_04EE_C3DFL, // 292 + // g1, g0, e + 0x777A_29EB_491D_EB2DL, 0x044F_EA8A_41A8_4ED0L, // -342 + 0x4AAC_5A33_0DB2_B2FCL, 0x12B1_F296_6909_3142L, // -341 + 0x5D57_70BF_D11F_5FBBL, 0x175E_6F3C_034B_7D93L, // -340 + 0x74AD_4CEF_C567_37A9L, 0x7D36_0B0B_041E_5CF8L, // -339 + 0x48EC_5015_DB60_82CAL, 0x1E41_C6E6_E292_FA1BL, // -338 + 0x5B27_641B_5238_A37CL, 0x65D2_38A0_9B37_B8A2L, // -337 + 0x71F1_3D22_26C6_CC5BL, 0x7F46_C6C8_C205_A6CAL, // -336 + 0x4736_C635_583C_3FB9L, 0x3F8C_3C3D_7943_883EL, // -335 + 0x5904_77C2_AE4B_4FA7L, 0x6F6F_4B4C_D794_6A4EL, // -334 + 0x6F45_95B3_59DE_2391L, 0x6B4B_1E20_0D79_84E1L, // -333 + 0x458B_7D90_182A_D63BL, 0x130E_F2D4_086B_F30DL, // -332 + 0x56EE_5CF4_1E35_8BC9L, 0x77D2_AF89_0A86_EFD0L, // -331 + 0x6CA9_F431_25C2_EEBCL, 0x35C7_5B6B_4D28_ABC4L, // -330 + 0x43EA_389E_B799_D535L, 0x619C_9923_1039_6B5BL, // -329 + 0x54E4_C6C6_6580_4A83L, 0x1A03_BF6B_D447_C631L, // -328 + 0x6A1D_F877_FEE0_5D24L, 0x0084_AF46_C959_B7BDL, // -327 + 0x4252_BB4A_FF4C_3A36L, 0x4052_ED8C_3DD8_12D6L, // -326 + 0x52E7_6A1D_BF1F_48C4L, 0x1067_A8EF_4D4E_178CL, // -325 + 0x67A1_44A5_2EE7_1AF5L, 0x1481_932B_20A1_9D6FL, // -324 + 0x40C4_CAE7_3D50_70D9L, 0x1CD0_FBFA_F465_0265L, // -323 + 0x50F5_FDA1_0CA4_8D0FL, 0x4405_3AF9_B17E_42FFL, // -322 + 0x6533_7D09_4FCD_B053L, 0x3506_89B8_1DDD_D3BEL, // -321 + 0x7E80_5C4B_A3C1_1C68L, 0x2248_2C26_2555_48AEL, // -320 + 0x4F10_39AF_4658_B1C1L, 0x156D_1B97_D755_4D6DL, // -319 + 0x62D4_481B_17EE_DE31L, 0x3AC8_627D_CD2A_A0C8L, // -318 + 0x7B89_5A21_DDEA_95BDL, 0x697A_7B1D_4075_48FAL, // -317 + 0x4D35_D855_2AB2_9D96L, 0x51EC_8CF2_4849_4D9CL, // -316 + 0x6083_4E6A_755F_44FCL, 0x2667_B02E_DA5B_A103L, // -315 + 0x78A4_2205_12B7_163BL, 0x3001_9C3A_90F2_8944L, // -314 + 0x4B66_9543_2BB2_6DE5L, 0x0E01_01A4_9A97_95CBL, // -313 + 0x5E40_3A93_F69F_095EL, 0x3181_420D_C13D_7B3DL, // -312 + 0x75D0_4938_F446_CBB5L, 0x7DE1_9291_318C_DA0CL, // -311 + 0x49A2_2DC3_98AC_3F51L, 0x5EAC_FB9A_BEF8_0848L, // -310 + 0x5C0A_B934_7ED7_4F26L, 0x1658_3A81_6EB6_0A5AL, // -309 + 0x730D_6781_9E8D_22EFL, 0x5BEE_4921_CA63_8CF0L, // -308 + 0x47E8_60B1_0318_35D5L, 0x6974_EDB5_1E7E_3816L, // -307 + 0x59E2_78DD_43DE_434BL, 0x23D2_2922_661D_C61CL, // -306 + 0x705B_1714_94D5_D41EL, 0x0CC6_B36A_FFA5_37A2L, // -305 + 0x4638_EE6C_DD05_A492L, 0x67FC_3022_DFC7_42C6L, // -304 + 0x57C7_2A08_1447_0DB7L, 0x41FB_3C2B_97B9_1377L, // -303 + 0x6DB8_F48A_1958_D125L, 0x327A_0B36_7DA7_5855L, // -302 + 0x4493_98D6_4FD7_82B7L, 0x2F8C_4702_0E88_9735L, // -301 + 0x55B8_7F0B_E3CD_6365L, 0x1B6F_58C2_922A_BD02L, // -300 + 0x6B26_9ECE_DCC0_BC3EL, 0x424B_2EF3_36B5_6C43L, // -299 + 0x42F8_2341_49F8_75A7L, 0x096E_FD58_0231_63AAL, // -298 + 0x53B6_2C11_9C76_9310L, 0x6BCA_BCAE_02BD_BC94L, // -297 + 0x68A3_B716_0394_37D5L, 0x06BD_6BD9_836D_2BB9L, // -296 + 0x4166_526D_C23C_A2E5L, 0x1436_6367_F224_3B54L, // -295 + 0x51BF_E709_32CB_CB9EL, 0x3943_FC41_EEAD_4A29L, // -294 + 0x662F_E0CB_7F7E_BE86L, 0x0794_FB52_6A58_9CB3L, // -293 + 0x7FBB_D8FE_5F5E_6E27L, 0x497A_3A27_04EE_C3DFL, // -292 + 0x4FD5_679E_FB9B_04D8L, 0x5DEC_6458_6315_3A6CL, // -291 + 0x63CA_C186_BA81_C60EL, 0x7567_7D6E_7BDA_8906L, // -290 + 0x7CBD_71E8_6922_3792L, 0x52C1_5CCA_1AD1_2B48L, // -289 + 0x4DF6_6731_41B5_62BBL, 0x53B8_D9FE_50C2_BB0DL, // -288 + 0x6174_00FD_9222_BB6AL, 0x48A7_107D_E4F3_69D0L, // -287 + 0x79D1_013C_F6AB_6A45L, 0x1AD0_D49D_5E30_4444L, // -286 + 0x4C22_A0C6_1A2B_226BL, 0x20C2_84E2_5ADE_2AABL, // -285 + 0x5F2B_48F7_A0B5_EB06L, 0x08F3_261A_F195_B555L, // -284 + 0x76F6_1B35_88E3_65C7L, 0x4B2F_EFA1_ADFB_22ABL, // -283 + 0x4A59_D101_758E_1F9CL, 0x5EFD_F5C5_0CBC_F5ABL, // -282 + 0x5CF0_4541_D2F1_A783L, 0x76BD_7336_4FEC_3315L, // -281 + 0x742C_5692_47AE_1164L, 0x746C_D003_E3E7_3FDBL, // -280 + 0x489B_B61B_6CCC_CADFL, 0x08C4_0202_6E70_87E9L, // -279 + 0x5AC2_A3A2_47FF_FD96L, 0x6AF5_0283_0A0C_A9E3L, // -278 + 0x7173_4C8A_D9FF_FCFCL, 0x45B2_4323_CC8F_D45CL, // -277 + 0x46E8_0FD6_C83F_FE1DL, 0x6B8F_69F6_5FD9_E4B9L, // -276 + 0x58A2_13CC_7A4F_FDA5L, 0x2673_4473_F7D0_5DE8L, // -275 + 0x6ECA_98BF_98E3_FD0EL, 0x5010_1590_F5C4_7561L, // -274 + 0x453E_9F77_BF8E_7E29L, 0x120A_0D7A_999A_C95DL, // -273 + 0x568E_4755_AF72_1DB3L, 0x368C_90D9_4001_7BB4L, // -272 + 0x6C31_D92B_1B4E_A520L, 0x242F_B50F_9001_DAA1L, // -271 + 0x439F_27BA_F111_2734L, 0x169D_D129_BA01_28A5L, // -270 + 0x5486_F1A9_AD55_7101L, 0x1C45_4574_2881_72CEL, // -269 + 0x69A8_AE14_18AA_CD41L, 0x4356_96D1_32A1_CF81L, // -268 + 0x4209_6CCC_8F6A_C048L, 0x7A16_1E42_BFA5_21B1L, // -267 + 0x528B_C7FF_B345_705BL, 0x189B_A5D3_6F8E_6A1DL, // -266 + 0x672E_B9FF_A016_CC71L, 0x7EC2_8F48_4B72_04A4L, // -265 + 0x407D_343F_C40E_3FC7L, 0x1F39_998D_2F27_42E7L, // -264 + 0x509C_814F_B511_CFB9L, 0x0707_FFF0_7AF1_13A1L, // -263 + 0x64C3_A1A3_A256_43A7L, 0x28C9_FFEC_99AD_5889L, // -262 + 0x7DF4_8A0C_8AEB_D491L, 0x12FC_7FE7_C018_AEABL, // -261 + 0x4EB8_D647_D6D3_64DAL, 0x5BDD_CFF0_D80F_6D2BL, // -260 + 0x6267_0BD9_CC88_3E11L, 0x32D5_43ED_0E13_4875L, // -259 + 0x7B00_CED0_3FAA_4D95L, 0x5F8A_94E8_5198_1A93L, // -258 + 0x4CE0_8142_27CA_707DL, 0x4BB6_9D11_32FF_109CL, // -257 + 0x6018_A192_B1BD_0C9CL, 0x7EA4_4455_7FBE_D4C3L, // -256 + 0x781E_C9F7_5E2C_4FC4L, 0x1E4D_556A_DFAE_89F3L, // -255 + 0x4B13_3E3A_9ADB_B1DAL, 0x52F0_5562_CBCD_1638L, // -254 + 0x5DD8_0DC9_4192_9E51L, 0x27AC_6ABB_7EC0_5BC6L, // -253 + 0x754E_113B_91F7_45E5L, 0x5197_856A_5E70_72B8L, // -252 + 0x4950_CAC5_3B3A_8BAFL, 0x42FE_B362_7B06_47B3L, // -251 + 0x5BA4_FD76_8A09_2E9BL, 0x33BE_603B_19C7_D99FL, // -250 + 0x728E_3CD4_2C8B_7A42L, 0x20AD_F849_E039_D007L, // -249 + 0x4798_E604_9BD7_2C69L, 0x346C_BB2E_2C24_2205L, // -248 + 0x597F_1F85_C2CC_F783L, 0x6187_E9F9_B72D_2A86L, // -247 + 0x6FDE_E767_3380_3564L, 0x59E9_E478_24F8_7527L, // -246 + 0x45EB_50A0_8030_215EL, 0x7832_2ECB_171B_4939L, // -245 + 0x5766_24C8_A03C_29B6L, 0x563E_BA7D_DCE2_1B87L, // -244 + 0x6D3F_ADFA_C84B_3424L, 0x2BCE_691D_541A_A268L, // -243 + 0x4447_CCBC_BD2F_0096L, 0x5B61_01B2_5490_A581L, // -242 + 0x5559_BFEB_EC7A_C0BCL, 0x3239_421E_E9B4_CEE1L, // -241 + 0x6AB0_2FE6_E799_70EBL, 0x3EC7_92A6_A422_029AL, // -240 + 0x42AE_1DF0_50BF_E693L, 0x173C_BBA8_2695_41A0L, // -239 + 0x5359_A56C_64EF_E037L, 0x7D0B_EA92_303A_9208L, // -238 + 0x6830_0EC7_7E2B_D845L, 0x7C4E_E536_BC49_368AL, // -237 + 0x411E_093C_AEDB_672BL, 0x5DB1_4F42_35AD_C217L, // -236 + 0x5165_8B8B_DA92_40F6L, 0x551D_A312_C319_329CL, // -235 + 0x65BE_EE6E_D136_D134L, 0x2A65_0BD7_73DF_7F43L, // -234 + 0x7F2E_AA0A_8584_8581L, 0x34FE_4ECD_50D7_5F14L, // -233 + 0x4F7D_2A46_9372_D370L, 0x711E_F140_5286_9B6CL, // -232 + 0x635C_74D8_384F_884DL, 0x0D66_AD90_6728_4247L, // -231 + 0x7C33_920E_4663_6A60L, 0x30C0_58F4_80F2_52D9L, // -230 + 0x4DA0_3B48_EBFE_227CL, 0x1E78_3798_D097_73C8L, // -229 + 0x6108_4A1B_26FD_AB1BL, 0x2616_457F_04BD_50BAL, // -228 + 0x794A_5CA1_F0BD_15E2L, 0x0F9B_D6DE_C5EC_A4E8L, // -227 + 0x4BCE_79E5_3676_2DADL, 0x29C1_664B_3BB3_E711L, // -226 + 0x5EC2_185E_8413_B918L, 0x5431_BFDE_0AA0_E0D5L, // -225 + 0x7672_9E76_2518_A75EL, 0x693E_2FD5_8D49_190BL, // -224 + 0x4A07_A309_D72F_689BL, 0x21C6_DDE5_784D_AFA7L, // -223 + 0x5C89_8BCC_4CFB_42C2L, 0x0A38_955E_D661_1B90L, // -222 + 0x73AB_EEBF_603A_1372L, 0x4CC6_BAB6_8BF9_6274L, // -221 + 0x484B_7537_9C24_4C27L, 0x4FFC_34B2_177B_DD89L, // -220 + 0x5A5E_5285_832D_5F31L, 0x43FB_41DE_9D5A_D4EBL, // -219 + 0x70F5_E726_E3F8_B6FDL, 0x74FA_1256_44B1_8A26L, // -218 + 0x4699_B078_4E7B_725EL, 0x591C_4B75_EAEE_F658L, // -217 + 0x5840_1C96_621A_4EF6L, 0x2F63_5E53_65AA_B3EDL, // -216 + 0x6E50_23BB_FAA0_E2B3L, 0x7B3C_35E8_3F15_60E9L, // -215 + 0x44F2_1655_7CA4_8DB0L, 0x3D05_A1B1_276D_5C92L, // -214 + 0x562E_9BEA_DBCD_B11CL, 0x4C47_0A1D_7148_B3B6L, // -213 + 0x6BBA_42E5_92C1_1D63L, 0x5F58_CCA4_CD9A_E0A3L, // -212 + 0x4354_69CF_7BB8_B25EL, 0x2B97_7FE7_0080_CC66L, // -211 + 0x5429_8443_5AA6_DEF5L, 0x767D_5FE0_C0A0_FF80L, // -210 + 0x6933_E554_3150_96B3L, 0x341C_B7D8_F0C9_3F5FL, // -209 + 0x41C0_6F54_9ED2_5E30L, 0x1091_F2E7_967D_C79CL, // -208 + 0x5230_8B29_C686_F5BCL, 0x14B6_6FA1_7C1D_3983L, // -207 + 0x66BC_ADF4_3828_B32BL, 0x19E4_0B89_DB24_87E3L, // -206 + 0x4035_ECB8_A319_6FFBL, 0x002E_8736_28F6_D4EEL, // -205 + 0x5043_67E6_CBDF_CBF9L, 0x603A_2903_B334_8A2AL, // -204 + 0x6454_41E0_7ED7_BEF8L, 0x1848_B344_A001_ACB4L, // -203 + 0x7D69_5258_9E8D_AEB6L, 0x1E5A_E015_C802_17E1L, // -202 + 0x4E61_D377_6318_8D31L, 0x72F8_CC0D_9D01_4EEDL, // -201 + 0x61FA_4855_3BDE_B07EL, 0x2FB6_FF11_0441_A2A8L, // -200 + 0x7A78_DA6A_8AD6_5C9DL, 0x7BA4_BED5_4552_0B52L, // -199 + 0x4C8B_8882_96C5_F9E2L, 0x5D46_F745_4B53_4713L, // -198 + 0x5FAE_6AA3_3C77_785BL, 0x3498_B516_9E28_18D8L, // -197 + 0x779A_054C_0B95_5672L, 0x21BE_E25C_45B2_1F0EL, // -196 + 0x4AC0_434F_873D_5607L, 0x3517_4D79_AB8F_5369L, // -195 + 0x5D70_5423_690C_AB89L, 0x225D_20D8_1673_2843L, // -194 + 0x74CC_692C_434F_D66BL, 0x4AF4_690E_1C0F_F253L, // -193 + 0x48FF_C1BB_AA11_E603L, 0x1ED8_C1A8_D189_F774L, // -192 + 0x5B3F_B22A_9496_5F84L, 0x068E_F213_05EC_7551L, // -191 + 0x720F_9EB5_39BB_F765L, 0x0832_AE97_C767_92A5L, // -190 + 0x4749_C331_4415_7A9FL, 0x151F_AD1E_DCA0_BBA8L, // -189 + 0x591C_33FD_951A_D946L, 0x7A67_9866_93C8_EA91L, // -188 + 0x6F63_40FC_FA61_8F98L, 0x5901_7E80_38BB_2536L, // -187 + 0x459E_089E_1C7C_F9BFL, 0x37A0_EF10_2374_F742L, // -186 + 0x5705_8AC5_A39C_382FL, 0x2589_2AD4_2C52_3512L, // -185 + 0x6CC6_ED77_0C83_463BL, 0x0EEB_7589_3766_C256L, // -184 + 0x43FC_546A_67D2_0BE4L, 0x7953_2975_C2A0_3976L, // -183 + 0x54FB_6985_01C6_8EDEL, 0x17A7_F3D3_3348_47D4L, // -182 + 0x6A3A_43E6_4238_3295L, 0x5D91_F0C8_001A_59C8L, // -181 + 0x4264_6A6F_E963_1F9DL, 0x4A7B_367D_0010_781DL, // -180 + 0x52FD_850B_E3BB_E784L, 0x7D1A_041C_4014_9625L, // -179 + 0x67BC_E64E_DCAA_E166L, 0x1C60_8523_5019_BBAEL, // -178 + 0x40D6_0FF1_49EA_CCDFL, 0x71BC_5336_1210_154DL, // -177 + 0x510B_93ED_9C65_8017L, 0x6E2B_6803_9694_1AA0L, // -176 + 0x654E_78E9_037E_E01DL, 0x69B6_4204_7C39_2148L, // -175 + 0x7EA2_1723_445E_9825L, 0x2423_D285_9B47_6999L, // -174 + 0x4F25_4E76_0ABB_1F17L, 0x2696_6393_810C_A200L, // -173 + 0x62EE_A213_8D69_E6DDL, 0x103B_FC78_614F_CA80L, // -172 + 0x7BAA_4A98_70C4_6094L, 0x344A_FB96_79A3_BD20L, // -171 + 0x4D4A_6E9F_467A_BC5CL, 0x60AE_DD3E_0C06_5634L, // -170 + 0x609D_0A47_1819_6B73L, 0x78DA_948D_8F07_EBC1L, // -169 + 0x78C4_4CD8_DE1F_C650L, 0x7711_39B0_F2C9_E6B1L, // -168 + 0x4B7A_B007_8AD3_DBF2L, 0x4A6A_C40E_97BE_302FL, // -167 + 0x5E59_5C09_6D88_D2EFL, 0x1D05_7512_3DAD_BC3AL, // -166 + 0x75EF_B30B_C8EB_07ABL, 0x0446_D256_CD19_2B49L, // -165 + 0x49B5_CFE7_5D92_E4CAL, 0x72AC_4376_402F_BB0EL, // -164 + 0x5C23_43E1_34F7_9DFDL, 0x4F57_5453_D03B_A9D1L, // -163 + 0x732C_14D9_8235_857DL, 0x032D_2968_C44A_9445L, // -162 + 0x47FB_8D07_F161_736EL, 0x11FC_39E1_7AAE_9CABL, // -161 + 0x59FA_7049_EDB9_D049L, 0x567B_4859_D95A_43D6L, // -160 + 0x7079_0C5C_6928_445CL, 0x0C1A_1A70_4FB0_D4CCL, // -159 + 0x464B_A7B9_C1B9_2AB9L, 0x4790_5086_31CE_84FFL, // -158 + 0x57DE_91A8_3227_7567L, 0x7974_64A7_BE42_263FL, // -157 + 0x6DD6_3612_3EB1_52C1L, 0x77D1_7DD1_ADD2_AFCFL, // -156 + 0x44A5_E1CB_672E_D3B9L, 0x1AE2_EEA3_0CA3_ADE1L, // -155 + 0x55CF_5A3E_40FA_88A7L, 0x419B_AA4B_CFCC_995AL, // -154 + 0x6B43_30CD_D139_2AD1L, 0x3202_94DE_C3BF_BFB0L, // -153 + 0x4309_FE80_A2C3_BAC2L, 0x6F41_9D0B_3A57_D7CEL, // -152 + 0x53CC_7E20_CB74_A973L, 0x4B12_044E_08ED_CDC2L, // -151 + 0x68BF_9DA8_FE51_D3D0L, 0x3DD6_8561_8B29_4132L, // -150 + 0x4177_C289_9EF3_2462L, 0x26A6_135C_F6F9_C8BFL, // -149 + 0x51D5_B32C_06AF_ED7AL, 0x704F_9834_34B8_3AEFL, // -148 + 0x664B_1FF7_085B_E8D9L, 0x4C63_7E41_41E6_49ABL, // -147 + 0x7FDD_E7F4_CA72_E30FL, 0x7F7C_5DD1_925F_DC15L, // -146 + 0x4FEA_B0F8_FE87_CDE9L, 0x7FAD_BAA2_FB7B_E98DL, // -145 + 0x63E5_5D37_3E29_C164L, 0x3F99_294B_BA5A_E3F1L, // -144 + 0x7CDE_B485_0DB4_31BDL, 0x4F7F_739E_A8F1_9CEDL, // -143 + 0x4E0B_30D3_2890_9F16L, 0x41AF_A843_2997_0214L, // -142 + 0x618D_FD07_F2B4_C6DCL, 0x121B_9253_F3FC_C299L, // -141 + 0x79F1_7C49_EF61_F893L, 0x16A2_76E8_F0FB_F33FL, // -140 + 0x4C36_EDAE_359D_3B5BL, 0x7E25_8A51_969D_7808L, // -139 + 0x5F44_A919_C304_8A32L, 0x7DAE_ECE5_FC44_D609L, // -138 + 0x7715_D360_33C5_ACBFL, 0x5D1A_A81F_7B56_0B8CL, // -137 + 0x4A6D_A41C_205B_8BF7L, 0x6A30_A913_AD15_C738L, // -136 + 0x5D09_0D23_2872_6EF5L, 0x64BC_D358_985B_3905L, // -135 + 0x744B_506B_F28F_0AB3L, 0x1DEC_082E_BE72_0746L, // -134 + 0x48AF_1243_7799_66B0L, 0x02B3_851D_3707_448CL, // -133 + 0x5ADA_D6D4_557F_C05CL, 0x0360_6664_84C9_15AFL, // -132 + 0x7191_8C89_6ADF_B073L, 0x0438_7FFD_A5FB_5B1BL, // -131 + 0x46FA_F7D5_E2CB_CE47L, 0x72A3_4FFE_87BD_18F1L, // -130 + 0x58B9_B5CB_5B7E_C1D9L, 0x6F4C_23FE_29AC_5F2DL, // -129 + 0x6EE8_233E_325E_7250L, 0x2B1F_2CFD_B417_76F8L, // -128 + 0x4551_1606_DF7B_0772L, 0x1AF3_7C1E_908E_AA5BL, // -127 + 0x56A5_5B88_9759_C94EL, 0x61B0_5B26_34B2_54F2L, // -126 + 0x6C4E_B26A_BD30_3BA2L, 0x3A1C_71EF_C1DE_EA2EL, // -125 + 0x43B1_2F82_B63E_2545L, 0x4451_C735_D92B_525DL, // -124 + 0x549D_7B63_63CD_AE96L, 0x7566_3903_4F76_26F4L, // -123 + 0x69C4_DA3C_3CC1_1A3CL, 0x52BF_C744_2353_B0B1L, // -122 + 0x421B_0865_A5F8_B065L, 0x73B7_DC8A_9614_4E6FL, // -121 + 0x52A1_CA7F_0F76_DC7FL, 0x30A5_D3AD_3B99_620BL, // -120 + 0x674A_3D1E_D354_939FL, 0x1CCF_4898_8A7F_BA8DL, // -119 + 0x408E_6633_4414_DC43L, 0x4201_8D5F_568F_D498L, // -118 + 0x50B1_FFC0_151A_1354L, 0x3281_F0B7_2C33_C9BEL, // -117 + 0x64DE_7FB0_1A60_9829L, 0x3F22_6CE4_F740_BC2EL, // -116 + 0x7E16_1F9C_20F8_BE33L, 0x6EEB_081E_3510_EB39L, // -115 + 0x4ECD_D3C1_949B_76E0L, 0x3552_E512_E12A_9304L, // -114 + 0x6281_48B1_F9C2_5498L, 0x42A7_9E57_9975_37C5L, // -113 + 0x7B21_9ADE_7832_E9BEL, 0x5351_85ED_7FD2_85B6L, // -112 + 0x4CF5_00CB_0B1F_D217L, 0x1412_F3B4_6FE3_9392L, // -111 + 0x6032_40FD_CDE7_C69CL, 0x7917_B0A1_8BDC_7876L, // -110 + 0x783E_D13D_4161_B844L, 0x175D_9CC9_EED3_9694L, // -109 + 0x4B27_42C6_48DD_132AL, 0x4E9A_81FE_3544_3E1CL, // -108 + 0x5DF1_1377_DB14_57F5L, 0x2241_227D_C295_4DA3L, // -107 + 0x756D_5855_D1D9_6DF2L, 0x4AD1_6B1D_333A_A10CL, // -106 + 0x4964_5735_A327_E4B7L, 0x4EC2_E2F2_4004_A4A8L, // -105 + 0x5BBD_6D03_0BF1_DDE5L, 0x4273_9BAE_D005_CDD2L, // -104 + 0x72AC_C843_CEEE_555EL, 0x7310_829A_8407_4146L, // -103 + 0x47AB_FD2A_6154_F55BL, 0x27EA_51A0_9284_88CCL, // -102 + 0x5996_FC74_F9AA_32B2L, 0x11E4_E608_B725_AAFFL, // -101 + 0x6FFC_BB92_3814_BF5EL, 0x565E_1F8A_E4EF_15BEL, // -100 + 0x45FD_F53B_630C_F79BL, 0x15FA_D3B6_CF15_6D97L, // -99 + 0x577D_728A_3BD0_3581L, 0x7B79_88A4_82DA_C8FDL, // -98 + 0x6D5C_CF2C_CAC4_42E2L, 0x3A57_EACD_A391_7B3CL, // -97 + 0x445A_017B_FEBA_A9CDL, 0x4476_F2C0_863A_ED06L, // -96 + 0x5570_81DA_FE69_5440L, 0x7594_AF70_A7C9_A847L, // -95 + 0x6ACC_A251_BE03_A951L, 0x12F9_DB4C_D1BC_1258L, // -94 + 0x42BF_E573_16C2_49D2L, 0x5BDC_2910_0315_8B77L, // -93 + 0x536F_DECF_DC72_DC47L, 0x32D3_3354_03DA_EE55L, // -92 + 0x684B_D683_D38F_9359L, 0x1F88_0029_04D1_A9EAL, // -91 + 0x412F_6612_6439_BC17L, 0x63B5_0019_A303_0A33L, // -90 + 0x517B_3F96_FD48_2B1DL, 0x5CA2_4020_0BC3_CCBFL, // -89 + 0x65DA_0F7C_BC9A_35E5L, 0x13CA_D028_0EB4_BFEFL, // -88 + 0x7F50_935B_EBC0_C35EL, 0x38BD_8432_1261_EFEBL, // -87 + 0x4F92_5C19_7358_7A1BL, 0x0376_729F_4B7D_35F3L, // -86 + 0x6376_F31F_D02E_98A1L, 0x6454_0F47_1E5C_836FL, // -85 + 0x7C54_AFE7_C43A_3ECAL, 0x1D69_1318_E5F3_A44BL, // -84 + 0x4DB4_EDF0_DAA4_673EL, 0x3261_ABEF_8FB8_46AFL, // -83 + 0x6122_296D_114D_810DL, 0x7EFA_16EB_73A6_585BL, // -82 + 0x796A_B3C8_55A0_E151L, 0x3EB8_9CA6_508F_EE71L, // -81 + 0x4BE2_B05D_3584_8CD2L, 0x7733_61E7_F259_F507L, // -80 + 0x5EDB_5C74_82E5_B007L, 0x5500_3A61_EEF0_7249L, // -79 + 0x7692_3391_A39F_1C09L, 0x4A40_48FA_6AAC_8EDBL, // -78 + 0x4A1B_603B_0643_7185L, 0x7E68_2D9C_82AB_D949L, // -77 + 0x5CA2_3849_C7D4_4DE7L, 0x3E02_3903_A356_CF9BL, // -76 + 0x73CA_C65C_39C9_6161L, 0x2D82_C744_8C2C_8382L, // -75 + 0x485E_BBF9_A41D_DCDCL, 0x6C71_BC8A_D79B_D231L, // -74 + 0x5A76_6AF8_0D25_5414L, 0x078E_2BAD_8D82_C6BDL, // -73 + 0x7114_05B6_106E_A919L, 0x0971_B698_F0E3_786DL, // -72 + 0x46AC_8391_CA45_29AFL, 0x55E7_121F_968E_2B44L, // -71 + 0x5857_A476_3CD6_741BL, 0x4B60_D6A7_7C31_B615L, // -70 + 0x6E6D_8D93_CC0C_1122L, 0x3E39_0C51_5B3E_239AL, // -69 + 0x4504_787C_5F87_8AB5L, 0x46E3_A7B2_D906_D640L, // -68 + 0x5645_969B_7769_6D62L, 0x789C_919F_8F48_8BD0L, // -67 + 0x6BD6_FC42_5543_C8BBL, 0x56C3_B607_731A_AEC4L, // -66 + 0x4366_5DA9_754A_5D75L, 0x263A_51C4_A7F0_AD3BL, // -65 + 0x543F_F513_D29C_F4D2L, 0x4FC8_E635_D1EC_D88AL, // -64 + 0x694F_F258_C744_3207L, 0x23BB_1FC3_4668_0EACL, // -63 + 0x41D1_F777_7C8A_9F44L, 0x4654_F3DA_0C01_092CL, // -62 + 0x5246_7555_5BAD_4715L, 0x57EA_30D0_8F01_4B76L, // -61 + 0x66D8_12AA_B298_98DBL, 0x0DE4_BD04_B2C1_9E54L, // -60 + 0x4047_0BAA_AF9F_5F88L, 0x78AE_F622_EFB9_02F5L, // -59 + 0x5058_CE95_5B87_376BL, 0x16DA_B3AB_ABA7_43B2L, // -58 + 0x646F_023A_B269_0545L, 0x7C91_6096_9691_149EL, // -57 + 0x7D8A_C2C9_5F03_4697L, 0x3BB5_B8BC_3C35_59C5L, // -56 + 0x4E76_B9BD_DB62_0C1EL, 0x5551_9375_A5A1_581BL, // -55 + 0x6214_682D_523A_8F26L, 0x2AA5_F853_0F09_AE22L, // -54 + 0x7A99_8238_A6C9_32EFL, 0x754F_7667_D2CC_19ABL, // -53 + 0x4C9F_F163_683D_BFD5L, 0x7951_AA00_E3BF_900BL, // -52 + 0x5FC7_EDBC_424D_2FCBL, 0x37A6_1481_1CAF_740DL, // -51 + 0x77B9_E92B_52E0_7BBEL, 0x258F_99A1_63DB_5111L, // -50 + 0x4AD4_31BB_13CC_4D56L, 0x7779_C004_DE69_12ABL, // -49 + 0x5D89_3E29_D8BF_60ACL, 0x5558_3006_1603_5755L, // -48 + 0x74EB_8DB4_4EEF_38D7L, 0x6AAE_3C07_9B84_2D2AL, // -47 + 0x4913_3890_B155_8386L, 0x72AC_E584_C132_9C3BL, // -46 + 0x5B58_06B4_DDAA_E468L, 0x4F58_1EE5_F17F_4349L, // -45 + 0x722E_0862_1515_9D82L, 0x632E_269F_6DDF_141BL, // -44 + 0x475C_C53D_4D2D_8271L, 0x5DFC_D823_A4AB_6C91L, // -43 + 0x5933_F68C_A078_E30EL, 0x157C_0E2C_8DD6_47B5L, // -42 + 0x6F80_F42F_C897_1BD1L, 0x5ADB_11B7_B14B_D9A3L, // -41 + 0x45B0_989D_DD5E_7163L, 0x08C8_EB12_CECF_6806L, // -40 + 0x571C_BEC5_54B6_0DBBL, 0x6AFB_25D7_8283_4207L, // -39 + 0x6CE3_EE76_A9E3_912AL, 0x65B9_EF4D_6324_1289L, // -38 + 0x440E_750A_2A2E_3ABAL, 0x5F94_3590_5DF6_8B96L, // -37 + 0x5512_124C_B4B9_C969L, 0x3779_42F4_7574_2E7BL, // -36 + 0x6A56_96DF_E1E8_3BC3L, 0x6557_93B1_92D1_3A1AL, // -35 + 0x4276_1E4B_ED31_255AL, 0x2F56_BC4E_FBC2_C450L, // -34 + 0x5313_A5DE_E87D_6EB0L, 0x7B2C_6B62_BAB3_7564L, // -33 + 0x67D8_8F56_A29C_CA5DL, 0x19F7_863B_6960_52BDL, // -32 + 0x40E7_5996_25A1_FE7AL, 0x203A_B3E5_21DC_33B6L, // -31 + 0x5121_2FFB_AF0A_7E18L, 0x6849_60DE_6A53_40A4L, // -30 + 0x6569_7BFA_9ACD_1D9FL, 0x025B_B916_04E8_10CDL, // -29 + 0x7EC3_DAF9_4180_6506L, 0x62F2_A75B_8622_1500L, // -28 + 0x4F3A_68DB_C8F0_3F24L, 0x1DD7_A899_33D5_4D20L, // -27 + 0x6309_0312_BB2C_4EEDL, 0x254D_92BF_80CA_A068L, // -26 + 0x7BCB_43D7_69F7_62A8L, 0x4EA0_F76F_60FD_4882L, // -25 + 0x4D5F_0A66_A23A_9DA9L, 0x3124_9AA5_9C9E_4D51L, // -24 + 0x60B6_CD00_4AC9_4513L, 0x5D6D_C14F_03C5_E0A5L, // -23 + 0x78E4_8040_5D7B_9658L, 0x54C9_31A2_C4B7_58CFL, // -22 + 0x4B8E_D028_3A6D_3DF7L, 0x34FD_BF05_BAF2_9781L, // -21 + 0x5E72_8432_4908_8D75L, 0x223D_2EC7_29AF_3D62L, // -20 + 0x760F_253E_DB4A_B0D2L, 0x4ACC_7A78_F41B_0CBAL, // -19 + 0x49C9_7747_490E_AE83L, 0x4EBF_CC8B_9890_E7F4L, // -18 + 0x5C3B_D519_1B52_5A24L, 0x426F_BFAE_7EB5_21F1L, // -17 + 0x734A_CA5F_6226_F0ADL, 0x530B_AF9A_1E62_6A6DL, // -16 + 0x480E_BE7B_9D58_566CL, 0x43E7_4DC0_52FD_8285L, // -15 + 0x5A12_6E1A_84AE_6C07L, 0x54E1_2130_67BC_E326L, // -14 + 0x7097_09A1_25DA_0709L, 0x4A19_697C_81AC_1BEFL, // -13 + 0x465E_6604_B7A8_4465L, 0x7E4F_E1ED_D10B_9175L, // -12 + 0x57F5_FF85_E592_557FL, 0x3DE3_DA69_454E_75D3L, // -11 + 0x6DF3_7F67_5EF6_EADFL, 0x2D5C_D103_96A2_1347L, // -10 + 0x44B8_2FA0_9B5A_52CBL, 0x4C5A_02A2_3E25_4C0DL, // -9 + 0x55E6_3B88_C230_E77EL, 0x3F70_834A_CDAE_9F10L, // -8 + 0x6B5F_CA6A_F2BD_215EL, 0x0F4C_A41D_811A_46D4L, // -7 + 0x431B_DE82_D7B6_34DAL, 0x698F_E692_70B0_6C44L, // -6 + 0x53E2_D623_8DA3_C211L, 0x43F3_E037_0CDC_8755L, // -5 + 0x68DB_8BAC_710C_B295L, 0x74F0_D844_D013_A92BL, // -4 + 0x4189_374B_C6A7_EF9DL, 0x5916_872B_020C_49BBL, // -3 + 0x51EB_851E_B851_EB85L, 0x0F5C_28F5_C28F_5C29L, // -2 + 0x6666_6666_6666_6666L, 0x3333_3333_3333_3334L, // -1 + 0x4000_0000_0000_0000L, 0x0000_0000_0000_0001L, // 0 + 0x5000_0000_0000_0000L, 0x0000_0000_0000_0001L, // 1 + 0x6400_0000_0000_0000L, 0x0000_0000_0000_0001L, // 2 + 0x7D00_0000_0000_0000L, 0x0000_0000_0000_0001L, // 3 + 0x4E20_0000_0000_0000L, 0x0000_0000_0000_0001L, // 4 + 0x61A8_0000_0000_0000L, 0x0000_0000_0000_0001L, // 5 + 0x7A12_0000_0000_0000L, 0x0000_0000_0000_0001L, // 6 + 0x4C4B_4000_0000_0000L, 0x0000_0000_0000_0001L, // 7 + 0x5F5E_1000_0000_0000L, 0x0000_0000_0000_0001L, // 8 + 0x7735_9400_0000_0000L, 0x0000_0000_0000_0001L, // 9 + 0x4A81_7C80_0000_0000L, 0x0000_0000_0000_0001L, // 10 + 0x5D21_DBA0_0000_0000L, 0x0000_0000_0000_0001L, // 11 + 0x746A_5288_0000_0000L, 0x0000_0000_0000_0001L, // 12 + 0x48C2_7395_0000_0000L, 0x0000_0000_0000_0001L, // 13 + 0x5AF3_107A_4000_0000L, 0x0000_0000_0000_0001L, // 14 + 0x71AF_D498_D000_0000L, 0x0000_0000_0000_0001L, // 15 + 0x470D_E4DF_8200_0000L, 0x0000_0000_0000_0001L, // 16 + 0x58D1_5E17_6280_0000L, 0x0000_0000_0000_0001L, // 17 + 0x6F05_B59D_3B20_0000L, 0x0000_0000_0000_0001L, // 18 + 0x4563_9182_44F4_0000L, 0x0000_0000_0000_0001L, // 19 + 0x56BC_75E2_D631_0000L, 0x0000_0000_0000_0001L, // 20 + 0x6C6B_935B_8BBD_4000L, 0x0000_0000_0000_0001L, // 21 + 0x43C3_3C19_3756_4800L, 0x0000_0000_0000_0001L, // 22 + 0x54B4_0B1F_852B_DA00L, 0x0000_0000_0000_0001L, // 23 + 0x69E1_0DE7_6676_D080L, 0x0000_0000_0000_0001L, // 24 + 0x422C_A8B0_A00A_4250L, 0x0000_0000_0000_0001L, // 25 + 0x52B7_D2DC_C80C_D2E4L, 0x0000_0000_0000_0001L, // 26 + 0x6765_C793_FA10_079DL, 0x0000_0000_0000_0001L, // 27 + 0x409F_9CBC_7C4A_04C2L, 0x1000_0000_0000_0001L, // 28 + 0x50C7_83EB_9B5C_85F2L, 0x5400_0000_0000_0001L, // 29 + 0x64F9_64E6_8233_A76FL, 0x2900_0000_0000_0001L, // 30 + 0x7E37_BE20_22C0_914BL, 0x1340_0000_0000_0001L, // 31 + 0x4EE2_D6D4_15B8_5ACEL, 0x7C08_0000_0000_0001L, // 32 + 0x629B_8C89_1B26_7182L, 0x5B0A_0000_0000_0001L, // 33 + 0x7B42_6FAB_61F0_0DE3L, 0x31CC_8000_0000_0001L, // 34 + 0x4D09_85CB_1D36_08AEL, 0x0F1F_D000_0000_0001L, // 35 + 0x604B_E73D_E483_8AD9L, 0x52E7_C400_0000_0001L, // 36 + 0x785E_E10D_5DA4_6D90L, 0x07A1_B500_0000_0001L, // 37 + 0x4B3B_4CA8_5A86_C47AL, 0x04C5_1120_0000_0001L, // 38 + 0x5E0A_1FD2_7128_7598L, 0x45F6_5568_0000_0001L, // 39 + 0x758C_A7C7_0D72_92FEL, 0x5773_EAC2_0000_0001L, // 40 + 0x4977_E8DC_6867_9BDFL, 0x16A8_72B9_4000_0001L, // 41 + 0x5BD5_E313_8281_82D6L, 0x7C52_8F67_9000_0001L, // 42 + 0x72CB_5BD8_6321_E38CL, 0x5B67_3341_7400_0001L, // 43 + 0x47BF_1967_3DF5_2E37L, 0x7920_8008_E880_0001L, // 44 + 0x59AE_DFC1_0D72_79C5L, 0x7768_A00B_22A0_0001L, // 45 + 0x701A_97B1_50CF_1837L, 0x3542_C80D_EB48_0001L, // 46 + 0x4610_9ECE_D281_6F22L, 0x5149_BD08_B30D_0001L, // 47 + 0x5794_C682_8721_CAEBL, 0x259C_2C4A_DFD0_4001L, // 48 + 0x6D79_F823_28EA_3DA6L, 0x0F03_375D_97C4_5001L, // 49 + 0x446C_3B15_F992_6687L, 0x6962_029A_7EDA_B201L, // 50 + 0x5587_49DB_77F7_0029L, 0x63BA_8341_1E91_5E81L, // 51 + 0x6AE9_1C52_55F4_C034L, 0x1CA9_2411_6635_B621L, // 52 + 0x42D1_B1B3_75B8_F820L, 0x51E9_B68A_DFE1_91D5L, // 53 + 0x5386_1E20_5327_3628L, 0x6664_242D_97D9_F64AL, // 54 + 0x6867_A5A8_67F1_03B2L, 0x7FFD_2D38_FDD0_73DCL, // 55 + 0x4140_C789_40F6_A24FL, 0x6FFE_3C43_9EA2_486AL, // 56 + 0x5190_F96B_9134_4AE3L, 0x6BFD_CB54_864A_DA84L, // 57 + 0x65F5_37C6_7581_5D9CL, 0x66FD_3E29_A7DD_9125L, // 58 + 0x7F72_85B8_12E1_B504L, 0x00BC_8DB4_11D4_F56EL, // 59 + 0x4FA7_9393_0BCD_1122L, 0x4075_D890_8B25_1965L, // 60 + 0x6391_7877_CEC0_556BL, 0x1093_4EB4_ADEE_5FBEL, // 61 + 0x7C75_D695_C270_6AC5L, 0x74B8_2261_D969_F7ADL, // 62 + 0x4DC9_A61D_9986_42BBL, 0x58F3_157D_27E2_3ACCL, // 63 + 0x613C_0FA4_FFE7_D36AL, 0x4F2F_DADC_71DA_C97FL, // 64 + 0x798B_138E_3FE1_C845L, 0x22FB_D193_8E51_7BDFL, // 65 + 0x4BF6_EC38_E7ED_1D2BL, 0x25DD_62FC_38F2_ED6CL, // 66 + 0x5EF4_A747_21E8_6476L, 0x0F54_BBBB_472F_A8C6L, // 67 + 0x76B1_D118_EA62_7D93L, 0x5329_EAAA_18FB_92F8L, // 68 + 0x4A2F_22AF_927D_8E7CL, 0x23FA_32AA_4F9D_3BDBL, // 69 + 0x5CBA_EB5B_771C_F21BL, 0x2CF8_BF54_E384_8AD2L, // 70 + 0x73E9_A632_54E4_2EA2L, 0x1836_EF2A_1C65_AD86L, // 71 + 0x4872_07DF_750E_9D25L, 0x2F22_557A_51BF_8C74L, // 72 + 0x5A8E_89D7_5252_446EL, 0x5AEA_EAD8_E62F_6F91L, // 73 + 0x7132_2C4D_26E6_D58AL, 0x31A5_A58F_1FBB_4B75L, // 74 + 0x46BF_5BB0_3850_4576L, 0x3F07_8779_73D5_0F29L, // 75 + 0x586F_329C_4664_56D4L, 0x0EC9_6957_D0CA_52F3L, // 76 + 0x6E8A_FF43_57FD_6C89L, 0x127B_C3AD_C4FC_E7B0L, // 77 + 0x4516_DF8A_16FE_63D5L, 0x5B8D_5A4C_9B1E_10CEL, // 78 + 0x565C_976C_9CBD_FCCBL, 0x1270_B0DF_C1E5_9502L, // 79 + 0x6BF3_BD47_C3ED_7BFDL, 0x770C_DD17_B25E_FA42L, // 80 + 0x4378_564C_DA74_6D7EL, 0x5A68_0A2E_CF7B_5C69L, // 81 + 0x5456_6BE0_1111_88DEL, 0x3102_0CBA_835A_3384L, // 82 + 0x696C_06D8_1555_EB15L, 0x7D42_8FE9_2430_C065L, // 83 + 0x41E3_8447_0D55_B2EDL, 0x5E49_99F1_B69E_783FL, // 84 + 0x525C_6558_D0AB_1FA9L, 0x15DC_006E_2446_164FL, // 85 + 0x66F3_7EAF_04D5_E793L, 0x3B53_0089_AD57_9BE2L, // 86 + 0x4058_2F2D_6305_B0BCL, 0x1513_E056_0C56_C16EL, // 87 + 0x506E_3AF8_BBC7_1CEBL, 0x1A58_D86B_8F6C_71C9L, // 88 + 0x6489_C9B6_EAB8_E426L, 0x00EF_0E86_7347_8E3BL, // 89 + 0x7DAC_3C24_A567_1D2FL, 0x412A_D228_1019_71C9L, // 90 + 0x4E8B_A596_E760_723DL, 0x58BA_C359_0A0F_E71EL, // 91 + 0x622E_8EFC_A138_8ECDL, 0x0EE9_742F_4C93_E0E6L, // 92 + 0x7ABA_32BB_C986_B280L, 0x32A3_D13B_1FB8_D91FL, // 93 + 0x4CB4_5FB5_5DF4_2F90L, 0x1FA6_62C4_F3D3_87B3L, // 94 + 0x5FE1_77A2_B571_3B74L, 0x278F_FB76_30C8_69A0L, // 95 + 0x77D9_D58B_62CD_8A51L, 0x3173_FA53_BCFA_8408L, // 96 + 0x4AE8_2577_1DC0_7672L, 0x6EE8_7C74_561C_9285L, // 97 + 0x5DA2_2ED4_E530_940FL, 0x4AA2_9B91_6BA3_B726L, // 98 + 0x750A_BA8A_1E7C_B913L, 0x3D4B_4275_C68C_A4F0L, // 99 + 0x4926_B496_530D_F3ACL, 0x164F_0989_9C17_E716L, // 100 + 0x5B70_61BB_E7D1_7097L, 0x1BE2_CBEC_031D_E0DCL, // 101 + 0x724C_7A2A_E1C5_CCBDL, 0x02DB_7EE7_03E5_5912L, // 102 + 0x476F_CC5A_CD1B_9FF6L, 0x11C9_2F50_626F_57ACL, // 103 + 0x594B_BF71_8062_87F3L, 0x563B_7B24_7B0B_2D96L, // 104 + 0x6F9E_AF4D_E07B_29F0L, 0x4BCA_59ED_99CD_F8FCL, // 105 + 0x45C3_2D90_AC4C_FA36L, 0x2F5E_7834_8020_BB9EL, // 106 + 0x5733_F8F4_D760_38C3L, 0x7B36_1641_A028_EA85L, // 107 + 0x6D00_F732_0D38_46F4L, 0x7A03_9BD2_0833_2526L, // 108 + 0x4420_9A7F_4843_2C59L, 0x0C42_4163_451F_F738L, // 109 + 0x5528_C11F_1A53_F76FL, 0x2F52_D1BC_1667_F506L, // 110 + 0x6A72_F166_E0E8_F54BL, 0x1B27_862B_1C01_F247L, // 111 + 0x4287_D6E0_4C91_994FL, 0x00F8_B3DA_F181_376DL, // 112 + 0x5329_CC98_5FB5_FFA2L, 0x6136_E0D1_ADE1_8548L, // 113 + 0x67F4_3FBE_77A3_7F8BL, 0x3984_9906_1959_E699L, // 114 + 0x40F8_A7D7_0AC6_2FB7L, 0x13F2_DFA3_CFD8_3020L, // 115 + 0x5136_D1CC_CD77_BBA4L, 0x78EF_978C_C3CE_3C28L, // 116 + 0x6584_8640_00D5_AA8EL, 0x172B_7D6F_F4C1_CB32L, // 117 + 0x7EE5_A7D0_010B_1531L, 0x5CF6_5CCB_F1F2_3DFEL, // 118 + 0x4F4F_88E2_00A6_ED3FL, 0x0A19_F9FF_7737_66BFL, // 119 + 0x6323_6B1A_80D0_A88EL, 0x6CA0_787F_5505_406FL, // 120 + 0x7BEC_45E1_2104_D2B2L, 0x47C8_969F_2A46_908AL, // 121 + 0x4D73_ABAC_B4A3_03AFL, 0x4CDD_5E23_7A6C_1A57L, // 122 + 0x60D0_9697_E1CB_C49BL, 0x4014_B5AC_5907_20ECL, // 123 + 0x7904_BC3D_DA3E_B5C2L, 0x3019_E317_6F48_E927L, // 124 + 0x4BA2_F5A6_A867_3199L, 0x3E10_2DEE_A58D_91B9L, // 125 + 0x5E8B_B310_5280_FDFFL, 0x6D94_396A_4EF0_F627L, // 126 + 0x762E_9FD4_6721_3D7FL, 0x68F9_47C4_E2AD_33B0L, // 127 + 0x49DD_23E4_C074_C66FL, 0x719B_CCDB_0DAC_404EL, // 128 + 0x5C54_6CDD_F091_F80BL, 0x6E02_C011_D117_5062L, // 129 + 0x7369_8815_6CB6_760EL, 0x6983_7016_455D_247AL, // 130 + 0x4821_F50D_63F2_09C9L, 0x21F2_260D_EB5A_36CCL, // 131 + 0x5A2A_7250_BCEE_8C3BL, 0x4A6E_AF91_6630_C47FL, // 132 + 0x70B5_0EE4_EC2A_2F4AL, 0x3D0A_5B75_BFBC_F59FL, // 133 + 0x4671_294F_139A_5D8EL, 0x4626_7929_97D6_1984L, // 134 + 0x580D_73A2_D880_F4F2L, 0x17B0_1773_FDCB_9FE4L, // 135 + 0x6E10_D08B_8EA1_322EL, 0x5D9C_1D50_FD3E_87DDL, // 136 + 0x44CA_8257_3924_BF5DL, 0x1A81_9252_9E47_14EBL, // 137 + 0x55FD_22ED_076D_EF34L, 0x4121_F6E7_45D8_DA25L, // 138 + 0x6B7C_6BA8_4949_6B01L, 0x516A_74A1_174F_10AEL, // 139 + 0x432D_C349_2DCD_E2E1L, 0x02E2_88E4_AE91_6A6DL, // 140 + 0x53F9_341B_7941_5B99L, 0x239B_2B1D_DA35_C508L, // 141 + 0x68F7_8122_5791_B27FL, 0x4C81_F5E5_50C3_364AL, // 142 + 0x419A_B0B5_76BB_0F8FL, 0x5FD1_39AF_527A_01EFL, // 143 + 0x5201_5CE2_D469_D373L, 0x57C5_881B_2718_826AL, // 144 + 0x6681_B41B_8984_4850L, 0x4DB6_EA21_F0DE_A304L, // 145 + 0x4011_1091_35F2_AD32L, 0x3092_5255_368B_25E3L, // 146 + 0x5015_54B5_836F_587EL, 0x7CB6_E6EA_842D_EF5CL, // 147 + 0x641A_A9E2_E44B_2E9EL, 0x5BE4_A0A5_2539_6B32L, // 148 + 0x7D21_545B_9D5D_FA46L, 0x32DD_C8CE_6E87_C5FFL, // 149 + 0x4E34_D4B9_425A_BC6BL, 0x7FCA_9D81_0514_DBBFL, // 150 + 0x61C2_09E7_92F1_6B86L, 0x7FBD_44E1_465A_12AFL, // 151 + 0x7A32_8C61_77AD_C668L, 0x5FAC_9619_97F0_975BL, // 152 + 0x4C5F_97BC_EACC_9C01L, 0x3BCB_DDCF_FEF6_5E99L, // 153 + 0x5F77_7DAC_257F_C301L, 0x6ABE_D543_FEB3_F63FL, // 154 + 0x7755_5D17_2EDF_B3C2L, 0x256E_8A94_FE60_F3CFL, // 155 + 0x4A95_5A2E_7D4B_D059L, 0x3765_169D_1EFC_9861L, // 156 + 0x5D3A_B0BA_1C9E_C46FL, 0x653E_5C44_66BB_BE7AL, // 157 + 0x7489_5CE8_A3C6_758BL, 0x5E8D_F355_806A_AE18L, // 158 + 0x48D5_DA11_665C_0977L, 0x2B18_B815_7042_ACCFL, // 159 + 0x5B0B_5095_BFF3_0BD5L, 0x15DE_E61A_CC53_5803L, // 160 + 0x71CE_24BB_2FEF_CECAL, 0x3B56_9FA1_7F68_2E03L, // 161 + 0x4720_D6F4_FDF5_E13EL, 0x4516_23C4_EFA1_1CC2L, // 162 + 0x58E9_0CB2_3D73_598EL, 0x165B_ACB6_2B89_63F3L, // 163 + 0x6F23_4FDE_CCD0_2FF1L, 0x5BF2_97E3_B66B_BCEFL, // 164 + 0x4576_11EB_4002_1DF7L, 0x0977_9EEE_5203_5616L, // 165 + 0x56D3_9666_1002_A574L, 0x6BD5_86A9_E684_2B9BL, // 166 + 0x6C88_7BFF_9403_4ED2L, 0x06CA_E854_6025_3682L, // 167 + 0x43D5_4D7F_BC82_1143L, 0x243E_D134_BC17_4211L, // 168 + 0x54CA_A0DF_ABA2_9594L, 0x0D4E_8581_EB1D_1295L, // 169 + 0x69FD_4917_968B_3AF9L, 0x10A2_26E2_65E4_573BL, // 170 + 0x423E_4DAE_BE17_04DBL, 0x5A65_584D_7FAE_B685L, // 171 + 0x52CD_E11A_6D9C_C612L, 0x50FE_AE60_DF9A_6426L, // 172 + 0x6781_5961_0903_F797L, 0x253E_59F9_1780_FD2FL, // 173 + 0x40B0_D7DC_A5A2_7ABEL, 0x4746_F83B_AEB0_9E3EL, // 174 + 0x50DD_0DD3_CF0B_196EL, 0x1918_B64A_9A5C_C5CDL, // 175 + 0x6514_5148_C2CD_DFC9L, 0x5F5E_E3DD_40F3_F740L, // 176 + 0x7E59_659A_F381_57BCL, 0x1736_9CD4_9130_F510L, // 177 + 0x4EF7_DF80_D830_D6D5L, 0x4E82_2204_DABE_992AL, // 178 + 0x62B5_D761_0E3D_0C8BL, 0x0222_AA86_116E_3F75L, // 179 + 0x7B63_4D39_51CC_4FADL, 0x62AB_5527_95C9_CF52L, // 180 + 0x4D1E_1043_D31F_B1CCL, 0x4DAB_1538_BD9E_2193L, // 181 + 0x6065_9454_C7E7_9E3FL, 0x6115_DA86_ED05_A9F8L, // 182 + 0x787E_F969_F9E1_85CFL, 0x595B_5128_A847_1476L, // 183 + 0x4B4F_5BE2_3C2C_F3A1L, 0x67D9_12B9_692C_6CCAL, // 184 + 0x5E23_32DA_CB38_308AL, 0x21CF_5767_C377_87FCL, // 185 + 0x75AB_FF91_7E06_3CACL, 0x6A43_2D41_B455_69FBL, // 186 + 0x498B_7FBA_EEC3_E5ECL, 0x0269_FC49_10B5_623DL, // 187 + 0x5BEE_5FA9_AA74_DF67L, 0x0304_7B5B_54E2_BACCL, // 188 + 0x72E9_F794_1512_1740L, 0x63C5_9A32_2A1B_697FL, // 189 + 0x47D2_3ABC_8D2B_4E88L, 0x3E5B_805F_5A51_21F0L, // 190 + 0x59C6_C96B_B076_222AL, 0x4DF2_6077_30E5_6A6CL, // 191 + 0x7038_7BC6_9C93_AAB5L, 0x216E_F894_FD1E_C506L, // 192 + 0x4623_4D5C_21DC_4AB1L, 0x24E5_5B5D_1E33_3B24L, // 193 + 0x57AC_20B3_2A53_5D5DL, 0x4E1E_B234_65C0_09EDL, // 194 + 0x6D97_28DF_F4E8_34B5L, 0x01A6_5EC1_7F30_0C68L, // 195 + 0x447E_798B_F911_20F1L, 0x1107_FB38_EF7E_07C1L, // 196 + 0x559E_17EE_F755_692DL, 0x3549_FA07_2B5D_89B1L, // 197 + 0x6B05_9DEA_B52A_C378L, 0x629C_7888_F634_EC1EL, // 198 + 0x42E3_82B2_B13A_BA2BL, 0x3DA1_CB55_99E1_1393L, // 199 + 0x539C_635F_5D89_68B6L, 0x2D0A_3E2B_0059_5877L, // 200 + 0x6883_7C37_34EB_C2E3L, 0x784C_CDB5_C06F_AE95L, // 201 + 0x4152_2DA2_8113_59CEL, 0x3B30_0091_9845_CD1DL, // 202 + 0x51A6_B90B_2158_3042L, 0x09FC_00B5_FE57_4065L, // 203 + 0x6610_674D_E9AE_3C52L, 0x4C7B_00E3_7DED_107EL, // 204 + 0x7F94_8121_6419_CB67L, 0x1F99_C11C_5D68_549DL, // 205 + 0x4FBC_D0B4_DE90_1F20L, 0x43C0_18B1_BA61_34E2L, // 206 + 0x63AC_04E2_1634_26E8L, 0x54B0_1EDE_28F9_821BL, // 207 + 0x7C97_061A_9BC1_30A2L, 0x69DC_2695_B337_E2A1L, // 208 + 0x4DDE_63D0_A158_BE65L, 0x6229_981D_9002_EDA5L, // 209 + 0x6155_FCC4_C9AE_EDFFL, 0x1AB3_FE24_F403_A90EL, // 210 + 0x79AB_7BF5_FC1A_A97FL, 0x0160_FDAE_3104_9351L, // 211 + 0x4C0B_2D79_BD90_A9EFL, 0x30DC_9E8C_DEA2_DC13L, // 212 + 0x5F0D_F8D8_2CF4_D46BL, 0x1D13_C630_164B_9318L, // 213 + 0x76D1_770E_3832_0986L, 0x0458_B7BC_1BDE_77DDL, // 214 + 0x4A42_EA68_E31F_45F3L, 0x62B7_72D5_916B_0AEBL, // 215 + 0x5CD3_A503_1BE7_1770L, 0x5B65_4F8A_F5C5_CDA5L, // 216 + 0x7408_8E43_E2E0_DD4CL, 0x723E_A36D_B337_410EL, // 217 + 0x4885_58EA_6DCC_8A50L, 0x0767_2624_9002_88A9L, // 218 + 0x5AA6_AF25_093F_ACE4L, 0x0940_EFAD_B403_2AD3L, // 219 + 0x7150_5AEE_4B8F_981DL, 0x0B91_2B99_2103_F588L, // 220 + 0x46D2_38D4_EF39_BF12L, 0x173A_BB3F_B4A2_7975L, // 221 + 0x5886_C70A_2B08_2ED6L, 0x5D09_6A0F_A1CB_17D2L, // 222 + 0x6EA8_78CC_B5CA_3A8CL, 0x344B_C493_8A3D_DDC7L, // 223 + 0x4529_4B7F_F19E_6497L, 0x60AF_5ADC_3666_AA9CL, // 224 + 0x5673_9E5F_EE05_FDBDL, 0x58DB_3193_4400_5543L, // 225 + 0x6C10_85F7_E987_7D2DL, 0x0F11_FDF8_1500_6A94L, // 226 + 0x438A_53BA_F1F4_AE3CL, 0x196B_3EBB_0D20_429DL, // 227 + 0x546C_E8A9_AE71_D9CBL, 0x1FC6_0E69_D068_5344L, // 228 + 0x6988_22D4_1A0E_503EL, 0x07B7_9204_4482_6815L, // 229 + 0x41F5_15C4_9048_F226L, 0x64D2_BB42_AAD1_810DL, // 230 + 0x5272_5B35_B45B_2EB0L, 0x3E07_6A13_5585_E150L, // 231 + 0x670E_F203_2171_FA5CL, 0x4D89_4498_2AE7_59A4L, // 232 + 0x4069_5741_F4E7_3C79L, 0x7075_CADF_1AD0_9807L, // 233 + 0x5083_AD12_7221_0B98L, 0x2C93_3D96_E184_BE08L, // 234 + 0x64A4_9857_0EA9_4E7EL, 0x37B8_0CFC_99E5_ED8AL, // 235 + 0x7DCD_BE6C_D253_A21EL, 0x05A6_103B_C05F_68EDL, // 236 + 0x4EA0_9704_0374_4552L, 0x6387_CA25_583B_A194L, // 237 + 0x6248_BCC5_0451_56A7L, 0x3C69_BCAE_AE4A_89F9L, // 238 + 0x7ADA_EBF6_4565_AC51L, 0x2B84_2BDA_59DD_2C77L, // 239 + 0x4CC8_D379_EB5F_8BB2L, 0x6B32_9B68_782A_3BCBL, // 240 + 0x5FFB_0858_6637_6E9FL, 0x45FF_4242_9634_CABDL, // 241 + 0x77F9_CA6E_7FC5_4A47L, 0x377F_12D3_3BC1_FD6DL, // 242 + 0x4AFC_1E85_0FDB_4E6CL, 0x52AF_6BC4_0559_3E64L, // 243 + 0x5DBB_2626_53D2_2207L, 0x675B_46B5_06AF_8DFDL, // 244 + 0x7529_EFAF_E8C6_AA89L, 0x6132_1862_485B_717CL, // 245 + 0x493A_35CD_F17C_2A96L, 0x0CBF_4F3D_6D39_26EEL, // 246 + 0x5B88_C341_6DDB_353BL, 0x4FEF_230C_C887_70A9L, // 247 + 0x726A_F411_C952_028AL, 0x43EA_EBCF_FAA9_4CD3L, // 248 + 0x4782_D88B_1DD3_4196L, 0x4A72_D361_FCA9_D004L, // 249 + 0x5963_8EAD_E548_11FCL, 0x1D0F_883A_7BD4_4405L, // 250 + 0x6FBC_7259_5E9A_167BL, 0x2453_6A49_1AC9_5506L, // 251 + 0x45D5_C777_DB20_4E0DL, 0x06B4_226D_B0BD_D524L, // 252 + 0x574B_3955_D1E8_6190L, 0x2861_2B09_1CED_4A6DL, // 253 + 0x6D1E_07AB_4662_79F4L, 0x3279_75CB_6428_9D08L, // 254 + 0x4432_C4CB_0BFD_8C38L, 0x5F8B_E99F_1E99_6225L, // 255 + 0x553F_75FD_CEFC_EF46L, 0x776E_E406_E63F_BAAEL, // 256 + 0x6A8F_537D_42BC_2B18L, 0x554A_9D08_9FCF_A95AL, // 257 + 0x4299_942E_49B5_9AEFL, 0x354E_A225_63E1_C9D8L, // 258 + 0x533F_F939_DC23_01ABL, 0x22A2_4AAE_BCDA_3C4EL, // 259 + 0x680F_F788_532B_C216L, 0x0B4A_DD5A_6C10_CB62L, // 260 + 0x4109_FAB5_33FB_594DL, 0x670E_CA58_838A_7F1DL, // 261 + 0x514C_7962_80FA_2FA1L, 0x20D2_7CEE_A46D_1EE4L, // 262 + 0x659F_97BB_2138_BB89L, 0x4907_1C2A_4D88_669DL, // 263 + 0x7F07_7DA9_E986_EA6BL, 0x7B48_E334_E0EA_8045L, // 264 + 0x4F64_AE8A_31F4_5283L, 0x3D0D_8E01_0C92_902BL, // 265 + 0x633D_DA2C_BE71_6724L, 0x2C50_F181_4FB7_3436L, // 266 + 0x7C0D_50B7_EE0D_C0EDL, 0x3765_2DE1_A3A5_0143L, // 267 + 0x4D88_5272_F4C8_9894L, 0x329F_3CAD_0647_20CAL, // 268 + 0x60EA_670F_B1FA_BEB9L, 0x3F47_0BD8_47D8_E8FDL, // 269 + 0x7925_00D3_9E79_6E67L, 0x6F18_CECE_59CF_233CL, // 270 + 0x4BB7_2084_430B_E500L, 0x756F_8140_F821_7605L, // 271 + 0x5EA4_E8A5_53CE_DE41L, 0x12CB_6191_3629_D387L, // 272 + 0x764E_22CE_A8C2_95D1L, 0x377E_39F5_83B4_4868L, // 273 + 0x49F0_D5C1_2979_9DA2L, 0x72AE_E439_7250_AD41L, // 274 + 0x5C6D_0B31_73D8_050BL, 0x4F5A_9D47_CEE4_D891L, // 275 + 0x7388_4DFD_D0CE_064EL, 0x4331_4499_C29E_0EB6L, // 276 + 0x4835_30BE_A280_C3F1L, 0x09FE_CAE0_19A2_C932L, // 277 + 0x5A42_7CEE_4B20_F4EDL, 0x2C7E_7D98_200B_7B7EL, // 278 + 0x70D3_1C29_DDE9_3228L, 0x579E_1CFE_280E_5A5DL, // 279 + 0x4683_F19A_2AB1_BF59L, 0x36C2_D21E_D908_F87BL, // 280 + 0x5824_EE00_B55E_2F2FL, 0x6473_86A6_8F4B_3699L, // 281 + 0x6E2E_2980_E2B5_BAFBL, 0x5D90_6850_331E_043FL, // 282 + 0x44DC_D9F0_8DB1_94DDL, 0x2A7A_4132_1FF2_C2A8L, // 283 + 0x5614_106C_B11D_FA14L, 0x5518_D17E_A7EF_7352L, // 284 + 0x6B99_1487_DD65_7899L, 0x6A5F_05DE_51EB_5026L, // 285 + 0x433F_ACD4_EA5F_6B60L, 0x127B_63AA_F333_1218L, // 286 + 0x540F_980A_24F7_4638L, 0x171A_3C95_AFFF_D69EL, // 287 + 0x6913_7E0C_AE35_17C6L, 0x1CE0_CBBB_1BFF_CC45L, // 288 + 0x41AC_2EC7_ECE1_2EDBL, 0x720C_7F54_F17F_DFABL, // 289 + 0x5217_3A79_E819_7A92L, 0x6E8F_9F2A_2DDF_D796L, // 290 + 0x669D_0918_621F_D937L, 0x4A33_86F4_B957_CD7BL, // 291 + 0x4022_25AF_3D53_E7C2L, 0x5E60_3458_F3D6_E06DL, // 292 + 0x502A_AF1B_0CA8_E1B3L, 0x35F8_416F_30CC_9888L, // 293 + 0x6435_5AE1_CFD3_1A20L, 0x2376_51CA_FCFF_BEAAL, // 294 + 0x7D42_B19A_43C7_E0A8L, 0x2C53_E63D_BC3F_AE55L, // 295 + 0x4E49_AF00_6A5C_EC69L, 0x1BB4_6FE6_95A7_CCF5L, // 296 + 0x61DC_1AC0_84F4_2783L, 0x42A1_8BE0_3B11_C033L, // 297 + 0x7A53_2170_A631_3164L, 0x3349_EED8_49D6_303FL, // 298 + 0x4C73_F4E6_67DE_BEDEL, 0x600E_3547_2E25_DE28L, // 299 + 0x5F90_F220_01D6_6E96L, 0x3811_C298_F9AF_55B1L, // 300 + 0x7775_2EA8_024C_0A3CL, 0x0616_333F_381B_2B1EL, // 301 + 0x4AA9_3D29_016F_8665L, 0x43CD_E007_8310_FAF3L, // 302 + 0x5D53_8C73_41CB_67FEL, 0x74C1_5809_63D5_39AFL, // 303 + 0x74A8_6F90_123E_41FEL, 0x51F1_AE0B_BCCA_881BL, // 304 + 0x48E9_45BA_0B66_E93FL, 0x1337_0CC7_55FE_9511L, // 305 + 0x5B23_9728_8E40_A38EL, 0x7804_CFF9_2B7E_3A55L, // 306 + 0x71EC_7CF2_B1D0_CC72L, 0x5606_03F7_765D_C8EAL, // 307 + 0x4733_CE17_AF22_7FC7L, 0x55C3_C27A_A9FA_9D93L, // 308 + 0x5900_C19D_9AEB_1FB9L, 0x4B34_B319_5479_44F7L, // 309 + 0x6F40_F205_01A5_E7A7L, 0x7E01_DFDF_A997_9635L, // 310 + 0x4588_9743_2107_B0C8L, 0x7EC1_2BEB_C9FE_BDE1L, // 311 + 0x56EA_BD13_E949_9CFBL, 0x1E71_76E6_BC7E_6D59L, // 312 + 0x6CA5_6C58_E39C_043AL, 0x060D_D4A0_6B9E_08B0L, // 313 + 0x43E7_63B7_8E41_82A4L, 0x23C8_A4E4_4342_C56EL, // 314 + 0x54E1_3CA5_71D1_E34DL, 0x2CBA_CE1D_5413_76C9L, // 315 + 0x6A19_8BCE_CE46_5C20L, 0x57E9_81A4_A918_547BL, // 316 + 0x424F_F761_40EB_F994L, 0x36F1_F106_E9AF_34CDL, // 317 + 0x52E3_F539_9126_F7F9L, 0x44AE_6D48_A41B_0201L, // 318 + 0x679C_F287_F570_B5F7L, 0x75DA_089A_CD21_C281L, // 319 + 0x40C2_1794_F966_71BAL, 0x79A8_4560_C035_1991L, // 320 + 0x50F2_9D7A_37C0_0E29L, 0x5812_56B8_F042_5FF5L, // 321 + 0x652F_44D8_C5B0_11B4L, 0x0E16_EC67_2C52_F7F2L, // 322 + 0x7E7B_160E_F71C_1621L, 0x119C_A780_F767_B5EEL, // 323 + 0x4F0C_EDC9_5A71_8DD4L, 0x5B01_E8B0_9AA0_D1B5L, // 324 }; } diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 52b7d8bf03e..3259a017b30 100644 --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -25,10 +25,10 @@ package jdk.internal.misc; -import jdk.internal.ref.Cleaner; import jdk.internal.value.ValueClass; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; +import sun.nio.Cleaner; import sun.nio.ch.DirectBuffer; import java.lang.reflect.Field; diff --git a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java index c520e6e636a..e7184b599f2 100644 --- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java +++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -34,7 +34,6 @@ import java.lang.module.ModuleReference; import java.lang.reflect.Constructor; import java.net.URI; -import java.net.URLConnection; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; @@ -54,9 +53,8 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; -import jdk.internal.jimage.ImageReaderFactory; +import jdk.internal.jimage.SystemImageReader; import jdk.internal.access.JavaNetUriAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.util.StaticProperty; @@ -210,7 +208,7 @@ public static ModuleFinder ofSystem() { } /** - * Parses the module-info.class of all module in the runtime image and + * Parses the {@code module-info.class} of all modules in the runtime image and * returns a ModuleFinder to find the modules. * * @apiNote The returned ModuleFinder is thread safe. @@ -219,20 +217,16 @@ private static ModuleFinder ofModuleInfos() { // parse the module-info.class in every module Map nameToAttributes = new HashMap<>(); Map nameToHash = new HashMap<>(); - ImageReader reader = SystemImage.reader(); - for (String mn : reader.getModuleNames()) { - ImageLocation loc = reader.findLocation(mn, "module-info.class"); - ModuleInfo.Attributes attrs - = ModuleInfo.read(reader.getResourceBuffer(loc), null); - nameToAttributes.put(mn, attrs); + allModuleAttributes().forEach(attrs -> { + nameToAttributes.put(attrs.descriptor().name(), attrs); ModuleHashes hashes = attrs.recordedHashes(); if (hashes != null) { for (String name : hashes.names()) { nameToHash.computeIfAbsent(name, k -> hashes.hashFor(name)); } } - } + }); // create a ModuleReference for each module Set mrefs = new HashSet<>(); @@ -253,6 +247,40 @@ private static ModuleFinder ofModuleInfos() { return new SystemModuleFinder(mrefs, nameToModule); } + /** + * Parses the {@code module-info.class} of all modules in the runtime image and + * returns a stream of {@link ModuleInfo.Attributes Attributes} for them. The + * returned attributes are in no specific order. + */ + private static Stream allModuleAttributes() { + // System-wide image reader. + ImageReader reader = SystemImage.reader(); + try { + return reader.findNode("/modules") + .getChildNames() + .map(mn -> readModuleAttributes(reader, mn)); + } catch (IOException e) { + throw new Error("Error reading root /modules entry", e); + } + } + + /** + * Returns the module's "module-info", returning a holder for its class file + * attributes. Every module is required to have a valid {@code module-info.class}. + */ + private static ModuleInfo.Attributes readModuleAttributes(ImageReader reader, String moduleName) { + Exception err = null; + try { + ImageReader.Node node = reader.findNode(moduleName + "/module-info.class"); + if (node != null && node.isResource()) { + return ModuleInfo.read(reader.getResourceBuffer(node), null); + } + } catch (IOException | UncheckedIOException e) { + err = e; + } + throw new Error("Missing or invalid module-info.class for module: " + moduleName, err); + } + /** * A ModuleFinder that finds module in an array or set of modules. */ @@ -364,7 +392,7 @@ public byte[] generate(String algorithm) { * Holder class for the ImageReader. */ private static class SystemImage { - static final ImageReader READER = ImageReaderFactory.getImageReader(); + static final ImageReader READER = SystemImageReader.get(); static ImageReader reader() { return READER; } @@ -382,43 +410,21 @@ private static class SystemModuleReader implements ModuleReader { this.module = module; } - /** - * Returns the ImageLocation for the given resource, {@code null} - * if not found. - */ - private ImageLocation findImageLocation(String name) throws IOException { - Objects.requireNonNull(name); - if (closed) - throw new IOException("ModuleReader is closed"); - ImageReader imageReader = SystemImage.reader(); - if (imageReader != null) { - return imageReader.findLocation(module, name); - } else { - // not an images build - return null; - } - } - /** * Returns {@code true} if the given resource exists, {@code false} * if not found. */ - private boolean containsImageLocation(String name) throws IOException { + private boolean containsResource(String module, String name) throws IOException { Objects.requireNonNull(name); if (closed) throw new IOException("ModuleReader is closed"); ImageReader imageReader = SystemImage.reader(); - if (imageReader != null) { - return imageReader.verifyLocation(module, name); - } else { - // not an images build - return false; - } + return imageReader != null && imageReader.containsResource(module, name); } @Override public Optional find(String name) throws IOException { - if (containsImageLocation(name)) { + if (containsResource(module, name)) { URI u = JNUA.create("jrt", "/" + module + "/" + name); return Optional.of(u); } else { @@ -442,14 +448,23 @@ private InputStream toInputStream(ByteBuffer bb) { // ## -> ByteBuffer? } } + /** + * Returns the node for the given resource if found. If the name references + * a non-resource node, then {@code null} is returned. + */ + private ImageReader.Node findResource(ImageReader reader, String name) throws IOException { + Objects.requireNonNull(name); + if (closed) { + throw new IOException("ModuleReader is closed"); + } + return reader.findResourceNode(module, name); + } + @Override public Optional read(String name) throws IOException { - ImageLocation location = findImageLocation(name); - if (location != null) { - return Optional.of(SystemImage.reader().getResourceBuffer(location)); - } else { - return Optional.empty(); - } + ImageReader reader = SystemImage.reader(); + return Optional.ofNullable(findResource(reader, name)) + .map(reader::getResourceBuffer); } @Override @@ -481,7 +496,7 @@ public void close() { private static class ModuleContentSpliterator implements Spliterator { final String moduleRoot; final Deque stack; - Iterator iterator; + Iterator iterator; ModuleContentSpliterator(String module) throws IOException { moduleRoot = "/modules/" + module; @@ -502,13 +517,10 @@ private static class ModuleContentSpliterator implements Spliterator { private String next() throws IOException { for (;;) { while (iterator.hasNext()) { - ImageReader.Node node = iterator.next(); - String name = node.getName(); + String name = iterator.next(); + ImageReader.Node node = SystemImage.reader().findNode(name); if (node.isDirectory()) { - // build node - ImageReader.Node dir = SystemImage.reader().findNode(name); - assert dir.isDirectory(); - stack.push(dir); + stack.push(node); } else { // strip /modules/$MODULE/ prefix return name.substring(moduleRoot.length() + 1); @@ -520,7 +532,7 @@ private String next() throws IOException { } else { ImageReader.Node dir = stack.poll(); assert dir.isDirectory(); - iterator = dir.getChildren().iterator(); + iterator = dir.getChildNames().iterator(); } } } diff --git a/src/java.base/share/classes/jdk/internal/ref/Cleaner.java b/src/java.base/share/classes/jdk/internal/ref/Cleaner.java deleted file mode 100644 index ecd1c32167f..00000000000 --- a/src/java.base/share/classes/jdk/internal/ref/Cleaner.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2003, 2024, 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. - */ - -package jdk.internal.ref; - -import java.lang.ref.*; - - -/** - * General-purpose phantom-reference-based cleaners. - * - *

    Cleaners are a lightweight and more robust alternative to finalization. - * They are lightweight because they are not created by the VM and thus do not - * require a JNI upcall to be created, and because their cleanup code is - * invoked directly by the reference-handler thread rather than by the - * finalizer thread. They are more robust because they use phantom references, - * the weakest type of reference object, thereby avoiding the nasty ordering - * problems inherent to finalization. - * - *

    A cleaner tracks a referent object and encapsulates a thunk of arbitrary - * cleanup code. Some time after the GC detects that a cleaner's referent has - * become phantom-reachable, the reference-handler thread will run the cleaner. - * Cleaners may also be invoked directly; they are thread safe and ensure that - * they run their thunks at most once. - * - *

    Cleaners are not a replacement for finalization. They should be used - * only when the cleanup code is extremely simple and straightforward. - * Nontrivial cleaners are inadvisable since they risk blocking the - * reference-handler thread and delaying further cleanup and finalization. - * - * - * @author Mark Reinhold - */ - -public class Cleaner - extends PhantomReference -{ - - // Dummy reference queue, needed because the PhantomReference constructor - // insists that we pass a queue. Nothing will ever be placed on this queue - // since the reference handler invokes cleaners explicitly. - // - private static final ReferenceQueue dummyQueue = new ReferenceQueue<>(); - - // Doubly-linked list of live cleaners, which prevents the cleaners - // themselves from being GC'd before their referents - // - private static Cleaner first = null; - - private Cleaner - next = null, - prev = null; - - private static synchronized Cleaner add(Cleaner cl) { - if (first != null) { - cl.next = first; - first.prev = cl; - } - first = cl; - return cl; - } - - private static synchronized boolean remove(Cleaner cl) { - - // If already removed, do nothing - if (cl.next == cl) - return false; - - // Update list - if (first == cl) { - if (cl.next != null) - first = cl.next; - else - first = cl.prev; - } - if (cl.next != null) - cl.next.prev = cl.prev; - if (cl.prev != null) - cl.prev.next = cl.next; - - // Indicate removal by pointing the cleaner to itself - cl.next = cl; - cl.prev = cl; - return true; - - } - - private final Runnable thunk; - - private Cleaner(Object referent, Runnable thunk) { - super(referent, dummyQueue); - this.thunk = thunk; - } - - /** - * Creates a new cleaner. - * - * @param ob the referent object to be cleaned - * @param thunk - * The cleanup code to be run when the cleaner is invoked. The - * cleanup code is run directly from the reference-handler thread, - * so it should be as simple and straightforward as possible. - * - * @return The new cleaner - */ - public static Cleaner create(Object ob, Runnable thunk) { - if (thunk == null) - return null; - return add(new Cleaner(ob, thunk)); - } - - /** - * Runs this cleaner, if it has not been run before. - */ - public void clean() { - if (!remove(this)) - return; - try { - thunk.run(); - } catch (final Throwable x) { - if (System.err != null) { - new Error("Cleaner terminated abnormally", x) - .printStackTrace(); - } - System.exit(1); - } - } -} diff --git a/src/java.base/share/classes/jdk/internal/util/regex/CaseFolding.java.template b/src/java.base/share/classes/jdk/internal/util/regex/CaseFolding.java.template new file mode 100644 index 00000000000..8ffbde6c535 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/util/regex/CaseFolding.java.template @@ -0,0 +1,116 @@ +/* + * 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. + */ + +package jdk.internal.util.regex; + +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; + +import static java.util.Map.entry; + +public final class CaseFolding { + + private static final Map expanded_case_map = Map.ofEntries( +%%%Entries + ); + + private static final int[] expanded_case_cps = expanded_case_map.keySet() + .stream() + .mapToInt(Integer::intValue) + .toArray(); + + private CaseFolding() {} + + /** + * Returns an expansion set to "close" a given regex Unicode character class range for case-sensitive + * matching, according to the + * Simple Loose Matches + * rule defined in Unicode Technical Standard #18: Unicode Regular Expressions. + *

    + * To conform with Level 1 of UTS #18, specifically RL1.5: Simple Loose Matches, simple case folding must + * be applied to literals and (optionally) to character classes. When applied to character classes, each + * character class is expected to be closed under simple case folding. See the standard for the + * detailed explanation and example of "closed". + *

    + * RL1.5 states: To meet this requirement, an implementation that supports case-sensitive matching should + *

      + *
    1. Provide at least the simple, default Unicode case-insensitive matching, and
    2. + *
    3. Specify which character properties or constructs are closed under the matching.
    4. + *
    + *

    + * In the {@code Pattern} implementation, 5 types of constructs maybe case-sensitive when matching: + * back-refs, string slice (sequences), single, family(char-property) and class range. Single and + * family may appears independently or within a class. + *

    + * For loose/case-insensitive matching, the back-refs, slices and singles apply {code toUpperCase} and + * {@code toLowerCase} to both the pattern and the input string. This effectively 'close' the class for + * matching. + *

    + * The family/char-properties are not "closed" and should remain unchanged. This is acceptable per RL1.5, + * if their behavior is clearly specified. + *

    + * This method addresses that requirement for the "range" construct within in character class by computing + * the additional characters that should be included to close the range under simple case folding: + *

    + * For each character in the input range {@code [start, end]} (inclusive), if the character has a simple + * case folding mapping in Unicode's CaseFolding.txt, the mapping is not a round-trip map, and the mapped + * character is not already in the range, then that mapped character (typically lowercase) is added to + * the expansion set. + *

    + * This allows regex character class "range" implementation to use the returned expansion set to support + * additional case-insensitive matching, without duplicating characters already covered by the existing + * regex range implementation. The expectation is the matching is done using both the uppercase and + * lowercase forms of the input character, for example + * + *

    {@code
    +     *
    +     *     ch -> inRange(lower, Character.toUpperCase(ch), upper) ||
    +     *           inRange(lower, Character.toLower(ch), upper) ||
    +     *           additionalClosingCharacters.contains(Character.toUpperCase(ch)) ||
    +     *           additionalClosingCharacters.contains(Character.toUpperCase(ch))
    +     * }
    + * + *

    + * @spec https://www.unicode.org/reports/tr18/#Simple_Loose_Matches + * @param start the starting code point of the character range + * @param end the ending code point of the character range + * @return a {@code int[]} containing the all simple case equivalents of characters in the range, excluding + * those already in the range + */ + public static int[] getClassRangeClosingCharacters(int start, int end) { + int[] expanded = new int[expanded_case_cps.length]; + int off = 0; + for (int cp : expanded_case_cps) { + if (cp >= start && cp <= end) { + int folding = expanded_case_map.get(cp); + if (folding < start || folding > end) { + expanded[off++] = folding; + } + } + } + return Arrays.copyOf(expanded, off); + } +} diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java index 58729774f24..a26003a3afb 100644 --- a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java +++ b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java @@ -177,8 +177,11 @@ private static void dumpThreads(ThreadContainer container, TextWriter writer) { container.children().forEach(c -> dumpThreads(c, writer)); } - private static void dumpThread(Thread thread, TextWriter writer) { + private static boolean dumpThread(Thread thread, TextWriter writer) { ThreadSnapshot snapshot = ThreadSnapshot.of(thread); + if (snapshot == null) { + return false; // thread terminated + } Instant now = Instant.now(); Thread.State state = snapshot.threadState(); writer.println("#" + thread.threadId() + " \"" + snapshot.threadName() @@ -217,6 +220,7 @@ private static void dumpThread(Thread thread, TextWriter writer) { depth++; } writer.println(); + return true; } /** @@ -284,8 +288,9 @@ private static void dumpThreads(ThreadContainer container, JsonWriter jsonWriter Iterator threads = container.threads().iterator(); while (threads.hasNext()) { Thread thread = threads.next(); - dumpThread(thread, jsonWriter); - threadCount++; + if (dumpThread(thread, jsonWriter)) { + threadCount++; + } } jsonWriter.endArray(); // threads @@ -303,11 +308,15 @@ private static void dumpThreads(ThreadContainer container, JsonWriter jsonWriter /** * Write a thread to the given JSON writer. + * @return true if the thread dump was written, false otherwise * @throws UncheckedIOException if an I/O error occurs */ - private static void dumpThread(Thread thread, JsonWriter jsonWriter) { + private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) { Instant now = Instant.now(); ThreadSnapshot snapshot = ThreadSnapshot.of(thread); + if (snapshot == null) { + return false; // thread terminated + } Thread.State state = snapshot.threadState(); StackTraceElement[] stackTrace = snapshot.stackTrace(); @@ -369,6 +378,7 @@ private static void dumpThread(Thread thread, JsonWriter jsonWriter) { } jsonWriter.endObject(); + return true; } /** diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java b/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java index e0dd4bbc508..4fcbaf24d2e 100644 --- a/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java +++ b/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java @@ -52,12 +52,14 @@ private ThreadSnapshot() {} /** * Take a snapshot of a Thread to get all information about the thread. + * Return null if a ThreadSnapshot is not created, for example if the + * thread has terminated. * @throws UnsupportedOperationException if not supported by VM */ static ThreadSnapshot of(Thread thread) { ThreadSnapshot snapshot = create(thread); if (snapshot == null) { - throw new UnsupportedOperationException(); + return null; // thread terminated } if (snapshot.stackTrace == null) { snapshot.stackTrace = EMPTY_STACK; diff --git a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java index 4a8ad79b50c..d3705a279ca 100644 --- a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -491,8 +491,8 @@ public interface LoadVectorOperationWithMap vClass, Class mClass, Class eClass, int length, Class> vectorIndexClass, - Object base, long offset, - W index_vector, + int indexLength, Object base, long offset, + W indexVector1, W indexVector2, W indexVector3, W indexVector4, M m, C container, int index, int[] indexMap, int indexM, S s, LoadVectorOperationWithMap defaultImpl) { assert isNonCapturingLambda(defaultImpl) : defaultImpl; @@ -558,8 +558,8 @@ public interface StoreVectorOperationWithMap vClass, Class mClass, Class eClass, int length, Class> vectorIndexClass, - Object base, long offset, - W index_vector, + int indexLength, Object base, long offset, + W indexVector, V v, M m, C container, int index, int[] indexMap, int indexM, StoreVectorOperationWithMap defaultImpl) { assert isNonCapturingLambda(defaultImpl) : defaultImpl; diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties index 1f922b4cf73..79b5968b210 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -34,8 +34,8 @@ java.launcher.opt.footer = \ -cp ...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ - Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n +java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die minimale und die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ + Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\nDie folgenden Optionen sind für macOS spezifisch:\n -XstartOnFirstThread\n Führt die main()-Methode für den ersten (AppKit-)Thread aus\n -Xdock:name=\n Setzt den im Dock angezeigten Standardanwendungsnamen außer Kraft\n -Xdock:icon=\n Setzt das im Dock angezeigte Standardsymbol außer Kraft\n\n @@ -51,6 +51,7 @@ java.launcher.cls.error4=Fehler: Beim Laden der Klasse {0} ist ein LinkageError java.launcher.cls.error5=Fehler: Hauptklasse {0} kann nicht initialisiert werden\nUrsache: {1}: {2} java.launcher.cls.error6=Fehler: Kein nicht privater Null-Argument-Konstruktor in Klasse {0} gefunden\nEntfernen Sie die Eigenschaft "private" aus dem vorhandenen Konstruktor, oder definieren Sie ihn als:\n public {0}() java.launcher.cls.error7=Fehler: Konstruktor mit nicht statischer innerer Klasse {0} kann nicht aufgerufen werden \nLegen Sie die innere Klasse als statisch fest, oder verschieben Sie sie in eine separate Quelldatei +java.launcher.cls.error8=Fehler: Abstrakte Klasse {0} kann nicht instanziiert werden.\nVerwenden Sie eine konkrete Klasse java.launcher.jar.error1=Fehler: Beim Versuch, Datei {0} zu öffnen, ist ein unerwarteter Fehler aufgetreten java.launcher.jar.error2=Manifest in {0} nicht gefunden java.launcher.jar.error3=kein Hauptmanifestattribut, in {0} diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties index c6f1b8b330a..04b68db3a8e 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -35,7 +35,7 @@ java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイ -disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの初期ヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ +java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの最小および初期のヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ これはテスト・オプションであり、断続的な失敗につながる\n 可能性があります。本番環境では使用しないでください。\n -XshowSettings すべての設定を表示して続行します\n -XshowSettings:all\n すべての設定を詳細に表示して続行します\n -XshowSettings:locale\n すべてのロケール関連の設定を表示して続行します\n -XshowSettings:properties\n すべてのプロパティ設定を表示して続行します\n -XshowSettings:vm\n すべてのVM関連の設定を表示して続行します\n -XshowSettings:security\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:all\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:properties\n セキュリティ・プロパティを表示して続行します\n -XshowSettings:security:providers\n 静的セキュリティ・プロバイダ設定を表示して続行します\n -XshowSettings:security:tls\n TLS関連のセキュリティ設定を表示して続行します\n -XshowSettings:system\n (Linuxのみ)ホスト・システムまたはコンテナを表示します\n 構成して続行します\n -Xss javaスレッドのスタック・サイズを設定します\n 実際のサイズは、次の倍数に切り上げられる場合があります: \n オペレーティング・システムの要件に応じたシステム・ページ・サイズ。\n -Xverify バイトコード・ベリファイアのモードを設定します\n オプション-Xverify:noneは非推奨になり、\n 将来のリリースで削除される可能性があります。\n --add-reads =(,)*\n モジュール宣言に関係なく、を更新してを\n 読み取ります。 \n をALL-UNNAMEDに設定すると、すべての名前のないモジュールを\n 読み取ることができます。\n --add-exports \ /=(,)*\n モジュール宣言に関係なく、を更新してに\n エクスポートします。\n をALL-UNNAMEDに設定すると、すべての名前のないモジュールに\n エクスポートできます。\n --add-opens /=(,)*\n モジュール宣言に関係なく、を更新してを\n に開きます。\n --limit-modules [,...]\n 参照可能なモジュールの領域を制限します\n --patch-module =({0})*\n JARファイルまたはディレクトリのクラスおよびリソースで\n モジュールをオーバーライドまたは拡張します。\n --source \n ソースファイル・モードでソースのバージョンを設定します。\n --finalization=\n JVMがオブジェクトのファイナライズを実行するかどうかを制御します\n は"enabled"または"disabled"のいずれかです。\n ファイナライズはデフォルトで有効になっています。\n --sun-misc-unsafe-memory-access=\n サポートされていないAPI sun.misc.Unsafeの使用を許可または拒否します\n は"allow"、"warn"、"debug"または"deny"のいずれかです。\n デフォルト値は"warn"です。\n\nこの追加オプションは予告なしに変更されることがあります。\n @@ -53,6 +53,7 @@ java.launcher.cls.error4=エラー: メイン・クラス{0}のロード中にLi java.launcher.cls.error5=エラー: メイン・クラス{0}を初期化できません\n原因: {1}: {2} java.launcher.cls.error6=エラー: 非privateのゼロ引数コンストラクタがクラス{0}に見つかりません\n既存のコンストラクタからprivateを削除するか、次のように定義してください:\n public {0}() java.launcher.cls.error7=エラー: staticでない内部クラス{0}コンストラクタを起動できません \n内部クラスをstaticにするか、内部クラスを外部に出してソース・ファイルを区別してください +java.launcher.cls.error8=エラー: 抽象クラス{0}はインスタンス化できません\n具象クラスを使用してください java.launcher.jar.error1=エラー: ファイル{0}を開こうとしているときに、予期しないエラーが発生しました java.launcher.jar.error2={0}にマニフェストが見つかりません java.launcher.jar.error3={0}にメイン・マニフェスト属性がありません diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties index 56d774b47db..ec466bf3019 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -34,7 +34,7 @@ java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径> 将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ +java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置最小和初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ 相关的安全设置并继续\n -XshowSettings:system\n (仅 Linux)显示主机系统或容器\n 配置并继续\n -Xss 设置 Java 线程堆栈大小\n 实际大小可以舍入到\n 操作系统要求的系统页面大小的倍数。\n -Xverify 设置字节码验证器的模式\n 请注意,选项 -Xverify:none 已过时,\n 可能会在未来发行版中删除。\n --add-reads =(,)*\n 更新 以读取 ,而无论\n 模块如何声明。 \n 可以是 ALL-UNNAMED,将读取所有未命名\n 模块。\n --add-exports /=(,)*\n 更新 以将 导出到 ,\n 而无论模块如何声明。\n 可以是 ALL-UNNAMED,将导出到所有\n 未命名模块。\n --add-opens /=(,)*\n 更新 以在 中打开\n ,而无论模块如何声明。\n --limit-modules [,...]\n 限制可观察模块的领域\n --patch-module =({0})*\n 使用 JAR 文件或目录中的类和资源\n 覆盖或增强模块。\n --source \n 设置源文件模式中源的版本。\n --finalization=\n 控制 JVM 是否执行对象最终处理,\n 其中 为 "enabled" 或 "disabled" 之一。\n 默认情况下,最终处理处于启用状态。\n --sun-misc-unsafe-memory-access=\n 允许或拒绝使用不受支持的 API sun.misc.Unsafe\n 为 "allow"、"warn"、"debug" 或 "deny" 之一。\n 默认值为 "warn"。\n\n这些额外选项如有更改, 恕不另行通知。\n # Translators please note do not translate the options themselves @@ -51,6 +51,7 @@ java.launcher.cls.error4=错误: 加载主类 {0} 时出现 LinkageError\n\t{1} java.launcher.cls.error5=错误: 无法初始化主类 {0}\n原因: {1}: {2} java.launcher.cls.error6=错误:在类 {0} 中未找到非专用零参数构造器\n请从现有构造器中删除专用,或者定义为:\n public {0}() java.launcher.cls.error7=错误:无法调用非静态内部类 {0} 构造器\n请将内部类设为静态或将内部类移出到单独的源文件 +java.launcher.cls.error8=错误:无法实例化抽象类 {0}\n请使用具体类 java.launcher.jar.error1=错误: 尝试打开文件{0}时出现意外错误 java.launcher.jar.error2=在{0}中找不到清单 java.launcher.jar.error3={0}中没有主清单属性 diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index d5c9a3feb44..1d6876f760e 100644 --- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -24,8 +24,6 @@ */ package sun.net.ftp.impl; - - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -61,6 +59,7 @@ import java.util.regex.Pattern; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; + import sun.net.ftp.FtpDirEntry; import sun.net.ftp.FtpDirParser; import sun.net.ftp.FtpProtocolException; @@ -68,6 +67,7 @@ import sun.net.util.IPAddressUtil; import sun.util.logging.PlatformLogger; +import static sun.net.util.ProxyUtil.copyProxy; public class FtpClient extends sun.net.ftp.FtpClient { @@ -954,7 +954,7 @@ public int getReadTimeout() { } public sun.net.ftp.FtpClient setProxy(Proxy p) { - proxy = p; + proxy = copyProxy(p); return this; } diff --git a/src/java.desktop/share/classes/java/applet/AudioClip.java b/src/java.base/share/classes/sun/net/util/ProxyUtil.java similarity index 59% rename from src/java.desktop/share/classes/java/applet/AudioClip.java rename to src/java.base/share/classes/sun/net/util/ProxyUtil.java index 50638ec215e..dfb60671e37 100644 --- a/src/java.desktop/share/classes/java/applet/AudioClip.java +++ b/src/java.base/share/classes/sun/net/util/ProxyUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,33 +23,27 @@ * questions. */ -package java.applet; +package sun.net.util; -/** - * The {@code AudioClip} interface is a simple abstraction for playing a sound - * clip. Multiple {@code AudioClip} items can be playing at the same time, and - * the resulting sound is mixed together to produce a composite. - * - * @author Arthur van Hoff - * @since 1.0 - * @deprecated The Applet API is deprecated, no replacement. - */ -@Deprecated(since = "9", forRemoval = true) -public interface AudioClip { +import sun.net.ApplicationProxy; - /** - * Starts playing this audio clip. Each time this method is called, the clip - * is restarted from the beginning. - */ - void play(); +import java.net.Proxy; - /** - * Starts playing this audio clip in a loop. - */ - void loop(); +public final class ProxyUtil { + + private ProxyUtil() {} /** - * Stops playing this audio clip. + * Creates a new {@link Proxy} instance for the given proxy iff it is + * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an + * {@link ApplicationProxy} instance, nor already a {@code Proxy} instance. */ - void stop(); + public static Proxy copyProxy(Proxy proxy) { + return proxy == null + || proxy.getClass() == Proxy.class + || proxy instanceof ApplicationProxy + ? proxy + : new Proxy(proxy.type(), proxy.address()); + } + } diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 1ab7396ad06..82ab4c199a5 100644 --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -41,6 +41,8 @@ import sun.net.www.protocol.http.AuthCacheImpl; import sun.net.www.protocol.http.HttpURLConnection; import sun.util.logging.PlatformLogger; + +import static sun.net.util.ProxyUtil.copyProxy; import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*; /** @@ -261,7 +263,7 @@ public HttpClient(URL url, String proxyHost, int proxyPort) } protected HttpClient(URL url, Proxy p, int to) throws IOException { - proxy = (p == null) ? Proxy.NO_PROXY : p; + proxy = p == null ? Proxy.NO_PROXY : copyProxy(p); this.host = url.getHost(); this.url = url; port = url.getPort(); @@ -326,9 +328,7 @@ public static HttpClient New(URL url, boolean useCache) public static HttpClient New(URL url, Proxy p, int to, boolean useCache, HttpURLConnection httpuc) throws IOException { - if (p == null) { - p = Proxy.NO_PROXY; - } + p = p == null ? Proxy.NO_PROXY : copyProxy(p); HttpClient ret = null; /* see if one's already around */ if (useCache) { diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index be24f1133f2..eb7a819bd47 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -43,6 +43,7 @@ import java.util.List; import java.util.StringTokenizer; import java.security.Permission; + import sun.net.NetworkClient; import sun.net.util.IPAddressUtil; import sun.net.www.MessageHeader; @@ -53,6 +54,7 @@ import sun.net.ftp.FtpProtocolException; import sun.net.www.ParseUtil; +import static sun.net.util.ProxyUtil.copyProxy; /** * This class Opens an FTP input (or output) stream given a URL. @@ -234,7 +236,7 @@ public synchronized void connect() throws IOException { throw new IOException("Failed to select a proxy", iae); } for (Proxy proxy : proxies) { - p = proxy; + p = copyProxy(proxy); if (p == null || p == Proxy.NO_PROXY || p.type() == Proxy.Type.SOCKS) { break; diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java index 1de4c52abea..53fa355cb01 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java +++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -33,11 +33,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.Proxy; -import java.util.Map; -import java.util.HashMap; import java.util.Objects; -import sun.net.ftp.FtpClient; -import sun.net.www.protocol.http.HttpURLConnection; + +import static sun.net.util.ProxyUtil.copyProxy; /** open an ftp connection given a URL */ public class Handler extends java.net.URLStreamHandler { @@ -57,11 +55,11 @@ protected java.net.URLConnection openConnection(URL u) return openConnection(u, null); } - protected java.net.URLConnection openConnection(URL u, Proxy p) + protected java.net.URLConnection openConnection(URL u, Proxy proxy) throws IOException { - FtpURLConnection connection = null; + FtpURLConnection connection; try { - connection = new FtpURLConnection(u, p); + connection = new FtpURLConnection(u, copyProxy(proxy)); } catch (IllegalArgumentException e) { var mfue = new MalformedURLException(e.getMessage()); mfue.initCause(e); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index b66d9ddb8cb..857c2f6ad6d 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -77,6 +77,7 @@ import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; +import static sun.net.util.ProxyUtil.copyProxy; import static sun.net.www.protocol.http.AuthScheme.BASIC; import static sun.net.www.protocol.http.AuthScheme.DIGEST; import static sun.net.www.protocol.http.AuthScheme.NTLM; @@ -854,7 +855,7 @@ protected HttpURLConnection(URL u, Proxy p, Handler handler) responses = new MessageHeader(maxHeaderSize); userHeaders = new MessageHeader(); this.handler = handler; - instProxy = p; + instProxy = copyProxy(p); cookieHandler = CookieHandler.getDefault(); cacheHandler = ResponseCache.getDefault(); } @@ -956,7 +957,7 @@ protected void plainConnect0() throws IOException { final Iterator it = proxies.iterator(); Proxy p; while (it.hasNext()) { - p = it.next(); + p = copyProxy(it.next()); try { if (!failedOnce) { http = getNewHttpClient(url, p, connectTimeout); diff --git a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java index 20b735fbdf3..b2133144d2f 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java @@ -34,7 +34,7 @@ import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReader.Node; -import jdk.internal.jimage.ImageReaderFactory; +import jdk.internal.jimage.SystemImageReader; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; @@ -48,7 +48,7 @@ public class JavaRuntimeURLConnection extends URLConnection { // ImageReader to access resources in jimage. - private static final ImageReader READER = ImageReaderFactory.getImageReader(); + private static final ImageReader READER = SystemImageReader.get(); // The module and resource name in the URL (i.e. "jrt:/[$MODULE[/$PATH]]"). // @@ -87,8 +87,8 @@ private synchronized Node connectResourceNode() throws IOException { if (module.isEmpty() || path == null) { throw new IOException("cannot connect to jrt:/" + module); } - Node node = READER.findNode("/modules/" + module + "/" + path); - if (node == null || !node.isResource()) { + Node node = READER.findResourceNode(module, path); + if (node == null) { throw new IOException(module + "/" + path + " not found"); } this.resourceNode = node; @@ -109,9 +109,11 @@ public InputStream getInputStream() throws IOException { @Override public long getContentLengthLong() { + // Note: UncheckedIOException is thrown by the Node subclass in + // ExplodedImage (this not obvious, so worth calling out). try { return connectResourceNode().size(); - } catch (IOException ioe) { + } catch (IOException | UncheckedIOException ioe) { return -1L; } } @@ -124,6 +126,10 @@ public int getContentLength() { // Perform percent decoding of the resource name/path from the URL. private static String percentDecode(String path) throws MalformedURLException { + if (path.indexOf('%') == -1) { + // Nothing to decode (overwhelmingly common case). + return path; + } // Any additional special case decoding logic should go here. try { return ParseUtil.decode(path); diff --git a/src/java.base/share/classes/sun/nio/Cleaner.java b/src/java.base/share/classes/sun/nio/Cleaner.java new file mode 100644 index 00000000000..8be99705d06 --- /dev/null +++ b/src/java.base/share/classes/sun/nio/Cleaner.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package sun.nio; + +/** + * {@code Cleaner} represents an object and a cleaning action. + */ +public interface Cleaner { + /** + * Unregisters the cleaner and invokes the cleaning action. + * The cleaner's cleaning action is invoked at most once, + * regardless of the number of calls to {@code clean}. + */ + void clean(); +} diff --git a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java index 8fcea1eb57d..794ea7a0a0b 100644 --- a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java +++ b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,7 +25,7 @@ package sun.nio.ch; -import jdk.internal.ref.Cleaner; +import sun.nio.Cleaner; public interface DirectBuffer { diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 240405c2f7c..7f37ad36452 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -58,11 +58,11 @@ import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.misc.VM.BufferPool; -import jdk.internal.ref.Cleaner; import jdk.internal.ref.CleanerFactory; import jdk.internal.event.FileReadEvent; import jdk.internal.event.FileWriteEvent; import jdk.internal.access.foreign.UnmapperProxy; +import sun.nio.Cleaner; public class FileChannelImpl extends FileChannel diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java index c055673b45b..609a81571ed 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java @@ -1097,6 +1097,15 @@ public void consume(ConnectionContext context, // clean up this consumer hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id); + + // Ensure that the Certificate message has not been sent w/o + // an EncryptedExtensions preceding + if (hc.handshakeConsumers.containsKey( + SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { + throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Certificate handshake message"); + } + T13CertificateMessage cm = new T13CertificateMessage(hc, message); if (hc.sslConfig.isClientMode) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java index 518a525b12f..09d07d8e62d 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -1163,6 +1163,14 @@ public void consume(ConnectionContext context, // Clean up this consumer hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id); + // Ensure that the Certificate Verify message has not been sent w/o + // a Certificate message preceding + if (hc.handshakeConsumers.containsKey( + SSLHandshake.CERTIFICATE.id)) { + throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Certificate Verify handshake message"); + } + T13CertificateVerifyMessage cvm = new T13CertificateVerifyMessage(hc, message); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { diff --git a/src/java.base/share/classes/sun/security/ssl/Finished.java b/src/java.base/share/classes/sun/security/ssl/Finished.java index e388672cb7f..9421d12ec15 100644 --- a/src/java.base/share/classes/sun/security/ssl/Finished.java +++ b/src/java.base/share/classes/sun/security/ssl/Finished.java @@ -899,6 +899,14 @@ public void consume(ConnectionContext context, private void onConsumeFinished(ClientHandshakeContext chc, ByteBuffer message) throws IOException { + // Ensure that the Finished message has not been sent w/o + // an EncryptedExtensions preceding + if (chc.handshakeConsumers.containsKey( + SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { + throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Finished handshake message"); + } + // Make sure that any expected CertificateVerify message // has been received and processed. if (!chc.isResumption) { diff --git a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java index 5c2a09b7c03..b3155f5170a 100644 --- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java +++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -187,7 +187,7 @@ boolean isCookieValid(ServerHandshakeContext context, byte[] secret; d10ManagerLock.lock(); try { - if (((cookieVersion >> 24) & 0xFF) == cookie[0]) { + if ((byte) ((cookieVersion >> 24) & 0xFF) == cookie[0]) { secret = cookieSecret; } else { secret = legacySecret; // including out of window cookies diff --git a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java index 2df6d26ff31..98e4693e917 100644 --- a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -46,7 +46,7 @@ final class KeyShareExtension { new CHKeyShareProducer(); static final ExtensionConsumer chOnLoadConsumer = new CHKeyShareConsumer(); - static final HandshakeAbsence chOnTradAbsence = + static final HandshakeAbsence chOnTradeAbsence = new CHKeyShareOnTradeAbsence(); static final SSLStringizer chStringizer = new CHKeyShareStringizer(); diff --git a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java index 76bb64a66c3..819fdd589cb 100644 --- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java @@ -58,7 +58,7 @@ final class PreSharedKeyExtension { new CHPreSharedKeyOnLoadAbsence(); static final HandshakeConsumer chOnTradeConsumer = new CHPreSharedKeyUpdate(); - static final HandshakeAbsence chOnTradAbsence = + static final HandshakeAbsence chOnTradeAbsence = new CHPreSharedKeyOnTradeAbsence(); static final SSLStringizer chStringizer = new CHPreSharedKeyStringizer(); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLExtension.java b/src/java.base/share/classes/sun/security/ssl/SSLExtension.java index b28ef763796..c7175ea7fdc 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -142,7 +142,7 @@ enum SSLExtension implements SSLStringizer { SupportedGroupsExtension.chOnLoadConsumer, null, null, - SupportedGroupsExtension.chOnTradAbsence, + SupportedGroupsExtension.chOnTradeAbsence, SupportedGroupsExtension.sgsStringizer), EE_SUPPORTED_GROUPS (0x000A, "supported_groups", SSLHandshake.ENCRYPTED_EXTENSIONS, @@ -433,7 +433,7 @@ enum SSLExtension implements SSLStringizer { KeyShareExtension.chOnLoadConsumer, null, null, - KeyShareExtension.chOnTradAbsence, + KeyShareExtension.chOnTradeAbsence, KeyShareExtension.chStringizer), SH_KEY_SHARE (0x0033, "key_share", SSLHandshake.SERVER_HELLO, @@ -486,7 +486,7 @@ enum SSLExtension implements SSLStringizer { PreSharedKeyExtension.chOnLoadConsumer, PreSharedKeyExtension.chOnLoadAbsence, PreSharedKeyExtension.chOnTradeConsumer, - PreSharedKeyExtension.chOnTradAbsence, + PreSharedKeyExtension.chOnTradeAbsence, PreSharedKeyExtension.chStringizer), SH_PRE_SHARED_KEY (0x0029, "pre_shared_key", SSLHandshake.SERVER_HELLO, diff --git a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java index d6e1391d09b..57e5f8c9093 100644 --- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -47,7 +47,7 @@ final class SupportedGroupsExtension { new CHSupportedGroupsProducer(); static final ExtensionConsumer chOnLoadConsumer = new CHSupportedGroupsConsumer(); - static final HandshakeAbsence chOnTradAbsence = + static final HandshakeAbsence chOnTradeAbsence = new CHSupportedGroupsOnTradeAbsence(); static final SSLStringizer sgsStringizer = new SupportedGroupsStringizer(); diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties index 6290bb2a7ac..1c7a9cd17cf 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties @@ -27,7 +27,7 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... +.OPTION.=\ [OPTION]... Options.=Optionen: option.1.set.twice=Die Option %s wurde mehrmals angegeben. Alle Angaben bis auf die letzte werden ignoriert. multiple.commands.1.2=Nur ein Befehl ist zulässig: Sowohl %1$s als auch %2$s wurden angegeben. @@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=Zertifikatsantwort wurde in Keystore Certificate.reply.was.not.installed.in.keystore=Zertifikatsantwort wurde nicht in Keystore installiert Certificate.was.added.to.keystore=Zertifikat wurde Keystore hinzugefügt Certificate.was.not.added.to.keystore=Zertifikat wurde nicht zu Keystore hinzugefügt -.Storing.ksfname.=[{0} wird gesichert] +.Storing.ksfname.=[{0} wird gespeichert] alias.has.no.public.key.certificate.={0} hat keinen Public Key (Zertifikat) Cannot.derive.signature.algorithm=Signaturalgorithmus kann nicht abgeleitet werden Alias.alias.does.not.exist=Alias <{0}> ist nicht vorhanden @@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=Alias <{0}> hat kein Zertifikat groupname.keysize.coexist=Es können nicht sowohl -groupname als auch -keysize angegeben werden deprecate.keysize.for.ec=Das Angeben von -keysize zum Generieren von EC-Schlüsseln ist veraltet. Verwenden Sie stattdessen "-groupname %s". Key.pair.not.generated.alias.alias.already.exists=Schlüsselpaar wurde nicht generiert. Alias <{0}> ist bereits vorhanden -size.bit.alg=%1$d-Bit %2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Schlüsselpaar {0} und selbstsigniertes Zertifikat ({1}) werden mit einer Gültigkeit von {2} Tagen generiert\n\tfür: {3} -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Schlüsselpaar {0} und Zertifikat ({1}) werden generiert, das von <{2}> mit einer Gültigkeit von {3} Tagen ausgestellt wurde\n\tfür: {4} +size.bit.alg=%1$d-Bit-%2$s +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und selbstsigniertem Zertifikat ({1}) mit einer Gültigkeit von {2} Tagen\n\tfür: {3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und einem von <{2}> ausgestellten Zertifikat ({1}) mit einer Gültigkeit von {3} Tagen\n\tfür: {4} Enter.key.password.for.alias.=Schlüsselkennwort für <{0}> eingeben .RETURN.if.same.as.keystore.password.=\t(RETURN, wenn identisch mit Keystore-Kennwort): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=Schlüsselkennwort ist zu kurz. Es muss mindestens sechs Zeichen lang sein @@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=Möchten Sie es trotzdem hinzufügen? [Nein]: \u Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=Zertifikat ist bereits unter Alias <{0}> im systemweiten CA-Keystore vorhanden Do.you.still.want.to.add.it.to.your.own.keystore.no.=Möchten Sie es trotzdem zu Ihrem eigenen Keystore hinzufügen? [Nein]: \u0020 Trust.this.certificate.no.=Diesem Zertifikat vertrauen? [Nein]: \u0020 -New.prompt.=Neues {0}:\u0020 +New.prompt.={0} (neu):\u0020 Passwords.must.differ=Kennwörter müssen sich unterscheiden Re.enter.new.prompt.=Neues {0} erneut eingeben:\u0020 Re.enter.password.=Geben Sie das Kennwort erneut ein:\u0020 @@ -238,7 +238,7 @@ Is.name.correct.=Ist {0} richtig? no=Nein yes=Ja y=J -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=Alias <{0}> verfügt über keinen Schlüssel Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=Alias <{0}> verweist auf einen Eintragstyp, der kein Private-Key-Eintrag ist. Der Befehl -keyclone unterstützt nur das Klonen von Private-Key-Einträgen @@ -302,8 +302,8 @@ alias.in.keystore=Aussteller <%s> with.weak=%s (schwach) with.disabled=%s (deaktiviert) key.bit=%s-Schlüssel -key.bit.weak=%s Schlüssel (schwach) -key.bit.disabled=%s Schlüssel (deaktiviert) +key.bit.weak=%s-Schlüssel (schwach) +key.bit.disabled=%s-Schlüssel (deaktiviert) .PATTERN.printX509Cert.with.weak=Eigentümer: {0}\nAussteller: {1}\nSeriennummer: {2}\nGültig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic-Key-Algorithmus von Subject: {8}\nVersion: {9} PKCS.10.with.weak=PKCS #10-Zertifikatsanforderung (Version 1.0)\nSubject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignaturalgorithmus: %4$s\n verified.by.s.in.s.weak=Von %1$s in %2$s mit %3$s verifiziert @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s verwendet den Signaturalgorithmus %2$s. Das gil Unable.to.parse.denyAfter.string.in.exception.message=denyAfter-Datumszeichenfolge in Ausnahmemeldung kann nicht geparst werden whose.sigalg.weak=%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko. whose.key.disabled=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert. -whose.key.weak=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Wird in einem zukünftigen Update deaktiviert. +whose.key.weak=%1$s verwendet %2$s. Das gilt als Sicherheitsrisiko. Dieser Schlüssel wird in einem zukünftigen Update deaktiviert. jks.storetype.warning=Der %1$s-Keystore verwendet ein proprietäres Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" ist. migrate.keystore.warning="%1$s" zu %4$s migriert. Der %2$s-Keystore wurde als "%3$s" gesichert. backup.keystore.warning=Der ursprüngliche Keystore "%1$s" wird als "%3$s" gesichert... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties index 416cf51007f..63ba4f220dd 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties @@ -27,7 +27,7 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... +.OPTION.=\ [OPTION]... Options.=オプション: option.1.set.twice=%sオプションが複数回指定されています。最後のもの以外はすべて無視されます。 multiple.commands.1.2=1つのコマンドのみ許可されます: %1$sと%2$sの両方が指定されました。 @@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=別名<{0}>には証明書がありません groupname.keysize.coexist=-groupnameと-keysizeの両方を指定できません deprecate.keysize.for.ec=-keysizeの指定によるECキーの生成は非推奨です。かわりに"-groupname %s"を使用してください。 Key.pair.not.generated.alias.alias.already.exists=キー・ペアは生成されませんでした。別名<{0}>はすでに存在します -size.bit.alg=%1$dビット%2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={0}キー・ペアおよび自己署名証明書({1})を{2}日の有効性で生成しています\n\t対象: {3} -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={0}キー・ペアと<{2}>によって発行された証明書({1})を{3}日間の有効性で生成しています\n\t対象: {4} +size.bit.alg=%1$d-ビット %2$s +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={2}日間有効な{0}のキー・ペアと自己署名型証明書({1})を生成しています\n\tディレクトリ名: {3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={3}日間有効な{0}キー・ペアと<{2}>によって発行される証明書({1})を生成しています\n\tディレクトリ名: {4} Enter.key.password.for.alias.=<{0}>のキー・パスワードを入力してください .RETURN.if.same.as.keystore.password.=\t(キーストアのパスワードと同じ場合はRETURNを押してください): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=キーのパスワードが短すぎます - 6文字以上を指定してください @@ -227,18 +227,18 @@ Enter.new.alias.name.RETURN.to.cancel.import.for.this.entry.=新しい別名を Enter.alias.name.=別名を入力してください: \u0020 .RETURN.if.same.as.for.otherAlias.=\t(<{0}>と同じ場合はRETURNを押してください) enter.dname.components=識別名を入力します。サブコンポーネントを空のままにする場合はドット(.)を1つ入力し、中カッコ内のデフォルト値を使用する場合は[ENTER]を押します。 -What.is.your.first.and.last.name.=姓名は何ですか。 -What.is.the.name.of.your.organizational.unit.=組織単位名は何ですか。 -What.is.the.name.of.your.organization.=組織名は何ですか。 -What.is.the.name.of.your.City.or.Locality.=都市名または地域名は何ですか。 -What.is.the.name.of.your.State.or.Province.=都道府県名または州名は何ですか。 -What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードは何ですか。 +What.is.your.first.and.last.name.=姓名を入力してください。 +What.is.the.name.of.your.organizational.unit.=組織単位名を入力してください。 +What.is.the.name.of.your.organization.=組織名を入力してください。 +What.is.the.name.of.your.City.or.Locality.=都市名または地域名を入力してください。 +What.is.the.name.of.your.State.or.Province.=都道府県名を入力してください。 +What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードを入力してください。 no.field.in.dname=少なくとも1つのフィールドを指定する必要があります。再度入力してください。 Is.name.correct.={0}でよろしいですか。 no=いいえ yes=はい y=y -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=別名<{0}>にはキーがありません Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=別名<{0}>が参照しているエントリ・タイプは秘密キー・エントリではありません。-keycloneコマンドは秘密キー・エントリのクローン作成のみをサポートします @@ -292,7 +292,7 @@ the.certificate=証明書 the.crl=CRL the.tsa.certificate=TSA証明書 the.input=入力 -reply=応答 +reply=返信 one.in.many=%1$s #%2$d / %3$d one.in.many1=%1$s #%2$d one.in.many2=署名者の%1$s #%2$d @@ -302,7 +302,7 @@ alias.in.keystore=発行者<%s> with.weak=%s (弱) with.disabled=%s (無効) key.bit=%sキー -key.bit.weak=%sキー(弱い) +key.bit.weak=%sキー(弱) key.bit.disabled=%sキー(無効) .PATTERN.printX509Cert.with.weak=所有者: {0}\n発行者: {1}\nシリアル番号: {2}\n有効期間の開始日: {3}終了日: {4}\n証明書のフィンガプリント:\n\t SHA1: {5}\n\t SHA256: {6}\n署名アルゴリズム名: {7}\nサブジェクト公開キー・アルゴリズム: {8}\nバージョン: {9} PKCS.10.with.weak=PKCS #10証明書リクエスト(バージョン1.0)\nサブジェクト: %1$s\nフォーマット: %2$s\n公開キー: %3$s\n署名アルゴリズム: %4$s\n @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$sは%2$s署名アルゴリズムを使用して Unable.to.parse.denyAfter.string.in.exception.message=例外メッセージのdenyAfter日付文字列を解析できません whose.sigalg.weak=%1$sは%2$s署名アルゴリズムを使用しており、これはセキュリティ・リスクとみなされます。 whose.key.disabled=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされ、無効化されています。 -whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。今後の更新では無効になります。 +whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。 jks.storetype.warning=%1$sキーストアは独自の形式を使用しています。"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12"を使用する業界標準の形式であるPKCS12に移行することをお薦めします。 migrate.keystore.warning="%1$s"が%4$sに移行されました。%2$sキーストアは"%3$s"としてバックアップされます。 backup.keystore.warning=元のキーストア"%1$s"は"%3$s"としてバックアップされます... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties index 5aa27eb2ed4..1f96aa12c57 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties @@ -27,13 +27,13 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... -Options.=选项: +.OPTION.=\ [OPTION]... +Options.=选项: option.1.set.twice=多次指定了 %s 选项。除最后一个之外, 其余的将全部忽略。 multiple.commands.1.2=只允许一个命令: 同时指定了 %1$s 和 %2$s。 Use.keytool.help.for.all.available.commands=使用 "keytool -?, -h, or --help" 可输出此帮助消息 Key.and.Certificate.Management.Tool=密钥和证书管理工具 -Commands.=命令: +Commands.=命令: Use.keytool.command.name.help.for.usage.of.command.name=使用 "keytool -command_name --help" 可获取 command_name 的用法。\n使用 -conf 选项可指定预配置的选项文件。 # keytool: help: commands Generates.a.certificate.request=生成证书请求 @@ -114,7 +114,7 @@ verbose.output=详细输出 validity.number.of.days=有效天数 Serial.ID.of.cert.to.revoke=要撤销的证书的序列 ID # keytool: Running part -keytool.error.=keytool 错误:\u0020 +keytool.error.=keytool 错误:\u0020 Illegal.option.=非法选项: \u0020 Illegal.value.=非法值:\u0020 Unknown.password.type.=未知口令类型:\u0020 @@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=证书回复已安装在密钥库中 Certificate.reply.was.not.installed.in.keystore=证书回复未安装在密钥库中 Certificate.was.added.to.keystore=证书已添加到密钥库中 Certificate.was.not.added.to.keystore=证书未添加到密钥库中 -.Storing.ksfname.=[正在存储{0}] +.Storing.ksfname.=[正在存储 {0}] alias.has.no.public.key.certificate.={0}没有公共密钥 (证书) Cannot.derive.signature.algorithm=无法派生签名算法 Alias.alias.does.not.exist=别名 <{0}> 不存在 @@ -179,8 +179,8 @@ groupname.keysize.coexist=无法同时指定 -groupname 和 -keysize deprecate.keysize.for.ec=为生成 EC 密钥指定 -keysize 已过时,请改为使用 "-groupname %s"。 Key.pair.not.generated.alias.alias.already.exists=未生成密钥对, 别名 <{0}> 已经存在 size.bit.alg=%1$d 位 %2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为 {3} 生成有效期为 {2} 天的 {0} 密钥对和自签名证书 ({1})\n -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=生成 {0} 密钥对和 <{2}> 颁发的证书 ({1}),有效期为 {3} 天 \n\t 对于:{4} +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和自签名证书 ({1})(有效期为 {2} 天):\n\t{3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和由 <{2}> 颁发的证书 ({1})(有效期为 {3} 天):\n\t{4} Enter.key.password.for.alias.=输入 <{0}> 的密钥口令 .RETURN.if.same.as.keystore.password.=\t(如果和密钥库口令相同, 按回车): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=密钥口令太短 - 至少必须为 6 个字符 @@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=是否仍要添加? [否]: \u0020 Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=在别名 <{0}> 之下, 证书已经存在于系统范围的 CA 密钥库中 Do.you.still.want.to.add.it.to.your.own.keystore.no.=是否仍要将它添加到自己的密钥库? [否]: \u0020 Trust.this.certificate.no.=是否信任此证书? [否]: \u0020 -New.prompt.=新{0}:\u0020 +New.prompt.=新 {0}:\u0020 Passwords.must.differ=口令不能相同 Re.enter.new.prompt.=重新输入新{0}:\u0020 Re.enter.password.=再次输入口令:\u0020 @@ -238,14 +238,14 @@ Is.name.correct.={0}是否正确? no=否 yes=是 y=y -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=别名 <{0}> 没有密钥 Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=别名 <{0}> 引用了不属于私有密钥条目的条目类型。-keyclone 命令仅支持对私有密钥条目的克隆 .WARNING.WARNING.WARNING.=***************** WARNING WARNING WARNING ***************** -Signer.d.=签名者 #%d: +Signer.d.=签名者 #%d: Certificate.d.=证书 #%d: -Timestamp.=时间戳: +Timestamp.=时间戳: Certificate.owner.=证书所有者:\u0020 Not.a.signed.jar.file=不是已签名的 jar 文件 No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书 @@ -256,7 +256,7 @@ No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书 Certificate.reply.does.not.contain.public.key.for.alias.=证书回复中不包含 <{0}> 的公共密钥 Incomplete.certificate.chain.in.reply=回复中的证书链不完整 Top.level.certificate.in.reply.=回复中的顶级证书:\n -.is.not.trusted.=... 是不可信的。 +.is.not.trusted.=... 是不可信的。\u0020 Install.reply.anyway.no.=是否仍要安装回复? [否]: \u0020 Public.keys.in.reply.and.keystore.don.t.match=回复中的公共密钥与密钥库不匹配 Certificate.reply.and.certificate.in.keystore.are.identical=证书回复与密钥库中的证书是相同的 @@ -269,14 +269,14 @@ Please.provide.keysize.for.secret.key.generation=请提供 -keysize 以生成密 warning.not.verified.make.sure.keystore.is.correct=警告: 未验证。请确保密钥库是正确的。 warning.not.verified.make.sure.keystore.is.correct.or.specify.trustcacerts=警告:未验证。请确保密钥库是正确的,或者指定 -trustcacerts。 -Extensions.=扩展:\u0020 +Extensions.=扩展:\u0020 .Empty.value.=(空值) Extension.Request.=扩展请求: Unknown.keyUsage.type.=未知 keyUsage 类型:\u0020 Unknown.extendedkeyUsage.type.=未知 extendedkeyUsage 类型:\u0020 Unknown.AccessDescription.type.=未知 AccessDescription 类型:\u0020 Unrecognized.GeneralName.type.=无法识别的 GeneralName 类型:\u0020 -This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。 +This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。\u0020 Odd.number.of.hex.digits.found.=找到奇数个十六进制数字:\u0020 Unknown.extension.type.=未知扩展类型:\u0020 command.{0}.is.ambiguous.=命令{0}不明确: @@ -299,11 +299,11 @@ one.in.many2=签名者 #%2$d 的 %1$s one.in.many3=签名者 #%3$d 的 %1$s #%2$d alias.in.cacerts=cacerts 中的发布者 <%s> alias.in.keystore=发布者 <%s> -with.weak=%s (弱) +with.weak=%s(弱) with.disabled=%s(禁用) key.bit=%s 密钥 key.bit.weak=%s 密钥(弱) -key.bit.disabled=%s 密钥(已禁用) +key.bit.disabled=%s 密钥(禁用) .PATTERN.printX509Cert.with.weak=所有者: {0}\n发布者: {1}\n序列号: {2}\n生效时间: {3}, 失效时间: {4}\n证书指纹:\n\t SHA1: {5}\n\t SHA256: {6}\n签名算法名称: {7}\n主体公共密钥算法: {8}\n版本: {9} PKCS.10.with.weak=PKCS #10 证书请求 (版本 1.0)\n主体: %1$s\n格式: %2$s\n公共密钥: %3$s\n签名算法: %4$s\n verified.by.s.in.s.weak=由 %2$s 中的 %1$s 以 %3$s 验证 @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s 使用的 %2$s 签名算法被视为存在安 Unable.to.parse.denyAfter.string.in.exception.message=无法解析异常错误消息中的 denyAfter 日期字符串 whose.sigalg.weak=%1$s 使用的 %2$s 签名算法存在安全风险。 whose.key.disabled=%1$s 使用的 %2$s 被视为存在安全风险而且被禁用。 -whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。在将来的更新中将禁用它。 +whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。它将在未来的更新中被禁用。 jks.storetype.warning=%1$s 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。 migrate.keystore.warning=已将 "%1$s" 迁移到 %4$s。将 %2$s 密钥库作为 "%3$s" 进行了备份。 backup.keystore.warning=已将原始密钥库 "%1$s" 备份为 "%3$s"... diff --git a/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties b/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties index 6d677804544..663b3f8993f 100644 --- a/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties @@ -24,22 +24,22 @@ # # NT principals -invalid.null.input.value=无效的空输入: {0} -NTDomainPrincipal.name=NTDomainPrincipal: {0} -NTNumericCredential.name=NTNumericCredential: {0} +invalid.null.input.value=无效的空输入:{0} +NTDomainPrincipal.name=NTDomainPrincipal:{0} +NTNumericCredential.name=NTNumericCredential:{0} Invalid.NTSid.value=无效的 NTSid 值 -NTSid.name=NTSid: {0} -NTSidDomainPrincipal.name=NTSidDomainPrincipal: {0} -NTSidGroupPrincipal.name=NTSidGroupPrincipal: {0} -NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal: {0} -NTSidUserPrincipal.name=NTSidUserPrincipal: {0} -NTUserPrincipal.name=NTUserPrincipal: {0} +NTSid.name=NTSid:{0} +NTSidDomainPrincipal.name=NTSidDomainPrincipal:{0} +NTSidGroupPrincipal.name=NTSidGroupPrincipal:{0} +NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal:{0} +NTSidUserPrincipal.name=NTSidUserPrincipal:{0} +NTUserPrincipal.name=NTUserPrincipal:{0} # UnixPrincipals -UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]: {0} +UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]:{0} UnixNumericGroupPrincipal.Supplementary.Group.name=UnixNumericGroupPrincipal [补充组]: {0} -UnixNumericUserPrincipal.name=UnixNumericUserPrincipal: {0} -UnixPrincipal.name=UnixPrincipal: {0} +UnixNumericUserPrincipal.name=UnixNumericUserPrincipal:{0} +UnixPrincipal.name=UnixPrincipal:{0} # com.sun.security.auth.login.ConfigFile Unable.to.properly.expand.config=无法正确扩展{0} @@ -53,8 +53,8 @@ Configuration.Error.Line.line.expected.expect.=配置错误: \n\t行 {0}: 应为 Configuration.Error.Line.line.system.property.value.expanded.to.empty.value=配置错误: \n\t行 {0}: 系统属性 [{1}] 扩展到空值 # com.sun.security.auth.module.JndiLoginModule -username.=用户名:\u0020 -password.=口令:\u0020 +username.=用户名:\u0020 +password.=密码:\u0020 # com.sun.security.auth.module.KeyStoreLoginModule Please.enter.keystore.information=请输入密钥库信息 @@ -63,5 +63,5 @@ Keystore.password.=密钥库口令:\u0020 Private.key.password.optional.=私有密钥口令 (可选):\u0020 # com.sun.security.auth.module.Krb5LoginModule -Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020 -Kerberos.password.for.username.={0}的 Kerberos 口令:\u0020 +Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020 +Kerberos.password.for.username.={0} 的 Kerberos 密码:\u0020 diff --git a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties index b9ec0a82cb9..ff13b37cf3b 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties @@ -66,7 +66,7 @@ Login.Failure.all.modules.ignored=ログイン失敗: すべてのモジュー # sun.security.provider.PolicyParser duplicate.keystore.domain.name=重複するキーストア・ドメイン名: {0} duplicate.keystore.name=重複するキーストア名: {0} -number.=数\u0020 +number.=数値\u0020 expected.expect.read.end.of.file.=[{0}]ではなく[ファイルの終わり]が読み込まれました expected.read.end.of.file.=[;]ではなく[ファイルの終わり]が読み込まれました line.number.msg=行{0}: {1} diff --git a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties index 0653fbdca52..6a4ec11de77 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties @@ -43,17 +43,17 @@ provided.null.OID.map=提供的 OID 映射为空值 NEWLINE=\n invalid.null.action.provided=提供了无效的空操作 invalid.null.Class.provided=提供了无效的空类 -Subject.=主体: \n -.Principal.=\t主用户:\u0020 -.Public.Credential.=\t公共身份证明:\u0020 -.Private.Credential.=\t专用身份证明:\u0020 +Subject.=主体:\n +.Principal.=\t主用户:\u0020 +.Public.Credential.=\t公共身份证明:\u0020 +.Private.Credential.=\t专用身份证明:\u0020 .Private.Credential.inaccessible.=\t无法访问专用身份证明\n Subject.is.read.only=主体为只读 attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set=正在尝试将一个非 java.security.Principal 实例的对象添加到主体的主用户集中 attempting.to.add.an.object.which.is.not.an.instance.of.class=正在尝试添加一个非{0}实例的对象 # javax.security.auth.login.AppConfigurationEntry -LoginModuleControlFlag.=LoginModuleControlFlag:\u0020 +LoginModuleControlFlag.=LoginModuleControlFlag:\u0020 # javax.security.auth.login.LoginContext Invalid.null.input.name=无效空输入: 名称 @@ -69,8 +69,8 @@ duplicate.keystore.name=密钥库名称重复: {0} number.=编号\u0020 expected.expect.read.end.of.file.=应为 [{0}], 读取的是 [文件结尾] expected.read.end.of.file.=应为 [;], 读取的是 [文件结尾] -line.number.msg=列{0}: {1} +line.number.msg=第 {0} 行:{1} line.number.expected.expect.found.actual.=行号 {0}: 应为 [{1}], 找到 [{2}] # sun.security.pkcs11.SunPKCS11 -PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 口令:\u0020 +PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 密码:\u0020 diff --git a/src/java.base/share/classes/sun/util/locale/LanguageTag.java b/src/java.base/share/classes/sun/util/locale/LanguageTag.java index a88937b7538..6036c1dd04f 100644 --- a/src/java.base/share/classes/sun/util/locale/LanguageTag.java +++ b/src/java.base/share/classes/sun/util/locale/LanguageTag.java @@ -51,7 +51,7 @@ public record LanguageTag(String language, String script, String region, String public static final String UNDETERMINED = "und"; public static final String PRIVUSE_VARIANT_PREFIX = "lvariant"; private static final String EMPTY_SUBTAG = ""; - private static final List EMPTY_SUBTAGS = Collections.emptyList(); + private static final List EMPTY_SUBTAGS = List.of(); // Map contains legacy language tags and its preferred mappings from // http://www.ietf.org/rfc/rfc5646.txt diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java index 57fbd3a7726..5efa512e432 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.IllformedLocaleException; import java.util.List; @@ -388,8 +387,7 @@ static Locale getLookupLocale(Locale locale) { * A dummy locale service provider list that indicates there is no * provider available */ - private static final List NULL_LIST = - Collections.emptyList(); + private static final List NULL_LIST = List.of(); /** * An interface to get a localized object for each locale sensitive diff --git a/src/java.base/share/data/unicodedata/CaseFolding.txt b/src/java.base/share/data/unicodedata/CaseFolding.txt new file mode 100644 index 00000000000..345c4f3dd03 --- /dev/null +++ b/src/java.base/share/data/unicodedata/CaseFolding.txt @@ -0,0 +1,1654 @@ +# CaseFolding-16.0.0.txt +# Date: 2024-04-30, 21:48:11 GMT +# © 2024 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use and license, see https://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see https://www.unicode.org/reports/tr44/ +# +# Case Folding Properties +# +# This file is a supplement to the UnicodeData file. +# It provides a case folding mapping generated from the Unicode Character Database. +# If all characters are mapped according to the full mapping below, then +# case differences (according to UnicodeData.txt and SpecialCasing.txt) +# are eliminated. +# +# The data supports both implementations that require simple case foldings +# (where string lengths don't change), and implementations that allow full case folding +# (where string lengths may grow). Note that where they can be supported, the +# full case foldings are superior: for example, they allow "MASSE" and "Maße" to match. +# +# All code points not listed in this file map to themselves. +# +# NOTE: case folding does not preserve normalization formats! +# +# For information on case folding, including how to have case folding +# preserve normalization formats, see Section 3.13 Default Case Algorithms in +# The Unicode Standard. +# +# ================================================================================ +# Format +# ================================================================================ +# The entries in this file are in the following machine-readable format: +# +# ; ; ; # +# +# The status field is: +# C: common case folding, common mappings shared by both simple and full mappings. +# F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. +# S: simple case folding, mappings to single characters where different from F. +# T: special case for uppercase I and dotted uppercase I +# - For non-Turkic languages, this mapping is normally not used. +# - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. +# Note that the Turkic mappings do not maintain canonical equivalence without additional processing. +# See the discussions of case mapping in the Unicode Standard for more information. +# +# Usage: +# A. To do a simple case folding, use the mappings with status C + S. +# B. To do a full case folding, use the mappings with status C + F. +# +# The mappings with status T can be used or omitted depending on the desired case-folding +# behavior. (The default option is to exclude them.) +# +# ================================================================= + +# Property: Case_Folding + +# All code points not explicitly listed for Case_Folding +# have the value C for the status field, and the code point itself for the mapping field. + +# ================================================================= +0041; C; 0061; # LATIN CAPITAL LETTER A +0042; C; 0062; # LATIN CAPITAL LETTER B +0043; C; 0063; # LATIN CAPITAL LETTER C +0044; C; 0064; # LATIN CAPITAL LETTER D +0045; C; 0065; # LATIN CAPITAL LETTER E +0046; C; 0066; # LATIN CAPITAL LETTER F +0047; C; 0067; # LATIN CAPITAL LETTER G +0048; C; 0068; # LATIN CAPITAL LETTER H +0049; C; 0069; # LATIN CAPITAL LETTER I +0049; T; 0131; # LATIN CAPITAL LETTER I +004A; C; 006A; # LATIN CAPITAL LETTER J +004B; C; 006B; # LATIN CAPITAL LETTER K +004C; C; 006C; # LATIN CAPITAL LETTER L +004D; C; 006D; # LATIN CAPITAL LETTER M +004E; C; 006E; # LATIN CAPITAL LETTER N +004F; C; 006F; # LATIN CAPITAL LETTER O +0050; C; 0070; # LATIN CAPITAL LETTER P +0051; C; 0071; # LATIN CAPITAL LETTER Q +0052; C; 0072; # LATIN CAPITAL LETTER R +0053; C; 0073; # LATIN CAPITAL LETTER S +0054; C; 0074; # LATIN CAPITAL LETTER T +0055; C; 0075; # LATIN CAPITAL LETTER U +0056; C; 0076; # LATIN CAPITAL LETTER V +0057; C; 0077; # LATIN CAPITAL LETTER W +0058; C; 0078; # LATIN CAPITAL LETTER X +0059; C; 0079; # LATIN CAPITAL LETTER Y +005A; C; 007A; # LATIN CAPITAL LETTER Z +00B5; C; 03BC; # MICRO SIGN +00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE +00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE +00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX +00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE +00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS +00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE +00C6; C; 00E6; # LATIN CAPITAL LETTER AE +00C7; C; 00E7; # LATIN CAPITAL LETTER C WITH CEDILLA +00C8; C; 00E8; # LATIN CAPITAL LETTER E WITH GRAVE +00C9; C; 00E9; # LATIN CAPITAL LETTER E WITH ACUTE +00CA; C; 00EA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX +00CB; C; 00EB; # LATIN CAPITAL LETTER E WITH DIAERESIS +00CC; C; 00EC; # LATIN CAPITAL LETTER I WITH GRAVE +00CD; C; 00ED; # LATIN CAPITAL LETTER I WITH ACUTE +00CE; C; 00EE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX +00CF; C; 00EF; # LATIN CAPITAL LETTER I WITH DIAERESIS +00D0; C; 00F0; # LATIN CAPITAL LETTER ETH +00D1; C; 00F1; # LATIN CAPITAL LETTER N WITH TILDE +00D2; C; 00F2; # LATIN CAPITAL LETTER O WITH GRAVE +00D3; C; 00F3; # LATIN CAPITAL LETTER O WITH ACUTE +00D4; C; 00F4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX +00D5; C; 00F5; # LATIN CAPITAL LETTER O WITH TILDE +00D6; C; 00F6; # LATIN CAPITAL LETTER O WITH DIAERESIS +00D8; C; 00F8; # LATIN CAPITAL LETTER O WITH STROKE +00D9; C; 00F9; # LATIN CAPITAL LETTER U WITH GRAVE +00DA; C; 00FA; # LATIN CAPITAL LETTER U WITH ACUTE +00DB; C; 00FB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX +00DC; C; 00FC; # LATIN CAPITAL LETTER U WITH DIAERESIS +00DD; C; 00FD; # LATIN CAPITAL LETTER Y WITH ACUTE +00DE; C; 00FE; # LATIN CAPITAL LETTER THORN +00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S +0100; C; 0101; # LATIN CAPITAL LETTER A WITH MACRON +0102; C; 0103; # LATIN CAPITAL LETTER A WITH BREVE +0104; C; 0105; # LATIN CAPITAL LETTER A WITH OGONEK +0106; C; 0107; # LATIN CAPITAL LETTER C WITH ACUTE +0108; C; 0109; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX +010A; C; 010B; # LATIN CAPITAL LETTER C WITH DOT ABOVE +010C; C; 010D; # LATIN CAPITAL LETTER C WITH CARON +010E; C; 010F; # LATIN CAPITAL LETTER D WITH CARON +0110; C; 0111; # LATIN CAPITAL LETTER D WITH STROKE +0112; C; 0113; # LATIN CAPITAL LETTER E WITH MACRON +0114; C; 0115; # LATIN CAPITAL LETTER E WITH BREVE +0116; C; 0117; # LATIN CAPITAL LETTER E WITH DOT ABOVE +0118; C; 0119; # LATIN CAPITAL LETTER E WITH OGONEK +011A; C; 011B; # LATIN CAPITAL LETTER E WITH CARON +011C; C; 011D; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX +011E; C; 011F; # LATIN CAPITAL LETTER G WITH BREVE +0120; C; 0121; # LATIN CAPITAL LETTER G WITH DOT ABOVE +0122; C; 0123; # LATIN CAPITAL LETTER G WITH CEDILLA +0124; C; 0125; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX +0126; C; 0127; # LATIN CAPITAL LETTER H WITH STROKE +0128; C; 0129; # LATIN CAPITAL LETTER I WITH TILDE +012A; C; 012B; # LATIN CAPITAL LETTER I WITH MACRON +012C; C; 012D; # LATIN CAPITAL LETTER I WITH BREVE +012E; C; 012F; # LATIN CAPITAL LETTER I WITH OGONEK +0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE +0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE +0132; C; 0133; # LATIN CAPITAL LIGATURE IJ +0134; C; 0135; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX +0136; C; 0137; # LATIN CAPITAL LETTER K WITH CEDILLA +0139; C; 013A; # LATIN CAPITAL LETTER L WITH ACUTE +013B; C; 013C; # LATIN CAPITAL LETTER L WITH CEDILLA +013D; C; 013E; # LATIN CAPITAL LETTER L WITH CARON +013F; C; 0140; # LATIN CAPITAL LETTER L WITH MIDDLE DOT +0141; C; 0142; # LATIN CAPITAL LETTER L WITH STROKE +0143; C; 0144; # LATIN CAPITAL LETTER N WITH ACUTE +0145; C; 0146; # LATIN CAPITAL LETTER N WITH CEDILLA +0147; C; 0148; # LATIN CAPITAL LETTER N WITH CARON +0149; F; 02BC 006E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +014A; C; 014B; # LATIN CAPITAL LETTER ENG +014C; C; 014D; # LATIN CAPITAL LETTER O WITH MACRON +014E; C; 014F; # LATIN CAPITAL LETTER O WITH BREVE +0150; C; 0151; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE +0152; C; 0153; # LATIN CAPITAL LIGATURE OE +0154; C; 0155; # LATIN CAPITAL LETTER R WITH ACUTE +0156; C; 0157; # LATIN CAPITAL LETTER R WITH CEDILLA +0158; C; 0159; # LATIN CAPITAL LETTER R WITH CARON +015A; C; 015B; # LATIN CAPITAL LETTER S WITH ACUTE +015C; C; 015D; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX +015E; C; 015F; # LATIN CAPITAL LETTER S WITH CEDILLA +0160; C; 0161; # LATIN CAPITAL LETTER S WITH CARON +0162; C; 0163; # LATIN CAPITAL LETTER T WITH CEDILLA +0164; C; 0165; # LATIN CAPITAL LETTER T WITH CARON +0166; C; 0167; # LATIN CAPITAL LETTER T WITH STROKE +0168; C; 0169; # LATIN CAPITAL LETTER U WITH TILDE +016A; C; 016B; # LATIN CAPITAL LETTER U WITH MACRON +016C; C; 016D; # LATIN CAPITAL LETTER U WITH BREVE +016E; C; 016F; # LATIN CAPITAL LETTER U WITH RING ABOVE +0170; C; 0171; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE +0172; C; 0173; # LATIN CAPITAL LETTER U WITH OGONEK +0174; C; 0175; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX +0176; C; 0177; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX +0178; C; 00FF; # LATIN CAPITAL LETTER Y WITH DIAERESIS +0179; C; 017A; # LATIN CAPITAL LETTER Z WITH ACUTE +017B; C; 017C; # LATIN CAPITAL LETTER Z WITH DOT ABOVE +017D; C; 017E; # LATIN CAPITAL LETTER Z WITH CARON +017F; C; 0073; # LATIN SMALL LETTER LONG S +0181; C; 0253; # LATIN CAPITAL LETTER B WITH HOOK +0182; C; 0183; # LATIN CAPITAL LETTER B WITH TOPBAR +0184; C; 0185; # LATIN CAPITAL LETTER TONE SIX +0186; C; 0254; # LATIN CAPITAL LETTER OPEN O +0187; C; 0188; # LATIN CAPITAL LETTER C WITH HOOK +0189; C; 0256; # LATIN CAPITAL LETTER AFRICAN D +018A; C; 0257; # LATIN CAPITAL LETTER D WITH HOOK +018B; C; 018C; # LATIN CAPITAL LETTER D WITH TOPBAR +018E; C; 01DD; # LATIN CAPITAL LETTER REVERSED E +018F; C; 0259; # LATIN CAPITAL LETTER SCHWA +0190; C; 025B; # LATIN CAPITAL LETTER OPEN E +0191; C; 0192; # LATIN CAPITAL LETTER F WITH HOOK +0193; C; 0260; # LATIN CAPITAL LETTER G WITH HOOK +0194; C; 0263; # LATIN CAPITAL LETTER GAMMA +0196; C; 0269; # LATIN CAPITAL LETTER IOTA +0197; C; 0268; # LATIN CAPITAL LETTER I WITH STROKE +0198; C; 0199; # LATIN CAPITAL LETTER K WITH HOOK +019C; C; 026F; # LATIN CAPITAL LETTER TURNED M +019D; C; 0272; # LATIN CAPITAL LETTER N WITH LEFT HOOK +019F; C; 0275; # LATIN CAPITAL LETTER O WITH MIDDLE TILDE +01A0; C; 01A1; # LATIN CAPITAL LETTER O WITH HORN +01A2; C; 01A3; # LATIN CAPITAL LETTER OI +01A4; C; 01A5; # LATIN CAPITAL LETTER P WITH HOOK +01A6; C; 0280; # LATIN LETTER YR +01A7; C; 01A8; # LATIN CAPITAL LETTER TONE TWO +01A9; C; 0283; # LATIN CAPITAL LETTER ESH +01AC; C; 01AD; # LATIN CAPITAL LETTER T WITH HOOK +01AE; C; 0288; # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK +01AF; C; 01B0; # LATIN CAPITAL LETTER U WITH HORN +01B1; C; 028A; # LATIN CAPITAL LETTER UPSILON +01B2; C; 028B; # LATIN CAPITAL LETTER V WITH HOOK +01B3; C; 01B4; # LATIN CAPITAL LETTER Y WITH HOOK +01B5; C; 01B6; # LATIN CAPITAL LETTER Z WITH STROKE +01B7; C; 0292; # LATIN CAPITAL LETTER EZH +01B8; C; 01B9; # LATIN CAPITAL LETTER EZH REVERSED +01BC; C; 01BD; # LATIN CAPITAL LETTER TONE FIVE +01C4; C; 01C6; # LATIN CAPITAL LETTER DZ WITH CARON +01C5; C; 01C6; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON +01C7; C; 01C9; # LATIN CAPITAL LETTER LJ +01C8; C; 01C9; # LATIN CAPITAL LETTER L WITH SMALL LETTER J +01CA; C; 01CC; # LATIN CAPITAL LETTER NJ +01CB; C; 01CC; # LATIN CAPITAL LETTER N WITH SMALL LETTER J +01CD; C; 01CE; # LATIN CAPITAL LETTER A WITH CARON +01CF; C; 01D0; # LATIN CAPITAL LETTER I WITH CARON +01D1; C; 01D2; # LATIN CAPITAL LETTER O WITH CARON +01D3; C; 01D4; # LATIN CAPITAL LETTER U WITH CARON +01D5; C; 01D6; # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON +01D7; C; 01D8; # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE +01D9; C; 01DA; # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON +01DB; C; 01DC; # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE +01DE; C; 01DF; # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON +01E0; C; 01E1; # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON +01E2; C; 01E3; # LATIN CAPITAL LETTER AE WITH MACRON +01E4; C; 01E5; # LATIN CAPITAL LETTER G WITH STROKE +01E6; C; 01E7; # LATIN CAPITAL LETTER G WITH CARON +01E8; C; 01E9; # LATIN CAPITAL LETTER K WITH CARON +01EA; C; 01EB; # LATIN CAPITAL LETTER O WITH OGONEK +01EC; C; 01ED; # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON +01EE; C; 01EF; # LATIN CAPITAL LETTER EZH WITH CARON +01F0; F; 006A 030C; # LATIN SMALL LETTER J WITH CARON +01F1; C; 01F3; # LATIN CAPITAL LETTER DZ +01F2; C; 01F3; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z +01F4; C; 01F5; # LATIN CAPITAL LETTER G WITH ACUTE +01F6; C; 0195; # LATIN CAPITAL LETTER HWAIR +01F7; C; 01BF; # LATIN CAPITAL LETTER WYNN +01F8; C; 01F9; # LATIN CAPITAL LETTER N WITH GRAVE +01FA; C; 01FB; # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE +01FC; C; 01FD; # LATIN CAPITAL LETTER AE WITH ACUTE +01FE; C; 01FF; # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE +0200; C; 0201; # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE +0202; C; 0203; # LATIN CAPITAL LETTER A WITH INVERTED BREVE +0204; C; 0205; # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE +0206; C; 0207; # LATIN CAPITAL LETTER E WITH INVERTED BREVE +0208; C; 0209; # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE +020A; C; 020B; # LATIN CAPITAL LETTER I WITH INVERTED BREVE +020C; C; 020D; # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE +020E; C; 020F; # LATIN CAPITAL LETTER O WITH INVERTED BREVE +0210; C; 0211; # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE +0212; C; 0213; # LATIN CAPITAL LETTER R WITH INVERTED BREVE +0214; C; 0215; # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE +0216; C; 0217; # LATIN CAPITAL LETTER U WITH INVERTED BREVE +0218; C; 0219; # LATIN CAPITAL LETTER S WITH COMMA BELOW +021A; C; 021B; # LATIN CAPITAL LETTER T WITH COMMA BELOW +021C; C; 021D; # LATIN CAPITAL LETTER YOGH +021E; C; 021F; # LATIN CAPITAL LETTER H WITH CARON +0220; C; 019E; # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG +0222; C; 0223; # LATIN CAPITAL LETTER OU +0224; C; 0225; # LATIN CAPITAL LETTER Z WITH HOOK +0226; C; 0227; # LATIN CAPITAL LETTER A WITH DOT ABOVE +0228; C; 0229; # LATIN CAPITAL LETTER E WITH CEDILLA +022A; C; 022B; # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON +022C; C; 022D; # LATIN CAPITAL LETTER O WITH TILDE AND MACRON +022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE +0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON +0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON +023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE +023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE +023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR +023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE +0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP +0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE +0244; C; 0289; # LATIN CAPITAL LETTER U BAR +0245; C; 028C; # LATIN CAPITAL LETTER TURNED V +0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE +0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE +024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL +024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE +024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE +0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI +0370; C; 0371; # GREEK CAPITAL LETTER HETA +0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI +0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA +037F; C; 03F3; # GREEK CAPITAL LETTER YOT +0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS +0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS +0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS +038A; C; 03AF; # GREEK CAPITAL LETTER IOTA WITH TONOS +038C; C; 03CC; # GREEK CAPITAL LETTER OMICRON WITH TONOS +038E; C; 03CD; # GREEK CAPITAL LETTER UPSILON WITH TONOS +038F; C; 03CE; # GREEK CAPITAL LETTER OMEGA WITH TONOS +0390; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +0391; C; 03B1; # GREEK CAPITAL LETTER ALPHA +0392; C; 03B2; # GREEK CAPITAL LETTER BETA +0393; C; 03B3; # GREEK CAPITAL LETTER GAMMA +0394; C; 03B4; # GREEK CAPITAL LETTER DELTA +0395; C; 03B5; # GREEK CAPITAL LETTER EPSILON +0396; C; 03B6; # GREEK CAPITAL LETTER ZETA +0397; C; 03B7; # GREEK CAPITAL LETTER ETA +0398; C; 03B8; # GREEK CAPITAL LETTER THETA +0399; C; 03B9; # GREEK CAPITAL LETTER IOTA +039A; C; 03BA; # GREEK CAPITAL LETTER KAPPA +039B; C; 03BB; # GREEK CAPITAL LETTER LAMDA +039C; C; 03BC; # GREEK CAPITAL LETTER MU +039D; C; 03BD; # GREEK CAPITAL LETTER NU +039E; C; 03BE; # GREEK CAPITAL LETTER XI +039F; C; 03BF; # GREEK CAPITAL LETTER OMICRON +03A0; C; 03C0; # GREEK CAPITAL LETTER PI +03A1; C; 03C1; # GREEK CAPITAL LETTER RHO +03A3; C; 03C3; # GREEK CAPITAL LETTER SIGMA +03A4; C; 03C4; # GREEK CAPITAL LETTER TAU +03A5; C; 03C5; # GREEK CAPITAL LETTER UPSILON +03A6; C; 03C6; # GREEK CAPITAL LETTER PHI +03A7; C; 03C7; # GREEK CAPITAL LETTER CHI +03A8; C; 03C8; # GREEK CAPITAL LETTER PSI +03A9; C; 03C9; # GREEK CAPITAL LETTER OMEGA +03AA; C; 03CA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA +03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA +03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA +03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL +03D0; C; 03B2; # GREEK BETA SYMBOL +03D1; C; 03B8; # GREEK THETA SYMBOL +03D5; C; 03C6; # GREEK PHI SYMBOL +03D6; C; 03C0; # GREEK PI SYMBOL +03D8; C; 03D9; # GREEK LETTER ARCHAIC KOPPA +03DA; C; 03DB; # GREEK LETTER STIGMA +03DC; C; 03DD; # GREEK LETTER DIGAMMA +03DE; C; 03DF; # GREEK LETTER KOPPA +03E0; C; 03E1; # GREEK LETTER SAMPI +03E2; C; 03E3; # COPTIC CAPITAL LETTER SHEI +03E4; C; 03E5; # COPTIC CAPITAL LETTER FEI +03E6; C; 03E7; # COPTIC CAPITAL LETTER KHEI +03E8; C; 03E9; # COPTIC CAPITAL LETTER HORI +03EA; C; 03EB; # COPTIC CAPITAL LETTER GANGIA +03EC; C; 03ED; # COPTIC CAPITAL LETTER SHIMA +03EE; C; 03EF; # COPTIC CAPITAL LETTER DEI +03F0; C; 03BA; # GREEK KAPPA SYMBOL +03F1; C; 03C1; # GREEK RHO SYMBOL +03F4; C; 03B8; # GREEK CAPITAL THETA SYMBOL +03F5; C; 03B5; # GREEK LUNATE EPSILON SYMBOL +03F7; C; 03F8; # GREEK CAPITAL LETTER SHO +03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL +03FA; C; 03FB; # GREEK CAPITAL LETTER SAN +03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL +03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL +03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL +0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE +0401; C; 0451; # CYRILLIC CAPITAL LETTER IO +0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE +0403; C; 0453; # CYRILLIC CAPITAL LETTER GJE +0404; C; 0454; # CYRILLIC CAPITAL LETTER UKRAINIAN IE +0405; C; 0455; # CYRILLIC CAPITAL LETTER DZE +0406; C; 0456; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +0407; C; 0457; # CYRILLIC CAPITAL LETTER YI +0408; C; 0458; # CYRILLIC CAPITAL LETTER JE +0409; C; 0459; # CYRILLIC CAPITAL LETTER LJE +040A; C; 045A; # CYRILLIC CAPITAL LETTER NJE +040B; C; 045B; # CYRILLIC CAPITAL LETTER TSHE +040C; C; 045C; # CYRILLIC CAPITAL LETTER KJE +040D; C; 045D; # CYRILLIC CAPITAL LETTER I WITH GRAVE +040E; C; 045E; # CYRILLIC CAPITAL LETTER SHORT U +040F; C; 045F; # CYRILLIC CAPITAL LETTER DZHE +0410; C; 0430; # CYRILLIC CAPITAL LETTER A +0411; C; 0431; # CYRILLIC CAPITAL LETTER BE +0412; C; 0432; # CYRILLIC CAPITAL LETTER VE +0413; C; 0433; # CYRILLIC CAPITAL LETTER GHE +0414; C; 0434; # CYRILLIC CAPITAL LETTER DE +0415; C; 0435; # CYRILLIC CAPITAL LETTER IE +0416; C; 0436; # CYRILLIC CAPITAL LETTER ZHE +0417; C; 0437; # CYRILLIC CAPITAL LETTER ZE +0418; C; 0438; # CYRILLIC CAPITAL LETTER I +0419; C; 0439; # CYRILLIC CAPITAL LETTER SHORT I +041A; C; 043A; # CYRILLIC CAPITAL LETTER KA +041B; C; 043B; # CYRILLIC CAPITAL LETTER EL +041C; C; 043C; # CYRILLIC CAPITAL LETTER EM +041D; C; 043D; # CYRILLIC CAPITAL LETTER EN +041E; C; 043E; # CYRILLIC CAPITAL LETTER O +041F; C; 043F; # CYRILLIC CAPITAL LETTER PE +0420; C; 0440; # CYRILLIC CAPITAL LETTER ER +0421; C; 0441; # CYRILLIC CAPITAL LETTER ES +0422; C; 0442; # CYRILLIC CAPITAL LETTER TE +0423; C; 0443; # CYRILLIC CAPITAL LETTER U +0424; C; 0444; # CYRILLIC CAPITAL LETTER EF +0425; C; 0445; # CYRILLIC CAPITAL LETTER HA +0426; C; 0446; # CYRILLIC CAPITAL LETTER TSE +0427; C; 0447; # CYRILLIC CAPITAL LETTER CHE +0428; C; 0448; # CYRILLIC CAPITAL LETTER SHA +0429; C; 0449; # CYRILLIC CAPITAL LETTER SHCHA +042A; C; 044A; # CYRILLIC CAPITAL LETTER HARD SIGN +042B; C; 044B; # CYRILLIC CAPITAL LETTER YERU +042C; C; 044C; # CYRILLIC CAPITAL LETTER SOFT SIGN +042D; C; 044D; # CYRILLIC CAPITAL LETTER E +042E; C; 044E; # CYRILLIC CAPITAL LETTER YU +042F; C; 044F; # CYRILLIC CAPITAL LETTER YA +0460; C; 0461; # CYRILLIC CAPITAL LETTER OMEGA +0462; C; 0463; # CYRILLIC CAPITAL LETTER YAT +0464; C; 0465; # CYRILLIC CAPITAL LETTER IOTIFIED E +0466; C; 0467; # CYRILLIC CAPITAL LETTER LITTLE YUS +0468; C; 0469; # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS +046A; C; 046B; # CYRILLIC CAPITAL LETTER BIG YUS +046C; C; 046D; # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS +046E; C; 046F; # CYRILLIC CAPITAL LETTER KSI +0470; C; 0471; # CYRILLIC CAPITAL LETTER PSI +0472; C; 0473; # CYRILLIC CAPITAL LETTER FITA +0474; C; 0475; # CYRILLIC CAPITAL LETTER IZHITSA +0476; C; 0477; # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT +0478; C; 0479; # CYRILLIC CAPITAL LETTER UK +047A; C; 047B; # CYRILLIC CAPITAL LETTER ROUND OMEGA +047C; C; 047D; # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO +047E; C; 047F; # CYRILLIC CAPITAL LETTER OT +0480; C; 0481; # CYRILLIC CAPITAL LETTER KOPPA +048A; C; 048B; # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL +048C; C; 048D; # CYRILLIC CAPITAL LETTER SEMISOFT SIGN +048E; C; 048F; # CYRILLIC CAPITAL LETTER ER WITH TICK +0490; C; 0491; # CYRILLIC CAPITAL LETTER GHE WITH UPTURN +0492; C; 0493; # CYRILLIC CAPITAL LETTER GHE WITH STROKE +0494; C; 0495; # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK +0496; C; 0497; # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER +0498; C; 0499; # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER +049A; C; 049B; # CYRILLIC CAPITAL LETTER KA WITH DESCENDER +049C; C; 049D; # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE +049E; C; 049F; # CYRILLIC CAPITAL LETTER KA WITH STROKE +04A0; C; 04A1; # CYRILLIC CAPITAL LETTER BASHKIR KA +04A2; C; 04A3; # CYRILLIC CAPITAL LETTER EN WITH DESCENDER +04A4; C; 04A5; # CYRILLIC CAPITAL LIGATURE EN GHE +04A6; C; 04A7; # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK +04A8; C; 04A9; # CYRILLIC CAPITAL LETTER ABKHASIAN HA +04AA; C; 04AB; # CYRILLIC CAPITAL LETTER ES WITH DESCENDER +04AC; C; 04AD; # CYRILLIC CAPITAL LETTER TE WITH DESCENDER +04AE; C; 04AF; # CYRILLIC CAPITAL LETTER STRAIGHT U +04B0; C; 04B1; # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE +04B2; C; 04B3; # CYRILLIC CAPITAL LETTER HA WITH DESCENDER +04B4; C; 04B5; # CYRILLIC CAPITAL LIGATURE TE TSE +04B6; C; 04B7; # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER +04B8; C; 04B9; # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE +04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA +04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE +04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER +04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA +04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE +04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK +04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL +04C7; C; 04C8; # CYRILLIC CAPITAL LETTER EN WITH HOOK +04C9; C; 04CA; # CYRILLIC CAPITAL LETTER EN WITH TAIL +04CB; C; 04CC; # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE +04CD; C; 04CE; # CYRILLIC CAPITAL LETTER EM WITH TAIL +04D0; C; 04D1; # CYRILLIC CAPITAL LETTER A WITH BREVE +04D2; C; 04D3; # CYRILLIC CAPITAL LETTER A WITH DIAERESIS +04D4; C; 04D5; # CYRILLIC CAPITAL LIGATURE A IE +04D6; C; 04D7; # CYRILLIC CAPITAL LETTER IE WITH BREVE +04D8; C; 04D9; # CYRILLIC CAPITAL LETTER SCHWA +04DA; C; 04DB; # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS +04DC; C; 04DD; # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS +04DE; C; 04DF; # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS +04E0; C; 04E1; # CYRILLIC CAPITAL LETTER ABKHASIAN DZE +04E2; C; 04E3; # CYRILLIC CAPITAL LETTER I WITH MACRON +04E4; C; 04E5; # CYRILLIC CAPITAL LETTER I WITH DIAERESIS +04E6; C; 04E7; # CYRILLIC CAPITAL LETTER O WITH DIAERESIS +04E8; C; 04E9; # CYRILLIC CAPITAL LETTER BARRED O +04EA; C; 04EB; # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS +04EC; C; 04ED; # CYRILLIC CAPITAL LETTER E WITH DIAERESIS +04EE; C; 04EF; # CYRILLIC CAPITAL LETTER U WITH MACRON +04F0; C; 04F1; # CYRILLIC CAPITAL LETTER U WITH DIAERESIS +04F2; C; 04F3; # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE +04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS +04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER +04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS +04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK +04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK +04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE +0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE +0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE +0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE +0506; C; 0507; # CYRILLIC CAPITAL LETTER KOMI DZJE +0508; C; 0509; # CYRILLIC CAPITAL LETTER KOMI LJE +050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE +050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE +050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE +0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE +0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK +0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA +0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA +0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE +051A; C; 051B; # CYRILLIC CAPITAL LETTER QA +051C; C; 051D; # CYRILLIC CAPITAL LETTER WE +051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA +0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK +0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK +0524; C; 0525; # CYRILLIC CAPITAL LETTER PE WITH DESCENDER +0526; C; 0527; # CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER +0528; C; 0529; # CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK +052A; C; 052B; # CYRILLIC CAPITAL LETTER DZZHE +052C; C; 052D; # CYRILLIC CAPITAL LETTER DCHE +052E; C; 052F; # CYRILLIC CAPITAL LETTER EL WITH DESCENDER +0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB +0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN +0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM +0534; C; 0564; # ARMENIAN CAPITAL LETTER DA +0535; C; 0565; # ARMENIAN CAPITAL LETTER ECH +0536; C; 0566; # ARMENIAN CAPITAL LETTER ZA +0537; C; 0567; # ARMENIAN CAPITAL LETTER EH +0538; C; 0568; # ARMENIAN CAPITAL LETTER ET +0539; C; 0569; # ARMENIAN CAPITAL LETTER TO +053A; C; 056A; # ARMENIAN CAPITAL LETTER ZHE +053B; C; 056B; # ARMENIAN CAPITAL LETTER INI +053C; C; 056C; # ARMENIAN CAPITAL LETTER LIWN +053D; C; 056D; # ARMENIAN CAPITAL LETTER XEH +053E; C; 056E; # ARMENIAN CAPITAL LETTER CA +053F; C; 056F; # ARMENIAN CAPITAL LETTER KEN +0540; C; 0570; # ARMENIAN CAPITAL LETTER HO +0541; C; 0571; # ARMENIAN CAPITAL LETTER JA +0542; C; 0572; # ARMENIAN CAPITAL LETTER GHAD +0543; C; 0573; # ARMENIAN CAPITAL LETTER CHEH +0544; C; 0574; # ARMENIAN CAPITAL LETTER MEN +0545; C; 0575; # ARMENIAN CAPITAL LETTER YI +0546; C; 0576; # ARMENIAN CAPITAL LETTER NOW +0547; C; 0577; # ARMENIAN CAPITAL LETTER SHA +0548; C; 0578; # ARMENIAN CAPITAL LETTER VO +0549; C; 0579; # ARMENIAN CAPITAL LETTER CHA +054A; C; 057A; # ARMENIAN CAPITAL LETTER PEH +054B; C; 057B; # ARMENIAN CAPITAL LETTER JHEH +054C; C; 057C; # ARMENIAN CAPITAL LETTER RA +054D; C; 057D; # ARMENIAN CAPITAL LETTER SEH +054E; C; 057E; # ARMENIAN CAPITAL LETTER VEW +054F; C; 057F; # ARMENIAN CAPITAL LETTER TIWN +0550; C; 0580; # ARMENIAN CAPITAL LETTER REH +0551; C; 0581; # ARMENIAN CAPITAL LETTER CO +0552; C; 0582; # ARMENIAN CAPITAL LETTER YIWN +0553; C; 0583; # ARMENIAN CAPITAL LETTER PIWR +0554; C; 0584; # ARMENIAN CAPITAL LETTER KEH +0555; C; 0585; # ARMENIAN CAPITAL LETTER OH +0556; C; 0586; # ARMENIAN CAPITAL LETTER FEH +0587; F; 0565 0582; # ARMENIAN SMALL LIGATURE ECH YIWN +10A0; C; 2D00; # GEORGIAN CAPITAL LETTER AN +10A1; C; 2D01; # GEORGIAN CAPITAL LETTER BAN +10A2; C; 2D02; # GEORGIAN CAPITAL LETTER GAN +10A3; C; 2D03; # GEORGIAN CAPITAL LETTER DON +10A4; C; 2D04; # GEORGIAN CAPITAL LETTER EN +10A5; C; 2D05; # GEORGIAN CAPITAL LETTER VIN +10A6; C; 2D06; # GEORGIAN CAPITAL LETTER ZEN +10A7; C; 2D07; # GEORGIAN CAPITAL LETTER TAN +10A8; C; 2D08; # GEORGIAN CAPITAL LETTER IN +10A9; C; 2D09; # GEORGIAN CAPITAL LETTER KAN +10AA; C; 2D0A; # GEORGIAN CAPITAL LETTER LAS +10AB; C; 2D0B; # GEORGIAN CAPITAL LETTER MAN +10AC; C; 2D0C; # GEORGIAN CAPITAL LETTER NAR +10AD; C; 2D0D; # GEORGIAN CAPITAL LETTER ON +10AE; C; 2D0E; # GEORGIAN CAPITAL LETTER PAR +10AF; C; 2D0F; # GEORGIAN CAPITAL LETTER ZHAR +10B0; C; 2D10; # GEORGIAN CAPITAL LETTER RAE +10B1; C; 2D11; # GEORGIAN CAPITAL LETTER SAN +10B2; C; 2D12; # GEORGIAN CAPITAL LETTER TAR +10B3; C; 2D13; # GEORGIAN CAPITAL LETTER UN +10B4; C; 2D14; # GEORGIAN CAPITAL LETTER PHAR +10B5; C; 2D15; # GEORGIAN CAPITAL LETTER KHAR +10B6; C; 2D16; # GEORGIAN CAPITAL LETTER GHAN +10B7; C; 2D17; # GEORGIAN CAPITAL LETTER QAR +10B8; C; 2D18; # GEORGIAN CAPITAL LETTER SHIN +10B9; C; 2D19; # GEORGIAN CAPITAL LETTER CHIN +10BA; C; 2D1A; # GEORGIAN CAPITAL LETTER CAN +10BB; C; 2D1B; # GEORGIAN CAPITAL LETTER JIL +10BC; C; 2D1C; # GEORGIAN CAPITAL LETTER CIL +10BD; C; 2D1D; # GEORGIAN CAPITAL LETTER CHAR +10BE; C; 2D1E; # GEORGIAN CAPITAL LETTER XAN +10BF; C; 2D1F; # GEORGIAN CAPITAL LETTER JHAN +10C0; C; 2D20; # GEORGIAN CAPITAL LETTER HAE +10C1; C; 2D21; # GEORGIAN CAPITAL LETTER HE +10C2; C; 2D22; # GEORGIAN CAPITAL LETTER HIE +10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE +10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR +10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE +10C7; C; 2D27; # GEORGIAN CAPITAL LETTER YN +10CD; C; 2D2D; # GEORGIAN CAPITAL LETTER AEN +13F8; C; 13F0; # CHEROKEE SMALL LETTER YE +13F9; C; 13F1; # CHEROKEE SMALL LETTER YI +13FA; C; 13F2; # CHEROKEE SMALL LETTER YO +13FB; C; 13F3; # CHEROKEE SMALL LETTER YU +13FC; C; 13F4; # CHEROKEE SMALL LETTER YV +13FD; C; 13F5; # CHEROKEE SMALL LETTER MV +1C80; C; 0432; # CYRILLIC SMALL LETTER ROUNDED VE +1C81; C; 0434; # CYRILLIC SMALL LETTER LONG-LEGGED DE +1C82; C; 043E; # CYRILLIC SMALL LETTER NARROW O +1C83; C; 0441; # CYRILLIC SMALL LETTER WIDE ES +1C84; C; 0442; # CYRILLIC SMALL LETTER TALL TE +1C85; C; 0442; # CYRILLIC SMALL LETTER THREE-LEGGED TE +1C86; C; 044A; # CYRILLIC SMALL LETTER TALL HARD SIGN +1C87; C; 0463; # CYRILLIC SMALL LETTER TALL YAT +1C88; C; A64B; # CYRILLIC SMALL LETTER UNBLENDED UK +1C89; C; 1C8A; # CYRILLIC CAPITAL LETTER TJE +1C90; C; 10D0; # GEORGIAN MTAVRULI CAPITAL LETTER AN +1C91; C; 10D1; # GEORGIAN MTAVRULI CAPITAL LETTER BAN +1C92; C; 10D2; # GEORGIAN MTAVRULI CAPITAL LETTER GAN +1C93; C; 10D3; # GEORGIAN MTAVRULI CAPITAL LETTER DON +1C94; C; 10D4; # GEORGIAN MTAVRULI CAPITAL LETTER EN +1C95; C; 10D5; # GEORGIAN MTAVRULI CAPITAL LETTER VIN +1C96; C; 10D6; # GEORGIAN MTAVRULI CAPITAL LETTER ZEN +1C97; C; 10D7; # GEORGIAN MTAVRULI CAPITAL LETTER TAN +1C98; C; 10D8; # GEORGIAN MTAVRULI CAPITAL LETTER IN +1C99; C; 10D9; # GEORGIAN MTAVRULI CAPITAL LETTER KAN +1C9A; C; 10DA; # GEORGIAN MTAVRULI CAPITAL LETTER LAS +1C9B; C; 10DB; # GEORGIAN MTAVRULI CAPITAL LETTER MAN +1C9C; C; 10DC; # GEORGIAN MTAVRULI CAPITAL LETTER NAR +1C9D; C; 10DD; # GEORGIAN MTAVRULI CAPITAL LETTER ON +1C9E; C; 10DE; # GEORGIAN MTAVRULI CAPITAL LETTER PAR +1C9F; C; 10DF; # GEORGIAN MTAVRULI CAPITAL LETTER ZHAR +1CA0; C; 10E0; # GEORGIAN MTAVRULI CAPITAL LETTER RAE +1CA1; C; 10E1; # GEORGIAN MTAVRULI CAPITAL LETTER SAN +1CA2; C; 10E2; # GEORGIAN MTAVRULI CAPITAL LETTER TAR +1CA3; C; 10E3; # GEORGIAN MTAVRULI CAPITAL LETTER UN +1CA4; C; 10E4; # GEORGIAN MTAVRULI CAPITAL LETTER PHAR +1CA5; C; 10E5; # GEORGIAN MTAVRULI CAPITAL LETTER KHAR +1CA6; C; 10E6; # GEORGIAN MTAVRULI CAPITAL LETTER GHAN +1CA7; C; 10E7; # GEORGIAN MTAVRULI CAPITAL LETTER QAR +1CA8; C; 10E8; # GEORGIAN MTAVRULI CAPITAL LETTER SHIN +1CA9; C; 10E9; # GEORGIAN MTAVRULI CAPITAL LETTER CHIN +1CAA; C; 10EA; # GEORGIAN MTAVRULI CAPITAL LETTER CAN +1CAB; C; 10EB; # GEORGIAN MTAVRULI CAPITAL LETTER JIL +1CAC; C; 10EC; # GEORGIAN MTAVRULI CAPITAL LETTER CIL +1CAD; C; 10ED; # GEORGIAN MTAVRULI CAPITAL LETTER CHAR +1CAE; C; 10EE; # GEORGIAN MTAVRULI CAPITAL LETTER XAN +1CAF; C; 10EF; # GEORGIAN MTAVRULI CAPITAL LETTER JHAN +1CB0; C; 10F0; # GEORGIAN MTAVRULI CAPITAL LETTER HAE +1CB1; C; 10F1; # GEORGIAN MTAVRULI CAPITAL LETTER HE +1CB2; C; 10F2; # GEORGIAN MTAVRULI CAPITAL LETTER HIE +1CB3; C; 10F3; # GEORGIAN MTAVRULI CAPITAL LETTER WE +1CB4; C; 10F4; # GEORGIAN MTAVRULI CAPITAL LETTER HAR +1CB5; C; 10F5; # GEORGIAN MTAVRULI CAPITAL LETTER HOE +1CB6; C; 10F6; # GEORGIAN MTAVRULI CAPITAL LETTER FI +1CB7; C; 10F7; # GEORGIAN MTAVRULI CAPITAL LETTER YN +1CB8; C; 10F8; # GEORGIAN MTAVRULI CAPITAL LETTER ELIFI +1CB9; C; 10F9; # GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN +1CBA; C; 10FA; # GEORGIAN MTAVRULI CAPITAL LETTER AIN +1CBD; C; 10FD; # GEORGIAN MTAVRULI CAPITAL LETTER AEN +1CBE; C; 10FE; # GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN +1CBF; C; 10FF; # GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN +1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW +1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE +1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW +1E06; C; 1E07; # LATIN CAPITAL LETTER B WITH LINE BELOW +1E08; C; 1E09; # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE +1E0A; C; 1E0B; # LATIN CAPITAL LETTER D WITH DOT ABOVE +1E0C; C; 1E0D; # LATIN CAPITAL LETTER D WITH DOT BELOW +1E0E; C; 1E0F; # LATIN CAPITAL LETTER D WITH LINE BELOW +1E10; C; 1E11; # LATIN CAPITAL LETTER D WITH CEDILLA +1E12; C; 1E13; # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW +1E14; C; 1E15; # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE +1E16; C; 1E17; # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE +1E18; C; 1E19; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW +1E1A; C; 1E1B; # LATIN CAPITAL LETTER E WITH TILDE BELOW +1E1C; C; 1E1D; # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE +1E1E; C; 1E1F; # LATIN CAPITAL LETTER F WITH DOT ABOVE +1E20; C; 1E21; # LATIN CAPITAL LETTER G WITH MACRON +1E22; C; 1E23; # LATIN CAPITAL LETTER H WITH DOT ABOVE +1E24; C; 1E25; # LATIN CAPITAL LETTER H WITH DOT BELOW +1E26; C; 1E27; # LATIN CAPITAL LETTER H WITH DIAERESIS +1E28; C; 1E29; # LATIN CAPITAL LETTER H WITH CEDILLA +1E2A; C; 1E2B; # LATIN CAPITAL LETTER H WITH BREVE BELOW +1E2C; C; 1E2D; # LATIN CAPITAL LETTER I WITH TILDE BELOW +1E2E; C; 1E2F; # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE +1E30; C; 1E31; # LATIN CAPITAL LETTER K WITH ACUTE +1E32; C; 1E33; # LATIN CAPITAL LETTER K WITH DOT BELOW +1E34; C; 1E35; # LATIN CAPITAL LETTER K WITH LINE BELOW +1E36; C; 1E37; # LATIN CAPITAL LETTER L WITH DOT BELOW +1E38; C; 1E39; # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON +1E3A; C; 1E3B; # LATIN CAPITAL LETTER L WITH LINE BELOW +1E3C; C; 1E3D; # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW +1E3E; C; 1E3F; # LATIN CAPITAL LETTER M WITH ACUTE +1E40; C; 1E41; # LATIN CAPITAL LETTER M WITH DOT ABOVE +1E42; C; 1E43; # LATIN CAPITAL LETTER M WITH DOT BELOW +1E44; C; 1E45; # LATIN CAPITAL LETTER N WITH DOT ABOVE +1E46; C; 1E47; # LATIN CAPITAL LETTER N WITH DOT BELOW +1E48; C; 1E49; # LATIN CAPITAL LETTER N WITH LINE BELOW +1E4A; C; 1E4B; # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW +1E4C; C; 1E4D; # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE +1E4E; C; 1E4F; # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS +1E50; C; 1E51; # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE +1E52; C; 1E53; # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE +1E54; C; 1E55; # LATIN CAPITAL LETTER P WITH ACUTE +1E56; C; 1E57; # LATIN CAPITAL LETTER P WITH DOT ABOVE +1E58; C; 1E59; # LATIN CAPITAL LETTER R WITH DOT ABOVE +1E5A; C; 1E5B; # LATIN CAPITAL LETTER R WITH DOT BELOW +1E5C; C; 1E5D; # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON +1E5E; C; 1E5F; # LATIN CAPITAL LETTER R WITH LINE BELOW +1E60; C; 1E61; # LATIN CAPITAL LETTER S WITH DOT ABOVE +1E62; C; 1E63; # LATIN CAPITAL LETTER S WITH DOT BELOW +1E64; C; 1E65; # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE +1E66; C; 1E67; # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE +1E68; C; 1E69; # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE +1E6A; C; 1E6B; # LATIN CAPITAL LETTER T WITH DOT ABOVE +1E6C; C; 1E6D; # LATIN CAPITAL LETTER T WITH DOT BELOW +1E6E; C; 1E6F; # LATIN CAPITAL LETTER T WITH LINE BELOW +1E70; C; 1E71; # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW +1E72; C; 1E73; # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW +1E74; C; 1E75; # LATIN CAPITAL LETTER U WITH TILDE BELOW +1E76; C; 1E77; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW +1E78; C; 1E79; # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE +1E7A; C; 1E7B; # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS +1E7C; C; 1E7D; # LATIN CAPITAL LETTER V WITH TILDE +1E7E; C; 1E7F; # LATIN CAPITAL LETTER V WITH DOT BELOW +1E80; C; 1E81; # LATIN CAPITAL LETTER W WITH GRAVE +1E82; C; 1E83; # LATIN CAPITAL LETTER W WITH ACUTE +1E84; C; 1E85; # LATIN CAPITAL LETTER W WITH DIAERESIS +1E86; C; 1E87; # LATIN CAPITAL LETTER W WITH DOT ABOVE +1E88; C; 1E89; # LATIN CAPITAL LETTER W WITH DOT BELOW +1E8A; C; 1E8B; # LATIN CAPITAL LETTER X WITH DOT ABOVE +1E8C; C; 1E8D; # LATIN CAPITAL LETTER X WITH DIAERESIS +1E8E; C; 1E8F; # LATIN CAPITAL LETTER Y WITH DOT ABOVE +1E90; C; 1E91; # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX +1E92; C; 1E93; # LATIN CAPITAL LETTER Z WITH DOT BELOW +1E94; C; 1E95; # LATIN CAPITAL LETTER Z WITH LINE BELOW +1E96; F; 0068 0331; # LATIN SMALL LETTER H WITH LINE BELOW +1E97; F; 0074 0308; # LATIN SMALL LETTER T WITH DIAERESIS +1E98; F; 0077 030A; # LATIN SMALL LETTER W WITH RING ABOVE +1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE +1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING +1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE +1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S +1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S +1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW +1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE +1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE +1EA6; C; 1EA7; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE +1EA8; C; 1EA9; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE +1EAA; C; 1EAB; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE +1EAC; C; 1EAD; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW +1EAE; C; 1EAF; # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE +1EB0; C; 1EB1; # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE +1EB2; C; 1EB3; # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE +1EB4; C; 1EB5; # LATIN CAPITAL LETTER A WITH BREVE AND TILDE +1EB6; C; 1EB7; # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW +1EB8; C; 1EB9; # LATIN CAPITAL LETTER E WITH DOT BELOW +1EBA; C; 1EBB; # LATIN CAPITAL LETTER E WITH HOOK ABOVE +1EBC; C; 1EBD; # LATIN CAPITAL LETTER E WITH TILDE +1EBE; C; 1EBF; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE +1EC0; C; 1EC1; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE +1EC2; C; 1EC3; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE +1EC4; C; 1EC5; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE +1EC6; C; 1EC7; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW +1EC8; C; 1EC9; # LATIN CAPITAL LETTER I WITH HOOK ABOVE +1ECA; C; 1ECB; # LATIN CAPITAL LETTER I WITH DOT BELOW +1ECC; C; 1ECD; # LATIN CAPITAL LETTER O WITH DOT BELOW +1ECE; C; 1ECF; # LATIN CAPITAL LETTER O WITH HOOK ABOVE +1ED0; C; 1ED1; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE +1ED2; C; 1ED3; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE +1ED4; C; 1ED5; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE +1ED6; C; 1ED7; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE +1ED8; C; 1ED9; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW +1EDA; C; 1EDB; # LATIN CAPITAL LETTER O WITH HORN AND ACUTE +1EDC; C; 1EDD; # LATIN CAPITAL LETTER O WITH HORN AND GRAVE +1EDE; C; 1EDF; # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE +1EE0; C; 1EE1; # LATIN CAPITAL LETTER O WITH HORN AND TILDE +1EE2; C; 1EE3; # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW +1EE4; C; 1EE5; # LATIN CAPITAL LETTER U WITH DOT BELOW +1EE6; C; 1EE7; # LATIN CAPITAL LETTER U WITH HOOK ABOVE +1EE8; C; 1EE9; # LATIN CAPITAL LETTER U WITH HORN AND ACUTE +1EEA; C; 1EEB; # LATIN CAPITAL LETTER U WITH HORN AND GRAVE +1EEC; C; 1EED; # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE +1EEE; C; 1EEF; # LATIN CAPITAL LETTER U WITH HORN AND TILDE +1EF0; C; 1EF1; # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW +1EF2; C; 1EF3; # LATIN CAPITAL LETTER Y WITH GRAVE +1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW +1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE +1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE +1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL +1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V +1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP +1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI +1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA +1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA +1F0B; C; 1F03; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA +1F0C; C; 1F04; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA +1F0D; C; 1F05; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA +1F0E; C; 1F06; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI +1F0F; C; 1F07; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI +1F18; C; 1F10; # GREEK CAPITAL LETTER EPSILON WITH PSILI +1F19; C; 1F11; # GREEK CAPITAL LETTER EPSILON WITH DASIA +1F1A; C; 1F12; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA +1F1B; C; 1F13; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA +1F1C; C; 1F14; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA +1F1D; C; 1F15; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA +1F28; C; 1F20; # GREEK CAPITAL LETTER ETA WITH PSILI +1F29; C; 1F21; # GREEK CAPITAL LETTER ETA WITH DASIA +1F2A; C; 1F22; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA +1F2B; C; 1F23; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA +1F2C; C; 1F24; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA +1F2D; C; 1F25; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA +1F2E; C; 1F26; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI +1F2F; C; 1F27; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI +1F38; C; 1F30; # GREEK CAPITAL LETTER IOTA WITH PSILI +1F39; C; 1F31; # GREEK CAPITAL LETTER IOTA WITH DASIA +1F3A; C; 1F32; # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA +1F3B; C; 1F33; # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA +1F3C; C; 1F34; # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA +1F3D; C; 1F35; # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA +1F3E; C; 1F36; # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI +1F3F; C; 1F37; # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI +1F48; C; 1F40; # GREEK CAPITAL LETTER OMICRON WITH PSILI +1F49; C; 1F41; # GREEK CAPITAL LETTER OMICRON WITH DASIA +1F4A; C; 1F42; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA +1F4B; C; 1F43; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA +1F4C; C; 1F44; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA +1F4D; C; 1F45; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA +1F50; F; 03C5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI +1F52; F; 03C5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA +1F54; F; 03C5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA +1F56; F; 03C5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI +1F59; C; 1F51; # GREEK CAPITAL LETTER UPSILON WITH DASIA +1F5B; C; 1F53; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA +1F5D; C; 1F55; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA +1F5F; C; 1F57; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI +1F68; C; 1F60; # GREEK CAPITAL LETTER OMEGA WITH PSILI +1F69; C; 1F61; # GREEK CAPITAL LETTER OMEGA WITH DASIA +1F6A; C; 1F62; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA +1F6B; C; 1F63; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA +1F6C; C; 1F64; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA +1F6D; C; 1F65; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA +1F6E; C; 1F66; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI +1F6F; C; 1F67; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI +1F80; F; 1F00 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI +1F81; F; 1F01 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI +1F82; F; 1F02 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F83; F; 1F03 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F84; F; 1F04 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F85; F; 1F05 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F86; F; 1F06 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F87; F; 1F07 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F88; F; 1F00 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI +1F88; S; 1F80; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI +1F89; F; 1F01 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI +1F89; S; 1F81; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI +1F8A; F; 1F02 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F8A; S; 1F82; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F8B; F; 1F03 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F8B; S; 1F83; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F8C; F; 1F04 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F8C; S; 1F84; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F8D; F; 1F05 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F8D; S; 1F85; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F8E; F; 1F06 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F8E; S; 1F86; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F8F; F; 1F07 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1F8F; S; 1F87; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1F90; F; 1F20 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI +1F91; F; 1F21 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI +1F92; F; 1F22 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F93; F; 1F23 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F94; F; 1F24 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F95; F; 1F25 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F96; F; 1F26 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F97; F; 1F27 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F98; F; 1F20 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI +1F98; S; 1F90; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI +1F99; F; 1F21 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI +1F99; S; 1F91; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI +1F9A; F; 1F22 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F9A; S; 1F92; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F9B; F; 1F23 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F9B; S; 1F93; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F9C; F; 1F24 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F9C; S; 1F94; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F9D; F; 1F25 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F9D; S; 1F95; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F9E; F; 1F26 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F9E; S; 1F96; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F9F; F; 1F27 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1F9F; S; 1F97; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FA0; F; 1F60 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI +1FA1; F; 1F61 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI +1FA2; F; 1F62 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1FA3; F; 1F63 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1FA4; F; 1F64 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1FA5; F; 1F65 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1FA6; F; 1F66 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1FA7; F; 1F67 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1FA8; F; 1F60 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI +1FA8; S; 1FA0; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI +1FA9; F; 1F61 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI +1FA9; S; 1FA1; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI +1FAA; F; 1F62 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1FAA; S; 1FA2; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1FAB; F; 1F63 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1FAB; S; 1FA3; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1FAC; F; 1F64 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1FAC; S; 1FA4; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1FAD; F; 1F65 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1FAD; S; 1FA5; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1FAE; F; 1F66 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1FAE; S; 1FA6; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1FAF; F; 1F67 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FAF; S; 1FA7; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FB2; F; 1F70 03B9; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI +1FB3; F; 03B1 03B9; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI +1FB4; F; 03AC 03B9; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI +1FB6; F; 03B1 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI +1FB7; F; 03B1 0342 03B9; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI +1FB8; C; 1FB0; # GREEK CAPITAL LETTER ALPHA WITH VRACHY +1FB9; C; 1FB1; # GREEK CAPITAL LETTER ALPHA WITH MACRON +1FBA; C; 1F70; # GREEK CAPITAL LETTER ALPHA WITH VARIA +1FBB; C; 1F71; # GREEK CAPITAL LETTER ALPHA WITH OXIA +1FBC; F; 03B1 03B9; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FBC; S; 1FB3; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FBE; C; 03B9; # GREEK PROSGEGRAMMENI +1FC2; F; 1F74 03B9; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI +1FC3; F; 03B7 03B9; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI +1FC4; F; 03AE 03B9; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI +1FC6; F; 03B7 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI +1FC7; F; 03B7 0342 03B9; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI +1FC8; C; 1F72; # GREEK CAPITAL LETTER EPSILON WITH VARIA +1FC9; C; 1F73; # GREEK CAPITAL LETTER EPSILON WITH OXIA +1FCA; C; 1F74; # GREEK CAPITAL LETTER ETA WITH VARIA +1FCB; C; 1F75; # GREEK CAPITAL LETTER ETA WITH OXIA +1FCC; F; 03B7 03B9; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA +1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD3; S; 0390; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI +1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI +1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY +1FD9; C; 1FD1; # GREEK CAPITAL LETTER IOTA WITH MACRON +1FDA; C; 1F76; # GREEK CAPITAL LETTER IOTA WITH VARIA +1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA +1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA +1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA +1FE3; S; 03B0; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA +1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI +1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI +1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI +1FE8; C; 1FE0; # GREEK CAPITAL LETTER UPSILON WITH VRACHY +1FE9; C; 1FE1; # GREEK CAPITAL LETTER UPSILON WITH MACRON +1FEA; C; 1F7A; # GREEK CAPITAL LETTER UPSILON WITH VARIA +1FEB; C; 1F7B; # GREEK CAPITAL LETTER UPSILON WITH OXIA +1FEC; C; 1FE5; # GREEK CAPITAL LETTER RHO WITH DASIA +1FF2; F; 1F7C 03B9; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI +1FF3; F; 03C9 03B9; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI +1FF4; F; 03CE 03B9; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI +1FF6; F; 03C9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI +1FF7; F; 03C9 0342 03B9; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI +1FF8; C; 1F78; # GREEK CAPITAL LETTER OMICRON WITH VARIA +1FF9; C; 1F79; # GREEK CAPITAL LETTER OMICRON WITH OXIA +1FFA; C; 1F7C; # GREEK CAPITAL LETTER OMEGA WITH VARIA +1FFB; C; 1F7D; # GREEK CAPITAL LETTER OMEGA WITH OXIA +1FFC; F; 03C9 03B9; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI +1FFC; S; 1FF3; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI +2126; C; 03C9; # OHM SIGN +212A; C; 006B; # KELVIN SIGN +212B; C; 00E5; # ANGSTROM SIGN +2132; C; 214E; # TURNED CAPITAL F +2160; C; 2170; # ROMAN NUMERAL ONE +2161; C; 2171; # ROMAN NUMERAL TWO +2162; C; 2172; # ROMAN NUMERAL THREE +2163; C; 2173; # ROMAN NUMERAL FOUR +2164; C; 2174; # ROMAN NUMERAL FIVE +2165; C; 2175; # ROMAN NUMERAL SIX +2166; C; 2176; # ROMAN NUMERAL SEVEN +2167; C; 2177; # ROMAN NUMERAL EIGHT +2168; C; 2178; # ROMAN NUMERAL NINE +2169; C; 2179; # ROMAN NUMERAL TEN +216A; C; 217A; # ROMAN NUMERAL ELEVEN +216B; C; 217B; # ROMAN NUMERAL TWELVE +216C; C; 217C; # ROMAN NUMERAL FIFTY +216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED +216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED +216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND +2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED +24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A +24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B +24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C +24B9; C; 24D3; # CIRCLED LATIN CAPITAL LETTER D +24BA; C; 24D4; # CIRCLED LATIN CAPITAL LETTER E +24BB; C; 24D5; # CIRCLED LATIN CAPITAL LETTER F +24BC; C; 24D6; # CIRCLED LATIN CAPITAL LETTER G +24BD; C; 24D7; # CIRCLED LATIN CAPITAL LETTER H +24BE; C; 24D8; # CIRCLED LATIN CAPITAL LETTER I +24BF; C; 24D9; # CIRCLED LATIN CAPITAL LETTER J +24C0; C; 24DA; # CIRCLED LATIN CAPITAL LETTER K +24C1; C; 24DB; # CIRCLED LATIN CAPITAL LETTER L +24C2; C; 24DC; # CIRCLED LATIN CAPITAL LETTER M +24C3; C; 24DD; # CIRCLED LATIN CAPITAL LETTER N +24C4; C; 24DE; # CIRCLED LATIN CAPITAL LETTER O +24C5; C; 24DF; # CIRCLED LATIN CAPITAL LETTER P +24C6; C; 24E0; # CIRCLED LATIN CAPITAL LETTER Q +24C7; C; 24E1; # CIRCLED LATIN CAPITAL LETTER R +24C8; C; 24E2; # CIRCLED LATIN CAPITAL LETTER S +24C9; C; 24E3; # CIRCLED LATIN CAPITAL LETTER T +24CA; C; 24E4; # CIRCLED LATIN CAPITAL LETTER U +24CB; C; 24E5; # CIRCLED LATIN CAPITAL LETTER V +24CC; C; 24E6; # CIRCLED LATIN CAPITAL LETTER W +24CD; C; 24E7; # CIRCLED LATIN CAPITAL LETTER X +24CE; C; 24E8; # CIRCLED LATIN CAPITAL LETTER Y +24CF; C; 24E9; # CIRCLED LATIN CAPITAL LETTER Z +2C00; C; 2C30; # GLAGOLITIC CAPITAL LETTER AZU +2C01; C; 2C31; # GLAGOLITIC CAPITAL LETTER BUKY +2C02; C; 2C32; # GLAGOLITIC CAPITAL LETTER VEDE +2C03; C; 2C33; # GLAGOLITIC CAPITAL LETTER GLAGOLI +2C04; C; 2C34; # GLAGOLITIC CAPITAL LETTER DOBRO +2C05; C; 2C35; # GLAGOLITIC CAPITAL LETTER YESTU +2C06; C; 2C36; # GLAGOLITIC CAPITAL LETTER ZHIVETE +2C07; C; 2C37; # GLAGOLITIC CAPITAL LETTER DZELO +2C08; C; 2C38; # GLAGOLITIC CAPITAL LETTER ZEMLJA +2C09; C; 2C39; # GLAGOLITIC CAPITAL LETTER IZHE +2C0A; C; 2C3A; # GLAGOLITIC CAPITAL LETTER INITIAL IZHE +2C0B; C; 2C3B; # GLAGOLITIC CAPITAL LETTER I +2C0C; C; 2C3C; # GLAGOLITIC CAPITAL LETTER DJERVI +2C0D; C; 2C3D; # GLAGOLITIC CAPITAL LETTER KAKO +2C0E; C; 2C3E; # GLAGOLITIC CAPITAL LETTER LJUDIJE +2C0F; C; 2C3F; # GLAGOLITIC CAPITAL LETTER MYSLITE +2C10; C; 2C40; # GLAGOLITIC CAPITAL LETTER NASHI +2C11; C; 2C41; # GLAGOLITIC CAPITAL LETTER ONU +2C12; C; 2C42; # GLAGOLITIC CAPITAL LETTER POKOJI +2C13; C; 2C43; # GLAGOLITIC CAPITAL LETTER RITSI +2C14; C; 2C44; # GLAGOLITIC CAPITAL LETTER SLOVO +2C15; C; 2C45; # GLAGOLITIC CAPITAL LETTER TVRIDO +2C16; C; 2C46; # GLAGOLITIC CAPITAL LETTER UKU +2C17; C; 2C47; # GLAGOLITIC CAPITAL LETTER FRITU +2C18; C; 2C48; # GLAGOLITIC CAPITAL LETTER HERU +2C19; C; 2C49; # GLAGOLITIC CAPITAL LETTER OTU +2C1A; C; 2C4A; # GLAGOLITIC CAPITAL LETTER PE +2C1B; C; 2C4B; # GLAGOLITIC CAPITAL LETTER SHTA +2C1C; C; 2C4C; # GLAGOLITIC CAPITAL LETTER TSI +2C1D; C; 2C4D; # GLAGOLITIC CAPITAL LETTER CHRIVI +2C1E; C; 2C4E; # GLAGOLITIC CAPITAL LETTER SHA +2C1F; C; 2C4F; # GLAGOLITIC CAPITAL LETTER YERU +2C20; C; 2C50; # GLAGOLITIC CAPITAL LETTER YERI +2C21; C; 2C51; # GLAGOLITIC CAPITAL LETTER YATI +2C22; C; 2C52; # GLAGOLITIC CAPITAL LETTER SPIDERY HA +2C23; C; 2C53; # GLAGOLITIC CAPITAL LETTER YU +2C24; C; 2C54; # GLAGOLITIC CAPITAL LETTER SMALL YUS +2C25; C; 2C55; # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL +2C26; C; 2C56; # GLAGOLITIC CAPITAL LETTER YO +2C27; C; 2C57; # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS +2C28; C; 2C58; # GLAGOLITIC CAPITAL LETTER BIG YUS +2C29; C; 2C59; # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS +2C2A; C; 2C5A; # GLAGOLITIC CAPITAL LETTER FITA +2C2B; C; 2C5B; # GLAGOLITIC CAPITAL LETTER IZHITSA +2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC +2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A +2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +2C2F; C; 2C5F; # GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI +2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR +2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE +2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE +2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL +2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER +2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER +2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER +2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA +2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK +2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A +2C70; C; 0252; # LATIN CAPITAL LETTER TURNED ALPHA +2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK +2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H +2C7E; C; 023F; # LATIN CAPITAL LETTER S WITH SWASH TAIL +2C7F; C; 0240; # LATIN CAPITAL LETTER Z WITH SWASH TAIL +2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA +2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA +2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA +2C86; C; 2C87; # COPTIC CAPITAL LETTER DALDA +2C88; C; 2C89; # COPTIC CAPITAL LETTER EIE +2C8A; C; 2C8B; # COPTIC CAPITAL LETTER SOU +2C8C; C; 2C8D; # COPTIC CAPITAL LETTER ZATA +2C8E; C; 2C8F; # COPTIC CAPITAL LETTER HATE +2C90; C; 2C91; # COPTIC CAPITAL LETTER THETHE +2C92; C; 2C93; # COPTIC CAPITAL LETTER IAUDA +2C94; C; 2C95; # COPTIC CAPITAL LETTER KAPA +2C96; C; 2C97; # COPTIC CAPITAL LETTER LAULA +2C98; C; 2C99; # COPTIC CAPITAL LETTER MI +2C9A; C; 2C9B; # COPTIC CAPITAL LETTER NI +2C9C; C; 2C9D; # COPTIC CAPITAL LETTER KSI +2C9E; C; 2C9F; # COPTIC CAPITAL LETTER O +2CA0; C; 2CA1; # COPTIC CAPITAL LETTER PI +2CA2; C; 2CA3; # COPTIC CAPITAL LETTER RO +2CA4; C; 2CA5; # COPTIC CAPITAL LETTER SIMA +2CA6; C; 2CA7; # COPTIC CAPITAL LETTER TAU +2CA8; C; 2CA9; # COPTIC CAPITAL LETTER UA +2CAA; C; 2CAB; # COPTIC CAPITAL LETTER FI +2CAC; C; 2CAD; # COPTIC CAPITAL LETTER KHI +2CAE; C; 2CAF; # COPTIC CAPITAL LETTER PSI +2CB0; C; 2CB1; # COPTIC CAPITAL LETTER OOU +2CB2; C; 2CB3; # COPTIC CAPITAL LETTER DIALECT-P ALEF +2CB4; C; 2CB5; # COPTIC CAPITAL LETTER OLD COPTIC AIN +2CB6; C; 2CB7; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE +2CB8; C; 2CB9; # COPTIC CAPITAL LETTER DIALECT-P KAPA +2CBA; C; 2CBB; # COPTIC CAPITAL LETTER DIALECT-P NI +2CBC; C; 2CBD; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI +2CBE; C; 2CBF; # COPTIC CAPITAL LETTER OLD COPTIC OOU +2CC0; C; 2CC1; # COPTIC CAPITAL LETTER SAMPI +2CC2; C; 2CC3; # COPTIC CAPITAL LETTER CROSSED SHEI +2CC4; C; 2CC5; # COPTIC CAPITAL LETTER OLD COPTIC SHEI +2CC6; C; 2CC7; # COPTIC CAPITAL LETTER OLD COPTIC ESH +2CC8; C; 2CC9; # COPTIC CAPITAL LETTER AKHMIMIC KHEI +2CCA; C; 2CCB; # COPTIC CAPITAL LETTER DIALECT-P HORI +2CCC; C; 2CCD; # COPTIC CAPITAL LETTER OLD COPTIC HORI +2CCE; C; 2CCF; # COPTIC CAPITAL LETTER OLD COPTIC HA +2CD0; C; 2CD1; # COPTIC CAPITAL LETTER L-SHAPED HA +2CD2; C; 2CD3; # COPTIC CAPITAL LETTER OLD COPTIC HEI +2CD4; C; 2CD5; # COPTIC CAPITAL LETTER OLD COPTIC HAT +2CD6; C; 2CD7; # COPTIC CAPITAL LETTER OLD COPTIC GANGIA +2CD8; C; 2CD9; # COPTIC CAPITAL LETTER OLD COPTIC DJA +2CDA; C; 2CDB; # COPTIC CAPITAL LETTER OLD COPTIC SHIMA +2CDC; C; 2CDD; # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA +2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI +2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI +2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU +2CEB; C; 2CEC; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI +2CED; C; 2CEE; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA +2CF2; C; 2CF3; # COPTIC CAPITAL LETTER BOHAIRIC KHEI +A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA +A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO +A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE +A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA +A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV +A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK +A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA +A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER +A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER +A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT +A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU +A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A +A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS +A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS +A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS +A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN +A660; C; A661; # CYRILLIC CAPITAL LETTER REVERSED TSE +A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE +A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL +A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM +A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O +A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O +A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O +A680; C; A681; # CYRILLIC CAPITAL LETTER DWE +A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE +A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE +A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE +A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE +A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK +A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE +A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE +A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE +A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE +A694; C; A695; # CYRILLIC CAPITAL LETTER HWE +A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE +A698; C; A699; # CYRILLIC CAPITAL LETTER DOUBLE O +A69A; C; A69B; # CYRILLIC CAPITAL LETTER CROSSED O +A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF +A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN +A726; C; A727; # LATIN CAPITAL LETTER HENG +A728; C; A729; # LATIN CAPITAL LETTER TZ +A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO +A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO +A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA +A732; C; A733; # LATIN CAPITAL LETTER AA +A734; C; A735; # LATIN CAPITAL LETTER AO +A736; C; A737; # LATIN CAPITAL LETTER AU +A738; C; A739; # LATIN CAPITAL LETTER AV +A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR +A73C; C; A73D; # LATIN CAPITAL LETTER AY +A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT +A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE +A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE +A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE +A746; C; A747; # LATIN CAPITAL LETTER BROKEN L +A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE +A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY +A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP +A74E; C; A74F; # LATIN CAPITAL LETTER OO +A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER +A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH +A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL +A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER +A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE +A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA +A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA +A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE +A760; C; A761; # LATIN CAPITAL LETTER VY +A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z +A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE +A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER +A768; C; A769; # LATIN CAPITAL LETTER VEND +A76A; C; A76B; # LATIN CAPITAL LETTER ET +A76C; C; A76D; # LATIN CAPITAL LETTER IS +A76E; C; A76F; # LATIN CAPITAL LETTER CON +A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D +A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F +A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G +A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G +A780; C; A781; # LATIN CAPITAL LETTER TURNED L +A782; C; A783; # LATIN CAPITAL LETTER INSULAR R +A784; C; A785; # LATIN CAPITAL LETTER INSULAR S +A786; C; A787; # LATIN CAPITAL LETTER INSULAR T +A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO +A78D; C; 0265; # LATIN CAPITAL LETTER TURNED H +A790; C; A791; # LATIN CAPITAL LETTER N WITH DESCENDER +A792; C; A793; # LATIN CAPITAL LETTER C WITH BAR +A796; C; A797; # LATIN CAPITAL LETTER B WITH FLOURISH +A798; C; A799; # LATIN CAPITAL LETTER F WITH STROKE +A79A; C; A79B; # LATIN CAPITAL LETTER VOLAPUK AE +A79C; C; A79D; # LATIN CAPITAL LETTER VOLAPUK OE +A79E; C; A79F; # LATIN CAPITAL LETTER VOLAPUK UE +A7A0; C; A7A1; # LATIN CAPITAL LETTER G WITH OBLIQUE STROKE +A7A2; C; A7A3; # LATIN CAPITAL LETTER K WITH OBLIQUE STROKE +A7A4; C; A7A5; # LATIN CAPITAL LETTER N WITH OBLIQUE STROKE +A7A6; C; A7A7; # LATIN CAPITAL LETTER R WITH OBLIQUE STROKE +A7A8; C; A7A9; # LATIN CAPITAL LETTER S WITH OBLIQUE STROKE +A7AA; C; 0266; # LATIN CAPITAL LETTER H WITH HOOK +A7AB; C; 025C; # LATIN CAPITAL LETTER REVERSED OPEN E +A7AC; C; 0261; # LATIN CAPITAL LETTER SCRIPT G +A7AD; C; 026C; # LATIN CAPITAL LETTER L WITH BELT +A7AE; C; 026A; # LATIN CAPITAL LETTER SMALL CAPITAL I +A7B0; C; 029E; # LATIN CAPITAL LETTER TURNED K +A7B1; C; 0287; # LATIN CAPITAL LETTER TURNED T +A7B2; C; 029D; # LATIN CAPITAL LETTER J WITH CROSSED-TAIL +A7B3; C; AB53; # LATIN CAPITAL LETTER CHI +A7B4; C; A7B5; # LATIN CAPITAL LETTER BETA +A7B6; C; A7B7; # LATIN CAPITAL LETTER OMEGA +A7B8; C; A7B9; # LATIN CAPITAL LETTER U WITH STROKE +A7BA; C; A7BB; # LATIN CAPITAL LETTER GLOTTAL A +A7BC; C; A7BD; # LATIN CAPITAL LETTER GLOTTAL I +A7BE; C; A7BF; # LATIN CAPITAL LETTER GLOTTAL U +A7C0; C; A7C1; # LATIN CAPITAL LETTER OLD POLISH O +A7C2; C; A7C3; # LATIN CAPITAL LETTER ANGLICANA W +A7C4; C; A794; # LATIN CAPITAL LETTER C WITH PALATAL HOOK +A7C5; C; 0282; # LATIN CAPITAL LETTER S WITH HOOK +A7C6; C; 1D8E; # LATIN CAPITAL LETTER Z WITH PALATAL HOOK +A7C7; C; A7C8; # LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY +A7C9; C; A7CA; # LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY +A7CB; C; 0264; # LATIN CAPITAL LETTER RAMS HORN +A7CC; C; A7CD; # LATIN CAPITAL LETTER S WITH DIAGONAL STROKE +A7D0; C; A7D1; # LATIN CAPITAL LETTER CLOSED INSULAR G +A7D6; C; A7D7; # LATIN CAPITAL LETTER MIDDLE SCOTS S +A7D8; C; A7D9; # LATIN CAPITAL LETTER SIGMOID S +A7DA; C; A7DB; # LATIN CAPITAL LETTER LAMBDA +A7DC; C; 019B; # LATIN CAPITAL LETTER LAMBDA WITH STROKE +A7F5; C; A7F6; # LATIN CAPITAL LETTER REVERSED HALF H +AB70; C; 13A0; # CHEROKEE SMALL LETTER A +AB71; C; 13A1; # CHEROKEE SMALL LETTER E +AB72; C; 13A2; # CHEROKEE SMALL LETTER I +AB73; C; 13A3; # CHEROKEE SMALL LETTER O +AB74; C; 13A4; # CHEROKEE SMALL LETTER U +AB75; C; 13A5; # CHEROKEE SMALL LETTER V +AB76; C; 13A6; # CHEROKEE SMALL LETTER GA +AB77; C; 13A7; # CHEROKEE SMALL LETTER KA +AB78; C; 13A8; # CHEROKEE SMALL LETTER GE +AB79; C; 13A9; # CHEROKEE SMALL LETTER GI +AB7A; C; 13AA; # CHEROKEE SMALL LETTER GO +AB7B; C; 13AB; # CHEROKEE SMALL LETTER GU +AB7C; C; 13AC; # CHEROKEE SMALL LETTER GV +AB7D; C; 13AD; # CHEROKEE SMALL LETTER HA +AB7E; C; 13AE; # CHEROKEE SMALL LETTER HE +AB7F; C; 13AF; # CHEROKEE SMALL LETTER HI +AB80; C; 13B0; # CHEROKEE SMALL LETTER HO +AB81; C; 13B1; # CHEROKEE SMALL LETTER HU +AB82; C; 13B2; # CHEROKEE SMALL LETTER HV +AB83; C; 13B3; # CHEROKEE SMALL LETTER LA +AB84; C; 13B4; # CHEROKEE SMALL LETTER LE +AB85; C; 13B5; # CHEROKEE SMALL LETTER LI +AB86; C; 13B6; # CHEROKEE SMALL LETTER LO +AB87; C; 13B7; # CHEROKEE SMALL LETTER LU +AB88; C; 13B8; # CHEROKEE SMALL LETTER LV +AB89; C; 13B9; # CHEROKEE SMALL LETTER MA +AB8A; C; 13BA; # CHEROKEE SMALL LETTER ME +AB8B; C; 13BB; # CHEROKEE SMALL LETTER MI +AB8C; C; 13BC; # CHEROKEE SMALL LETTER MO +AB8D; C; 13BD; # CHEROKEE SMALL LETTER MU +AB8E; C; 13BE; # CHEROKEE SMALL LETTER NA +AB8F; C; 13BF; # CHEROKEE SMALL LETTER HNA +AB90; C; 13C0; # CHEROKEE SMALL LETTER NAH +AB91; C; 13C1; # CHEROKEE SMALL LETTER NE +AB92; C; 13C2; # CHEROKEE SMALL LETTER NI +AB93; C; 13C3; # CHEROKEE SMALL LETTER NO +AB94; C; 13C4; # CHEROKEE SMALL LETTER NU +AB95; C; 13C5; # CHEROKEE SMALL LETTER NV +AB96; C; 13C6; # CHEROKEE SMALL LETTER QUA +AB97; C; 13C7; # CHEROKEE SMALL LETTER QUE +AB98; C; 13C8; # CHEROKEE SMALL LETTER QUI +AB99; C; 13C9; # CHEROKEE SMALL LETTER QUO +AB9A; C; 13CA; # CHEROKEE SMALL LETTER QUU +AB9B; C; 13CB; # CHEROKEE SMALL LETTER QUV +AB9C; C; 13CC; # CHEROKEE SMALL LETTER SA +AB9D; C; 13CD; # CHEROKEE SMALL LETTER S +AB9E; C; 13CE; # CHEROKEE SMALL LETTER SE +AB9F; C; 13CF; # CHEROKEE SMALL LETTER SI +ABA0; C; 13D0; # CHEROKEE SMALL LETTER SO +ABA1; C; 13D1; # CHEROKEE SMALL LETTER SU +ABA2; C; 13D2; # CHEROKEE SMALL LETTER SV +ABA3; C; 13D3; # CHEROKEE SMALL LETTER DA +ABA4; C; 13D4; # CHEROKEE SMALL LETTER TA +ABA5; C; 13D5; # CHEROKEE SMALL LETTER DE +ABA6; C; 13D6; # CHEROKEE SMALL LETTER TE +ABA7; C; 13D7; # CHEROKEE SMALL LETTER DI +ABA8; C; 13D8; # CHEROKEE SMALL LETTER TI +ABA9; C; 13D9; # CHEROKEE SMALL LETTER DO +ABAA; C; 13DA; # CHEROKEE SMALL LETTER DU +ABAB; C; 13DB; # CHEROKEE SMALL LETTER DV +ABAC; C; 13DC; # CHEROKEE SMALL LETTER DLA +ABAD; C; 13DD; # CHEROKEE SMALL LETTER TLA +ABAE; C; 13DE; # CHEROKEE SMALL LETTER TLE +ABAF; C; 13DF; # CHEROKEE SMALL LETTER TLI +ABB0; C; 13E0; # CHEROKEE SMALL LETTER TLO +ABB1; C; 13E1; # CHEROKEE SMALL LETTER TLU +ABB2; C; 13E2; # CHEROKEE SMALL LETTER TLV +ABB3; C; 13E3; # CHEROKEE SMALL LETTER TSA +ABB4; C; 13E4; # CHEROKEE SMALL LETTER TSE +ABB5; C; 13E5; # CHEROKEE SMALL LETTER TSI +ABB6; C; 13E6; # CHEROKEE SMALL LETTER TSO +ABB7; C; 13E7; # CHEROKEE SMALL LETTER TSU +ABB8; C; 13E8; # CHEROKEE SMALL LETTER TSV +ABB9; C; 13E9; # CHEROKEE SMALL LETTER WA +ABBA; C; 13EA; # CHEROKEE SMALL LETTER WE +ABBB; C; 13EB; # CHEROKEE SMALL LETTER WI +ABBC; C; 13EC; # CHEROKEE SMALL LETTER WO +ABBD; C; 13ED; # CHEROKEE SMALL LETTER WU +ABBE; C; 13EE; # CHEROKEE SMALL LETTER WV +ABBF; C; 13EF; # CHEROKEE SMALL LETTER YA +FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF +FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI +FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL +FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI +FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL +FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T +FB05; S; FB06; # LATIN SMALL LIGATURE LONG S T +FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST +FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW +FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH +FB15; F; 0574 056B; # ARMENIAN SMALL LIGATURE MEN INI +FB16; F; 057E 0576; # ARMENIAN SMALL LIGATURE VEW NOW +FB17; F; 0574 056D; # ARMENIAN SMALL LIGATURE MEN XEH +FF21; C; FF41; # FULLWIDTH LATIN CAPITAL LETTER A +FF22; C; FF42; # FULLWIDTH LATIN CAPITAL LETTER B +FF23; C; FF43; # FULLWIDTH LATIN CAPITAL LETTER C +FF24; C; FF44; # FULLWIDTH LATIN CAPITAL LETTER D +FF25; C; FF45; # FULLWIDTH LATIN CAPITAL LETTER E +FF26; C; FF46; # FULLWIDTH LATIN CAPITAL LETTER F +FF27; C; FF47; # FULLWIDTH LATIN CAPITAL LETTER G +FF28; C; FF48; # FULLWIDTH LATIN CAPITAL LETTER H +FF29; C; FF49; # FULLWIDTH LATIN CAPITAL LETTER I +FF2A; C; FF4A; # FULLWIDTH LATIN CAPITAL LETTER J +FF2B; C; FF4B; # FULLWIDTH LATIN CAPITAL LETTER K +FF2C; C; FF4C; # FULLWIDTH LATIN CAPITAL LETTER L +FF2D; C; FF4D; # FULLWIDTH LATIN CAPITAL LETTER M +FF2E; C; FF4E; # FULLWIDTH LATIN CAPITAL LETTER N +FF2F; C; FF4F; # FULLWIDTH LATIN CAPITAL LETTER O +FF30; C; FF50; # FULLWIDTH LATIN CAPITAL LETTER P +FF31; C; FF51; # FULLWIDTH LATIN CAPITAL LETTER Q +FF32; C; FF52; # FULLWIDTH LATIN CAPITAL LETTER R +FF33; C; FF53; # FULLWIDTH LATIN CAPITAL LETTER S +FF34; C; FF54; # FULLWIDTH LATIN CAPITAL LETTER T +FF35; C; FF55; # FULLWIDTH LATIN CAPITAL LETTER U +FF36; C; FF56; # FULLWIDTH LATIN CAPITAL LETTER V +FF37; C; FF57; # FULLWIDTH LATIN CAPITAL LETTER W +FF38; C; FF58; # FULLWIDTH LATIN CAPITAL LETTER X +FF39; C; FF59; # FULLWIDTH LATIN CAPITAL LETTER Y +FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z +10400; C; 10428; # DESERET CAPITAL LETTER LONG I +10401; C; 10429; # DESERET CAPITAL LETTER LONG E +10402; C; 1042A; # DESERET CAPITAL LETTER LONG A +10403; C; 1042B; # DESERET CAPITAL LETTER LONG AH +10404; C; 1042C; # DESERET CAPITAL LETTER LONG O +10405; C; 1042D; # DESERET CAPITAL LETTER LONG OO +10406; C; 1042E; # DESERET CAPITAL LETTER SHORT I +10407; C; 1042F; # DESERET CAPITAL LETTER SHORT E +10408; C; 10430; # DESERET CAPITAL LETTER SHORT A +10409; C; 10431; # DESERET CAPITAL LETTER SHORT AH +1040A; C; 10432; # DESERET CAPITAL LETTER SHORT O +1040B; C; 10433; # DESERET CAPITAL LETTER SHORT OO +1040C; C; 10434; # DESERET CAPITAL LETTER AY +1040D; C; 10435; # DESERET CAPITAL LETTER OW +1040E; C; 10436; # DESERET CAPITAL LETTER WU +1040F; C; 10437; # DESERET CAPITAL LETTER YEE +10410; C; 10438; # DESERET CAPITAL LETTER H +10411; C; 10439; # DESERET CAPITAL LETTER PEE +10412; C; 1043A; # DESERET CAPITAL LETTER BEE +10413; C; 1043B; # DESERET CAPITAL LETTER TEE +10414; C; 1043C; # DESERET CAPITAL LETTER DEE +10415; C; 1043D; # DESERET CAPITAL LETTER CHEE +10416; C; 1043E; # DESERET CAPITAL LETTER JEE +10417; C; 1043F; # DESERET CAPITAL LETTER KAY +10418; C; 10440; # DESERET CAPITAL LETTER GAY +10419; C; 10441; # DESERET CAPITAL LETTER EF +1041A; C; 10442; # DESERET CAPITAL LETTER VEE +1041B; C; 10443; # DESERET CAPITAL LETTER ETH +1041C; C; 10444; # DESERET CAPITAL LETTER THEE +1041D; C; 10445; # DESERET CAPITAL LETTER ES +1041E; C; 10446; # DESERET CAPITAL LETTER ZEE +1041F; C; 10447; # DESERET CAPITAL LETTER ESH +10420; C; 10448; # DESERET CAPITAL LETTER ZHEE +10421; C; 10449; # DESERET CAPITAL LETTER ER +10422; C; 1044A; # DESERET CAPITAL LETTER EL +10423; C; 1044B; # DESERET CAPITAL LETTER EM +10424; C; 1044C; # DESERET CAPITAL LETTER EN +10425; C; 1044D; # DESERET CAPITAL LETTER ENG +10426; C; 1044E; # DESERET CAPITAL LETTER OI +10427; C; 1044F; # DESERET CAPITAL LETTER EW +104B0; C; 104D8; # OSAGE CAPITAL LETTER A +104B1; C; 104D9; # OSAGE CAPITAL LETTER AI +104B2; C; 104DA; # OSAGE CAPITAL LETTER AIN +104B3; C; 104DB; # OSAGE CAPITAL LETTER AH +104B4; C; 104DC; # OSAGE CAPITAL LETTER BRA +104B5; C; 104DD; # OSAGE CAPITAL LETTER CHA +104B6; C; 104DE; # OSAGE CAPITAL LETTER EHCHA +104B7; C; 104DF; # OSAGE CAPITAL LETTER E +104B8; C; 104E0; # OSAGE CAPITAL LETTER EIN +104B9; C; 104E1; # OSAGE CAPITAL LETTER HA +104BA; C; 104E2; # OSAGE CAPITAL LETTER HYA +104BB; C; 104E3; # OSAGE CAPITAL LETTER I +104BC; C; 104E4; # OSAGE CAPITAL LETTER KA +104BD; C; 104E5; # OSAGE CAPITAL LETTER EHKA +104BE; C; 104E6; # OSAGE CAPITAL LETTER KYA +104BF; C; 104E7; # OSAGE CAPITAL LETTER LA +104C0; C; 104E8; # OSAGE CAPITAL LETTER MA +104C1; C; 104E9; # OSAGE CAPITAL LETTER NA +104C2; C; 104EA; # OSAGE CAPITAL LETTER O +104C3; C; 104EB; # OSAGE CAPITAL LETTER OIN +104C4; C; 104EC; # OSAGE CAPITAL LETTER PA +104C5; C; 104ED; # OSAGE CAPITAL LETTER EHPA +104C6; C; 104EE; # OSAGE CAPITAL LETTER SA +104C7; C; 104EF; # OSAGE CAPITAL LETTER SHA +104C8; C; 104F0; # OSAGE CAPITAL LETTER TA +104C9; C; 104F1; # OSAGE CAPITAL LETTER EHTA +104CA; C; 104F2; # OSAGE CAPITAL LETTER TSA +104CB; C; 104F3; # OSAGE CAPITAL LETTER EHTSA +104CC; C; 104F4; # OSAGE CAPITAL LETTER TSHA +104CD; C; 104F5; # OSAGE CAPITAL LETTER DHA +104CE; C; 104F6; # OSAGE CAPITAL LETTER U +104CF; C; 104F7; # OSAGE CAPITAL LETTER WA +104D0; C; 104F8; # OSAGE CAPITAL LETTER KHA +104D1; C; 104F9; # OSAGE CAPITAL LETTER GHA +104D2; C; 104FA; # OSAGE CAPITAL LETTER ZA +104D3; C; 104FB; # OSAGE CAPITAL LETTER ZHA +10570; C; 10597; # VITHKUQI CAPITAL LETTER A +10571; C; 10598; # VITHKUQI CAPITAL LETTER BBE +10572; C; 10599; # VITHKUQI CAPITAL LETTER BE +10573; C; 1059A; # VITHKUQI CAPITAL LETTER CE +10574; C; 1059B; # VITHKUQI CAPITAL LETTER CHE +10575; C; 1059C; # VITHKUQI CAPITAL LETTER DE +10576; C; 1059D; # VITHKUQI CAPITAL LETTER DHE +10577; C; 1059E; # VITHKUQI CAPITAL LETTER EI +10578; C; 1059F; # VITHKUQI CAPITAL LETTER E +10579; C; 105A0; # VITHKUQI CAPITAL LETTER FE +1057A; C; 105A1; # VITHKUQI CAPITAL LETTER GA +1057C; C; 105A3; # VITHKUQI CAPITAL LETTER HA +1057D; C; 105A4; # VITHKUQI CAPITAL LETTER HHA +1057E; C; 105A5; # VITHKUQI CAPITAL LETTER I +1057F; C; 105A6; # VITHKUQI CAPITAL LETTER IJE +10580; C; 105A7; # VITHKUQI CAPITAL LETTER JE +10581; C; 105A8; # VITHKUQI CAPITAL LETTER KA +10582; C; 105A9; # VITHKUQI CAPITAL LETTER LA +10583; C; 105AA; # VITHKUQI CAPITAL LETTER LLA +10584; C; 105AB; # VITHKUQI CAPITAL LETTER ME +10585; C; 105AC; # VITHKUQI CAPITAL LETTER NE +10586; C; 105AD; # VITHKUQI CAPITAL LETTER NJE +10587; C; 105AE; # VITHKUQI CAPITAL LETTER O +10588; C; 105AF; # VITHKUQI CAPITAL LETTER PE +10589; C; 105B0; # VITHKUQI CAPITAL LETTER QA +1058A; C; 105B1; # VITHKUQI CAPITAL LETTER RE +1058C; C; 105B3; # VITHKUQI CAPITAL LETTER SE +1058D; C; 105B4; # VITHKUQI CAPITAL LETTER SHE +1058E; C; 105B5; # VITHKUQI CAPITAL LETTER TE +1058F; C; 105B6; # VITHKUQI CAPITAL LETTER THE +10590; C; 105B7; # VITHKUQI CAPITAL LETTER U +10591; C; 105B8; # VITHKUQI CAPITAL LETTER VE +10592; C; 105B9; # VITHKUQI CAPITAL LETTER XE +10594; C; 105BB; # VITHKUQI CAPITAL LETTER Y +10595; C; 105BC; # VITHKUQI CAPITAL LETTER ZE +10C80; C; 10CC0; # OLD HUNGARIAN CAPITAL LETTER A +10C81; C; 10CC1; # OLD HUNGARIAN CAPITAL LETTER AA +10C82; C; 10CC2; # OLD HUNGARIAN CAPITAL LETTER EB +10C83; C; 10CC3; # OLD HUNGARIAN CAPITAL LETTER AMB +10C84; C; 10CC4; # OLD HUNGARIAN CAPITAL LETTER EC +10C85; C; 10CC5; # OLD HUNGARIAN CAPITAL LETTER ENC +10C86; C; 10CC6; # OLD HUNGARIAN CAPITAL LETTER ECS +10C87; C; 10CC7; # OLD HUNGARIAN CAPITAL LETTER ED +10C88; C; 10CC8; # OLD HUNGARIAN CAPITAL LETTER AND +10C89; C; 10CC9; # OLD HUNGARIAN CAPITAL LETTER E +10C8A; C; 10CCA; # OLD HUNGARIAN CAPITAL LETTER CLOSE E +10C8B; C; 10CCB; # OLD HUNGARIAN CAPITAL LETTER EE +10C8C; C; 10CCC; # OLD HUNGARIAN CAPITAL LETTER EF +10C8D; C; 10CCD; # OLD HUNGARIAN CAPITAL LETTER EG +10C8E; C; 10CCE; # OLD HUNGARIAN CAPITAL LETTER EGY +10C8F; C; 10CCF; # OLD HUNGARIAN CAPITAL LETTER EH +10C90; C; 10CD0; # OLD HUNGARIAN CAPITAL LETTER I +10C91; C; 10CD1; # OLD HUNGARIAN CAPITAL LETTER II +10C92; C; 10CD2; # OLD HUNGARIAN CAPITAL LETTER EJ +10C93; C; 10CD3; # OLD HUNGARIAN CAPITAL LETTER EK +10C94; C; 10CD4; # OLD HUNGARIAN CAPITAL LETTER AK +10C95; C; 10CD5; # OLD HUNGARIAN CAPITAL LETTER UNK +10C96; C; 10CD6; # OLD HUNGARIAN CAPITAL LETTER EL +10C97; C; 10CD7; # OLD HUNGARIAN CAPITAL LETTER ELY +10C98; C; 10CD8; # OLD HUNGARIAN CAPITAL LETTER EM +10C99; C; 10CD9; # OLD HUNGARIAN CAPITAL LETTER EN +10C9A; C; 10CDA; # OLD HUNGARIAN CAPITAL LETTER ENY +10C9B; C; 10CDB; # OLD HUNGARIAN CAPITAL LETTER O +10C9C; C; 10CDC; # OLD HUNGARIAN CAPITAL LETTER OO +10C9D; C; 10CDD; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE +10C9E; C; 10CDE; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE +10C9F; C; 10CDF; # OLD HUNGARIAN CAPITAL LETTER OEE +10CA0; C; 10CE0; # OLD HUNGARIAN CAPITAL LETTER EP +10CA1; C; 10CE1; # OLD HUNGARIAN CAPITAL LETTER EMP +10CA2; C; 10CE2; # OLD HUNGARIAN CAPITAL LETTER ER +10CA3; C; 10CE3; # OLD HUNGARIAN CAPITAL LETTER SHORT ER +10CA4; C; 10CE4; # OLD HUNGARIAN CAPITAL LETTER ES +10CA5; C; 10CE5; # OLD HUNGARIAN CAPITAL LETTER ESZ +10CA6; C; 10CE6; # OLD HUNGARIAN CAPITAL LETTER ET +10CA7; C; 10CE7; # OLD HUNGARIAN CAPITAL LETTER ENT +10CA8; C; 10CE8; # OLD HUNGARIAN CAPITAL LETTER ETY +10CA9; C; 10CE9; # OLD HUNGARIAN CAPITAL LETTER ECH +10CAA; C; 10CEA; # OLD HUNGARIAN CAPITAL LETTER U +10CAB; C; 10CEB; # OLD HUNGARIAN CAPITAL LETTER UU +10CAC; C; 10CEC; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE +10CAD; C; 10CED; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE +10CAE; C; 10CEE; # OLD HUNGARIAN CAPITAL LETTER EV +10CAF; C; 10CEF; # OLD HUNGARIAN CAPITAL LETTER EZ +10CB0; C; 10CF0; # OLD HUNGARIAN CAPITAL LETTER EZS +10CB1; C; 10CF1; # OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN +10CB2; C; 10CF2; # OLD HUNGARIAN CAPITAL LETTER US +10D50; C; 10D70; # GARAY CAPITAL LETTER A +10D51; C; 10D71; # GARAY CAPITAL LETTER CA +10D52; C; 10D72; # GARAY CAPITAL LETTER MA +10D53; C; 10D73; # GARAY CAPITAL LETTER KA +10D54; C; 10D74; # GARAY CAPITAL LETTER BA +10D55; C; 10D75; # GARAY CAPITAL LETTER JA +10D56; C; 10D76; # GARAY CAPITAL LETTER SA +10D57; C; 10D77; # GARAY CAPITAL LETTER WA +10D58; C; 10D78; # GARAY CAPITAL LETTER LA +10D59; C; 10D79; # GARAY CAPITAL LETTER GA +10D5A; C; 10D7A; # GARAY CAPITAL LETTER DA +10D5B; C; 10D7B; # GARAY CAPITAL LETTER XA +10D5C; C; 10D7C; # GARAY CAPITAL LETTER YA +10D5D; C; 10D7D; # GARAY CAPITAL LETTER TA +10D5E; C; 10D7E; # GARAY CAPITAL LETTER RA +10D5F; C; 10D7F; # GARAY CAPITAL LETTER NYA +10D60; C; 10D80; # GARAY CAPITAL LETTER FA +10D61; C; 10D81; # GARAY CAPITAL LETTER NA +10D62; C; 10D82; # GARAY CAPITAL LETTER PA +10D63; C; 10D83; # GARAY CAPITAL LETTER HA +10D64; C; 10D84; # GARAY CAPITAL LETTER OLD KA +10D65; C; 10D85; # GARAY CAPITAL LETTER OLD NA +118A0; C; 118C0; # WARANG CITI CAPITAL LETTER NGAA +118A1; C; 118C1; # WARANG CITI CAPITAL LETTER A +118A2; C; 118C2; # WARANG CITI CAPITAL LETTER WI +118A3; C; 118C3; # WARANG CITI CAPITAL LETTER YU +118A4; C; 118C4; # WARANG CITI CAPITAL LETTER YA +118A5; C; 118C5; # WARANG CITI CAPITAL LETTER YO +118A6; C; 118C6; # WARANG CITI CAPITAL LETTER II +118A7; C; 118C7; # WARANG CITI CAPITAL LETTER UU +118A8; C; 118C8; # WARANG CITI CAPITAL LETTER E +118A9; C; 118C9; # WARANG CITI CAPITAL LETTER O +118AA; C; 118CA; # WARANG CITI CAPITAL LETTER ANG +118AB; C; 118CB; # WARANG CITI CAPITAL LETTER GA +118AC; C; 118CC; # WARANG CITI CAPITAL LETTER KO +118AD; C; 118CD; # WARANG CITI CAPITAL LETTER ENY +118AE; C; 118CE; # WARANG CITI CAPITAL LETTER YUJ +118AF; C; 118CF; # WARANG CITI CAPITAL LETTER UC +118B0; C; 118D0; # WARANG CITI CAPITAL LETTER ENN +118B1; C; 118D1; # WARANG CITI CAPITAL LETTER ODD +118B2; C; 118D2; # WARANG CITI CAPITAL LETTER TTE +118B3; C; 118D3; # WARANG CITI CAPITAL LETTER NUNG +118B4; C; 118D4; # WARANG CITI CAPITAL LETTER DA +118B5; C; 118D5; # WARANG CITI CAPITAL LETTER AT +118B6; C; 118D6; # WARANG CITI CAPITAL LETTER AM +118B7; C; 118D7; # WARANG CITI CAPITAL LETTER BU +118B8; C; 118D8; # WARANG CITI CAPITAL LETTER PU +118B9; C; 118D9; # WARANG CITI CAPITAL LETTER HIYO +118BA; C; 118DA; # WARANG CITI CAPITAL LETTER HOLO +118BB; C; 118DB; # WARANG CITI CAPITAL LETTER HORR +118BC; C; 118DC; # WARANG CITI CAPITAL LETTER HAR +118BD; C; 118DD; # WARANG CITI CAPITAL LETTER SSUU +118BE; C; 118DE; # WARANG CITI CAPITAL LETTER SII +118BF; C; 118DF; # WARANG CITI CAPITAL LETTER VIYO +16E40; C; 16E60; # MEDEFAIDRIN CAPITAL LETTER M +16E41; C; 16E61; # MEDEFAIDRIN CAPITAL LETTER S +16E42; C; 16E62; # MEDEFAIDRIN CAPITAL LETTER V +16E43; C; 16E63; # MEDEFAIDRIN CAPITAL LETTER W +16E44; C; 16E64; # MEDEFAIDRIN CAPITAL LETTER ATIU +16E45; C; 16E65; # MEDEFAIDRIN CAPITAL LETTER Z +16E46; C; 16E66; # MEDEFAIDRIN CAPITAL LETTER KP +16E47; C; 16E67; # MEDEFAIDRIN CAPITAL LETTER P +16E48; C; 16E68; # MEDEFAIDRIN CAPITAL LETTER T +16E49; C; 16E69; # MEDEFAIDRIN CAPITAL LETTER G +16E4A; C; 16E6A; # MEDEFAIDRIN CAPITAL LETTER F +16E4B; C; 16E6B; # MEDEFAIDRIN CAPITAL LETTER I +16E4C; C; 16E6C; # MEDEFAIDRIN CAPITAL LETTER K +16E4D; C; 16E6D; # MEDEFAIDRIN CAPITAL LETTER A +16E4E; C; 16E6E; # MEDEFAIDRIN CAPITAL LETTER J +16E4F; C; 16E6F; # MEDEFAIDRIN CAPITAL LETTER E +16E50; C; 16E70; # MEDEFAIDRIN CAPITAL LETTER B +16E51; C; 16E71; # MEDEFAIDRIN CAPITAL LETTER C +16E52; C; 16E72; # MEDEFAIDRIN CAPITAL LETTER U +16E53; C; 16E73; # MEDEFAIDRIN CAPITAL LETTER YU +16E54; C; 16E74; # MEDEFAIDRIN CAPITAL LETTER L +16E55; C; 16E75; # MEDEFAIDRIN CAPITAL LETTER Q +16E56; C; 16E76; # MEDEFAIDRIN CAPITAL LETTER HP +16E57; C; 16E77; # MEDEFAIDRIN CAPITAL LETTER NY +16E58; C; 16E78; # MEDEFAIDRIN CAPITAL LETTER X +16E59; C; 16E79; # MEDEFAIDRIN CAPITAL LETTER D +16E5A; C; 16E7A; # MEDEFAIDRIN CAPITAL LETTER OE +16E5B; C; 16E7B; # MEDEFAIDRIN CAPITAL LETTER N +16E5C; C; 16E7C; # MEDEFAIDRIN CAPITAL LETTER R +16E5D; C; 16E7D; # MEDEFAIDRIN CAPITAL LETTER O +16E5E; C; 16E7E; # MEDEFAIDRIN CAPITAL LETTER AI +16E5F; C; 16E7F; # MEDEFAIDRIN CAPITAL LETTER Y +1E900; C; 1E922; # ADLAM CAPITAL LETTER ALIF +1E901; C; 1E923; # ADLAM CAPITAL LETTER DAALI +1E902; C; 1E924; # ADLAM CAPITAL LETTER LAAM +1E903; C; 1E925; # ADLAM CAPITAL LETTER MIIM +1E904; C; 1E926; # ADLAM CAPITAL LETTER BA +1E905; C; 1E927; # ADLAM CAPITAL LETTER SINNYIIYHE +1E906; C; 1E928; # ADLAM CAPITAL LETTER PE +1E907; C; 1E929; # ADLAM CAPITAL LETTER BHE +1E908; C; 1E92A; # ADLAM CAPITAL LETTER RA +1E909; C; 1E92B; # ADLAM CAPITAL LETTER E +1E90A; C; 1E92C; # ADLAM CAPITAL LETTER FA +1E90B; C; 1E92D; # ADLAM CAPITAL LETTER I +1E90C; C; 1E92E; # ADLAM CAPITAL LETTER O +1E90D; C; 1E92F; # ADLAM CAPITAL LETTER DHA +1E90E; C; 1E930; # ADLAM CAPITAL LETTER YHE +1E90F; C; 1E931; # ADLAM CAPITAL LETTER WAW +1E910; C; 1E932; # ADLAM CAPITAL LETTER NUN +1E911; C; 1E933; # ADLAM CAPITAL LETTER KAF +1E912; C; 1E934; # ADLAM CAPITAL LETTER YA +1E913; C; 1E935; # ADLAM CAPITAL LETTER U +1E914; C; 1E936; # ADLAM CAPITAL LETTER JIIM +1E915; C; 1E937; # ADLAM CAPITAL LETTER CHI +1E916; C; 1E938; # ADLAM CAPITAL LETTER HA +1E917; C; 1E939; # ADLAM CAPITAL LETTER QAAF +1E918; C; 1E93A; # ADLAM CAPITAL LETTER GA +1E919; C; 1E93B; # ADLAM CAPITAL LETTER NYA +1E91A; C; 1E93C; # ADLAM CAPITAL LETTER TU +1E91B; C; 1E93D; # ADLAM CAPITAL LETTER NHA +1E91C; C; 1E93E; # ADLAM CAPITAL LETTER VA +1E91D; C; 1E93F; # ADLAM CAPITAL LETTER KHA +1E91E; C; 1E940; # ADLAM CAPITAL LETTER GBE +1E91F; C; 1E941; # ADLAM CAPITAL LETTER ZAL +1E920; C; 1E942; # ADLAM CAPITAL LETTER KPO +1E921; C; 1E943; # ADLAM CAPITAL LETTER SHA +# +# EOF \ No newline at end of file diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 3831fc64f88..96e9147e218 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -3757,9 +3757,10 @@ general form: be loaded on top of those in the ``. - On Windows, the above path delimiter `:` should be replaced with `;` -(The names "static" and "dynamic" are used for historical reasons. -The only significance is that the "static" archive is loaded first and -the "dynamic" archive is loaded second). +The names "static" and "dynamic" are used for historical reasons. The dynamic +archive, while still useful, supports fewer optimizations than +available for the static CDS archive. If the full set of CDS/AOT +optimizations are desired, consider using the AOT cache described below. The JVM can use up to two archives. To use only a single ``, you can omit the `` portion: diff --git a/src/java.base/share/native/libjimage/imageFile.cpp b/src/java.base/share/native/libjimage/imageFile.cpp index d97a8f95a60..31ac4ebc8d4 100644 --- a/src/java.base/share/native/libjimage/imageFile.cpp +++ b/src/java.base/share/native/libjimage/imageFile.cpp @@ -404,7 +404,7 @@ u4 ImageFileReader::find_location_index(const char* path, u8 *size) const { // Make sure result is not a false positive. if (verify_location(location, path)) { *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); - return offset; + return offset; } } return 0; // not found @@ -435,7 +435,7 @@ bool ImageFileReader::verify_location(ImageLocation& location, const char* path) } // Get base name string. const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); - // Compare with basne name. + // Compare with base name. if (!(next = ImageStrings::starts_with(next, base))) return false; // Get extension string. const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); diff --git a/src/java.base/share/native/libjimage/imageFile.hpp b/src/java.base/share/native/libjimage/imageFile.hpp index 5fb4ea3baaa..ea0afa98380 100644 --- a/src/java.base/share/native/libjimage/imageFile.hpp +++ b/src/java.base/share/native/libjimage/imageFile.hpp @@ -237,13 +237,27 @@ class ImageLocation { ATTRIBUTE_MODULE, // String table offset of module name ATTRIBUTE_PARENT, // String table offset of resource path parent ATTRIBUTE_BASE, // String table offset of resource path base - ATTRIBUTE_EXTENSION, // String table offset of resource path extension + ATTRIBUTE_EXTENSION, // String table offset of resource path extension ATTRIBUTE_OFFSET, // Container byte offset of resource - ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource - ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource + ATTRIBUTE_COMPRESSED, // In-image byte size of the compressed resource + ATTRIBUTE_UNCOMPRESSED, // In-memory byte size of the uncompressed resource + ATTRIBUTE_PREVIEW_FLAGS, // Flags relating to preview mode resources. ATTRIBUTE_COUNT // Number of attribute kinds }; + // Flag masks for the ATTRIBUTE_PREVIEW_FLAGS attribute. Defined so + // that zero is the overwhelmingly common case for normal resources. + enum { + // Set on a "normal" (non-preview) location if a preview version of + // it exists in the same module. + FLAGS_HAS_PREVIEW_VERSION = 0x1, + // Set on all preview locations in "/modules/xxx/META-INF/preview/..." + FLAGS_IS_PREVIEW_VERSION = 0x2, + // Set on a preview location if no normal (non-preview) version of + // it exists in the same module. + FLAGS_IS_PREVIEW_ONLY = 0x4 + }; + private: // Values of inflated attributes. u8 _attributes[ATTRIBUTE_COUNT]; @@ -300,6 +314,11 @@ class ImageLocation { inline const char* get_attribute(u4 kind, const ImageStrings& strings) const { return strings.get((u4)get_attribute(kind)); } + + // Retrieve flags from the ATTRIBUTE_PREVIEW_FLAGS attribute. + inline u4 get_preview_flags() const { + return (u4) get_attribute(ATTRIBUTE_PREVIEW_FLAGS); + } }; // Image file header, starting at offset 0. @@ -394,6 +413,7 @@ class ImageFileReaderTable { // leads the ImageFileReader to be actually closed and discarded. class ImageFileReader { friend class ImageFileReaderTable; +friend class PackageFlags; private: // Manage a number of image files such that an image can be shared across // multiple uses (ex. loader.) @@ -433,7 +453,7 @@ friend class ImageFileReaderTable; // Image file major version number. MAJOR_VERSION = 1, // Image file minor version number. - MINOR_VERSION = 0 + MINOR_VERSION = 1 }; // Locate an image if file already open. diff --git a/src/java.base/share/native/libjimage/jimage.cpp b/src/java.base/share/native/libjimage/jimage.cpp index 10e85eb2520..b20e9b027b4 100644 --- a/src/java.base/share/native/libjimage/jimage.cpp +++ b/src/java.base/share/native/libjimage/jimage.cpp @@ -91,45 +91,97 @@ JIMAGE_Close(JImageFile* image) { * name, a version string and the name of a class/resource, return location * information describing the resource and its size. If no resource is found, the * function returns JIMAGE_NOT_FOUND and the value of size is undefined. - * The version number should be "9.0" and is not used in locating the resource. * The resulting location does/should not have to be released. * All strings are utf-8, zero byte terminated. * * Ex. * jlong size; * JImageLocationRef location = (*JImageFindResource)(image, - * "java.base", "9.0", "java/lang/String.class", &size); + * "java.base", "java/lang/String.class", is_preview_mode, &size); */ extern "C" JNIEXPORT JImageLocationRef JIMAGE_FindResource(JImageFile* image, - const char* module_name, const char* version, const char* name, + const char* module_name, const char* name, bool is_preview_mode, jlong* size) { + static const char str_modules[] = "modules"; + static const char str_packages[] = "packages"; + static const char preview_infix[] = "/META-INF/preview"; + + size_t module_name_len = strlen(module_name); + size_t name_len = strlen(name); + size_t preview_infix_len = strlen(preview_infix); + + // TBD: assert(module_name_len > 0 && "module name must be non-empty"); + assert(name_len > 0 && "name must non-empty"); + + // Do not attempt to lookup anything of the form /modules/... or /packages/... + if (strncmp(module_name, str_modules, sizeof(str_modules)) == 0 + || strncmp(module_name, str_packages, sizeof(str_packages)) == 0) { + return 0L; + } + // If the preview mode version of the path string is too long for the buffer, + // return not found (even when not in preview mode). + if (1 + module_name_len + preview_infix_len + 1 + name_len + 1 > IMAGE_MAX_PATH) { + return 0L; + } + // Concatenate to get full path - char fullpath[IMAGE_MAX_PATH]; - size_t moduleNameLen = strlen(module_name); - size_t nameLen = strlen(name); - size_t index; + char name_buffer[IMAGE_MAX_PATH]; + char* path; + { // Write the buffer with room to prepend the preview mode infix + // at the start (saves copying the trailing name part twice). + size_t index = preview_infix_len; + name_buffer[index++] = '/'; + memcpy(&name_buffer[index], module_name, module_name_len); + index += module_name_len; + name_buffer[index++] = '/'; + memcpy(&name_buffer[index], name, name_len); + index += name_len; + name_buffer[index++] = '\0'; + // Path begins at the leading '/' (not the start of the buffer). + path = &name_buffer[preview_infix_len]; + } - // TBD: assert(moduleNameLen > 0 && "module name must be non-empty"); - assert(nameLen > 0 && "name must non-empty"); + // find_location_index() returns the data "offset", not an index. + const ImageFileReader* image_file = (ImageFileReader*) image; + u4 locOffset = image_file->find_location_index(path, (u8*) size); + if (locOffset == 0) { + return 0L; + } + ImageLocation loc; + loc.set_data(image_file->get_location_offset_data(locOffset)); - // If the concatenated string is too long for the buffer, return not found - if (1 + moduleNameLen + 1 + nameLen + 1 > IMAGE_MAX_PATH) { + u4 flags = loc.get_preview_flags(); + // No preview flags means "a normal resource, without a preview version". + // This is the overwhelmingly common case, with or without preview mode. + if (flags == 0) { + return locOffset; + } + // Regardless of preview mode, don't return resources requested directly + // via their preview path. + if ((flags & ImageLocation::FLAGS_IS_PREVIEW_VERSION) != 0) { return 0L; } + // Even if there is a preview version, we might not want to return it. + if (!is_preview_mode || (flags & ImageLocation::FLAGS_HAS_PREVIEW_VERSION) == 0) { + return locOffset; + } + + { // Rewrite the front of the name buffer to make it a preview path. + size_t index = 0; + name_buffer[index++] = '/'; + memcpy(&name_buffer[index], module_name, module_name_len); + index += module_name_len; + memcpy(&name_buffer[index], preview_infix, preview_infix_len); + index += preview_infix_len; + // Check we copied up to the expected '/' separator. + assert(name_buffer[index] == '/' && "bad string concatenation"); + // The preview path now begins at the start of the buffer. + path = &name_buffer[0]; + } - index = 0; - fullpath[index++] = '/'; - memcpy(&fullpath[index], module_name, moduleNameLen); - index += moduleNameLen; - fullpath[index++] = '/'; - memcpy(&fullpath[index], name, nameLen); - index += nameLen; - fullpath[index++] = '\0'; - - JImageLocationRef loc = - (JImageLocationRef) ((ImageFileReader*) image)->find_location_index(fullpath, (u8*) size); - return loc; + // Lookup the preview version (which *should* exist). + return image_file->find_location_index(path, (u8*) size); } /* diff --git a/src/java.base/share/native/libjimage/jimage.hpp b/src/java.base/share/native/libjimage/jimage.hpp index a514e737b49..960d8e8ee21 100644 --- a/src/java.base/share/native/libjimage/jimage.hpp +++ b/src/java.base/share/native/libjimage/jimage.hpp @@ -98,21 +98,20 @@ typedef void (*JImageClose_t)(JImageFile* jimage); * name, a version string and the name of a class/resource, return location * information describing the resource and its size. If no resource is found, the * function returns JIMAGE_NOT_FOUND and the value of size is undefined. - * The version number should be "9.0" and is not used in locating the resource. * The resulting location does/should not have to be released. * All strings are utf-8, zero byte terminated. * * Ex. * jlong size; * JImageLocationRef location = (*JImageFindResource)(image, - * "java.base", "9.0", "java/lang/String.class", &size); + * "java.base", "java/lang/String.class", is_preview_mode, &size); */ extern "C" JNIEXPORT JImageLocationRef JIMAGE_FindResource(JImageFile* jimage, - const char* module_name, const char* version, const char* name, + const char* module_name, const char* name, bool is_preview_mode, jlong* size); typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, - const char* module_name, const char* version, const char* name, + const char* module_name, const char* name, bool is_preview_mode, jlong* size); diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index 7266ac8f93c..cc6e96582d0 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -2145,8 +2145,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac break; if ( (GET_ITEM_TYPE(top_type) == ITEM_NewObject || (GET_ITEM_TYPE(top_type) == ITEM_InitObject)) - && ((opcode == JVM_OPC_astore) || (opcode == JVM_OPC_aload) - || (opcode == JVM_OPC_ifnull) || (opcode == JVM_OPC_ifnonnull))) + && ((opcode == JVM_OPC_astore) || (opcode == JVM_OPC_aload))) break; /* The 2nd edition VM of the specification allows field * initializations before the superclass initializer, diff --git a/src/java.base/share/native/libzip/zip_util.c b/src/java.base/share/native/libzip/zip_util.c index 86223f22a43..3ad148b0be5 100644 --- a/src/java.base/share/native/libzip/zip_util.c +++ b/src/java.base/share/native/libzip/zip_util.c @@ -579,7 +579,9 @@ readCEN(jzfile *zip, jint knownTotal) jlong offset; #endif unsigned char endbuf[ENDHDR]; +#ifdef USE_MMAP jint endhdrlen = ENDHDR; +#endif jzcell *entries; jint *table; @@ -604,7 +606,9 @@ readCEN(jzfile *zip, jint knownTotal) cenoff = ZIP64_ENDOFF(end64buf); total = (jint)ZIP64_ENDTOT(end64buf); endpos = end64pos; +#ifdef USE_MMAP endhdrlen = ZIP64_ENDHDR; +#endif } } diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c index 1d0c8d21d37..f7531ad5abe 100644 --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -732,7 +732,7 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, (fds[2] == -1 && pipe(err) < 0) || (pipe(childenv) < 0) || (pipe(fail) < 0)) { - throwInternalIOException(env, errno, "Bad file descriptor", c->mode); + throwInternalIOException(env, errno, "Bad file descriptor", mode); goto Catch; } c->fds[0] = fds[0]; diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 1d5435d5229..000eb4b953e 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -239,6 +239,7 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s if (language != NULL && mapLookup(language_names, language, std_language) == 0) { *std_language = malloc(strlen(language)+1); if (*std_language == NULL) { + free(temp); free(encoding_variant); JNU_ThrowOutOfMemoryError(env, NULL); return 0; @@ -252,6 +253,7 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s if (mapLookup(country_names, country, std_country) == 0) { *std_country = malloc(strlen(country)+1); if (*std_country == NULL) { + free(temp); free(encoding_variant); JNU_ThrowOutOfMemoryError(env, NULL); return 0; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java b/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java index 6ada2337cbb..a5adfb73ebc 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -356,7 +356,9 @@ private static String readLinkImpl(WindowsPath path, long handle) if (target.isEmpty()) { throw new IOException("Symbolic link target is invalid"); } - return target; + + // return normalized path string + return WindowsPathParser.parse(target).path(); } } diff --git a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c index df5ad1e8911..10513b28cb6 100644 --- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c +++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c @@ -965,29 +965,34 @@ void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret) { DWORD pattern = 0; int style = numberStyle; - int got = 0; + // int got = 0; if (positive) { if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { - got = getLocaleInfoWrapper(langtag, + // got = + getLocaleInfoWrapper(langtag, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER, (LPWSTR)&pattern, sizeof(pattern)); } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { - got = getLocaleInfoWrapper(langtag, + // got = + getLocaleInfoWrapper(langtag, LOCALE_IPOSITIVEPERCENT | LOCALE_RETURN_NUMBER, (LPWSTR)&pattern, sizeof(pattern)); } } else { if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { - got = getLocaleInfoWrapper(langtag, + // got = + getLocaleInfoWrapper(langtag, LOCALE_INEGCURR | LOCALE_RETURN_NUMBER, (LPWSTR)&pattern, sizeof(pattern)); } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { - got = getLocaleInfoWrapper(langtag, + // got = + getLocaleInfoWrapper(langtag, LOCALE_INEGATIVEPERCENT | LOCALE_RETURN_NUMBER, (LPWSTR)&pattern, sizeof(pattern)); } else { - got = getLocaleInfoWrapper(langtag, + // got = + getLocaleInfoWrapper(langtag, LOCALE_INEGNUMBER | LOCALE_RETURN_NUMBER, (LPWSTR)&pattern, sizeof(pattern)); } diff --git a/src/java.base/windows/native/libjava/TimeZone_md.c b/src/java.base/windows/native/libjava/TimeZone_md.c index fc9e29f01ac..0a73bc26028 100644 --- a/src/java.base/windows/native/libjava/TimeZone_md.c +++ b/src/java.base/windows/native/libjava/TimeZone_md.c @@ -232,7 +232,7 @@ static int getWinTimeZone(char *winZoneName, size_t winZoneNameBufSize) WCHAR stdNameInReg[MAX_ZONE_CHAR]; TziValue tempTzi; WCHAR *stdNamePtr = tzi.StandardName; - int onlyMapID; + // int onlyMapID; timeType = GetTimeZoneInformation(&tzi); if (timeType == TIME_ZONE_ID_INVALID) { @@ -304,7 +304,7 @@ static int getWinTimeZone(char *winZoneName, size_t winZoneNameBufSize) * Compare to the "Std" value of each subkey and find the entry that * matches the current control panel setting. */ - onlyMapID = 0; + // onlyMapID = 0; for (i = 0; i < nSubKeys; ++i) { DWORD size = sizeof(subKeyName); ret = RegEnumKeyEx(hKey, i, subKeyName, &size, NULL, NULL, NULL, NULL); @@ -325,7 +325,7 @@ static int getWinTimeZone(char *winZoneName, size_t winZoneNameBufSize) * entry in the Time Zones registry. */ RegCloseKey(hSubKey); - onlyMapID = 1; + // onlyMapID = 1; ret = RegOpenKeyExW(hKey, stdNamePtr, 0, KEY_READ, (PHKEY)&hSubKey); if (ret != ERROR_SUCCESS) { goto err; diff --git a/src/java.base/windows/native/libnet/NTLMAuthSequence.c b/src/java.base/windows/native/libnet/NTLMAuthSequence.c index 3864ceedd51..62627504ecd 100644 --- a/src/java.base/windows/native/libnet/NTLMAuthSequence.c +++ b/src/java.base/windows/native/libnet/NTLMAuthSequence.c @@ -47,7 +47,7 @@ static jfieldID ntlm_ctxHandleID; static jfieldID ntlm_crdHandleID; static jfieldID status_seqCompleteID; -static HINSTANCE lib = NULL; +// static HINSTANCE lib = NULL; JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst (JNIEnv *env, jclass authseq_clazz, jclass status_clazz) diff --git a/src/java.base/windows/native/libnio/ch/Net.c b/src/java.base/windows/native/libnio/ch/Net.c index 105cb9cf743..814f502c48a 100644 --- a/src/java.base/windows/native/libnio/ch/Net.c +++ b/src/java.base/windows/native/libnio/ch/Net.c @@ -214,6 +214,13 @@ Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean prefe JNIEXPORT void JNICALL Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog) { + /* + * Use SOMAXCONN_HINT when backlog larger than 200. It will adjust the value + * to be within the range (200, 65535). + */ + if (backlog > 200) { + backlog = SOMAXCONN_HINT(backlog); + } if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "listen"); } diff --git a/src/java.desktop/aix/data/fontconfig/fontconfig.properties b/src/java.desktop/aix/data/fontconfig/fontconfig.properties index dc3bfcac2fb..790591d3fe7 100644 --- a/src/java.desktop/aix/data/fontconfig/fontconfig.properties +++ b/src/java.desktop/aix/data/fontconfig/fontconfig.properties @@ -360,8 +360,6 @@ filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987- filename.-monotype-wt_serif_k-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__k__b.ttf filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf filename.-monotype-wt_serif_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__s__b.ttf -filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf -filename.-monotype-wt_serif_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__s__b.ttf filename.-monotype-wt_serif_tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__tt_b.ttf filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIConstants.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIConstants.java index 9da55002b72..d15ba24fb91 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIConstants.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIConstants.java @@ -39,7 +39,7 @@ public final class JRSUIConstants { private static native long getPtrForConstant(final int constant); - static class Key { + static final class Key { @Native protected static final int _value = 20; public static final Key VALUE = new Key(_value); @@ -84,12 +84,13 @@ private String getConstantName(Key hit) { return getClass().getSimpleName(); } + @Override public String toString() { return getConstantName(this) + (ptr == 0 ? "(unlinked)" : ""); } } - static class DoubleValue { + static final class DoubleValue { @Native protected static final byte TYPE_CODE = 1; final double doubleValue; @@ -106,21 +107,24 @@ public void putValueInBuffer(final ByteBuffer buffer) { buffer.putDouble(doubleValue); } + @Override public boolean equals(final Object obj) { return (obj instanceof DoubleValue) && (((DoubleValue)obj).doubleValue == doubleValue); } + @Override public int hashCode() { return Double.hashCode(doubleValue); } + @Override public String toString() { return Double.toString(doubleValue); } } - static class PropertyEncoding { + static final class PropertyEncoding { final long mask; final byte shift; @@ -150,12 +154,13 @@ public long apply(final long encodedState) { return (encodedState & ~encoding.mask) | value; } + @Override public String toString() { return getClass().getSimpleName(); } } - public static class Size extends Property { + public static final class Size extends Property { @Native private static final byte SHIFT = 0; @Native private static final byte SIZE = 3; @Native private static final long MASK = (long)0x7 << SHIFT; @@ -175,7 +180,7 @@ public static class Size extends Property { public static final Size LARGE = new Size(_large); } - public static class State extends Property { + public static final class State extends Property { @Native private static final byte SHIFT = Size.SHIFT + Size.SIZE; @Native private static final byte SIZE = 4; @Native private static final long MASK = (long)0xF << SHIFT; @@ -209,7 +214,7 @@ public static class State extends Property { public static final State DRAG = new State(_drag); } - public static class Direction extends Property { + public static final class Direction extends Property { @Native private static final byte SHIFT = State.SHIFT + State.SIZE; @Native private static final byte SIZE = 4; @Native private static final long MASK = (long)0xF << SHIFT; @@ -239,7 +244,7 @@ public static class Direction extends Property { public static final Direction WEST = new Direction(_west); } - public static class Orientation extends Property { + public static final class Orientation extends Property { @Native private static final byte SHIFT = Direction.SHIFT + Direction.SIZE; @Native private static final byte SIZE = 2; @Native private static final long MASK = (long)0x3 << SHIFT; @@ -255,7 +260,7 @@ public static class Orientation extends Property { public static final Orientation VERTICAL = new Orientation(_vertical); } - public static class AlignmentVertical extends Property { + public static final class AlignmentVertical extends Property { @Native private static final byte SHIFT = Orientation.SHIFT + Orientation.SIZE; @Native private static final byte SIZE = 2; @Native private static final long MASK = (long)0x3 << SHIFT; @@ -273,7 +278,7 @@ public static class AlignmentVertical extends Property { public static final AlignmentVertical BOTTOM = new AlignmentVertical(_bottom); } - public static class AlignmentHorizontal extends Property { + public static final class AlignmentHorizontal extends Property { @Native private static final byte SHIFT = AlignmentVertical.SHIFT + AlignmentVertical.SIZE; @Native private static final byte SIZE = 2; @Native private static final long MASK = (long)0x3 << SHIFT; @@ -291,7 +296,7 @@ public static class AlignmentHorizontal extends Property { public static final AlignmentHorizontal RIGHT = new AlignmentHorizontal(_right); } - public static class SegmentPosition extends Property { + public static final class SegmentPosition extends Property { @Native private static final byte SHIFT = AlignmentHorizontal.SHIFT + AlignmentHorizontal.SIZE; @Native private static final byte SIZE = 3; @Native private static final long MASK = (long)0x7 << SHIFT; @@ -311,7 +316,7 @@ public static class SegmentPosition extends Property { public static final SegmentPosition ONLY = new SegmentPosition(_only); } - public static class ScrollBarPart extends Property { + public static final class ScrollBarPart extends Property { @Native private static final byte SHIFT = SegmentPosition.SHIFT + SegmentPosition.SIZE; @Native private static final byte SIZE = 4; @Native private static final long MASK = (long)0xF << SHIFT; @@ -339,7 +344,7 @@ public static class ScrollBarPart extends Property { public static final ScrollBarPart TRACK_MAX = new ScrollBarPart(_trackMax); } - public static class Variant extends Property { + public static final class Variant extends Property { @Native private static final byte SHIFT = ScrollBarPart.SHIFT + ScrollBarPart.SIZE; @Native private static final byte SIZE = 4; @Native private static final long MASK = (long)0xF << SHIFT; @@ -370,7 +375,7 @@ public static class Variant extends Property { public static final Variant GRADIENT_SIDE_BAR_FOCUSED_SELECTION = new Variant(_gradientSideBarFocusedSelection); } - public static class WindowType extends Property { + public static final class WindowType extends Property { @Native private static final byte SHIFT = Variant.SHIFT + Variant.SIZE; @Native private static final byte SIZE = 2; @Native private static final long MASK = (long)0x3 << SHIFT; @@ -388,7 +393,7 @@ public static class WindowType extends Property { public static final WindowType TITLELESS_UTILITY = new WindowType(_titlelessUtility); } - public static class Focused extends Property { + public static final class Focused extends Property { @Native private static final byte SHIFT = WindowType.SHIFT + WindowType.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -404,7 +409,7 @@ public static class Focused extends Property { public static final Focused YES = new Focused(_yes); } - public static class IndicatorOnly extends Property { + public static final class IndicatorOnly extends Property { @Native private static final byte SHIFT = Focused.SHIFT + Focused.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -420,7 +425,7 @@ public static class IndicatorOnly extends Property { public static final IndicatorOnly YES = new IndicatorOnly(_yes); } - public static class NoIndicator extends Property { + public static final class NoIndicator extends Property { @Native private static final byte SHIFT = IndicatorOnly.SHIFT + IndicatorOnly.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -436,7 +441,7 @@ public static class NoIndicator extends Property { public static final NoIndicator YES = new NoIndicator(_yes); } - public static class ArrowsOnly extends Property { + public static final class ArrowsOnly extends Property { @Native private static final byte SHIFT = NoIndicator.SHIFT + NoIndicator.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -452,7 +457,7 @@ public static class ArrowsOnly extends Property { public static final ArrowsOnly YES = new ArrowsOnly(_yes); } - public static class FrameOnly extends Property { + public static final class FrameOnly extends Property { @Native private static final byte SHIFT = ArrowsOnly.SHIFT + ArrowsOnly.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -468,7 +473,7 @@ public static class FrameOnly extends Property { public static final FrameOnly YES = new FrameOnly(_yes); } - public static class SegmentTrailingSeparator extends Property { + public static final class SegmentTrailingSeparator extends Property { @Native private static final byte SHIFT = FrameOnly.SHIFT + FrameOnly.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -484,7 +489,7 @@ public static class SegmentTrailingSeparator extends Property { public static final SegmentTrailingSeparator YES = new SegmentTrailingSeparator(_yes); } - public static class SegmentLeadingSeparator extends Property { + public static final class SegmentLeadingSeparator extends Property { @Native private static final byte SHIFT = SegmentTrailingSeparator.SHIFT + SegmentTrailingSeparator.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -500,7 +505,7 @@ public static class SegmentLeadingSeparator extends Property { public static final SegmentLeadingSeparator YES = new SegmentLeadingSeparator(_yes); } - public static class NothingToScroll extends Property { + public static final class NothingToScroll extends Property { @Native private static final byte SHIFT = SegmentLeadingSeparator.SHIFT + SegmentLeadingSeparator.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -516,7 +521,7 @@ public static class NothingToScroll extends Property { public static final NothingToScroll YES = new NothingToScroll(_yes); } - public static class WindowTitleBarSeparator extends Property { + public static final class WindowTitleBarSeparator extends Property { @Native private static final byte SHIFT = NothingToScroll.SHIFT + NothingToScroll.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -532,7 +537,7 @@ public static class WindowTitleBarSeparator extends Property { public static final WindowTitleBarSeparator YES = new WindowTitleBarSeparator(_yes); } - public static class WindowClipCorners extends Property { + public static final class WindowClipCorners extends Property { @Native private static final byte SHIFT = WindowTitleBarSeparator.SHIFT + WindowTitleBarSeparator.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -548,7 +553,7 @@ public static class WindowClipCorners extends Property { public static final WindowClipCorners YES = new WindowClipCorners(_yes); } - public static class ShowArrows extends Property { + public static final class ShowArrows extends Property { @Native private static final byte SHIFT = WindowClipCorners.SHIFT + WindowClipCorners.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -564,7 +569,7 @@ public static class ShowArrows extends Property { public static final ShowArrows YES = new ShowArrows(_yes); } - public static class BooleanValue extends Property { + public static final class BooleanValue extends Property { @Native private static final byte SHIFT = ShowArrows.SHIFT + ShowArrows.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -580,7 +585,7 @@ public static class BooleanValue extends Property { public static final BooleanValue YES = new BooleanValue(_yes); } - public static class Animating extends Property { + public static final class Animating extends Property { @Native private static final byte SHIFT = BooleanValue.SHIFT + BooleanValue.SIZE; @Native private static final byte SIZE = 1; @Native private static final long MASK = (long)0x1 << SHIFT; @@ -596,7 +601,7 @@ public static class Animating extends Property { public static final Animating YES = new Animating(_yes); } - public static class Widget extends Property { + public static final class Widget extends Property { @Native private static final byte SHIFT = Animating.SHIFT + Animating.SIZE; @Native private static final byte SIZE = 7; @Native private static final long MASK = (long)0x7F << SHIFT; @@ -811,12 +816,13 @@ private String getConstantName(Hit hit) { return getClass().getSimpleName(); } + @Override public String toString() { return getConstantName(this); } } - public static class ScrollBarHit extends Hit { + public static final class ScrollBarHit extends Hit { @Native private static final int _thumb = 2; public static final ScrollBarHit THUMB = new ScrollBarHit(_thumb); diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java index cfe3b916161..f1f5ebe5ff1 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java @@ -68,7 +68,7 @@ public static void initJRSUI() { } private static final int NIO_BUFFER_SIZE = 128; - private static class ThreadLocalByteBuffer { + private static final class ThreadLocalByteBuffer { final ByteBuffer buffer; final long ptr; @@ -114,6 +114,7 @@ public JRSUIControl(final boolean flipped){ changes.putAll(other.changes); } + @Override @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (cfDictionaryPtr == 0) return; diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIFocus.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIFocus.java index 8d0a83f990d..e990273b200 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIFocus.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIFocus.java @@ -25,7 +25,7 @@ package apple.laf; -public class JRSUIFocus { +public final class JRSUIFocus { private static final int SUCCESS = 0; private static final int NULL_PTR = -1; private static final int NULL_CG_REF = -2; diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIState.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIState.java index 116e85c3509..62176e40497 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIState.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIState.java @@ -93,7 +93,7 @@ public int hashCode() { return Long.hashCode(encodedState) ^ getClass().hashCode(); } - public static class AnimationFrameState extends JRSUIState { + public static final class AnimationFrameState extends JRSUIState { final int animationFrame; int derivedAnimationFrame; @@ -187,7 +187,7 @@ public int hashCode() { } } - public static class TitleBarHeightState extends ValueState { + public static final class TitleBarHeightState extends ValueState { TitleBarHeightState(final long encodedState, final double value) { super(encodedState, value); } @@ -204,7 +204,7 @@ public void apply(final JRSUIControl control) { } } - public static class ScrollBarState extends ValueState { + public static final class ScrollBarState extends ValueState { final double thumbProportion; double derivedThumbProportion; final double thumbStart; diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIStateFactory.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIStateFactory.java index 8b3049c1527..52913b9ed23 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIStateFactory.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIStateFactory.java @@ -28,7 +28,7 @@ import apple.laf.JRSUIConstants.*; import apple.laf.JRSUIState.*; -public class JRSUIStateFactory { +public final class JRSUIStateFactory { public static JRSUIState getSliderTrack() { return new JRSUIState(Widget.SLIDER.apply(NoIndicator.YES.apply(0))); } diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java index 2cf3df3ce2a..217985eecfa 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java @@ -90,7 +90,7 @@ static boolean currentMacOSXVersionMatchesGivenVersionRange( return false; } - public static class TabbedPane { + public static final class TabbedPane { public static boolean useLegacyTabs() { return isLeopard; } @@ -99,19 +99,19 @@ public static boolean shouldUseTabbedPaneContrastUI() { } } - public static class InternalFrame { + public static final class InternalFrame { public static boolean shouldUseLegacyBorderMetrics() { return isSnowLeopardOrBelow; } } - public static class Tree { + public static final class Tree { public static boolean useLegacyTreeKnobs() { return isLeopard; } } - public static class ScrollBar { + public static final class ScrollBar { private static native boolean shouldUseScrollToClick(); public static boolean useScrollToClick() { @@ -137,13 +137,13 @@ public static double getNativeOffsetChange(final JRSUIControl control, } } - public static class Images { + public static final class Images { public static boolean shouldUseLegacySecurityUIPath() { return isSnowLeopardOrBelow; } } - public static class HitDetection { + public static final class HitDetection { public static Hit getHitForPoint(final JRSUIControl control, final int x, final int y, final int w, final int h, final int hitX, diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/Application.java b/src/java.desktop/macosx/classes/com/apple/eawt/Application.java index 11c34ff7c5c..c1daee47912 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/Application.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/Application.java @@ -73,7 +73,7 @@ * * @since 1.4 */ -public class Application { +public final class Application { private static native void nativeInitializeApplicationDelegate(); static Application sApplication = null; diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationBeanInfo.java b/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationBeanInfo.java index e9cc203bc3d..9fc34576857 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationBeanInfo.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationBeanInfo.java @@ -31,7 +31,8 @@ /** * This class is used by JavaBeans tools and should not be used directly by applications. */ -public class ApplicationBeanInfo extends SimpleBeanInfo { +public final class ApplicationBeanInfo extends SimpleBeanInfo { + @Override public Image getIcon(final int iconKind) { return Toolkit.getDefaultToolkit().getImage("NSImage://NSGenericApplication"); } diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/FullScreenAdapter.java b/src/java.desktop/macosx/classes/com/apple/eawt/FullScreenAdapter.java index 79fcd34b920..c1fdb932c90 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/FullScreenAdapter.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/FullScreenAdapter.java @@ -41,8 +41,12 @@ * @since Java for Mac OS X 10.7 Update 1 */ public abstract class FullScreenAdapter implements FullScreenListener { + @Override public void windowEnteringFullScreen(final FullScreenEvent e) {} + @Override public void windowEnteredFullScreen(final FullScreenEvent e) {} + @Override public void windowExitingFullScreen(final FullScreenEvent e) {} + @Override public void windowExitedFullScreen(final FullScreenEvent e) {} } diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/MacQuitResponse.java b/src/java.desktop/macosx/classes/com/apple/eawt/MacQuitResponse.java index 5b9eb054c33..c207e8d58a8 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/MacQuitResponse.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/MacQuitResponse.java @@ -41,7 +41,7 @@ * @since Java for Mac OS X 10.6 Update 3 * @since Java for Mac OS X 10.5 Update 8 */ -public class MacQuitResponse implements QuitResponse { +public final class MacQuitResponse implements QuitResponse { final _AppEventHandler appEventHandler; MacQuitResponse(final _AppEventHandler appEventHandler) { diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/_AppDockIconHandler.java b/src/java.desktop/macosx/classes/com/apple/eawt/_AppDockIconHandler.java index 8f1363f774c..0fcbdce4720 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/_AppDockIconHandler.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/_AppDockIconHandler.java @@ -32,7 +32,7 @@ import sun.lwawt.macosx.*; import sun.lwawt.macosx.CImage.Creator; -class _AppDockIconHandler { +final class _AppDockIconHandler { private static native void nativeSetDockMenu(final long cmenu); private static native void nativeSetDockIconImage(final long image); private static native void nativeSetDockIconProgress(final int value); diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/_AppEventHandler.java b/src/java.desktop/macosx/classes/com/apple/eawt/_AppEventHandler.java index 248ae55f6d7..3cf6a1ba1d6 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/_AppEventHandler.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/_AppEventHandler.java @@ -66,7 +66,7 @@ import sun.awt.AppContext; import sun.awt.SunToolkit; -class _AppEventHandler { +final class _AppEventHandler { private static final int NOTIFY_ABOUT = 1; private static final int NOTIFY_PREFS = 2; private static final int NOTIFY_OPEN_APP = 3; @@ -271,17 +271,20 @@ private static void handleNativeNotification(final int code) { } - class _AboutDispatcher extends _AppEventDispatcher { + final class _AboutDispatcher extends _AppEventDispatcher { + @Override void performDefaultAction(final _NativeEvent event) { openCocoaAboutWindow(); // if the handler is null, fall back to showing the Cocoa default } + @Override void performUsing(final AboutHandler handler, final _NativeEvent event) { handler.handleAbout(new AboutEvent()); } } - static class _PreferencesDispatcher extends _AppEventDispatcher { + static final class _PreferencesDispatcher extends _AppEventDispatcher { + @Override synchronized void setHandler(final PreferencesHandler handler) { super.setHandler(handler); @@ -289,99 +292,121 @@ synchronized void setHandler(final PreferencesHandler handler) { _AppMenuBarHandler.getInstance().setPreferencesMenuItemEnabled(handler != null); } + @Override void performUsing(final PreferencesHandler handler, final _NativeEvent event) { handler.handlePreferences(new PreferencesEvent()); } } - static class _OpenAppDispatcher extends _QueuingAppEventDispatcher { + static final class _OpenAppDispatcher extends _QueuingAppEventDispatcher { + @Override void performUsing(com.apple.eawt._OpenAppHandler handler, _NativeEvent event) { handler.handleOpenApp(); } } - static class _AppReOpenedDispatcher extends _AppEventMultiplexor { + static final class _AppReOpenedDispatcher extends _AppEventMultiplexor { + @Override void performOnListener(AppReopenedListener listener, final _NativeEvent event) { final AppReopenedEvent e = new AppReopenedEvent(); listener.appReopened(e); } } - static class _AppForegroundDispatcher extends _BooleanAppEventMultiplexor { + static final class _AppForegroundDispatcher extends _BooleanAppEventMultiplexor { + @Override AppForegroundEvent createEvent(final boolean isTrue) { return new AppForegroundEvent(); } + @Override void performFalseEventOn(final AppForegroundListener listener, final AppForegroundEvent e) { listener.appMovedToBackground(e); } + @Override void performTrueEventOn(final AppForegroundListener listener, final AppForegroundEvent e) { listener.appRaisedToForeground(e); } } - static class _HiddenAppDispatcher extends _BooleanAppEventMultiplexor { + static final class _HiddenAppDispatcher extends _BooleanAppEventMultiplexor { + @Override AppHiddenEvent createEvent(final boolean isTrue) { return new AppHiddenEvent(); } + @Override void performFalseEventOn(final AppHiddenListener listener, final AppHiddenEvent e) { listener.appUnhidden(e); } + @Override void performTrueEventOn(final AppHiddenListener listener, final AppHiddenEvent e) { listener.appHidden(e); } } - static class _UserSessionDispatcher extends _BooleanAppEventMultiplexor { + static final class _UserSessionDispatcher extends _BooleanAppEventMultiplexor { + @Override UserSessionEvent createEvent(final boolean isTrue) { return new UserSessionEvent(Reason.UNSPECIFIED); } + @Override void performFalseEventOn(final UserSessionListener listener, final UserSessionEvent e) { listener.userSessionDeactivated(e); } + @Override void performTrueEventOn(final UserSessionListener listener, final UserSessionEvent e) { listener.userSessionActivated(e); } + @Override void registerNativeListener() { nativeRegisterForNotification(REGISTER_USER_SESSION); } } - static class _ScreenSleepDispatcher extends _BooleanAppEventMultiplexor { + static final class _ScreenSleepDispatcher extends _BooleanAppEventMultiplexor { + @Override ScreenSleepEvent createEvent(final boolean isTrue) { return new ScreenSleepEvent(); } + @Override void performFalseEventOn(final ScreenSleepListener listener, final ScreenSleepEvent e) { listener.screenAwoke(e); } + @Override void performTrueEventOn(final ScreenSleepListener listener, final ScreenSleepEvent e) { listener.screenAboutToSleep(e); } + @Override void registerNativeListener() { nativeRegisterForNotification(REGISTER_SCREEN_SLEEP); } } - static class _SystemSleepDispatcher extends _BooleanAppEventMultiplexor { + static final class _SystemSleepDispatcher extends _BooleanAppEventMultiplexor { + @Override SystemSleepEvent createEvent(final boolean isTrue) { return new SystemSleepEvent(); } + @Override void performFalseEventOn(final SystemSleepListener listener, final SystemSleepEvent e) { listener.systemAwoke(e); } + @Override void performTrueEventOn(final SystemSleepListener listener, final SystemSleepEvent e) { listener.systemAboutToSleep(e); } + @Override void registerNativeListener() { nativeRegisterForNotification(REGISTER_SYSTEM_SLEEP); } } - static class _OpenFileDispatcher extends _QueuingAppEventDispatcher { + static final class _OpenFileDispatcher extends _QueuingAppEventDispatcher { + @Override void performUsing(final OpenFilesHandler handler, final _NativeEvent event) { // create file list from fileNames final List fileNameList = event.get(0); @@ -394,7 +419,8 @@ void performUsing(final OpenFilesHandler handler, final _NativeEvent event) { } } - static class _PrintFileDispatcher extends _QueuingAppEventDispatcher { + static final class _PrintFileDispatcher extends _QueuingAppEventDispatcher { + @Override void performUsing(final PrintFilesHandler handler, final _NativeEvent event) { // create file list from fileNames final List fileNameList = event.get(0); @@ -406,7 +432,8 @@ void performUsing(final PrintFilesHandler handler, final _NativeEvent event) { } // Java URLs can't handle unknown protocol types, which is why we use URIs - static class _OpenURIDispatcher extends _QueuingAppEventDispatcher { + static final class _OpenURIDispatcher extends _QueuingAppEventDispatcher { + @Override void performUsing(final OpenURIHandler handler, final _NativeEvent event) { final String urlString = event.get(0); try { @@ -417,11 +444,13 @@ void performUsing(final OpenURIHandler handler, final _NativeEvent event) { } } - class _QuitDispatcher extends _AppEventDispatcher { + final class _QuitDispatcher extends _AppEventDispatcher { + @Override void performDefaultAction(final _NativeEvent event) { obtainQuitResponse().performQuit(); } + @Override void performUsing(final QuitHandler handler, final _NativeEvent event) { if (_AppMiscHandlers.isSuddenTerminationEnbaled()) { performDefaultAction(event); @@ -436,7 +465,7 @@ void performUsing(final QuitHandler handler, final _NativeEvent event) { // -- ABSTRACT QUEUE/EVENT/LISTENER HELPERS -- // generic little "raw event" that's constructed easily from the native callbacks - static class _NativeEvent { + static final class _NativeEvent { Object[] args; public _NativeEvent(final Object... args) { @@ -591,6 +620,7 @@ void dispatch(final _NativeEvent event) { super.dispatch(event); } + @Override synchronized void setHandler(final H handler) { this._handler = handler; diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java b/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java index 394b9d59592..d891c65acf5 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java @@ -40,7 +40,7 @@ import com.apple.laf.AquaMenuBarUI; -class _AppMenuBarHandler { +final class _AppMenuBarHandler { private static final int MENU_ABOUT = 1; private static final int MENU_PREFS = 2; diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/_AppMiscHandlers.java b/src/java.desktop/macosx/classes/com/apple/eawt/_AppMiscHandlers.java index 1851e2aa90c..5870b8d3586 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/_AppMiscHandlers.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/_AppMiscHandlers.java @@ -25,7 +25,7 @@ package com.apple.eawt; -class _AppMiscHandlers { +final class _AppMiscHandlers { private static boolean isSuddenTerminationEnabled; private static native void nativeOpenHelpViewer(); diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/FullScreenEvent.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/FullScreenEvent.java index 3ff90ac5e1d..cf4ec3bea99 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/FullScreenEvent.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/FullScreenEvent.java @@ -30,7 +30,7 @@ import java.util.EventObject; @SuppressWarnings("serial") // JDK implementation class -public class FullScreenEvent extends EventObject { +public final class FullScreenEvent extends EventObject { final Window window; diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureAdapter.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureAdapter.java index 0f6c6d9ee7f..1b1da4fb095 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureAdapter.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureAdapter.java @@ -37,12 +37,20 @@ * @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2 */ public abstract class GestureAdapter implements GesturePhaseListener, MagnificationListener, RotationListener, SwipeListener { + @Override public void gestureBegan(final GesturePhaseEvent e) { } + @Override public void gestureEnded(final GesturePhaseEvent e) { } + @Override public void magnify(final MagnificationEvent e) { } + @Override public void rotate(final RotationEvent e) { } + @Override public void swipedDown(final SwipeEvent e) { } + @Override public void swipedLeft(final SwipeEvent e) { } + @Override public void swipedRight(final SwipeEvent e) { } + @Override public void swipedUp(final SwipeEvent e) { } } diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureHandler.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureHandler.java index 4514da90ca9..e3ff511f6f0 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureHandler.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/GestureHandler.java @@ -126,7 +126,7 @@ void removeListener(final GestureListener listener) { // notifies all listeners in a particular component/handler pair // and recursively notifies up the component hierarchy - static class PerComponentNotifier { + static final class PerComponentNotifier { final Component component; final GestureHandler handler; diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/GesturePhaseEvent.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/GesturePhaseEvent.java index e18d4d57cc9..befad3d2633 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/GesturePhaseEvent.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/GesturePhaseEvent.java @@ -32,7 +32,7 @@ * * @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2 */ -public class GesturePhaseEvent extends GestureEvent { +public final class GesturePhaseEvent extends GestureEvent { GesturePhaseEvent() { // package private } diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/MagnificationEvent.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/MagnificationEvent.java index dd6b744b784..3e771e21833 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/MagnificationEvent.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/MagnificationEvent.java @@ -32,7 +32,7 @@ * * @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2 */ -public class MagnificationEvent extends GestureEvent { +public final class MagnificationEvent extends GestureEvent { final double magnification; MagnificationEvent(final double magnification) { diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/RotationEvent.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/RotationEvent.java index 19d6cbd7d28..3b8375f83c2 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/RotationEvent.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/RotationEvent.java @@ -32,7 +32,7 @@ * * @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2 */ -public class RotationEvent extends GestureEvent { +public final class RotationEvent extends GestureEvent { final double rotation; RotationEvent(final double rotation) { diff --git a/src/java.desktop/macosx/classes/com/apple/eawt/event/SwipeEvent.java b/src/java.desktop/macosx/classes/com/apple/eawt/event/SwipeEvent.java index ddcf220fb58..07ea97fcb7c 100644 --- a/src/java.desktop/macosx/classes/com/apple/eawt/event/SwipeEvent.java +++ b/src/java.desktop/macosx/classes/com/apple/eawt/event/SwipeEvent.java @@ -32,7 +32,7 @@ * * @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2 */ -public class SwipeEvent extends GestureEvent { +public final class SwipeEvent extends GestureEvent { SwipeEvent() { // package private } diff --git a/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java b/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java index 8bc47f66efb..ce206446ce5 100644 --- a/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java +++ b/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java @@ -53,7 +53,7 @@ * * @since 1.4 */ -public class FileManager { +public final class FileManager { static { loadOSXLibrary(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java index 60ceb4893a8..e39ea5ec757 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java @@ -69,6 +69,7 @@ public AquaButtonBorder(final AquaButtonBorder other) { super(other); } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { // for now we don't paint a border. We let the button paint it since there // needs to be a strict ordering for aqua components. @@ -144,6 +145,7 @@ public boolean hasSmallerInsets(final JComponent c) { * Returns the insets of the border. * @param c the component for which this border insets value applies */ + @Override public Insets getBorderInsets(final Component c) { if (!(c instanceof AbstractButton button)) return new Insets(0, 0, 0, 0); @@ -172,18 +174,19 @@ public void alterPreferredSize(final Dimension d) { * is opaque, it is responsible for filling in it's own * background when painting. */ + @Override public boolean isBorderOpaque() { return false; } - static class SizeConstants { + static final class SizeConstants { protected static final int fNormalButtonHeight = 29; protected static final int fNormalMinButtonWidth = 40; protected static final int fSquareButtonHeightThreshold = 23; protected static final int fSquareButtonWidthThreshold = 16; } - public static class Dynamic extends AquaButtonBorder { + public static final class Dynamic extends AquaButtonBorder { final Insets ALTERNATE_PUSH_INSETS = new Insets(3, 12, 5, 12); final Insets ALTERNATE_BEVEL_INSETS = new Insets(0, 5, 0, 5); final Insets ALTERNATE_SQUARE_INSETS = new Insets(0, 2, 0, 2); @@ -202,6 +205,7 @@ public Dynamic(final Dynamic other) { super(other); } + @Override public Insets getContentInsets(final AbstractButton b, final int width, final int height) { final Size size = AquaUtilControlSize.getUserSizeFrom(b); final Widget style = getStyleForSize(b, size, width, height); @@ -219,6 +223,7 @@ public Insets getContentInsets(final AbstractButton b, final int width, final in return null; } + @Override protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, int x, int y, int width, int height) { final Size size = AquaUtilControlSize.getUserSizeFrom(b); painter.state.set(size); @@ -256,7 +261,7 @@ protected Widget getStyleForSize(final AbstractButton b, final Size size, final } } - public static class Toggle extends AquaButtonBorder { + public static final class Toggle extends AquaButtonBorder { public Toggle() { super(new SizeDescriptor(new SizeVariant().alterMargins(6, 6, 6, 6))); } @@ -265,6 +270,7 @@ public Toggle(final Toggle other) { super(other); } + @Override protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, final int x, final int y, final int width, final int height) { if (height < SizeConstants.fSquareButtonHeightThreshold || width < SizeConstants.fSquareButtonWidthThreshold) { painter.state.set(Widget.BUTTON_BEVEL); @@ -288,13 +294,14 @@ public Named(final Named sizeDescriptor) { super(sizeDescriptor); } + @Override protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, final int x, final int y, final int width, final int height) { painter.state.set(model.isSelected() ? BooleanValue.YES : BooleanValue.NO); super.doButtonPaint(b, model, g, x, y, width, height); } } - public static class Toolbar extends AquaButtonBorder { + public static final class Toolbar extends AquaButtonBorder { public Toolbar() { super(new SizeDescriptor(new SizeVariant().alterMargins(5, 5, 5, 5))); painter.state.set(Widget.TOOLBAR_ITEM_WELL); @@ -304,6 +311,7 @@ public Toolbar(final Toolbar other) { super(other); } + @Override protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, final int x, final int y, final int w, final int h) { if (!model.isSelected()) return; // only paint when the toolbar button is selected super.doButtonPaint(b, model, g, x, y, w, h); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonCheckBoxUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonCheckBoxUI.java index bef9fe83fc5..0e92da43084 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonCheckBoxUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonCheckBoxUI.java @@ -33,7 +33,7 @@ import com.apple.laf.AquaUtilControlSize.*; import com.apple.laf.AquaUtils.*; -public class AquaButtonCheckBoxUI extends AquaButtonLabeledUI { +public final class AquaButtonCheckBoxUI extends AquaButtonLabeledUI { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaButtonCheckBoxUI.class); private static final RecyclableSingleton sizingIcon = new RecyclableSingleton() { protected ImageIcon getInstance() { @@ -49,15 +49,17 @@ public static Icon getSizingCheckBoxIcon() { return sizingIcon.get(); } + @Override public String getPropertyPrefix() { return "CheckBox" + "."; } + @Override protected AquaButtonBorder getPainter() { return new CheckBoxButtonBorder(); } - public static class CheckBoxButtonBorder extends LabeledButtonBorder { + public static final class CheckBoxButtonBorder extends LabeledButtonBorder { public CheckBoxButtonBorder() { super(new SizeDescriptor(new SizeVariant().replaceMargins("CheckBox.margin"))); painter.state.set(Widget.BUTTON_CHECK_BOX); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java index aa48414e801..0927df6aa9e 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonExtendedTypes.java @@ -43,7 +43,7 @@ * "default font" and sizes for controls in Java Aqua Look and Feel * has been addressed, and we can cull widget metrics from the native system. */ -public class AquaButtonExtendedTypes { +public final class AquaButtonExtendedTypes { protected static Border getBorderForPosition(final AbstractButton c, final Object type, final Object logicalPosition) { final String name = (logicalPosition == null ? (String)type : type + "-" + getRealPositionForLogicalPosition((String)logicalPosition, c.getComponentOrientation().isLeftToRight())); final TypeSpecifier specifier = getSpecifierByName(name); @@ -96,6 +96,7 @@ public SizeVariant deriveMini(final SizeVariant v) { patchUp(border.sizeDescriptor); } + @Override Border getBorder() { return border; } void patchUp(final SizeDescriptor descriptor) {} @@ -104,7 +105,7 @@ AquaBorder initBorder(final Widget widget, final SizeDescriptor desc) { } } - static class SegmentedBorderDefinedTypeSpecifier extends BorderDefinedTypeSpecifier { + static final class SegmentedBorderDefinedTypeSpecifier extends BorderDefinedTypeSpecifier { public SegmentedBorderDefinedTypeSpecifier(final String name, final Widget widget, final SegmentPosition position, final SizeVariant variant) { this(name, widget, position, variant, 0, 0, 0, 0); } @@ -115,12 +116,13 @@ public SegmentedBorderDefinedTypeSpecifier(final String name, final Widget widge border.painter.state.set(position); } + @Override AquaBorder initBorder(final Widget widget, final SizeDescriptor desc) { return new SegmentedNamedBorder(widget, desc); } } - public static class SegmentedNamedBorder extends AquaButtonBorder.Named { + public static final class SegmentedNamedBorder extends AquaButtonBorder.Named { public SegmentedNamedBorder(final SegmentedNamedBorder sizeDescriptor) { super(sizeDescriptor); } @@ -129,6 +131,7 @@ public SegmentedNamedBorder(final Widget widget, final SizeDescriptor sizeDescri super(widget, sizeDescriptor); } + @Override protected boolean isSelectionPressing() { return false; } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java index 3c21b325f36..c4e2e1b8a5e 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java @@ -46,10 +46,11 @@ public abstract class AquaButtonLabeledUI extends AquaButtonToggleUI implements private static final RecyclableSizingIcon smallIcon = new RecyclableSizingIcon(16); private static final RecyclableSizingIcon miniIcon = new RecyclableSizingIcon(14); - protected static class RecyclableSizingIcon extends RecyclableSingleton { + protected static final class RecyclableSizingIcon extends RecyclableSingleton { final int iconSize; public RecyclableSizingIcon(final int iconSize) { this.iconSize = iconSize; } + @Override protected Icon getInstance() { return new ImageIcon(new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB_PRE)); } @@ -61,6 +62,7 @@ public AquaButtonLabeledUI() { widgetBorder = getPainter(); } + @Override public void applySizeFor(final JComponent c, final Size newSize) { super.applySizeFor(c, newSize); widgetBorder = (AquaButtonBorder)widgetBorder.deriveBorderForSize(newSize); @@ -74,6 +76,7 @@ public Icon getDefaultIcon(final JComponent c) { return regularIcon.get(); } + @Override protected void setThemeBorder(final AbstractButton b) { super.setThemeBorder(b); @@ -86,6 +89,7 @@ protected void setThemeBorder(final AbstractButton b) { protected abstract AquaButtonBorder getPainter(); + @Override public synchronized void paint(final Graphics g, final JComponent c) { final AbstractButton b = (AbstractButton)c; final ButtonModel model = b.getModel(); @@ -192,6 +196,7 @@ public synchronized void paint(final Graphics g, final JComponent c) { /** * The preferred size of the button */ + @Override public Dimension getPreferredSize(final JComponent c) { if (c.getComponentCount() > 0) { return null; } @@ -244,12 +249,14 @@ protected AquaPainter createPainter() { return painter; } + @Override protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, final int x, final int y, final int width, final int height) { painter.state.set(AquaUtilControlSize.getUserSizeFrom(b)); ((ValueState)painter.state).setValue(model.isSelected() ? isIndeterminate(b) ? 2 : 1 : 0); // 2=mixed, 1=on, 0=off super.doButtonPaint(b, model, g, x, y, width, height); } + @Override protected State getButtonState(final AbstractButton b, final ButtonModel model) { final State state = super.getButtonState(b, model); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java index d0370ac9b5f..1fdb8a30f5d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonRadioUI.java @@ -55,7 +55,7 @@ import java.util.Set; import java.util.Enumeration; -public class AquaButtonRadioUI extends AquaButtonLabeledUI { +public final class AquaButtonRadioUI extends AquaButtonLabeledUI { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaButtonRadioUI.class); private static final RecyclableSingleton sizingIcon = new RecyclableSingleton() { @@ -72,15 +72,17 @@ public static Icon getSizingRadioButtonIcon() { return sizingIcon.get(); } + @Override protected String getPropertyPrefix() { return "RadioButton" + "."; } + @Override protected AquaButtonBorder getPainter() { return new RadioButtonBorder(); } - public static class RadioButtonBorder extends LabeledButtonBorder { + public static final class RadioButtonBorder extends LabeledButtonBorder { public RadioButtonBorder() { super(new SizeDescriptor(new SizeVariant().replaceMargins("RadioButton.margin"))); painter.state.set(Widget.BUTTON_RADIO); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonToggleUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonToggleUI.java index d4f55f3c874..5eb0fbbccb6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonToggleUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonToggleUI.java @@ -37,6 +37,7 @@ public static ComponentUI createUI(final JComponent b) { return aquaToggleButtonUI.get(); } + @Override protected String getPropertyPrefix() { return "ToggleButton" + "."; } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java index 17818d09121..6b6eb4f535b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java @@ -89,6 +89,7 @@ public static ComponentUI createUI(final JComponent c) { private boolean defaults_initialized = false; private Color defaultDisabledTextColor = null; + @Override protected void installDefaults(final AbstractButton b) { // load shared instance defaults final String pp = getPropertyPrefix(); @@ -120,6 +121,7 @@ protected void installDefaults(final AbstractButton b) { } } + @Override public void applySizeFor(final JComponent c, final Size size) { // this space intentionally left blank // (subclasses need to do work here) @@ -216,6 +218,7 @@ protected boolean setButtonType(final AbstractButton b, final Object prop) { return true; } + @Override protected void installListeners(final AbstractButton b) { super.installListeners(b); AquaButtonListener listener = getAquaButtonListener(b); @@ -228,12 +231,14 @@ protected void installListeners(final AbstractButton b) { AquaUtilControlSize.addSizePropertyListener(b); } + @Override protected void installKeyboardActions(final AbstractButton b) { final BasicButtonListener listener = (BasicButtonListener)b.getClientProperty(this); if (listener != null) listener.installKeyboardActions(b); } // Uninstall PLAF + @Override public void uninstallUI(final JComponent c) { uninstallKeyboardActions((AbstractButton)c); uninstallListeners((AbstractButton)c); @@ -241,11 +246,13 @@ public void uninstallUI(final JComponent c) { //BasicHTML.updateRenderer(c, ""); } + @Override protected void uninstallKeyboardActions(final AbstractButton b) { final BasicButtonListener listener = (BasicButtonListener)b.getClientProperty(this); if (listener != null) listener.uninstallKeyboardActions(b); } + @Override protected void uninstallListeners(final AbstractButton b) { super.uninstallListeners(b); b.putClientProperty(this, null); @@ -253,12 +260,14 @@ protected void uninstallListeners(final AbstractButton b) { AquaUtilControlSize.removeSizePropertyListener(b); } + @Override protected void uninstallDefaults(final AbstractButton b) { LookAndFeel.uninstallBorder(b); defaults_initialized = false; } // Create Listeners + @Override protected AquaButtonListener createButtonListener(final AbstractButton b) { return new AquaButtonListener(b); } @@ -281,6 +290,7 @@ private AquaButtonListener getAquaButtonListener(AbstractButton b) { } // Paint Methods + @Override public void paint(final Graphics g, final JComponent c) { final AbstractButton b = (AbstractButton)c; final ButtonModel model = b.getModel(); @@ -352,6 +362,7 @@ public void paint(final Graphics g, final JComponent c) { } } + @Override protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { Graphics2D g2d = null; @@ -479,6 +490,7 @@ protected void paintIcon(final Graphics g, final AbstractButton b, final Rectang * As of Java 2 platform v 1.4 this method should not be used or overridden. * Use the paintText method which takes the AbstractButton argument. */ + @Override protected void paintText(final Graphics g, final JComponent c, final Rectangle localTextRect, final String text) { final AbstractButton b = (AbstractButton)c; final ButtonModel model = b.getModel(); @@ -496,15 +508,18 @@ protected void paintText(final Graphics g, final JComponent c, final Rectangle l SwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex, localTextRect.x, localTextRect.y + fm.getAscent()); } + @Override protected void paintText(final Graphics g, final AbstractButton b, final Rectangle localTextRect, final String text) { paintText(g, (JComponent)b, localTextRect, text); } + @Override protected void paintButtonPressed(final Graphics g, final AbstractButton b) { paint(g, b); } // Layout Methods + @Override public Dimension getMinimumSize(final JComponent c) { final Dimension d = getPreferredSize(c); final View v = (View)c.getClientProperty(BasicHTML.propertyKey); @@ -514,6 +529,7 @@ public Dimension getMinimumSize(final JComponent c) { return d; } + @Override public Dimension getPreferredSize(final JComponent c) { final AbstractButton b = (AbstractButton)c; @@ -529,6 +545,7 @@ public Dimension getPreferredSize(final JComponent c) { return d; } + @Override public Dimension getMaximumSize(final JComponent c) { final Dimension d = getPreferredSize(c); @@ -565,9 +582,10 @@ protected void uninstallHierListener(final AbstractButton b) { } } - static class AquaHierarchyButtonListener implements HierarchyListener { + static final class AquaHierarchyButtonListener implements HierarchyListener { // Every time a hierarchy is changed we need to check if the button is moved on or from // the toolbar. If that is the case, we need to re-set the border of the button. + @Override public void hierarchyChanged(final HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0) return; @@ -583,7 +601,7 @@ public void hierarchyChanged(final HierarchyEvent e) { } } - class AquaButtonListener extends BasicButtonListener { + final class AquaButtonListener extends BasicButtonListener { protected final AbstractButton b; public AquaButtonListener(final AbstractButton b) { @@ -591,10 +609,12 @@ public AquaButtonListener(final AbstractButton b) { this.b = b; } + @Override public void focusGained(final FocusEvent e) { ((Component)e.getSource()).repaint(); } + @Override public void focusLost(final FocusEvent e) { // 10-06-03 VL: [Radar 3187049] // If focusLost arrives while the button has been left-clicked this would disarm the button, @@ -604,6 +624,7 @@ public void focusLost(final FocusEvent e) { ((Component)e.getSource()).repaint(); } + @Override public void propertyChange(final PropertyChangeEvent e) { super.propertyChange(e); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaCaret.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaCaret.java index 3c1b147d1ea..eaf84295c11 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaCaret.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaCaret.java @@ -44,7 +44,7 @@ import javax.swing.SwingUtilities; @SuppressWarnings("serial") // Superclass is not serializable across versions -public class AquaCaret extends DefaultCaret +public final class AquaCaret extends DefaultCaret implements UIResource, PropertyChangeListener { private boolean isMultiLineEditor; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java index a9eab801b0d..e691153df73 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java @@ -53,7 +53,7 @@ import apple.laf.JRSUIState; @SuppressWarnings("serial") // Superclass is not serializable across versions -class AquaComboBoxButton extends JButton { +final class AquaComboBoxButton extends JButton { protected final JComboBox comboBox; protected final JList list; protected final CellRendererPane rendererPane; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRenderer.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRenderer.java index f4d4225efe0..02e0cc7aaf6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRenderer.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRenderer.java @@ -29,7 +29,7 @@ import javax.swing.plaf.UIResource; @SuppressWarnings("serial") // Superclass is not serializable across versions -class AquaComboBoxRenderer extends AquaComboBoxRendererInternal implements UIResource { +final class AquaComboBoxRenderer extends AquaComboBoxRendererInternal implements UIResource { public AquaComboBoxRenderer(final JComboBox comboBox) { super(comboBox); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java index a320d054a25..ac76eb0f771 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxRendererInternal.java @@ -47,6 +47,7 @@ public AquaComboBoxRendererInternal(final JComboBox comboBox) { // Don't include checkIcon space, because this is also used for button size calculations // - the popup-size calc will get checkIcon space from getInsets + @Override public Dimension getPreferredSize() { // From BasicComboBoxRenderer - trick to avoid zero-height items final Dimension size; @@ -63,15 +64,18 @@ public Dimension getPreferredSize() { } // Don't paint the border here, it gets painted by the UI + @Override protected void paintBorder(final Graphics g) { } + @Override public int getBaseline(int width, int height) { return super.getBaseline(width, height) - 1; } // Really means is the one with the mouse over it + @Override public Component getListCellRendererComponent(final JList list, final E value, int index, final boolean isSelected, @@ -127,6 +131,7 @@ public Component getListCellRendererComponent(final JList list, return this; } + @Override public Insets getInsets(Insets insets) { if (insets == null) insets = new Insets(0, 0, 0, 0); insets.top = 1; @@ -141,6 +146,7 @@ protected void setDrawCheckedItem(final boolean drawCheckedItem) { } // Paint this component, and a checkbox if it's the selected item and not in the button + @Override protected void paintComponent(final Graphics g) { if (fInList) { if (fSelected && !fEditable) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java index 130c30aa9e1..a4c85a7676f 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -76,7 +76,7 @@ import com.apple.laf.ClientPropertyApplicator.Property; // Inspired by MetalComboBoxUI, which also has a combined text-and-arrow button for noneditables -public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { +public final class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { static final String POPDOWN_CLIENT_PROPERTY_KEY = "JComboBox.isPopDown"; static final String ISSQUARE_CLIENT_PROPERTY_KEY = "JComboBox.isSquare"; @@ -85,6 +85,7 @@ public static ComponentUI createUI(final JComponent c) { } private boolean wasOpaque; + @Override public void installUI(final JComponent c) { super.installUI(c); @@ -96,21 +97,25 @@ public void installUI(final JComponent c) { c.setOpaque(false); } + @Override public void uninstallUI(final JComponent c) { c.setOpaque(wasOpaque); super.uninstallUI(c); } + @Override protected void installListeners() { super.installListeners(); AquaUtilControlSize.addSizePropertyListener(comboBox); } + @Override protected void uninstallListeners() { AquaUtilControlSize.removeSizePropertyListener(comboBox); super.uninstallListeners(); } + @Override protected void installComponents() { super.installComponents(); @@ -119,6 +124,7 @@ protected void installComponents() { getApplicator().attachAndApplyClientProperties(comboBox); } + @Override protected void uninstallComponents() { getApplicator().removeFrom(comboBox); // AquaButtonUI install some listeners to all parents, which means that @@ -129,6 +135,7 @@ protected void uninstallComponents() { super.uninstallComponents(); } + @Override protected ItemListener createItemListener() { return new ItemListener() { long lastBlink = 0L; @@ -161,22 +168,27 @@ public void paintSelected(final boolean selected) { }; } + @Override public void paint(final Graphics g, final JComponent c) { // this space intentionally left blank } + @Override protected ListCellRenderer createRenderer() { return new AquaComboBoxRenderer(comboBox); } + @Override protected ComboPopup createPopup() { return new AquaComboBoxPopup(comboBox); } + @Override protected JButton createArrowButton() { return new AquaComboBoxButton(this, comboBox, currentValuePane, listBox); } + @Override protected ComboBoxEditor createEditor() { return new AquaComboBoxEditor(); } @@ -229,7 +241,7 @@ private void editorTextChanged() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - class AquaCustomComboTextField extends JTextField { + final class AquaCustomComboTextField extends JTextField { public AquaCustomComboTextField() { final InputMap inputMap = getInputMap(); inputMap.put(KeyStroke.getKeyStroke("DOWN"), highlightNextAction); @@ -258,6 +270,7 @@ public void actionPerformed(final ActionEvent e) { } // workaround for 4530952 + @Override public void setText(final String s) { if (getText().equals(s)) { return; @@ -274,6 +287,7 @@ public void setText(final String s) { * around a Solaris-only bug that we don't have on Mac OS X. So, remove the lightweight * popup check here. rdar://Problem/3518582 */ + @Override protected FocusListener createFocusListener() { return new BasicComboBoxUI.FocusHandler() { @Override @@ -306,6 +320,7 @@ public void focusLost(final FocusEvent e) { }; } + @Override protected void installKeyboardActions() { super.installKeyboardActions(); @@ -330,6 +345,7 @@ protected void installKeyboardActions() { @SuppressWarnings("serial") // Superclass is not serializable across versions private abstract class ComboBoxAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { if (!comboBox.isEnabled() || !comboBox.isShowing()) { return; @@ -443,11 +459,12 @@ public ComboPopup getPopup() { return popup; } + @Override protected LayoutManager createLayoutManager() { return new AquaComboBoxLayoutManager(); } - class AquaComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { + final class AquaComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { protected Rectangle rectangleForCurrentValue() { int width = comboBox.getWidth(); int height = comboBox.getBorder() == null ? 22 : comboBox.getHeight(); @@ -473,6 +490,7 @@ protected Rectangle rectangleForCurrentValue() { } } + @Override public void layoutContainer(final Container parent) { if (arrowButton != null && !comboBox.isEditable()) { final Insets insets = comboBox.getInsets(); @@ -615,6 +633,7 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; + @Override public void applySizeFor(final JComponent c, final Size size) { if (arrowButton == null) return; final Border border = arrowButton.getBorder(); @@ -623,6 +642,7 @@ public void applySizeFor(final JComponent c, final Size size) { arrowButton.setBorder(aquaBorder.deriveBorderForSize(size)); } + @Override public Dimension getMinimumSize(final JComponent c) { if (!isMinimumSizeDirty) { return new Dimension(cachedMinimumSize); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java index 7e208a77296..2f2e8e6c107 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaEditorPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.plaf.basic.BasicEditorPaneUI; import javax.swing.text.*; -public class AquaEditorPaneUI extends BasicEditorPaneUI { +public final class AquaEditorPaneUI extends BasicEditorPaneUI { public static ComponentUI createUI(final JComponent c){ return new AquaEditorPaneUI(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java index 90b02fb6dad..feeec997ea4 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -113,7 +113,7 @@ import sun.swing.SwingUtilities2; -public class AquaFileChooserUI extends FileChooserUI { +public final class AquaFileChooserUI extends FileChooserUI { /* FileView icons */ protected Icon directoryIcon = null; protected Icon fileIcon = null; @@ -204,6 +204,7 @@ public AquaFileChooserUI(final JFileChooser filechooser) { super(); } + @Override public void installUI(final JComponent c) { accessoryPanel = new JPanel(new BorderLayout()); filechooser = (JFileChooser)c; @@ -217,6 +218,7 @@ public void installUI(final JComponent c) { AquaUtils.enforceComponentOrientation(filechooser, ComponentOrientation.getOrientation(Locale.getDefault())); } + @Override public void uninstallUI(final JComponent c) { uninstallListeners(filechooser); uninstallComponents(filechooser); @@ -564,11 +566,13 @@ public void setDirectoryName(final String dirname) { // PENDING(jeff) - set the name in the directory combobox } + @Override public void rescanCurrentDirectory(final JFileChooser fc) { getModel().invalidateFileCache(); getModel().validateFileCache(); } + @Override public void ensureFileIsVisible(final JFileChooser fc, final File f) { if (f == null) { fFileList.requestFocusInWindow(); @@ -609,6 +613,7 @@ public String getApproveButtonToolTipText(final JFileChooser fc) { return fSubPanel.getApproveButtonToolTipText(fc); } + @Override public String getApproveButtonText(final JFileChooser fc) { return fSubPanel.getApproveButtonText(fc); } @@ -642,7 +647,8 @@ public ListSelectionListener createListSelectionListener(final JFileChooser fc) return new SelectionListener(); } - protected class SelectionListener implements ListSelectionListener { + protected final class SelectionListener implements ListSelectionListener { + @Override public void valueChanged(final ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; @@ -689,12 +695,14 @@ public void valueChanged(final ListSelectionEvent e) { // When the Save textfield has the focus, the button should say "Save" // Otherwise, it depends on the list selection - protected class SaveTextFocusListener implements FocusListener { + protected final class SaveTextFocusListener implements FocusListener { + @Override public void focusGained(final FocusEvent e) { updateButtonState(getFileChooser()); } // Do nothing, we might be losing focus due to window deactivation + @Override public void focusLost(final FocusEvent e) { } @@ -702,15 +710,18 @@ public void focusLost(final FocusEvent e) { // When the Save textfield is empty and the button says "Save", it should be disabled // Otherwise, it depends on the list selection - protected class SaveTextDocumentListener implements DocumentListener { + protected final class SaveTextDocumentListener implements DocumentListener { + @Override public void insertUpdate(final DocumentEvent e) { textChanged(); } + @Override public void removeUpdate(final DocumentEvent e) { textChanged(); } + @Override public void changedUpdate(final DocumentEvent e) { } @@ -734,13 +745,14 @@ protected boolean openDirectory(final File f) { } // From Basic - protected class DoubleClickListener extends MouseAdapter { + protected final class DoubleClickListener extends MouseAdapter { JTableExtension list; public DoubleClickListener(final JTableExtension list) { this.list = list; } + @Override public void mouseClicked(final MouseEvent e) { if (e.getClickCount() != 2) return; @@ -764,19 +776,23 @@ protected MouseListener createDoubleClickListener(final JFileChooser fc, final J } // listens for drag events onto the JFileChooser and sets the selected file or directory - class DnDHandler extends DropTargetAdapter { + final class DnDHandler extends DropTargetAdapter { + @Override public void dragEnter(final DropTargetDragEvent dtde) { tryToAcceptDrag(dtde); } + @Override public void dragOver(final DropTargetDragEvent dtde) { tryToAcceptDrag(dtde); } + @Override public void dropActionChanged(final DropTargetDragEvent dtde) { tryToAcceptDrag(dtde); } + @Override public void drop(final DropTargetDropEvent dtde) { if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { handleFileDropEvent(dtde); @@ -884,10 +900,12 @@ public void run() { /** * Returns the default accept all file filter */ + @Override public FileFilter getAcceptAllFileFilter(final JFileChooser fc) { return acceptAllFileFilter; } + @Override public FileView getFileView(final JFileChooser fc) { return fileView; } @@ -895,6 +913,7 @@ public FileView getFileView(final JFileChooser fc) { /** * Returns the title of this dialog */ + @Override public String getDialogTitle(final JFileChooser fc) { if (fc.getDialogTitle() == null) { if (getFileChooser().getDialogType() == JFileChooser.OPEN_DIALOG) { @@ -938,7 +957,8 @@ boolean textfieldIsValid() { // Action to attach to the file list so we can override the default action // of the table for the return key, which is to select the next line. @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class DefaultButtonAction extends AbstractAction { + protected final class DefaultButtonAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { final JRootPane root = AquaFileChooserUI.this.getFileChooser().getRootPane(); final JFileChooser fc = AquaFileChooserUI.this.getFileChooser(); @@ -956,6 +976,7 @@ public void actionPerformed(final ActionEvent e) { } } + @Override public boolean isEnabled() { return true; } @@ -965,7 +986,7 @@ public boolean isEnabled() { * Creates a new folder. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class NewFolderAction extends AbstractAction { + protected final class NewFolderAction extends AbstractAction { protected NewFolderAction() { super(newFolderAccessibleName); } @@ -992,6 +1013,7 @@ private Object showNewFolderDialog(final Component parentComponent, final Object return pane.getInputValue(); } + @Override public void actionPerformed(final ActionEvent e) { final JFileChooser fc = getFileChooser(); final File currentDirectory = fc.getCurrentDirectory(); @@ -1028,7 +1050,8 @@ public void actionPerformed(final ActionEvent e) { * Responds to an Open, Save, or Choose request */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class ApproveSelectionAction extends AbstractAction { + protected final class ApproveSelectionAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { fSubPanel.approveSelection(getFileChooser()); } @@ -1038,7 +1061,8 @@ public void actionPerformed(final ActionEvent e) { * Responds to an OpenDirectory request */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class OpenSelectionAction extends AbstractAction { + protected final class OpenSelectionAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { final int index = fFileList.getSelectedRow(); if (index >= 0) { @@ -1052,11 +1076,13 @@ public void actionPerformed(final ActionEvent e) { * Responds to a cancel request. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class CancelSelectionAction extends AbstractAction { + protected final class CancelSelectionAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { getFileChooser().cancelSelection(); } + @Override public boolean isEnabled() { return getFileChooser().isEnabled(); } @@ -1066,7 +1092,8 @@ public boolean isEnabled() { * Rescans the files in the current directory */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class UpdateAction extends AbstractAction { + protected final class UpdateAction extends AbstractAction { + @Override public void actionPerformed(final ActionEvent e) { final JFileChooser fc = getFileChooser(); fc.setCurrentDirectory(fc.getFileSystemView().createFileObject(getDirectoryName())); @@ -1077,14 +1104,16 @@ public void actionPerformed(final ActionEvent e) { // ***************************************** // ***** default AcceptAll file filter ***** // ***************************************** - private static class AcceptAllFileFilter extends FileFilter { + private static final class AcceptAllFileFilter extends FileFilter { public AcceptAllFileFilter() { } + @Override public boolean accept(final File f) { return true; } + @Override public String getDescription() { return UIManager.getString("FileChooser.acceptAllFileFilterText"); } @@ -1101,6 +1130,7 @@ public MacFCTableCellRenderer(final Font f) { setIconTextGap(10); } + @Override public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, final boolean cellHasFocus, final int index, final int col) { super.getTableCellRendererComponent(list, value, isSelected, false, index, col); // No focus border, thanks fIsSelected = isSelected; @@ -1115,6 +1145,7 @@ protected String layoutCL(final JLabel label, final FontMetrics fontMetrics, fin return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon, label.getVerticalAlignment(), label.getHorizontalAlignment(), label.getVerticalTextPosition(), label.getHorizontalTextPosition(), viewR, iconR, textR, label.getIconTextGap()); } + @Override protected void paintComponent(final Graphics g) { final String text = getText(); Icon icon = getIcon(); @@ -1173,11 +1204,12 @@ protected void paintComponent(final Graphics g) { } @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class FileRenderer extends MacFCTableCellRenderer { + protected final class FileRenderer extends MacFCTableCellRenderer { public FileRenderer(final Font f) { super(f); } + @Override public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, @@ -1200,11 +1232,12 @@ public Component getTableCellRendererComponent(final JTable list, } @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class DateRenderer extends MacFCTableCellRenderer { + protected final class DateRenderer extends MacFCTableCellRenderer { public DateRenderer(final Font f) { super(f); } + @Override public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, @@ -1278,7 +1311,7 @@ protected DirectoryComboBoxModel createDirectoryComboBoxModel(final JFileChooser * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { + protected final class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { Vector fDirectories = new Vector(); int topIndex = -1; int fPathCount = 0; @@ -1340,19 +1373,23 @@ void addItem(final File directory) { // dump(); } + @Override public void setSelectedItem(final Object selectedDirectory) { this.fSelectedDirectory = (File)selectedDirectory; fireContentsChanged(this, -1, -1); } + @Override public Object getSelectedItem() { return fSelectedDirectory; } + @Override public int getSize() { return fDirectories.size(); } + @Override public File getElementAt(final int index) { return fDirectories.elementAt(index); } @@ -1386,7 +1423,7 @@ protected FilterComboBoxModel createFilterComboBoxModel() { * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, + protected final class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { protected FileFilter[] filters; Object oldFileFilter = getFileChooser().getFileFilter(); @@ -1396,6 +1433,7 @@ protected FilterComboBoxModel() { filters = getFileChooser().getChoosableFileFilters(); } + @Override public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { @@ -1406,6 +1444,7 @@ public void propertyChange(PropertyChangeEvent e) { } } + @Override public void setSelectedItem(Object filter) { if (filter != null && !isSelectedFileFilterInModel(filter)) { oldFileFilter = filter; @@ -1418,6 +1457,7 @@ private boolean isSelectedFileFilterInModel(Object filter) { return Objects.equals(filter, oldFileFilter); } + @Override public Object getSelectedItem() { // Ensure that the current filter is in the list. // NOTE: we shouldn't have to do this, since JFileChooser adds @@ -1439,6 +1479,7 @@ public Object getSelectedItem() { return getFileChooser().getFileFilter(); } + @Override public int getSize() { if(filters != null) { return filters.length; @@ -1447,6 +1488,7 @@ public int getSize() { } } + @Override public FileFilter getElementAt(int index) { if(index > getSize() - 1) { // This shouldn't happen. Try to recover gracefully. @@ -1468,11 +1510,12 @@ private boolean containsFileFilter(Object fileFilter) { * Acts when FilterComboBox has changed the selected item. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class FilterComboBoxAction extends AbstractAction { + protected final class FilterComboBoxAction extends AbstractAction { protected FilterComboBoxAction() { super("FilterComboBoxAction"); } + @Override public void actionPerformed(final ActionEvent e) { Object selectedFilter = filterComboBox.getSelectedItem(); if (!containsFileFilter(selectedFilter)) { @@ -1485,11 +1528,12 @@ public void actionPerformed(final ActionEvent e) { * Acts when DirectoryComboBox has changed the selected item. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class DirectoryComboBoxAction extends AbstractAction { + protected final class DirectoryComboBoxAction extends AbstractAction { protected DirectoryComboBoxAction() { super("DirectoryComboBoxAction"); } + @Override public void actionPerformed(final ActionEvent e) { getFileChooser().setCurrentDirectory((File)directoryComboBox.getSelectedItem()); } @@ -1497,7 +1541,7 @@ public void actionPerformed(final ActionEvent e) { // Sorting Table operations @SuppressWarnings("serial") // Superclass is not serializable across versions - class JSortingTableHeader extends JTableHeader { + final class JSortingTableHeader extends JTableHeader { public JSortingTableHeader(final TableColumnModel cm) { super(cm); setReorderingAllowed(true); // This causes mousePress to call setDraggedColumn @@ -1507,6 +1551,7 @@ public JSortingTableHeader(final TableColumnModel cm) { final boolean[] fSortAscending = {true, true}; // Instead of dragging, it selects which one to sort by + @Override public void setDraggedColumn(final TableColumn aColumn) { if (!getFileChooser().isEnabled()) { return; @@ -1526,10 +1571,12 @@ public void setDraggedColumn(final TableColumn aColumn) { } // This stops mouseDrags from moving the column + @Override public TableColumn getDraggedColumn() { return null; } + @Override protected TableCellRenderer createDefaultRenderer() { final DefaultTableCellRenderer label = new AquaTableCellRenderer(); label.setHorizontalAlignment(SwingConstants.LEFT); @@ -1537,7 +1584,8 @@ protected TableCellRenderer createDefaultRenderer() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - class AquaTableCellRenderer extends DefaultTableCellRenderer implements UIResource { + final class AquaTableCellRenderer extends DefaultTableCellRenderer implements UIResource { + @Override public Component getTableCellRendererComponent(final JTable localTable, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { if (localTable != null) { final JTableHeader header = localTable.getTableHeader(); @@ -1841,7 +1889,8 @@ public void uninstallComponents(final JFileChooser fc) { // Consistent with the AppKit NSSavePanel, clicks on a file (not a directory) should populate the text field // with that file's display name. - protected class FileListMouseListener extends MouseAdapter { + protected final class FileListMouseListener extends MouseAdapter { + @Override public void mouseClicked(final MouseEvent e) { final Point p = e.getPoint(); final int row = fFileList.rowAtPoint(p); @@ -1917,9 +1966,10 @@ protected JPanel createList(final JFileChooser fc) { } @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class ScrollPaneCornerPanel extends JPanel { + protected final class ScrollPaneCornerPanel extends JPanel { final Border border = UIManager.getBorder("TableHeader.cellBorder"); + @Override protected void paintComponent(final Graphics g) { border.paintBorder(this, g, 0, 0, getWidth() + 1, getHeight()); } @@ -2095,6 +2145,7 @@ String getCancelButtonToolTipText(final JFileChooser fc) { List - everything is enabled */ class CustomFilePanel extends FCSubpanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { fTextfieldPanel.setVisible(true); // do we really want one in multi-select? It's confusing fOpenButton.setVisible(false); @@ -2113,6 +2164,7 @@ boolean inOpenDirectoryMode(final JFileChooser fc, final File f) { } // The approve button is overloaded to mean OpenDirectory or Save + @Override void approveSelection(final JFileChooser fc) { File f = getFirstSelectedItem(); if (inOpenDirectoryMode(fc, f)) { @@ -2131,6 +2183,7 @@ void approveSelection(final JFileChooser fc) { // The approve button should be enabled // - if something in the list can be opened // - if the textfield has something in it + @Override void updateButtonState(final JFileChooser fc, final File f) { boolean enabled = true; if (!inOpenDirectoryMode(fc, f)) { @@ -2146,11 +2199,13 @@ void updateButtonState(final JFileChooser fc, final File f) { } // everything's enabled, because we don't know what they're doing with them + @Override boolean isSelectableInList(final JFileChooser fc, final File f) { if (f == null) return false; return fc.accept(f); } + @Override String getApproveButtonToolTipText(final JFileChooser fc) { // The approve Button should have openDirectoryButtonToolTipText when the selection is a folder... if (inOpenDirectoryMode(fc, getFirstSelectedItem())) return openDirectoryButtonToolTipText; @@ -2170,7 +2225,8 @@ Has NewFolder button (by text field) List is always SINGLE_SELECT */ // Subclasses CustomFilePanel because they look alike and have some common behavior - class SaveFilePanel extends CustomFilePanel { + final class SaveFilePanel extends CustomFilePanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { fTextfieldPanel.setVisible(true); fOpenButton.setVisible(false); @@ -2179,11 +2235,13 @@ void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { // only traversables are enabled, regardless of mode // because all you can do is select the next folder to open + @Override boolean isSelectableInList(final JFileChooser fc, final File f) { return fc.accept(f) && fc.isTraversable(f); } // The approve button means 'approve the file name in the text field.' + @Override void approveSelection(final JFileChooser fc) { final File f = makeFile(fc, getFileName()); if (f != null) { @@ -2195,26 +2253,31 @@ void approveSelection(final JFileChooser fc) { } // The approve button should be enabled if the textfield has something in it + @Override void updateButtonState(final JFileChooser fc, final File f) { final boolean enabled = textfieldIsValid(); getApproveButton(fc).setEnabled(enabled); } + @Override String getApproveButtonText(final JFileChooser fc) { // Get the custom text, or fallback to "Save" return this.getApproveButtonText(fc, saveButtonText); } + @Override int getApproveButtonMnemonic(final JFileChooser fc) { return saveButtonMnemonic; } + @Override String getApproveButtonToolTipText(final JFileChooser fc) { // The approve Button should have openDirectoryButtonToolTipText when the selection is a folder... if (inOpenDirectoryMode(fc, getFirstSelectedItem())) return openDirectoryButtonToolTipText; return this.getApproveButtonToolTipText(fc, saveButtonToolTipText); } + @Override String getCancelButtonToolTipText(final JFileChooser fc) { return cancelSaveButtonToolTipText; } @@ -2229,7 +2292,8 @@ String getCancelButtonToolTipText(final JFileChooser fc) { No NewFolder button List - all items are enabled */ - class OpenFilePanel extends FCSubpanel { + final class OpenFilePanel extends FCSubpanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { fTextfieldPanel.setVisible(false); fOpenButton.setVisible(false); @@ -2242,10 +2306,12 @@ boolean inOpenDirectoryMode(final JFileChooser fc, final File f) { } // Default to the list + @Override JComponent getFocusComponent(final JFileChooser fc) { return fFileList; } + @Override void updateButtonState(final JFileChooser fc, final File f) { // Button is disabled if there's nothing selected final boolean enabled = (f != null) && !fc.isTraversable(f); @@ -2253,23 +2319,28 @@ void updateButtonState(final JFileChooser fc, final File f) { } // all items are enabled + @Override boolean isSelectableInList(final JFileChooser fc, final File f) { return f != null && fc.accept(f); } + @Override String getApproveButtonText(final JFileChooser fc) { // Get the custom text, or fallback to "Open" return this.getApproveButtonText(fc, openButtonText); } + @Override int getApproveButtonMnemonic(final JFileChooser fc) { return openButtonMnemonic; } + @Override String getApproveButtonToolTipText(final JFileChooser fc) { return this.getApproveButtonToolTipText(fc, openButtonToolTipText); } + @Override String getCancelButtonToolTipText(final JFileChooser fc) { return cancelOpenButtonToolTipText; } @@ -2277,14 +2348,17 @@ String getCancelButtonToolTipText(final JFileChooser fc) { // used by open and custom panels for Directory only or files and directories abstract class DirOrAnyPanel extends FCSubpanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { fOpenButton.setVisible(false); } + @Override JButton getDefaultButton(final JFileChooser fc) { return getApproveButton(fc); } + @Override void updateButtonState(final JFileChooser fc, final File f) { // Button is disabled if there's nothing selected // Approve button is handled by the subclasses @@ -2307,7 +2381,8 @@ void updateButtonState(final JFileChooser fc, final File f) { No text field List - files are disabled in DIRECTORIES_ONLY */ - class OpenDirOrAnyPanel extends DirOrAnyPanel { + final class OpenDirOrAnyPanel extends DirOrAnyPanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { super.installPanel(fc, controlButtonsAreShown); fTextfieldPanel.setVisible(false); @@ -2315,14 +2390,17 @@ void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { } // Default to the list + @Override JComponent getFocusComponent(final JFileChooser fc) { return fFileList; } + @Override int getApproveButtonMnemonic(final JFileChooser fc) { return chooseButtonMnemonic; } + @Override String getApproveButtonToolTipText(final JFileChooser fc) { String fallbackText; if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) fallbackText = chooseFolderButtonToolTipText; @@ -2330,6 +2408,7 @@ String getApproveButtonToolTipText(final JFileChooser fc) { return this.getApproveButtonToolTipText(fc, fallbackText); } + @Override void updateButtonState(final JFileChooser fc, final File f) { // Button is disabled if there's nothing selected getApproveButton(fc).setEnabled(f != null); @@ -2347,7 +2426,8 @@ void updateButtonState(final JFileChooser fc, final File f) { Has NewFolder button (by text field) List - files are disabled in DIRECTORIES_ONLY */ - class CustomDirOrAnyPanel extends DirOrAnyPanel { + final class CustomDirOrAnyPanel extends DirOrAnyPanel { + @Override void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { super.installPanel(fc, controlButtonsAreShown); fTextfieldPanel.setVisible(true); @@ -2355,6 +2435,7 @@ void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) { } // If there's text, make a file and select it + @Override void approveSelection(final JFileChooser fc) { final File f = makeFile(fc, getFileName()); if (f != null) { @@ -2365,6 +2446,7 @@ void approveSelection(final JFileChooser fc) { getFileChooser().approveSelection(); } + @Override void updateButtonState(final JFileChooser fc, final File f) { // Button is disabled if there's nothing selected getApproveButton(fc).setEnabled(f != null || textfieldIsValid()); @@ -2374,7 +2456,7 @@ void updateButtonState(final JFileChooser fc, final File f) { // See FileRenderer - documents in Save dialogs draw disabled, so they shouldn't be selected @SuppressWarnings("serial") // Superclass is not serializable across versions - class MacListSelectionModel extends DefaultListSelectionModel { + final class MacListSelectionModel extends DefaultListSelectionModel { AquaFileSystemModel fModel; MacListSelectionModel(final AquaFileSystemModel model) { @@ -2427,14 +2509,17 @@ void verifySelectionInterval(int index0, int index1, boolean isSetSelection) { } while (start <= index1); } + @Override public void setAnchorSelectionIndex(final int anchorIndex) { if (isSelectableInListIndex(anchorIndex)) super.setAnchorSelectionIndex(anchorIndex); } + @Override public void setLeadSelectionIndex(final int leadIndex) { if (isSelectableInListIndex(leadIndex)) super.setLeadSelectionIndex(leadIndex); } + @Override public void setSelectionInterval(final int index0, final int index1) { if (index0 == -1 || index1 == -1) { return; } @@ -2445,6 +2530,7 @@ public void setSelectionInterval(final int index0, final int index1) { } } + @Override public void addSelectionInterval(final int index0, final int index1) { if (index0 == -1 || index1 == -1) { return; } @@ -2465,7 +2551,7 @@ public void addSelectionInterval(final int index0, final int index1) { // Convenience, to translate from the JList directory view to the Mac-style JTable // & minimize diffs between this and BasicFileChooserUI @SuppressWarnings("serial") // Superclass is not serializable across versions - static class JTableExtension extends JTable { + static final class JTableExtension extends JTable { public void setSelectedIndex(final int index) { getSelectionModel().setSelectionInterval(index, index); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java index 80ffc080f99..1c0b01e0a36 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java @@ -41,7 +41,7 @@ * Some of it came from BasicDirectoryModel */ @SuppressWarnings("serial") // Superclass is not serializable across versions -class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeListener { +final class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeListener { private final JTable fFileList; private FilesLoader filesLoader = null; private Vector files = null; @@ -75,6 +75,7 @@ void updateSelectionMode() { fFileList.setSelectionMode(b ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION); } + @Override public void propertyChange(final PropertyChangeEvent e) { final String prop = e.getPropertyName(); if (prop == JFileChooser.DIRECTORY_CHANGED_PROPERTY || prop == JFileChooser.FILE_VIEW_CHANGED_PROPERTY || prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY || prop == JFileChooser.FILE_HIDING_CHANGED_PROPERTY) { @@ -186,19 +187,23 @@ public void validateFileCache() { filesLoader = new FilesLoader(currentDirectory, fetchID); } + @Override public int getColumnCount() { return 2; } + @Override public String getColumnName(final int col) { return fColumnNames[col]; } + @Override public Class getColumnClass(final int col) { if (col == 0) return File.class; return Date.class; } + @Override public int getRowCount() { synchronized(fileCacheLock) { if (fileCache != null) { @@ -238,6 +243,7 @@ public Object getElementAt(final int row) { // AbstractTableModel interface + @Override public Object getValueAt(int row, final int col) { if (row < 0 || col < 0) return null; final boolean isAscending = fSortNames ? fSortAscending[0] : fSortAscending[1]; @@ -338,7 +344,8 @@ private void swap(final Vector a, final int i, final int j) { protected abstract boolean lt(SortableFile a, SortableFile b); } - static class QuickSortNames extends QuickSort { + static final class QuickSortNames extends QuickSort { + @Override protected boolean lt(final SortableFile a, final SortableFile b) { final String aLower = a.fName.toLowerCase(); final String bLower = b.fName.toLowerCase(); @@ -346,14 +353,15 @@ protected boolean lt(final SortableFile a, final SortableFile b) { } } - static class QuickSortDates extends QuickSort { + static final class QuickSortDates extends QuickSort { + @Override protected boolean lt(final SortableFile a, final SortableFile b) { return a.fDateValue < b.fDateValue; } } // for speed in sorting, displaying - static class SortableFile /* extends FileView */{ + static final class SortableFile /* extends FileView */{ File fFile; String fName; long fDateValue; @@ -371,6 +379,7 @@ public Object getValueAt(final int col) { return fDate; } + @Override public boolean equals(final Object other) { final SortableFile otherFile = (SortableFile)other; return otherFile.fFile.equals(fFile); @@ -382,7 +391,7 @@ public int hashCode() { } } - class FilesLoader implements Runnable { + final class FilesLoader implements Runnable { ArrayList queuedTasks = new ArrayList<>(); File currentDirectory = null; int fid; @@ -449,7 +458,7 @@ public void cancelRunnables(final Vector runnables) { } } - class DoChangeContents implements Runnable { + final class DoChangeContents implements Runnable { private Vector contentFiles; private boolean doFire = true; private final Object lock = new Object(); @@ -466,6 +475,7 @@ synchronized void cancel() { } } + @Override public void run() { if (fetchID == fid) { synchronized(lock) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java index 653cf49cb55..6a2c9f9466b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java @@ -39,7 +39,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; -class AquaFileView extends FileView { +final class AquaFileView extends FileView { private static final boolean DEBUG = false; private static final int UNINITALIZED_LS_INFO = -1; @@ -97,7 +97,7 @@ protected static String getPathToSharedJDKBundle() { return getNativePathToSharedJDKBundle(); } - static class FileInfo { + static final class FileInfo { final boolean isDirectory; final String absolutePath; byte[] pathBytes; @@ -150,6 +150,7 @@ boolean _applicationIsTraversable() { return fFileChooserUI.fApplicationIsTraversable == AquaFileChooserUI.kOpenAlways; } + @Override public String getName(final File f) { final FileInfo info = getFileInfoFor(f); if (info.displayName != null) return info.displayName; @@ -171,15 +172,18 @@ public String getName(final File f) { return displayName; } + @Override public String getDescription(final File f) { return f.getName(); } + @Override public String getTypeDescription(final File f) { if (f.isDirectory()) return _directoryDescriptionText(); return _fileDescriptionText(); } + @Override public Icon getIcon(final File f) { final FileInfo info = getFileInfoFor(f); if (info.icon != null) return info.icon; @@ -210,6 +214,7 @@ public Icon getIcon(final File f) { } // aliases are traversable though they aren't directories + @Override public Boolean isTraversable(final File f) { if (f.isDirectory()) { // Doesn't matter if it's a package or app, because they're traversable diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFocus.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFocus.java index acdd441a947..c8ce8dd058b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFocus.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFocus.java @@ -39,7 +39,7 @@ import com.apple.laf.AquaUtils.Painter; -public class AquaFocus { +public final class AquaFocus { interface Drawable { public void draw(final Graphics2D sg2d); } @@ -109,7 +109,7 @@ public void draw(SunGraphics2D sg2d) { } */ - static class FocusedIcon extends AquaUtils.ShadowBorder implements Icon { + static final class FocusedIcon extends AquaUtils.ShadowBorder implements Icon { final Icon icon; final int slack; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFocusHandler.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFocusHandler.java index 1786d85cd93..a245ae35d8c 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFocusHandler.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFocusHandler.java @@ -55,6 +55,7 @@ public class AquaFocusHandler implements FocusListener, PropertyChangeListener { protected static final String FRAME_ACTIVE_PROPERTY = "Frame.active"; + @Override public void focusGained(final FocusEvent ev) { // If we gained focus and it wasn't due to a previous temporary focus loss // or the frame became active again, then repaint the border on the component. @@ -65,6 +66,7 @@ public void focusGained(final FocusEvent ev) { wasTemporary = false; } + @Override public void focusLost(final FocusEvent ev) { wasTemporary = ev.isTemporary(); @@ -74,6 +76,7 @@ public void focusLost(final FocusEvent ev) { } } + @Override public void propertyChange(final PropertyChangeEvent ev) { if (!FRAME_ACTIVE_PROPERTY.equals(ev.getPropertyName())) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFonts.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFonts.java index 1e9c778695b..21886f9709f 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFonts.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFonts.java @@ -35,7 +35,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; @SuppressWarnings("serial") // JDK implementation class -public class AquaFonts { +public final class AquaFonts { private static final String MAC_DEFAULT_FONT_NAME = "Lucida Grande"; private static final RecyclableSingleton lucida9Pt = new RecyclableSingleton() { @@ -131,26 +131,32 @@ public DerivedUIResourceFont(final String name, final int style, final int size) super(name, style, size); } + @Override public Font deriveFont(final AffineTransform trans) { return new DerivedUIResourceFont(super.deriveFont(trans)); } + @Override public Font deriveFont(final float derivedSize) { return new DerivedUIResourceFont(super.deriveFont(derivedSize)); } + @Override public Font deriveFont(final int derivedStyle) { return new DerivedUIResourceFont(super.deriveFont(derivedStyle)); } + @Override public Font deriveFont(final int derivedStyle, final AffineTransform trans) { return new DerivedUIResourceFont(super.deriveFont(derivedStyle, trans)); } + @Override public Font deriveFont(final int derivedStyle, final float derivedSize) { return new DerivedUIResourceFont(super.deriveFont(derivedStyle, derivedSize)); } + @Override public Font deriveFont(final Map attributes) { return new DerivedUIResourceFont(super.deriveFont(attributes)); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaGroupBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaGroupBorder.java index 59a437d4aaf..d85025a3b77 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaGroupBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaGroupBorder.java @@ -55,6 +55,7 @@ protected AquaGroupBorder(final SizeVariant sizeVariant) { painter.state.set(Widget.FRAME_GROUP_BOX); } + @Override public void paintBorder(final Component c, final Graphics g, int x, int y, int width, int height) { // sg2d.setColor(Color.MAGENTA); // sg2d.drawRect(x, y, width - 1, height - 1); @@ -70,19 +71,19 @@ public void paintBorder(final Component c, final Graphics g, int x, int y, int w // sg2d.drawRect(x, y, width, height); } - protected static class TabbedPane extends AquaGroupBorder { + protected static final class TabbedPane extends AquaGroupBorder { public TabbedPane() { super(new SizeVariant().alterMargins(8, 12, 8, 12).alterInsets(5, 5, 7, 5)); } } - protected static class Titled extends AquaGroupBorder { + protected static final class Titled extends AquaGroupBorder { public Titled() { super(new SizeVariant().alterMargins(16, 20, 16, 20).alterInsets(16, 5, 4, 5)); } } - protected static class Titleless extends AquaGroupBorder { + protected static final class Titleless extends AquaGroupBorder { public Titleless() { super(new SizeVariant().alterMargins(8, 12, 8, 12).alterInsets(3, 5, 1, 5)); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaHighlighter.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaHighlighter.java index 7b1a1c8d507..cdb36932893 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaHighlighter.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaHighlighter.java @@ -36,7 +36,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; -public class AquaHighlighter extends DefaultHighlighter implements UIResource { +public final class AquaHighlighter extends DefaultHighlighter implements UIResource { private static final RecyclableSingleton instance = new RecyclableSingleton() { protected LayerPainter getInstance() { return new AquaHighlightPainter(null); @@ -47,7 +47,7 @@ protected static LayeredHighlighter.LayerPainter getInstance() { return instance.get(); } - public static class AquaHighlightPainter extends DefaultHighlightPainter { + public static final class AquaHighlightPainter extends DefaultHighlightPainter { Color selectionColor; Color disabledSelectionColor; @@ -55,6 +55,7 @@ public AquaHighlightPainter(final Color c) { super(c); } + @Override public Color getColor() { return selectionColor == null ? super.getColor() : selectionColor; } @@ -82,11 +83,13 @@ void setColor(final JTextComponent c) { } } + @Override public void paint(final Graphics g, final int offs0, final int offs1, final Shape bounds, final JTextComponent c) { setColor(c); super.paint(g, offs0, offs1, bounds, c); } + @Override public Shape paintLayer(final Graphics g, final int offs0, final int offs1, final Shape bounds, final JTextComponent c, final View view) { setColor(c); return super.paintLayer(g, offs0, offs1, bounds, c, view); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java index 936fe567c66..07287402b97 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java @@ -39,7 +39,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import sun.lwawt.macosx.CImage; -public class AquaIcon { +public final class AquaIcon { interface InvertableIcon extends Icon { public Icon getInvertedIcon(); } @@ -77,6 +77,7 @@ public interface JRSUIControlSpec { abstract static class JRSUIIcon implements Icon, UIResource { protected final AquaPainter painter = AquaPainter.create(JRSUIState.getInstance()); + @Override public void paintIcon(final Component c, final Graphics g, final int x, final int y) { painter.paint(g, c, x, y, getIconWidth(), getIconHeight()); } @@ -94,14 +95,17 @@ public DynamicallySizingJRSUIIcon(final SizeDescriptor sizeDescriptor) { public abstract void initJRSUIState(); + @Override public int getIconHeight() { return sizeVariant == null ? 0 : sizeVariant.h; } + @Override public int getIconWidth() { return sizeVariant == null ? 0 : sizeVariant.w; } + @Override public void paintIcon(final Component c, final Graphics g, final int x, final int y) { final Size size = c instanceof JComponent ? AquaUtilControlSize.getUserSizeFrom((JComponent)c) : Size.REGULAR; sizeVariant = sizeDescriptor.get(size); @@ -142,6 +146,7 @@ public boolean hasIconRef() { return getImage() != null; } + @Override public void paintIcon(final Component c, Graphics g, final int x, final int y) { g = g.create(); @@ -158,10 +163,12 @@ public void paintIcon(final Component c, Graphics g, final int x, final int y) { g.dispose(); } + @Override public int getIconWidth() { return width; } + @Override public int getIconHeight() { return height; } @@ -214,7 +221,7 @@ public int getIconHeight() { } } - static class FileIcon extends CachingScalingIcon { + static final class FileIcon extends CachingScalingIcon { final File file; public FileIcon(final File file, final int width, final int height) { @@ -226,12 +233,13 @@ public FileIcon(final File file) { this(file, 16, 16); } + @Override Image createImage() { return CImage.createImageOfFile(file.getAbsolutePath(), getIconWidth(), getIconHeight()); } } - static class SystemIconSingleton extends RecyclableSingleton { + static final class SystemIconSingleton extends RecyclableSingleton { final String selector; public SystemIconSingleton(String selector) { @@ -244,7 +252,7 @@ protected SystemIcon getInstance() { } } - static class SystemIconUIResourceSingleton extends RecyclableSingleton { + static final class SystemIconUIResourceSingleton extends RecyclableSingleton { final String selector; public SystemIconUIResourceSingleton(String selector) { @@ -257,7 +265,7 @@ protected IconUIResource getInstance() { } } - static class SystemIcon extends CachingScalingIcon { + static final class SystemIcon extends CachingScalingIcon { private static final SystemIconUIResourceSingleton folderIcon = new SystemIconUIResourceSingleton("fldr"); static IconUIResource getFolderIconUIResource() { return folderIcon.get(); } @@ -299,6 +307,7 @@ public SystemIcon(final String iconSelector) { this(iconSelector, 16, 16); } + @Override Image createImage() { return CImage.createSystemImageFromSelector( selector, getIconWidth(), getIconHeight()); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java index 2d6d965134c..679632db107 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java @@ -50,7 +50,7 @@ import sun.lwawt.macosx.CImage; import sun.swing.ImageIconUIResource; -public class AquaImageFactory { +public final class AquaImageFactory { public static IconUIResource getConfirmImageIcon() { // public, because UIDefaults.ProxyLazyValue uses reflection to get this value @@ -193,7 +193,7 @@ public void initIconPainter(final AquaPainter painter) { }, 20, 20); } - static class NamedImageSingleton extends RecyclableSingleton { + static final class NamedImageSingleton extends RecyclableSingleton { final String namedImage; NamedImageSingleton(final String namedImage) { @@ -206,7 +206,7 @@ protected Image getInstance() { } } - static class IconUIResourceSingleton extends RecyclableSingleton { + static final class IconUIResourceSingleton extends RecyclableSingleton { final NamedImageSingleton holder; public IconUIResourceSingleton(final NamedImageSingleton holder) { @@ -220,7 +220,7 @@ protected IconUIResource getInstance() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - static class InvertableImageIcon extends ImageIcon implements InvertableIcon, UIResource { + static final class InvertableImageIcon extends ImageIcon implements InvertableIcon, UIResource { Icon invertedImage; private Icon disabledIcon; public InvertableImageIcon(final Image image) { @@ -296,7 +296,7 @@ private static Image getNSIcon(String imageName) { return icon; } - public static class NineSliceMetrics { + public static final class NineSliceMetrics { public final int wCut, eCut, nCut, sCut; public final int minW, minH; public final boolean showMiddle, stretchH, stretchV; @@ -320,7 +320,7 @@ public NineSliceMetrics(final int minWidth, final int minHeight, final int westC * A "paintable" which holds nine images, which represent a sliced up initial * image that can be stretched from its middles. */ - public static class SlicedImageControl { + public static final class SlicedImageControl { final BufferedImage NW, N, NE; final BufferedImage W, C, E; final BufferedImage SW, S, SE; @@ -466,6 +466,7 @@ public SystemColorProxy(final Color color) { this.color = color; } + @Override public int getRGB() { return color.getRGB(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java index 74697ed417b..7d988912829 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java @@ -42,7 +42,7 @@ import com.apple.laf.AquaInternalFrameBorderMetrics; import java.awt.geom.AffineTransform; -public class AquaInternalFrameBorder implements Border, UIResource { +public final class AquaInternalFrameBorder implements Border, UIResource { private static final int kCloseButton = 0; private static final int kIconButton = 1; private static final int kGrowButton = 2; @@ -142,11 +142,13 @@ protected void setInBounds(final int x, final int y, final int w, final int h) { } // Border interface + @Override public boolean isBorderOpaque() { return false; } // Border interface + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) { // For expanded InternalFrames, the frame & component are the same object paintBorder((JInternalFrame)c, c, g, x, y, w, h); @@ -412,6 +414,7 @@ boolean isDirty(final JInternalFrame frame) { } // Border interface + @Override public Insets getBorderInsets(final Component c) { if (fBorderInsets == null) fBorderInsets = new Insets(0, 0, 0, 0); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java index c2ce10b0e4a..388710e5416 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java @@ -73,6 +73,7 @@ public class AquaInternalFrameManager extends DefaultDesktopManager { */ Vector fChildFrames = new Vector(1); + @Override public void closeFrame(final JInternalFrame f) { if (f == fCurrentFrame) { activateNextFrame(); @@ -81,6 +82,7 @@ public void closeFrame(final JInternalFrame f) { super.closeFrame(f); } + @Override public void deiconifyFrame(final JInternalFrame f) { JInternalFrame.JDesktopIcon desktopIcon; @@ -96,6 +98,7 @@ void addIcon(final Container c, final JInternalFrame.JDesktopIcon desktopIcon) { } /** Removes the frame from its parent and adds its desktopIcon to the parent. */ + @Override public void iconifyFrame(final JInternalFrame f) { // Same as super except doesn't deactivate it JInternalFrame.JDesktopIcon desktopIcon; @@ -117,6 +120,7 @@ public void iconifyFrame(final JInternalFrame f) { } // WindowsDesktopManager code + @Override public void activateFrame(final JInternalFrame f) { try { if (f != null) super.activateFrame(f); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java index 01c8cac203e..a41cee6ca30 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java @@ -34,7 +34,7 @@ import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicDesktopPaneUI; -public class AquaInternalFramePaneUI extends BasicDesktopPaneUI implements MouseListener { +public final class AquaInternalFramePaneUI extends BasicDesktopPaneUI implements MouseListener { JComponent fDock; DockLayoutManager fLayoutMgr; @@ -43,6 +43,7 @@ public static ComponentUI createUI(final JComponent c) { return new AquaInternalFramePaneUI(); } + @Override public void update(final Graphics g, final JComponent c) { if (c.isOpaque()) { super.update(g, c); @@ -51,6 +52,7 @@ public void update(final Graphics g, final JComponent c) { paint(g, c); } + @Override public void installUI(final JComponent c) { super.installUI(c); fLayoutMgr = new DockLayoutManager(); @@ -59,6 +61,7 @@ public void installUI(final JComponent c) { c.addMouseListener(this); } + @Override public void uninstallUI(final JComponent c) { c.removeMouseListener(this); @@ -74,6 +77,7 @@ public void uninstallUI(final JComponent c) { } // Our superclass hardcodes DefaultDesktopManager - how rude! + @Override protected void installDesktopManager() { if (desktop.getDesktopManager() == null) { desktopManager = new AquaDockingDesktopManager(); @@ -81,6 +85,7 @@ protected void installDesktopManager() { } } + @Override protected void uninstallDesktopManager() { final DesktopManager manager = desktop.getDesktopManager(); if (manager instanceof AquaDockingDesktopManager) { @@ -96,28 +101,33 @@ JComponent getDock() { return fDock; } - class DockLayoutManager implements LayoutManager { + final class DockLayoutManager implements LayoutManager { + @Override public void addLayoutComponent(final String name, final Component comp) { } + @Override public void removeLayoutComponent(final Component comp) { } + @Override public Dimension preferredLayoutSize(final Container parent) { return parent.getSize(); } + @Override public Dimension minimumLayoutSize(final Container parent) { return parent.getSize(); } + @Override public void layoutContainer(final Container parent) { if (fDock != null) ((Dock)fDock).updateSize(); } } @SuppressWarnings("serial") // Superclass is not serializable across versions - class Dock extends JComponent implements Border { + final class Dock extends JComponent implements Border { static final int DOCK_EDGE_SLACK = 8; Dock(final JComponent parent) { @@ -126,6 +136,7 @@ class Dock extends JComponent implements Border { setVisible(false); } + @Override public void removeNotify() { fDock = null; super.removeNotify(); @@ -136,6 +147,7 @@ void updateSize() { setBounds((getParent().getWidth() - d.width) / 2, getParent().getHeight() - d.height, d.width, d.height); } + @Override public Component add(final Component c) { super.add(c); if (!isVisible()) { @@ -147,6 +159,7 @@ public Component add(final Component c) { return c; } + @Override public void remove(final Component c) { super.remove(c); if (getComponentCount() == 0) { @@ -157,14 +170,17 @@ public void remove(final Component c) { } } + @Override public Insets getBorderInsets(final Component c) { return new Insets(DOCK_EDGE_SLACK / 4, DOCK_EDGE_SLACK, 0, DOCK_EDGE_SLACK); } + @Override public boolean isBorderOpaque() { return false; } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) { if (!(g instanceof Graphics2D)) return; final Graphics2D g2d = (Graphics2D)g; @@ -187,7 +203,8 @@ public void paintBorder(final Component c, final Graphics g, final int x, final } @SuppressWarnings("serial") // JDK implementation class - static class AquaDockingDesktopManager extends AquaInternalFrameManager { + static final class AquaDockingDesktopManager extends AquaInternalFrameManager { + @Override public void openFrame(final JInternalFrame f) { final JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); final Container dock = desktopIcon.getParent(); @@ -197,6 +214,7 @@ public void openFrame(final JInternalFrame f) { removeIconFor(f); } + @Override public void deiconifyFrame(final JInternalFrame f) { final JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); final Container dock = desktopIcon.getParent(); @@ -213,6 +231,7 @@ public void deiconifyFrame(final JInternalFrame f) { } catch(final PropertyVetoException pve) { /* do nothing */ } } + @Override public void iconifyFrame(final JInternalFrame f) { final JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); // paint the frame onto the icon before hiding the frame, else the contents won't show @@ -220,12 +239,14 @@ public void iconifyFrame(final JInternalFrame f) { super.iconifyFrame(f); } + @Override void addIcon(final Container c, final JInternalFrame.JDesktopIcon desktopIcon) { final DesktopPaneUI ui = ((JDesktopPane)c).getUI(); ((AquaInternalFramePaneUI)ui).getDock().add(desktopIcon); } } + @Override public void mousePressed(final MouseEvent e) { JInternalFrame selectedFrame = desktop.getSelectedFrame(); if (selectedFrame != null) { @@ -236,8 +257,12 @@ public void mousePressed(final MouseEvent e) { } } + @Override public void mouseReleased(final MouseEvent e) { } + @Override public void mouseClicked(final MouseEvent e) { } + @Override public void mouseEntered(final MouseEvent e) { } + @Override public void mouseExited(final MouseEvent e) { } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java index bdf9809ea68..56829f8abf7 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java @@ -52,7 +52,7 @@ * so be very careful about subclassing so you know you get what you want * */ -public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingConstants { +public final class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingConstants { protected static final String IS_PALETTE_PROPERTY = "JInternalFrame.isPalette"; private static final String FRAME_TYPE = "JInternalFrame.frameType"; private static final String NORMAL_FRAME = "normal"; @@ -177,7 +177,7 @@ public static Icon exportZoomIcon() { return zoomIcon.get(); } - static class AquaInternalFrameButtonIcon extends AquaIcon.JRSUIIcon { + static final class AquaInternalFrameButtonIcon extends AquaIcon.JRSUIIcon { public AquaInternalFrameButtonIcon(final Widget widget) { painter.state.set(widget); } @@ -385,7 +385,7 @@ public void paint(final Graphics g, final JComponent c) { /** * Listens for border adjustments. */ - protected class AquaBorderListener extends MouseInputAdapter { + protected final class AquaBorderListener extends MouseInputAdapter { // _x & _y are the mousePressed location in absolute coordinate system int _x, _y; // __x & __y are the mousePressed location in source view's coordinate system @@ -431,7 +431,6 @@ public void repaintButtons() { } @Override - @SuppressWarnings("removal") public void mouseReleased(final MouseEvent e) { if (didForwardEvent(e)) return; @@ -467,9 +466,6 @@ public void mouseReleased(final MouseEvent e) { ((JFrame)frame.getTopLevelAncestor()).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); ((JFrame)frame.getTopLevelAncestor()).getGlassPane().setVisible(false); - } else if (c instanceof JApplet) { - ((JApplet)c).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - ((JApplet)c).getGlassPane().setVisible(false); } else if (c instanceof JWindow) { ((JWindow)c).getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); ((JWindow)c).getGlassPane().setVisible(false); @@ -701,7 +697,7 @@ static void updateComponentTreeUIActivation(final Component c, final Object acti } } - class PropertyListener implements PropertyChangeListener { + final class PropertyListener implements PropertyChangeListener { @Override public void propertyChange(final PropertyChangeEvent e) { final String name = e.getPropertyName(); @@ -798,7 +794,7 @@ Border getBackgroundShadowBorder() { }; @SuppressWarnings("serial") // Superclass is not serializable across versions - static class CompoundUIBorder extends CompoundBorder implements UIResource { + static final class CompoundUIBorder extends CompoundBorder implements UIResource { public CompoundUIBorder(final Border inside, final Border outside) { super(inside, outside); } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java index f9779afdf47..c6224c63543 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -36,7 +36,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaKeyBindings { +public final class AquaKeyBindings { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaKeyBindings.class); static AquaKeyBindings instance() { return instance.get(); @@ -423,10 +423,14 @@ LateBoundInputMap getTreeInputMap() { "KP_UP", "selectPrevious", "shift UP", "selectPreviousExtendSelection", "shift KP_UP", "selectPreviousExtendSelection", + "shift ctrl UP", "selectPreviousExtendSelection", + "shift ctrl KP_UP", "selectPreviousExtendSelection", "DOWN", "selectNext", "KP_DOWN", "selectNext", "shift DOWN", "selectNextExtendSelection", "shift KP_DOWN", "selectNextExtendSelection", + "shift ctrl DOWN", "selectNextExtendSelection", + "shift ctrl KP_DOWN", "selectNextExtendSelection", "RIGHT", "aquaExpandNode", "KP_RIGHT", "aquaExpandNode", "LEFT", "aquaCollapseNode", @@ -471,14 +475,15 @@ interface BindingsProvider { } // wraps basic string arrays - static class SimpleBinding implements BindingsProvider { + static final class SimpleBinding implements BindingsProvider { final String[] bindings; public SimpleBinding(final String[] bindings) { this.bindings = bindings; } + @Override public String[] getBindings() { return bindings; } } // patches all providers together at the moment the UIManager needs the real InputMap - static class LateBoundInputMap implements LazyValue, BindingsProvider { + static final class LateBoundInputMap implements LazyValue, BindingsProvider { private final BindingsProvider[] providerList; private String[] mergedBindings; @@ -486,10 +491,12 @@ public LateBoundInputMap(final BindingsProvider ... providerList) { this.providerList = providerList; } + @Override public Object createValue(final UIDefaults table) { return LookAndFeel.makeInputMap(getBindings()); } + @Override public String[] getBindings() { if (mergedBindings != null) return mergedBindings; @@ -544,6 +551,7 @@ void installAquaUpDownActions(final JTextComponent component) { abstract static class DeleteWordAction extends TextAction { public DeleteWordAction(final String name) { super(name); } + @Override public void actionPerformed(final ActionEvent e) { if (e == null) return; @@ -579,7 +587,7 @@ public void actionPerformed(final ActionEvent e) { final TextAction pageDownMultilineAction = new AquaMultilineAction(pageDownMultiline, DefaultEditorKit.pageDownAction, DefaultEditorKit.endAction); @SuppressWarnings("serial") // Superclass is not serializable across versions - static class AquaMultilineAction extends TextAction { + static final class AquaMultilineAction extends TextAction { final String targetActionName; final String proxyActionName; @@ -589,6 +597,7 @@ public AquaMultilineAction(final String actionName, final String targetActionNam this.proxyActionName = proxyActionName; } + @Override public void actionPerformed(final ActionEvent e) { final JTextComponent c = getTextComponent(e); final ActionMap actionMap = c.getActionMap(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java index e0f282325e4..bff6d13106d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaLabelUI.java @@ -39,23 +39,26 @@ import sun.swing.MnemonicHandler; import sun.swing.SwingUtilities2; -public class AquaLabelUI extends BasicLabelUI { +public final class AquaLabelUI extends BasicLabelUI { private static final RecyclableSingleton aquaLabelUI = new RecyclableSingletonFromDefaultConstructor(AquaLabelUI.class); public static ComponentUI createUI(final JComponent c) { return aquaLabelUI.get(); } + @Override protected void installListeners(final JLabel c) { super.installListeners(c); AquaUtilControlSize.addSizePropertyListener(c); } + @Override protected void uninstallListeners(final JLabel c) { AquaUtilControlSize.removeSizePropertyListener(c); super.uninstallListeners(c); } + @Override protected void paintEnabledText(final JLabel l, final Graphics g, final String s, final int textX, final int textY) { int mnemIndex = l.getDisplayedMnemonicIndex(); if (MnemonicHandler.isMnemonicHidden()) { @@ -73,6 +76,7 @@ protected void paintEnabledText(final JLabel l, final Graphics g, final String s * @see #paint * @see #paintEnabledText */ + @Override protected void paintDisabledText(final JLabel l, final Graphics g, final String s, final int textX, final int textY) { int accChar = l.getDisplayedMnemonicIndex(); if (MnemonicHandler.isMnemonicHidden()) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaListUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaListUI.java index 24217af311c..f0760c1f551 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaListUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaListUI.java @@ -42,7 +42,7 @@ * * All this does is look for a ThemeBorder and invalidate it when the focus changes */ -public class AquaListUI extends BasicListUI { +public final class AquaListUI extends BasicListUI { public static ComponentUI createUI(final JComponent c) { return new AquaListUI(); } @@ -50,6 +50,7 @@ public static ComponentUI createUI(final JComponent c) { /** * Creates the focus listener to repaint the focus ring */ + @Override protected FocusListener createFocusListener() { return new AquaListUI.FocusHandler(); } @@ -57,10 +58,12 @@ protected FocusListener createFocusListener() { /** * Creates a delegate that implements MouseInputListener. */ + @Override protected MouseInputListener createMouseInputListener() { return new AquaListUI.MouseInputHandler(); } + @Override protected void installKeyboardActions() { super.installKeyboardActions(); list.getActionMap().put("aquaHome", new AquaHomeEndAction(true)); @@ -68,7 +71,7 @@ protected void installKeyboardActions() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - static class AquaHomeEndAction extends AbstractAction { + static final class AquaHomeEndAction extends AbstractAction { private boolean fHomeAction = false; protected AquaHomeEndAction(final boolean isHomeAction) { @@ -78,6 +81,7 @@ protected AquaHomeEndAction(final boolean isHomeAction) { /** * For a Home action, scrolls to the top. Otherwise, scroll to the end. */ + @Override public void actionPerformed(final ActionEvent e) { final JList list = (JList)e.getSource(); @@ -94,23 +98,27 @@ public void actionPerformed(final ActionEvent e) { * This inner class is marked "public" due to a compiler bug. This class should be treated as a * "protected" inner class. Instantiate it only within subclasses of BasicListUI. */ - class FocusHandler extends BasicListUI.FocusHandler { + final class FocusHandler extends BasicListUI.FocusHandler { + @Override public void focusGained(final FocusEvent e) { super.focusGained(e); AquaBorder.repaintBorder(getComponent()); } + @Override public void focusLost(final FocusEvent e) { super.focusLost(e); AquaBorder.repaintBorder(getComponent()); } } + @Override protected PropertyChangeListener createPropertyChangeListener() { return new AquaPropertyChangeHandler(); } - class AquaPropertyChangeHandler extends PropertyChangeHandler { + final class AquaPropertyChangeHandler extends PropertyChangeHandler { + @Override public void propertyChange(final PropertyChangeEvent e) { final String prop = e.getPropertyName(); if (AquaFocusHandler.FRAME_ACTIVE_PROPERTY.equals(prop)) { @@ -126,7 +134,7 @@ public void propertyChange(final PropertyChangeEvent e) { // Replace the mouse event with one that returns the cmd-key state when asked // for the control-key state, which super assumes is what everyone does to discontiguously extend selections - class MouseInputHandler extends BasicListUI.MouseInputHandler { + final class MouseInputHandler extends BasicListUI.MouseInputHandler { /*public void mousePressed(final MouseEvent e) { super.mousePressed(new SelectionMouseEvent(e)); } @@ -194,7 +202,8 @@ public static Border getListOddBackgroundPainter() { return border; } - static class ComponentPainter extends AquaBorder.Default { + static final class ComponentPainter extends AquaBorder.Default { + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) { final JComponent jc = c instanceof JComponent ? (JComponent)c : null; if (jc != null && !AquaFocusHandler.isActive(jc)) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 07637d5454c..633b292dbc3 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -62,7 +62,7 @@ import static javax.swing.UIDefaults.LazyValue; @SuppressWarnings("serial") // Superclass is not serializable across versions -public class AquaLookAndFeel extends BasicLookAndFeel { +public final class AquaLookAndFeel extends BasicLookAndFeel { static final String sPropertyPrefix = "apple.laf."; // new prefix for things like 'useScreenMenuBar' // for lazy initalizers. Following the pattern from metal. @@ -77,6 +77,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { * that would be useful to a user trying to select a L&F from a list * of names. */ + @Override public String getName() { return "Mac OS X"; } @@ -90,6 +91,7 @@ public String getName() { * that doesn't make any fundamental changes to the look or feel * shouldn't override this method. */ + @Override public String getID() { return "Aqua"; } @@ -99,6 +101,7 @@ public String getID() { * e.g. "The CDE/Motif Look and Feel". This string is intended for * the user, e.g. in the title of a window or in a ToolTip message. */ + @Override public String getDescription() { return "Aqua Look and Feel for Mac OS X"; } @@ -118,6 +121,7 @@ public String getDescription() { * @see JRootPane#setWindowDecorationStyle * @since 1.4 */ + @Override public boolean getSupportsWindowDecorations() { return false; } @@ -126,6 +130,7 @@ public boolean getSupportsWindowDecorations() { * If the underlying platform has a "native" look and feel, and this * is an implementation of it, return true. */ + @Override public boolean isNativeLookAndFeel() { return true; } @@ -138,6 +143,7 @@ public boolean isNativeLookAndFeel() { * * @see UIManager#setLookAndFeel */ + @Override public boolean isSupportedLookAndFeel() { return true; } @@ -153,6 +159,7 @@ public boolean isSupportedLookAndFeel() { * @see #uninitialize * @see UIManager#setLookAndFeel */ + @Override @SuppressWarnings("restricted") public void initialize() { System.loadLibrary("osxui"); @@ -175,6 +182,7 @@ public void initialize() { * * @see #initialize */ + @Override public void uninitialize() { KeyboardFocusManager.getCurrentKeyboardFocusManager() .removeKeyEventPostProcessor(AltProcessor.getInstance()); @@ -209,6 +217,7 @@ public void uninitialize() { * @see #playSound(Action) * @since 1.4 */ + @Override protected ActionMap getAudioActionMap() { ActionMap audioActionMap = (ActionMap)UIManager.get("AuditoryCues.actionMap"); if (audioActionMap != null) return audioActionMap; @@ -229,6 +238,7 @@ protected ActionMap getAudioActionMap() { * We override getDefaults() so we can install our own debug defaults * if needed for testing */ + @Override public UIDefaults getDefaults() { final UIDefaults table = new UIDefaults(); // use debug defaults if you want to see every query into the defaults object. @@ -279,6 +289,7 @@ private void initResourceBundle(final UIDefaults table) { /** * This is the last step in the getDefaults routine usually called from our superclass */ + @Override protected void initComponentDefaults(final UIDefaults table) { initResourceBundle(table); @@ -1017,6 +1028,7 @@ public Object createValue(UIDefaults defaultsTable) { SwingUtilities2.putAATextInfo(true, table); } + @Override protected void initSystemColorDefaults(final UIDefaults table) { // String[] defaultSystemColors = { // "desktop", "#005C5C", /* Color of the desktop background */ @@ -1059,6 +1071,7 @@ protected void initSystemColorDefaults(final UIDefaults table) { * * @see #getDefaults */ + @Override protected void initClassDefaults(final UIDefaults table) { final String basicPackageName = "javax.swing.plaf.basic."; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarBorder.java index b3276c9c0d7..ed70450ce88 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarBorder.java @@ -38,7 +38,7 @@ /** * The class represents the border of a {@code JMenuBar}. */ -public class AquaMenuBarBorder implements Border, UIResource { +public final class AquaMenuBarBorder implements Border, UIResource { @Override public void paintBorder(final Component c, final Graphics g, final int x, diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java index 070fb93b68d..d1804c8ae29 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java @@ -40,13 +40,14 @@ // MenuBar implementation for Mac L&F @SuppressWarnings("restricted") -public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvider { +public final class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvider { static { System.loadLibrary("osxui"); } // Utilities + @Override public void uninstallUI(final JComponent c) { if (fScreenMenuBar != null) { final JFrame frame = (JFrame)(c.getTopLevelAncestor()); @@ -65,12 +66,14 @@ public static ComponentUI createUI(final JComponent c) { // [3320390] -- If the screen menu bar is in use, don't register keyboard actions that // show the menus when F10 is pressed. + @Override protected void installKeyboardActions() { if (!useScreenMenuBar) { super.installKeyboardActions(); } } + @Override protected void uninstallKeyboardActions() { if (!useScreenMenuBar) { super.uninstallKeyboardActions(); @@ -78,10 +81,12 @@ protected void uninstallKeyboardActions() { } // Paint Methods + @Override public void paint(final Graphics g, final JComponent c) { AquaMenuPainter.instance().paintMenuBarBackground(g, c.getWidth(), c.getHeight(), c); } + @Override public Dimension getPreferredSize(final JComponent c) { if (isScreenMenuBar((JMenuBar)c)) { if (setScreenMenuBar((JFrame)(c.getTopLevelAncestor()))) { @@ -111,6 +116,7 @@ boolean setScreenMenuBar(final JFrame frame) { return true; } + @Override public ScreenMenuBar getScreenMenuBar() { // Lazy init of member variables means we should use a synchronized block. synchronized(this) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBorder.java index 207e35c7070..1712b4c2448 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBorder.java @@ -31,7 +31,7 @@ import javax.swing.border.Border; import javax.swing.plaf.UIResource; -public class AquaMenuBorder implements Border, UIResource { +public final class AquaMenuBorder implements Border, UIResource { public AquaMenuBorder() { } /** @@ -44,6 +44,7 @@ public AquaMenuBorder() { } * @param width the width of the painted border * @param height the height of the painted border */ + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { // for now we don't paint a border. We let the button paint it since there // needs to be a strict ordering for aqua components. @@ -59,6 +60,7 @@ public void paintBorder(final Component c, final Graphics g, final int x, final * is opaque, it is responsible for filling in it's own * background when painting. */ + @Override public boolean isBorderOpaque() { return false; } @@ -79,6 +81,7 @@ protected static Insets getPopupInsets() { * Returns the insets of the border. * @param c the component for which this border insets value applies */ + @Override public Insets getBorderInsets(final Component c) { if (!(c instanceof JPopupMenu)) { return getItemInsets(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuItemUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuItemUI.java index c39f089701f..901fbd7b2c6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuItemUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuItemUI.java @@ -35,7 +35,7 @@ import apple.laf.JRSUIConstants.Size; // TODO: no screen menu bar for now -public class AquaMenuItemUI extends BasicMenuItemUI implements AquaMenuPainter.Client/*, ScreenMenuItemUI*/ { +public final class AquaMenuItemUI extends BasicMenuItemUI implements AquaMenuPainter.Client/*, ScreenMenuItemUI*/ { static final int kPlain = 0, kCheckBox = 1, kRadioButton = 2; static final String[] sPropertyPrefixes = { "MenuItem", "CheckBoxMenuItem", "RadioButtonMenuItem" }; @@ -57,6 +57,7 @@ public static ComponentUI createUI(final JComponent c) { // The only real difference between the three is which property prefix it returns // and therefore which icons! + @Override protected String getPropertyPrefix() { return sPropertyPrefixes[fType]; } @@ -99,14 +100,17 @@ protected void addListeners() { menuItem.addMenuDragMouseListener(menuDragMouseListener); } + @Override protected void paintMenuItem(final Graphics g, final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final Color background, final Color foreground, final int localDefaultTextIconGap) { AquaMenuPainter.instance().paintMenuItem(this, g, c, localCheckIcon, localArrowIcon, background, foreground, disabledForeground, selectionForeground, localDefaultTextIconGap, acceleratorFont); } + @Override protected Dimension getPreferredMenuItemSize(final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final int localDefaultTextIconGap) { return AquaMenuPainter.instance().getPreferredMenuItemSize(c, localCheckIcon, localArrowIcon, localDefaultTextIconGap, acceleratorFont); } + @Override public void update(final Graphics g, final JComponent c) { if (c.isOpaque()) { // sja fix ((PenGraphics)g).alphaClearRect(0,0,c.getWidth(),c.getHeight()); @@ -119,6 +123,7 @@ public void update(final Graphics g, final JComponent c) { paint(g, c); } + @Override public void paintBackground(final Graphics g, final JComponent c, final int menuWidth, final int menuHeight) { if ((c.getParent() instanceof JMenuBar)) return; final Color oldColor = g.getColor(); @@ -146,6 +151,7 @@ public void paintBackground(final Graphics g, final JComponent c, final int menu g.setColor(oldColor); } + @Override protected void doClick(final MenuSelectionManager msm) { final Dimension size = menuItem.getSize(); AquaUtils.blinkMenu(new AquaUtils.Selectable() { @@ -158,7 +164,7 @@ public void paintSelected(final boolean selected) { } static final IndeterminateListener INDETERMINATE_LISTENER = new IndeterminateListener(); - static class IndeterminateListener implements PropertyChangeListener { + static final class IndeterminateListener implements PropertyChangeListener { static final String CLIENT_PROPERTY_KEY = "JMenuItem.selectedState"; static void install(final JMenuItem menuItem) { @@ -170,6 +176,7 @@ static void uninstall(final JMenuItem menuItem) { menuItem.removePropertyChangeListener(CLIENT_PROPERTY_KEY, INDETERMINATE_LISTENER); } + @Override public void propertyChange(final PropertyChangeEvent evt) { final String key = evt.getPropertyName(); if (!CLIENT_PROPERTY_KEY.equalsIgnoreCase(key)) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java index 8f1a6799ff6..b7878b67483 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuPainter.java @@ -68,7 +68,7 @@ * that allows them to paint their own backgrounds */ -public class AquaMenuPainter { +public final class AquaMenuPainter { // Glyph statics: // ASCII character codes static final byte @@ -151,9 +151,10 @@ static AquaMenuPainter instance() { static final int defaultMenuItemGap = 2; static final int kAcceleratorArrowSpace = 16; // Accel space doesn't overlap arrow space, even though items can't have both - static class RecyclableBorder extends RecyclableSingleton { + static final class RecyclableBorder extends RecyclableSingleton { final String borderName; RecyclableBorder(final String borderName) { this.borderName = borderName; } + @Override protected Border getInstance() { return UIManager.getBorder(borderName); } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuUI.java index e21b9d22323..7057e583c58 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuUI.java @@ -33,15 +33,17 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicMenuUI; -public class AquaMenuUI extends BasicMenuUI implements AquaMenuPainter.Client { +public final class AquaMenuUI extends BasicMenuUI implements AquaMenuPainter.Client { public static ComponentUI createUI(final JComponent x) { return new AquaMenuUI(); } + @Override protected ChangeListener createChangeListener(final JComponent c) { return new ChangeHandler((JMenu)c, this); } + @Override protected void installDefaults() { super.installDefaults(); @@ -51,16 +53,19 @@ protected void installDefaults() { ((JMenu)menuItem).setDelay(8 * 1000 / 60); } + @Override protected void paintMenuItem(final Graphics g, final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final Color background, final Color foreground, final int localDefaultTextIconGap) { AquaMenuPainter.instance().paintMenuItem(this, g, c, localCheckIcon, localArrowIcon, background, foreground, disabledForeground, selectionForeground, localDefaultTextIconGap, acceleratorFont); } + @Override protected Dimension getPreferredMenuItemSize(final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final int localDefaultTextIconGap) { final Dimension d = AquaMenuPainter.instance().getPreferredMenuItemSize(c, localCheckIcon, localArrowIcon, localDefaultTextIconGap, acceleratorFont); if (c.getParent() instanceof JMenuBar) d.height = Math.max(d.height, 21); return d; } + @Override public void paintBackground(final Graphics g, final JComponent c, final int menuWidth, final int menuHeight) { final Container parent = c.getParent(); final boolean parentIsMenuBar = parent instanceof JMenuBar; @@ -82,16 +87,19 @@ public void paintBackground(final Graphics g, final JComponent c, final int menu } } + @Override protected MouseInputListener createMouseInputListener(final JComponent c) { return new AquaMouseInputHandler(); } + @Override protected MenuDragMouseListener createMenuDragMouseListener(final JComponent c) { //return super.createMenuDragMouseListener(c); return new MenuDragMouseHandler(); } - class MenuDragMouseHandler implements MenuDragMouseListener { + final class MenuDragMouseHandler implements MenuDragMouseListener { + @Override public void menuDragMouseDragged(final MenuDragMouseEvent e) { if (menuItem.isEnabled() == false) return; @@ -118,8 +126,11 @@ public void menuDragMouseDragged(final MenuDragMouseEvent e) { } } + @Override public void menuDragMouseEntered(final MenuDragMouseEvent e) { } + @Override public void menuDragMouseExited(final MenuDragMouseEvent e) { } + @Override public void menuDragMouseReleased(final MenuDragMouseEvent e) { } } @@ -130,7 +141,7 @@ static void appendPath(final MenuElement[] path, final MenuElement elem) { MenuSelectionManager.defaultManager().setSelectedPath(newPath); } - protected class AquaMouseInputHandler extends MouseInputHandler { + protected final class AquaMouseInputHandler extends MouseInputHandler { /** * Invoked when the cursor enters the menu. This method sets the selected * path for the MenuSelectionManager and handles the case @@ -139,6 +150,7 @@ protected class AquaMouseInputHandler extends MouseInputHandler { * * @param e the mouse event; not used */ + @Override public void mouseEntered(final MouseEvent e) { final JMenu menu = (JMenu)menuItem; if (!menu.isEnabled()) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java index baa83c4390b..22457379fa1 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java @@ -33,14 +33,14 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; @SuppressWarnings("restricted") -public class AquaNativeResources { +public final class AquaNativeResources { static { System.loadLibrary("osxui"); } // TODO: removing CColorPaint for now @SuppressWarnings("serial") // JDK implementation class - static class CColorPaintUIResource extends Color/*CColorPaint*/ implements UIResource { + static final class CColorPaintUIResource extends Color/*CColorPaint*/ implements UIResource { // The color passed to this MUST be a retained NSColor, and the CColorPaintUIResource // takes ownership of that retain. public CColorPaintUIResource(long color, int r, int g, int b, int a) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java index 0628a1dfaba..b3312d9fa7b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java @@ -31,7 +31,7 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicOptionPaneUI; -public class AquaOptionPaneUI extends BasicOptionPaneUI { +public final class AquaOptionPaneUI extends BasicOptionPaneUI { private static final int kOKCancelButtonWidth = 79; private static final int kButtonHeight = 23; @@ -49,6 +49,7 @@ public static ComponentUI createUI(final JComponent x) { * Creates and returns a Container containin the buttons. The buttons * are created by calling {@code getButtons}. */ + @Override protected Container createButtonArea() { final Container bottom = super.createButtonArea(); // Now replace the Layout @@ -61,6 +62,7 @@ protected Container createButtonArea() { * body of the message. * The icon and body should be aligned on their top edges */ + @Override protected Container createMessageArea() { final JPanel top = new JPanel(); top.setBorder(UIManager.getBorder("OptionPane.messageAreaBorder")); @@ -111,11 +113,12 @@ protected Container createMessageArea() { * BasicOptionPaneUI expects that its buttons are laid out with * a subclass of ButtonAreaLayout */ - public static class AquaButtonAreaLayout extends ButtonAreaLayout { + public static final class AquaButtonAreaLayout extends ButtonAreaLayout { public AquaButtonAreaLayout(final boolean syncAllWidths, final int padding) { super(true, padding); } + @Override public void layoutContainer(final Container container) { final Component[] children = container.getComponents(); if (children == null || 0 >= children.length) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaPainter.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaPainter.java index a2ebaf1c920..910907134ee 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaPainter.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaPainter.java @@ -91,7 +91,7 @@ final void paint(final Graphics g, final Component c, final int x, state = nextState; } - private static class AquaNineSlicingImagePainter + private static final class AquaNineSlicingImagePainter extends AquaPainter { private final HashMap slicedControlImages; @@ -205,7 +205,7 @@ private static Image createImage(int imgX, int imgY, int imgW, int imgH, } } - private static class AquaPixelsKey implements ImageCache.PixelsKey { + private static final class AquaPixelsKey implements ImageCache.PixelsKey { private final int pixelCount; private final int hash; @@ -259,7 +259,7 @@ public boolean equals(Object obj) { } } - private static class RecyclableJRSUISlicedImageControl + private static final class RecyclableJRSUISlicedImageControl extends RecyclableSlicedImageControl { private final JRSUIControl control; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaPanelUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaPanelUI.java index b6509ef3254..3db2eca1754 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaPanelUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaPanelUI.java @@ -34,7 +34,7 @@ import java.awt.Graphics; -public class AquaPanelUI extends BasicPanelUI { +public final class AquaPanelUI extends BasicPanelUI { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaPanelUI.class); public static ComponentUI createUI(final JComponent c) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuSeparatorUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuSeparatorUI.java index 64291c1f8b1..3b7388062cc 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuSeparatorUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuSeparatorUI.java @@ -33,17 +33,19 @@ import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaPopupMenuSeparatorUI extends BasicSeparatorUI { +public final class AquaPopupMenuSeparatorUI extends BasicSeparatorUI { private static final RecyclableSingletonFromDefaultConstructor instance = new RecyclableSingletonFromDefaultConstructor(AquaPopupMenuSeparatorUI.class); public static ComponentUI createUI(final JComponent c) { return instance.get(); } + @Override public void update(final Graphics g, final JComponent c) { paint(g, c); } + @Override public void paint(final Graphics g, final JComponent c) { final Dimension s = c.getSize(); @@ -62,6 +64,7 @@ public void paint(final Graphics g, final JComponent c) { } } + @Override public Dimension getPreferredSize(final JComponent c) { if (((JSeparator)c).getOrientation() == SwingConstants.VERTICAL) { return new Dimension(12, 0); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuUI.java index 6facaf09ebc..4b9d9a301ba 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaPopupMenuUI.java @@ -32,11 +32,12 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPopupMenuUI; -public class AquaPopupMenuUI extends BasicPopupMenuUI { +public final class AquaPopupMenuUI extends BasicPopupMenuUI { public static ComponentUI createUI(final JComponent x) { return new AquaPopupMenuUI(); } + @Override public boolean isPopupTrigger(final MouseEvent e) { // Use the awt popup trigger code since this only runs on our OS! return e.isPopupTrigger(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java index 71500f3a95c..b6e5fb5f170 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java @@ -43,7 +43,7 @@ import com.apple.laf.AquaUtilControlSize.*; import com.apple.laf.AquaUtils.RecyclableSingleton; -public class AquaProgressBarUI extends ProgressBarUI implements ChangeListener, PropertyChangeListener, AncestorListener, Sizeable { +public final class AquaProgressBarUI extends ProgressBarUI implements ChangeListener, PropertyChangeListener, AncestorListener, Sizeable { private static final boolean ADJUSTTIMER = true; private static final RecyclableSingleton sizeDescriptor = new RecyclableSingleton() { @@ -76,12 +76,14 @@ public static ComponentUI createUI(final JComponent x) { protected AquaProgressBarUI() { } + @Override public void installUI(final JComponent c) { progressBar = (JProgressBar)c; installDefaults(); installListeners(); } + @Override public void uninstallUI(final JComponent c) { uninstallDefaults(); uninstallListeners(); @@ -114,10 +116,12 @@ protected void uninstallListeners() { progressBar.removeChangeListener(this); } + @Override public void stateChanged(final ChangeEvent e) { progressBar.repaint(); } + @Override public void propertyChange(final PropertyChangeEvent e) { final String prop = e.getPropertyName(); if ("indeterminate".equals(prop)) { @@ -137,10 +141,12 @@ public void propertyChange(final PropertyChangeEvent e) { // listen for Ancestor events to stop our timer when we are no longer visible // JProgressBar: UI in Aqua look and feel causes memory leaks + @Override public void ancestorRemoved(final AncestorEvent e) { stopAnimationTimer(); } + @Override public void ancestorAdded(final AncestorEvent e) { if (!progressBar.isIndeterminate()) return; if (progressBar.isDisplayable()) { @@ -148,8 +154,10 @@ public void ancestorAdded(final AncestorEvent e) { } } + @Override public void ancestorMoved(final AncestorEvent e) { } + @Override public void paint(final Graphics g, final JComponent c) { revalidateAnimationTimers(); // revalidate to turn on/off timers when values change @@ -263,6 +271,7 @@ static Dimension getCircularPreferredSize() { return new Dimension(20, 20); } + @Override public Dimension getPreferredSize(final JComponent c) { if (isCircular) { return getCircularPreferredSize(); @@ -322,6 +331,7 @@ protected Dimension getPreferredVerticalSize(final FontMetrics metrics) { return size; } + @Override public Dimension getMinimumSize(final JComponent c) { if (isCircular) { return getCircularPreferredSize(); @@ -340,6 +350,7 @@ public Dimension getMinimumSize(final JComponent c) { return pref; } + @Override public Dimension getMaximumSize(final JComponent c) { if (isCircular) { return getCircularPreferredSize(); @@ -356,6 +367,7 @@ public Dimension getMaximumSize(final JComponent c) { return pref; } + @Override public void applySizeFor(final JComponent c, final Size size) { painter.state.set(sizeVariant = size == Size.MINI ? Size.SMALL : sizeVariant); // CUI doesn't support mini progress bars right now } @@ -440,7 +452,7 @@ protected void repaint() { progressBar.repaint(repaintRect); } - protected class Animator implements ActionListener { + protected final class Animator implements ActionListener { private static final int MINIMUM_DELAY = 5; private Timer timer; private long previousDelay; // used to tune the repaint interval @@ -476,6 +488,7 @@ protected void stop() { timer.stop(); } + @Override public void actionPerformed(final ActionEvent e) { if (!ADJUSTTIMER) { repaint(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java index 6bd472b7605..7317231c6c9 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java @@ -42,7 +42,7 @@ * * AquaRootPaneUI is a singleton object */ -public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, WindowListener, ContainerListener { +public final class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, WindowListener, ContainerListener { private static final RecyclableSingleton sRootPaneUI = new RecyclableSingletonFromDefaultConstructor(AquaRootPaneUI.class); static final boolean sUseScreenMenuBar = AquaMenuBarUI.getScreenMenuBarProperty(); @@ -50,6 +50,7 @@ public static ComponentUI createUI(final JComponent c) { return sRootPaneUI.get(); } + @Override public void installUI(final JComponent c) { super.installUI(c); c.addAncestorListener(this); @@ -80,6 +81,7 @@ public void installUI(final JComponent c) { } } + @Override public void uninstallUI(final JComponent c) { c.removeAncestorListener(this); @@ -97,6 +99,7 @@ public void uninstallUI(final JComponent c) { * because it holds the JMenuBar. So, if a new layered pane was added, listen to it. * If a new JMenuBar was added, tell the menu bar UI, because it will need to update the menu bar. */ + @Override public void componentAdded(final ContainerEvent e) { if (e.getContainer() instanceof JRootPane) { final JRootPane root = (JRootPane)e.getContainer(); @@ -125,6 +128,7 @@ public void componentAdded(final ContainerEvent e) { * Likewise, when the layered pane is removed from the root pane, stop listening to it. * If the JMenuBar is removed, tell the menu bar UI to clear the menu bar. */ + @Override public void componentRemoved(final ContainerEvent e) { if (e.getContainer() instanceof JRootPane) { final JRootPane root = (JRootPane)e.getContainer(); @@ -156,6 +160,7 @@ public void componentRemoved(final ContainerEvent e) { * And, if a JMenuBar was added before the root pane was added to the window, we now need * to notify the menu bar UI. */ + @Override public void ancestorAdded(final AncestorEvent event) { // this is so we can handle window activated and deactivated events so // our swing controls can color/enable/disable/focus draw correctly @@ -178,27 +183,36 @@ public void ancestorAdded(final AncestorEvent event) { * before it was removed. By the time ancestorRemoved was called, the JRootPane has already been removed */ + @Override public void ancestorRemoved(final AncestorEvent event) { } + @Override public void ancestorMoved(final AncestorEvent event) { } + @Override public void windowActivated(final WindowEvent e) { updateComponentTreeUIActivation((Component)e.getSource(), Boolean.TRUE); } + @Override public void windowDeactivated(final WindowEvent e) { updateComponentTreeUIActivation((Component)e.getSource(), Boolean.FALSE); } + @Override public void windowOpened(final WindowEvent e) { } + @Override public void windowClosing(final WindowEvent e) { } + @Override public void windowClosed(final WindowEvent e) { // We know the window is closed so remove the listener. final Window w = e.getWindow(); w.removeWindowListener(this); } + @Override public void windowIconified(final WindowEvent e) { } + @Override public void windowDeiconified(final WindowEvent e) { } public void windowStateChanged(final WindowEvent e) { } public void windowGainedFocus(final WindowEvent e) { } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java index f71a15a9787..d8cc229eb55 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollBarUI.java @@ -68,7 +68,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; -public class AquaScrollBarUI extends ScrollBarUI { +public final class AquaScrollBarUI extends ScrollBarUI { private static final int kInitialDelay = 300; private static final int kNormalDelay = 100; @@ -96,12 +96,14 @@ public static ComponentUI createUI(final JComponent c) { public AquaScrollBarUI() { } + @Override public void installUI(final JComponent c) { fScrollBar = (JScrollBar)c; installListeners(); configureScrollBarColors(); } + @Override public void uninstallUI(final JComponent c) { uninstallListeners(); fScrollBar = null; @@ -169,6 +171,7 @@ protected void syncState(final JComponent c) { scrollBarState.set(shouldShowArrows() ? ShowArrows.YES : ShowArrows.NO); } + @Override public void paint(final Graphics g, final JComponent c) { syncState(c); Rectangle trackBounds = getTrackBounds(); @@ -268,7 +271,8 @@ protected Hit getPartHit(final int x, final int y) { fScrollBar.getHeight() - (insets.top + insets.bottom), x, y); } - protected class PropertyChangeHandler implements PropertyChangeListener { + protected final class PropertyChangeHandler implements PropertyChangeListener { + @Override public void propertyChange(final PropertyChangeEvent e) { final String propertyName = e.getPropertyName(); @@ -285,20 +289,22 @@ public void propertyChange(final PropertyChangeEvent e) { } } - protected class ModelListener implements ChangeListener { + protected final class ModelListener implements ChangeListener { + @Override public void stateChanged(final ChangeEvent e) { layoutContainer(fScrollBar); } } // Track mouse drags. - protected class TrackListener extends MouseAdapter implements MouseMotionListener { + protected final class TrackListener extends MouseAdapter implements MouseMotionListener { protected transient int fCurrentMouseX, fCurrentMouseY; protected transient boolean fInArrows; // are we currently tracking arrows? protected transient boolean fStillInArrow = false; // Whether mouse is in an arrow during arrow tracking protected transient boolean fStillInTrack = false; // Whether mouse is in the track during pageup/down tracking protected transient int fFirstMouseX, fFirstMouseY, fFirstValue; // Values for getValueFromOffset + @Override public void mouseReleased(final MouseEvent e) { if (!fScrollBar.isEnabled()) return; if (fInArrows) { @@ -315,6 +321,7 @@ public void mouseReleased(final MouseEvent e) { fScrollBar.revalidate(); } + @Override public void mousePressed(final MouseEvent e) { if (!fScrollBar.isEnabled()) return; @@ -331,6 +338,7 @@ public void mousePressed(final MouseEvent e) { } } + @Override public void mouseDragged(final MouseEvent e) { if (!fScrollBar.isEnabled()) return; @@ -541,7 +549,7 @@ void moveToMouse(final MouseEvent e) { /** * Listener for scrolling events initiated in the ScrollPane. */ - protected class ScrollListener implements ActionListener { + protected final class ScrollListener implements ActionListener { boolean fUseBlockIncrement; int fDirection = 1; @@ -553,6 +561,7 @@ void setScrollByBlock(final boolean block) { this.fUseBlockIncrement = block; } + @Override public void actionPerformed(final ActionEvent e) { Component parent = fScrollBar.getParent(); do { @@ -625,14 +634,17 @@ float getThumbPercent() { * @see #getMaximumSize * @see #getMinimumSize */ + @Override public Dimension getPreferredSize(final JComponent c) { return isHorizontal() ? new Dimension(96, 15) : new Dimension(15, 96); } + @Override public Dimension getMinimumSize(final JComponent c) { return isHorizontal() ? new Dimension(54, 15) : new Dimension(15, 54); } + @Override public Dimension getMaximumSize(final JComponent c) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } @@ -699,7 +711,7 @@ Point getScrollToHereStartPoint(final int clickPosX, final int clickPosY) { return startPoint; } - static class HitUtil { + static final class HitUtil { static boolean isIncrement(final Hit hit) { return (hit == ScrollBarHit.ARROW_MAX) || (hit == ScrollBarHit.ARROW_MAX_INSIDE); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java index 0729321552d..f1f30e39cc9 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java @@ -31,16 +31,18 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollPaneUI; -public class AquaScrollPaneUI extends javax.swing.plaf.basic.BasicScrollPaneUI { +public final class AquaScrollPaneUI extends javax.swing.plaf.basic.BasicScrollPaneUI { public static ComponentUI createUI(final JComponent x) { return new AquaScrollPaneUI(); } + @Override protected MouseWheelListener createMouseWheelListener() { return new XYMouseWheelHandler(); } - protected class XYMouseWheelHandler extends BasicScrollPaneUI.MouseWheelHandler { + protected final class XYMouseWheelHandler extends BasicScrollPaneUI.MouseWheelHandler { + @Override public void mouseWheelMoved(final MouseWheelEvent e) { super.mouseWheelMoved(e); // Consume the event even when the scrollBar is invisible diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollRegionBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollRegionBorder.java index d09aa654b5c..4c03991e55d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollRegionBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollRegionBorder.java @@ -39,7 +39,7 @@ import com.apple.laf.AquaUtilControlSize.SizeVariant; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaScrollRegionBorder extends AquaBorder { +public final class AquaScrollRegionBorder extends AquaBorder { private static final RecyclableSingletonFromDefaultConstructor instance = new RecyclableSingletonFromDefaultConstructor(AquaScrollRegionBorder.class); public static AquaScrollRegionBorder getScrollRegionBorder() { @@ -57,6 +57,7 @@ protected AquaPainter createPainter() { return AquaPainter.create(state, 7, 7, 3, 3, 3, 3); } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { final State state = getState((JComponent)c); painter.state.set(state); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java index 876bc543d14..9f8b4458f73 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java @@ -42,7 +42,7 @@ import com.apple.laf.AquaImageFactory.NineSliceMetrics; import com.apple.laf.AquaUtils.RecyclableSingleton; -public class AquaSliderUI extends BasicSliderUI implements Sizeable { +public final class AquaSliderUI extends BasicSliderUI implements Sizeable { // static final Dimension roundThumbSize = new Dimension(21 + 4, 21 + 4); // +2px on both sides for focus fuzz // static final Dimension pointingThumbSize = new Dimension(19 + 4, 22 + 4); @@ -100,6 +100,7 @@ public AquaSliderUI(final JSlider b) { super(b); } + @Override public void installUI(final JComponent c) { super.installUI(c); @@ -107,28 +108,33 @@ public void installUI(final JComponent c) { tickColor = UIManager.getColor("Slider.tickColor"); } + @Override protected BasicSliderUI.TrackListener createTrackListener(final JSlider s) { return new TrackListener(); } + @Override protected void installListeners(final JSlider s) { super.installListeners(s); AquaFocusHandler.install(s); AquaUtilControlSize.addSizePropertyListener(s); } + @Override protected void uninstallListeners(final JSlider s) { AquaUtilControlSize.removeSizePropertyListener(s); AquaFocusHandler.uninstall(s); super.uninstallListeners(s); } + @Override public void applySizeFor(final JComponent c, final Size size) { thumbPainter.state.set(size); trackPainter.state.set(size); } // Paint Methods + @Override public void paint(final Graphics g, final JComponent c) { // We have to override paint of BasicSliderUI because we need slight differences. // We don't paint focus the same way - it is part of the thumb. @@ -214,6 +220,7 @@ State getState() { return State.ACTIVE; } + @Override public void paintTicks(final Graphics g) { if (slider.isEnabled()) { g.setColor(tickColor); @@ -230,6 +237,7 @@ public void paintTicks(final Graphics g) { // Layout Methods // Used lots + @Override protected void calculateThumbLocation() { super.calculateThumbLocation(); @@ -252,6 +260,7 @@ protected void calculateThumbLocation() { } // Only called from calculateGeometry + @Override protected void calculateThumbSize() { final SizeDescriptor descriptor = shouldUseArrowThumb() ? pointingThumbDescriptor.get() : roundThumbDescriptor.get(); final SizeVariant variant = descriptor.get(slider); @@ -274,6 +283,7 @@ protected boolean shouldUseArrowThumb() { return false; } + @Override protected void calculateTickRect() { // super assumes tickRect ends align with trackRect ends. // Ours need to inset by trackBuffer @@ -293,14 +303,17 @@ protected void calculateTickRect() { } // Basic's preferred size doesn't allow for our focus ring, throwing off things like SwingSet2 + @Override public Dimension getPreferredHorizontalSize() { return new Dimension(190, 21); } + @Override public Dimension getPreferredVerticalSize() { return new Dimension(21, 190); } + @Override protected ChangeListener createChangeListener(final JSlider s) { return new ChangeListener() { public void stateChanged(final ChangeEvent e) { @@ -313,10 +326,11 @@ public void stateChanged(final ChangeEvent e) { // This is copied almost verbatim from superclass, except we changed things to use fIsDragging // instead of isDragging since isDragging was a private member. - class TrackListener extends javax.swing.plaf.basic.BasicSliderUI.TrackListener { + final class TrackListener extends javax.swing.plaf.basic.BasicSliderUI.TrackListener { protected transient int offset; protected transient int currentMouseX = -1, currentMouseY = -1; + @Override public void mouseReleased(final MouseEvent e) { if (!slider.isEnabled()) return; @@ -342,6 +356,7 @@ public void mouseReleased(final MouseEvent e) { slider.repaint(); } + @Override public void mousePressed(final MouseEvent e) { if (!slider.isEnabled()) return; @@ -398,6 +413,7 @@ public void mousePressed(final MouseEvent e) { fIsDragging = false; } + @Override public boolean shouldScroll(final int direction) { final Rectangle r = thumbRect; if (slider.getOrientation() == SwingConstants.VERTICAL) { @@ -429,6 +445,7 @@ public boolean shouldScroll(final int direction) { * Set the models value to the position of the top/left * of the thumb relative to the origin of the track. */ + @Override public void mouseDragged(final MouseEvent e) { int thumbMiddle = 0; @@ -493,6 +510,7 @@ public void mouseDragged(final MouseEvent e) { } } + @Override public void mouseMoved(final MouseEvent e) { } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java index 3a4347d0a31..057e898519a 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java @@ -90,7 +90,7 @@ * This is originally derived from BasicSpinnerUI, but they made everything * private so we can't subclass! */ -public class AquaSpinnerUI extends SpinnerUI { +public final class AquaSpinnerUI extends SpinnerUI { private static final RecyclableSingleton propertyChangeListener = new RecyclableSingletonFromDefaultConstructor<>(PropertyChangeHandler.class); @@ -270,7 +270,7 @@ public Component.BaselineResizeBehavior getBaselineResizeBehavior( } @SuppressWarnings("serial") // Superclass is not serializable across versions - class TransparentButton extends JButton implements SwingConstants { + final class TransparentButton extends JButton implements SwingConstants { boolean interceptRepaints = false; @@ -386,7 +386,7 @@ private ActionMap createActionMap() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class ArrowButtonHandler extends AbstractAction implements FocusListener, MouseListener { + private static final class ArrowButtonHandler extends AbstractAction implements FocusListener, MouseListener { final javax.swing.Timer autoRepeatTimer; final boolean isNext; @@ -607,9 +607,11 @@ private void focusSpinnerIfNecessary() { } } + @Override public void focusGained(FocusEvent e) { } + @Override public void focusLost(FocusEvent e) { if (spinner == eventToSpinner(e)) { if (autoRepeatTimer.isRunning()) { @@ -626,7 +628,7 @@ public void focusLost(FocusEvent e) { } @SuppressWarnings("serial") // Superclass is not serializable across versions - class SpinPainter extends JComponent { + final class SpinPainter extends JComponent { final AquaPainter painter = AquaPainter.create(JRSUIStateFactory.getSpinnerArrows()); @@ -693,7 +695,7 @@ public Dimension getPreferredSize() { * the AquaSpinnerUI javadoc for more information about exactly how the * components are arranged. */ - static class SpinnerLayout implements LayoutManager { + static final class SpinnerLayout implements LayoutManager { private Component nextButton = null; private Component previousButton = null; @@ -800,7 +802,7 @@ public void layoutContainer(final Container parent) { * (although they can by overriding createPropertyChangeListener) since all * of the interesting property changes are delegated to protected methods. */ - static class PropertyChangeHandler implements PropertyChangeListener { + static final class PropertyChangeHandler implements PropertyChangeListener { @Override public void propertyChange(final PropertyChangeEvent e) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneDividerUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneDividerUI.java index 6f7580496d2..7a4bc27470b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneDividerUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneDividerUI.java @@ -40,7 +40,7 @@ import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; @SuppressWarnings("serial") // Superclass is not serializable across versions -public class AquaSplitPaneDividerUI extends BasicSplitPaneDivider { +public final class AquaSplitPaneDividerUI extends BasicSplitPaneDivider { final AquaPainter painter = AquaPainter.create(JRSUIStateFactory.getSplitPaneDivider()); public AquaSplitPaneDividerUI(final AquaSplitPaneUI ui) { @@ -52,6 +52,7 @@ public AquaSplitPaneDividerUI(final AquaSplitPaneUI ui) { * Property change event, presumably from the JSplitPane, will message * updateOrientation if necessary. */ + @Override public void propertyChange(final PropertyChangeEvent e) { if (e.getSource() == splitPane) { final String propName = e.getPropertyName(); @@ -80,6 +81,7 @@ public int getMaxDividerSize() { /** * Paints the divider. */ + @Override public void paint(final Graphics g) { final Dimension size = getSize(); int x = 0; @@ -118,10 +120,12 @@ protected State getState() { return splitPane.isEnabled() ? State.ACTIVE : State.DISABLED; } + @Override protected JButton createLeftOneTouchButton() { return createButtonForDirection(getDirection(true)); } + @Override protected JButton createRightOneTouchButton() { return createButtonForDirection(getDirection(false)); } @@ -156,7 +160,8 @@ int getDirection(final boolean isLeft) { } static final int kMaxPopupArrowSize = 9; - protected class DividerLayout extends BasicSplitPaneDivider.DividerLayout { + protected final class DividerLayout extends BasicSplitPaneDivider.DividerLayout { + @Override public void layoutContainer(final Container c) { final int maxSize = getMaxDividerSize(); final Dimension size = getSize(); @@ -204,7 +209,7 @@ public static Border getHorizontalSplitDividerGradientVariant() { return HorizontalSplitDividerGradientPainter.instance(); } - static class HorizontalSplitDividerGradientPainter implements Border { + static final class HorizontalSplitDividerGradientPainter implements Border { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(HorizontalSplitDividerGradientPainter.class); static HorizontalSplitDividerGradientPainter instance() { return instance.get(); @@ -214,14 +219,17 @@ static HorizontalSplitDividerGradientPainter instance() { final Color endColor = new Color(217, 217, 217); final Color borderLines = Color.lightGray; + @Override public Insets getBorderInsets(final Component c) { return new Insets(0, 0, 0, 0); } + @Override public boolean isBorderOpaque() { return true; } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { if (!(g instanceof Graphics2D)) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneUI.java index b9ec41b88a0..62e77a378dc 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaSplitPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.*; -public class AquaSplitPaneUI extends BasicSplitPaneUI implements MouseListener, PropertyChangeListener { +public final class AquaSplitPaneUI extends BasicSplitPaneUI implements MouseListener, PropertyChangeListener { static final String DIVIDER_PAINTER_KEY = "JSplitPane.dividerPainter"; public AquaSplitPaneUI() { @@ -44,22 +44,26 @@ public static ComponentUI createUI(final JComponent x) { return new AquaSplitPaneUI(); } + @Override public BasicSplitPaneDivider createDefaultDivider() { return new AquaSplitPaneDividerUI(this); } + @Override protected void installListeners() { super.installListeners(); splitPane.addPropertyChangeListener(DIVIDER_PAINTER_KEY, this); divider.addMouseListener(this); } + @Override protected void uninstallListeners() { divider.removeMouseListener(this); splitPane.removePropertyChangeListener(DIVIDER_PAINTER_KEY, this); super.uninstallListeners(); } + @Override public void mouseClicked(final MouseEvent e) { if (e.getClickCount() < 2) return; if (!splitPane.isOneTouchExpandable()) return; @@ -90,11 +94,16 @@ public void mouseClicked(final MouseEvent e) { } } + @Override public void mouseEntered(final MouseEvent e) { } + @Override public void mouseExited(final MouseEvent e) { } + @Override public void mousePressed(final MouseEvent e) { } + @Override public void mouseReleased(final MouseEvent e) { } + @Override public void propertyChange(final PropertyChangeEvent evt) { if (!DIVIDER_PAINTER_KEY.equals(evt.getPropertyName())) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java index f29b63f6ba9..121af1c8bdc 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneContrastUI.java @@ -41,7 +41,7 @@ import apple.laf.JRSUIUtils; import apple.laf.JRSUIConstants.*; -public class AquaTabbedPaneContrastUI extends AquaTabbedPaneUI { +public final class AquaTabbedPaneContrastUI extends AquaTabbedPaneUI { private static boolean isFrameActive = false; public static ComponentUI createUI(final JComponent c) { @@ -50,6 +50,7 @@ public static ComponentUI createUI(final JComponent c) { public AquaTabbedPaneContrastUI() { } + @Override protected void paintTitle(final Graphics2D g2d, final Font font, final FontMetrics metrics, final Rectangle textRect, final int tabIndex, final String title) { final View v = getTextViewForTab(tabIndex); if (v != null) { @@ -101,10 +102,12 @@ protected boolean isPressedAt(int index) { return ((MouseHandler)mouseListener).trackingTab == index; } + @Override protected boolean shouldRepaintSelectedTabOnMouseDown() { return true; } + @Override protected State getState(final int index, final boolean frameActive, final boolean isSelected) { isFrameActive = frameActive; if (!frameActive) return State.INACTIVE; @@ -113,11 +116,13 @@ protected State getState(final int index, final boolean frameActive, final boole return State.ACTIVE; } + @Override protected SegmentTrailingSeparator getSegmentTrailingSeparator(final int index, final int selectedIndex, final boolean isLeftToRight) { if (isTabBeforeSelectedTab(index, selectedIndex, isLeftToRight)) return SegmentTrailingSeparator.NO; return SegmentTrailingSeparator.YES; } + @Override protected SegmentLeadingSeparator getSegmentLeadingSeparator(final int index, final int selectedIndex, final boolean isLeftToRight) { if (index == selectedIndex) return SegmentLeadingSeparator.YES; return SegmentLeadingSeparator.NO; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java index 3106a73e7eb..eaab92334d8 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -211,6 +211,7 @@ static void loadActionMap(final LazyActionMap map) { // UI Installation/De-installation + @Override public void installUI(final JComponent c) { this.tabPane = (JTabbedPane)c; @@ -224,6 +225,7 @@ public void installUI(final JComponent c) { installKeyboardActions(); } + @Override public void uninstallUI(final JComponent c) { uninstallKeyboardActions(); uninstallListeners(); @@ -404,7 +406,11 @@ protected void installListeners() { } tabPane.addContainerListener(getHandler()); if (tabPane.getTabCount() > 0) { - htmlViews = createHTMLVector(); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); + if (!(Boolean.TRUE.equals(htmlDisabled))) { + htmlViews = createHTMLVector(); + } } } @@ -572,11 +578,13 @@ protected int getRolloverTab() { return rolloverTabIndex; } + @Override public Dimension getMinimumSize(final JComponent c) { // Default to LayoutManager's minimumLayoutSize return null; } + @Override public Dimension getMaximumSize(final JComponent c) { // Default to LayoutManager's maximumLayoutSize return null; @@ -590,6 +598,7 @@ public Dimension getMaximumSize(final JComponent c) { * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */ + @Override public int getBaseline(final JComponent c, final int width, final int height) { super.getBaseline(c, width, height); int baseline = calculateBaselineIfNecessary(); @@ -621,6 +630,7 @@ public int getBaseline(final JComponent c, final int width, final int height) { * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */ + @Override public Component.BaselineResizeBehavior getBaselineResizeBehavior(final JComponent c) { super.getBaselineResizeBehavior(c); switch (tabPane.getTabPlacement()) { @@ -742,6 +752,7 @@ private void calculateBaseline() { // UI Rendering + @Override public void paint(final Graphics g, final JComponent c) { final int selectedIndex = tabPane.getSelectedIndex(); final int tabPlacement = tabPane.getTabPlacement(); @@ -1349,12 +1360,14 @@ protected void ensureCurrentLayout() { * Returns the bounds of the specified tab index. The bounds are * with respect to the JTabbedPane's coordinate space. */ + @Override public Rectangle getTabBounds(final JTabbedPane pane, final int i) { ensureCurrentLayout(); final Rectangle tabRect = new Rectangle(); return getTabBounds(i, tabRect); } + @Override public int getTabRunCount(final JTabbedPane pane) { ensureCurrentLayout(); return runCount; @@ -1364,6 +1377,7 @@ public int getTabRunCount(final JTabbedPane pane) { * Returns the tab index which intersects the specified point * in the JTabbedPane's coordinate space. */ + @Override public int tabForCoordinate(final JTabbedPane pane, final int x, final int y) { return tabForCoordinate(pane, x, y, true); } @@ -2010,7 +2024,7 @@ boolean requestFocusForVisibleComponent() { return SwingUtilities2.tabbedPaneChangeFocusTo(getVisibleComponent()); } - private static class Actions extends UIAction { + private static final class Actions extends UIAction { static final String NEXT = "navigateNext"; static final String PREVIOUS = "navigatePrevious"; static final String RIGHT = "navigateRight"; @@ -2037,6 +2051,7 @@ static Object getUIOfType(final ComponentUI ui, final Class 0) { final Component child = getComponent(0); @@ -3260,7 +3289,7 @@ public void doLayout() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class ScrollableTabButton extends javax.swing.plaf.basic.BasicArrowButton implements UIResource, SwingConstants { + private static final class ScrollableTabButton extends javax.swing.plaf.basic.BasicArrowButton implements UIResource, SwingConstants { public ScrollableTabButton(final int direction) { super(direction, UIManager.getColor("TabbedPane.selected"), UIManager.getColor("TabbedPane.shadow"), UIManager.getColor("TabbedPane.darkShadow"), UIManager.getColor("TabbedPane.highlight")); } @@ -3268,10 +3297,11 @@ public ScrollableTabButton(final int direction) { // Controller: event listeners - private class Handler implements ChangeListener, ContainerListener, FocusListener, MouseListener, MouseMotionListener, PropertyChangeListener { + private final class Handler implements ChangeListener, ContainerListener, FocusListener, MouseListener, MouseMotionListener, PropertyChangeListener { // // PropertyChangeListener // + @Override public void propertyChange(final PropertyChangeEvent e) { final JTabbedPane pane = (JTabbedPane)e.getSource(); final String name = e.getPropertyName(); @@ -3330,6 +3360,7 @@ public void propertyChange(final PropertyChangeEvent e) { // // ChangeListener // + @Override public void stateChanged(final ChangeEvent e) { final JTabbedPane tabPane = (JTabbedPane)e.getSource(); tabPane.revalidate(); @@ -3348,18 +3379,23 @@ public void stateChanged(final ChangeEvent e) { // // MouseListener // + @Override public void mouseClicked(final MouseEvent e) {} + @Override public void mouseReleased(final MouseEvent e) {} + @Override public void mouseEntered(final MouseEvent e) { setRolloverTab(e.getX(), e.getY()); } + @Override public void mouseExited(final MouseEvent e) { setRolloverTab(-1); } + @Override public void mousePressed(final MouseEvent e) { if (!tabPane.isEnabled()) { return; @@ -3383,8 +3419,10 @@ public void mousePressed(final MouseEvent e) { // // MouseMotionListener // + @Override public void mouseDragged(final MouseEvent e) {} + @Override public void mouseMoved(final MouseEvent e) { setRolloverTab(e.getX(), e.getY()); } @@ -3392,10 +3430,12 @@ public void mouseMoved(final MouseEvent e) { // // FocusListener // + @Override public void focusGained(final FocusEvent e) { setFocusIndex(tabPane.getSelectedIndex(), true); } + @Override public void focusLost(final FocusEvent e) { repaintTab(focusIndex); } @@ -3433,6 +3473,7 @@ The Views (one per tab title requiring HTML rendering) are changes to tab text, this code should be removed and replaced by something which uses that. */ + @Override public void componentAdded(final ContainerEvent e) { final JTabbedPane tp = (JTabbedPane)e.getContainer(); final Component child = e.getChild(); @@ -3445,8 +3486,10 @@ public void componentAdded(final ContainerEvent e) { private void updateHtmlViews(int index, boolean inserted) { final String title = tabPane.getTitleAt(index); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); final boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { + if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { if (htmlViews == null) { // Initialize vector htmlViews = createHTMLVector(); } else { // Vector already exists @@ -3469,6 +3512,7 @@ private void setHtmlView(View v, boolean inserted, int index) { } } + @Override public void componentRemoved(final ContainerEvent e) { final JTabbedPane tp = (JTabbedPane)e.getContainer(); final Component child = e.getChild(); @@ -3505,6 +3549,7 @@ public class PropertyChangeHandler implements PropertyChangeListener { // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. + @Override public void propertyChange(final PropertyChangeEvent e) { getHandler().propertyChange(e); } @@ -3514,11 +3559,12 @@ public void propertyChange(final PropertyChangeEvent e) { * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTabbedPaneUI. */ - public class TabSelectionHandler implements ChangeListener { + public final class TabSelectionHandler implements ChangeListener { // NOTE: This class exists only for backward compatibility. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. + @Override public void stateChanged(final ChangeEvent e) { getHandler().stateChanged(e); } @@ -3528,11 +3574,12 @@ public void stateChanged(final ChangeEvent e) { * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTabbedPaneUI. */ - public class MouseHandler extends MouseAdapter { + public final class MouseHandler extends MouseAdapter { // NOTE: This class exists only for backward compatibility. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. + @Override public void mousePressed(final MouseEvent e) { getHandler().mousePressed(e); } @@ -3542,15 +3589,17 @@ public void mousePressed(final MouseEvent e) { * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTabbedPaneUI. */ - public class FocusHandler extends FocusAdapter { + public final class FocusHandler extends FocusAdapter { // NOTE: This class exists only for backward compatibility. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. + @Override public void focusGained(final FocusEvent e) { getHandler().focusGained(e); } + @Override public void focusLost(final FocusEvent e) { getHandler().focusLost(e); } @@ -3573,7 +3622,7 @@ private Vector createHTMLVector() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class TabContainer extends JPanel implements UIResource { + private final class TabContainer extends JPanel implements UIResource { private boolean notifyTabbedPane = true; public TabContainer() { @@ -3581,6 +3630,7 @@ public TabContainer() { setOpaque(false); } + @Override public void remove(final Component comp) { final int index = tabPane.indexOfTabComponent(comp); super.remove(comp); @@ -3600,10 +3650,12 @@ private void removeUnusedTabComponents() { } } + @Override public boolean isOptimizedDrawingEnabled() { return tabScroller != null && !tabScroller.croppedEdge.isParamsSet(); } + @Override public void doLayout() { // We layout tabComponents in JTabbedPane's layout manager // and use this method as a hook for repainting tabs @@ -3618,7 +3670,7 @@ public void doLayout() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class CroppedEdge extends JPanel implements UIResource { + private final class CroppedEdge extends JPanel implements UIResource { private Shape shape; private int tabIndex; private int cropline; @@ -3675,6 +3727,7 @@ private Color getBgColor() { return UIManager.getColor("control"); } + @Override protected void paintComponent(final Graphics g) { super.paintComponent(g); if (isParamsSet() && g instanceof Graphics2D) { @@ -3698,7 +3751,7 @@ protected void paintComponent(final Graphics g) { * @author Scott Violet */ @SuppressWarnings("serial") // Superclass is not serializable across versions - static class LazyActionMap extends ActionMapUIResource { + static final class LazyActionMap extends ActionMapUIResource { /** * Object to invoke {@code loadActionMap} on. This may be * a Class object. @@ -3756,41 +3809,49 @@ public void put(final Action action) { put(action.getValue(Action.NAME), action); } + @Override public void put(final Object key, final Action action) { loadIfNecessary(); super.put(key, action); } + @Override public Action get(final Object key) { loadIfNecessary(); return super.get(key); } + @Override public void remove(final Object key) { loadIfNecessary(); super.remove(key); } + @Override public void clear() { loadIfNecessary(); super.clear(); } + @Override public Object[] keys() { loadIfNecessary(); return super.keys(); } + @Override public int size() { loadIfNecessary(); return super.size(); } + @Override public Object[] allKeys() { loadIfNecessary(); return super.allKeys(); } + @Override public void setParent(final ActionMap map) { loadIfNecessary(); super.setParent(map); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneTabState.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneTabState.java index 3f8de4249b5..649b9d0f345 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneTabState.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneTabState.java @@ -29,7 +29,7 @@ import javax.swing.SwingConstants; -class AquaTabbedPaneTabState { +final class AquaTabbedPaneTabState { static final int FIXED_SCROLL_TAB_LENGTH = 27; protected final Rectangle leftScrollTabRect = new Rectangle(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java index 1a10e30a6c6..3e9a98d220b 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java @@ -66,6 +66,7 @@ public static ComponentUI createUI(final JComponent c) { public AquaTabbedPaneUI() { } + @Override protected void installListeners() { super.installListeners(); @@ -75,6 +76,7 @@ protected void installListeners() { } } + @Override protected void installDefaults() { super.installDefaults(); @@ -90,6 +92,7 @@ protected void installDefaults() { tabPane.setOpaque(false); } + @Override protected void assureRectsCreated(final int tabCount) { visibleTabState.init(tabCount); super.assureRectsCreated(tabCount); @@ -106,22 +109,27 @@ protected void uninstallListeners() { super.uninstallListeners(); } + @Override protected void uninstallDefaults() { contentDrawingInsets.set(0, 0, 0, 0); } + @Override protected MouseListener createMouseListener() { return new MouseHandler(); } + @Override protected FocusListener createFocusListener() { return new FocusHandler(); } + @Override protected PropertyChangeListener createPropertyChangeListener() { return new TabbedPanePropertyChangeHandler(); } + @Override protected LayoutManager createLayoutManager() { return new AquaTruncatingTabbedPaneLayout(); } @@ -137,6 +145,7 @@ protected boolean shouldRepaintSelectedTabOnMouseDown() { final Rectangle fTextRect = new Rectangle(); // UI Rendering + @Override public void paint(final Graphics g, final JComponent c) { painter.state.set(getDirection()); @@ -229,6 +238,7 @@ protected static void transposeRect(final Rectangle r) { r.height = temp; } + @Override protected int getTabLabelShiftX(final int tabPlacement, final int tabIndex, final boolean isSelected) { final Rectangle tabRect = (tabIndex >= 0 ? rects[tabIndex] : visibleTabState.getRightScrollTabRect()); int nudge = 0; @@ -245,6 +255,7 @@ protected int getTabLabelShiftX(final int tabPlacement, final int tabIndex, fina return nudge; } + @Override protected int getTabLabelShiftY(final int tabPlacement, final int tabIndex, final boolean isSelected) { switch (tabPlacement) { case RIGHT: @@ -546,7 +557,7 @@ protected State getState(final int index, final boolean frameActive, final boole * whether we're talking about a first tab or last tab. NOTE that this code is very much * Aqua 2 dependent! */ - static class AlterRects { + static final class AlterRects { Rectangle standard, first, last; AlterRects(final int x, final int y, final int w, final int h) { standard = new Rectangle(x, y, w, h); } AlterRects start(final int x, final int y, final int w, final int h) { first = new Rectangle(x, y, w, h); return this; } @@ -588,6 +599,7 @@ protected void fillTabWithBackground(final Graphics g, final Rectangle rect, fin g.fillRoundRect(fillRect.x, fillRect.y, fillRect.width, fillRect.height, 3, 1); } + @Override protected Insets getContentBorderInsets(final int tabPlacement) { final Insets draw = getContentDrawingInsets(tabPlacement); // will be rotated @@ -635,6 +647,7 @@ protected Insets getContentDrawingInsets(final int tabPlacement) { return currentContentDrawingInsets; } + @Override protected Icon getIconForTab(final int tabIndex) { final Icon mainIcon = super.getIconForTab(tabIndex); if (mainIcon == null) return null; @@ -652,6 +665,7 @@ Image createImage() { } private static final int TAB_BORDER_INSET = 9; + @Override protected void paintContentBorder(final Graphics g, final int tabPlacement, final int selectedIndex) { final int width = tabPane.getWidth(); final int height = tabPane.getHeight(); @@ -745,6 +759,7 @@ public Rectangle getTabBounds(final JTabbedPane pane, final int i) { * Returns the tab index which intersects the specified point * in the JTabbedPane's coordinate space. */ + @Override public int tabForCoordinate(final JTabbedPane pane, final int x, final int y) { ensureCurrentLayout(); final Point p = new Point(x, y); @@ -764,6 +779,7 @@ public int tabForCoordinate(final JTabbedPane pane, final int x, final int y) { return -1; } + @Override protected Insets getTabInsets(final int tabPlacement, final int tabIndex) { switch (tabPlacement) { case LEFT: return UIManager.getInsets("TabbedPane.leftTabInsets"); @@ -773,6 +789,7 @@ protected Insets getTabInsets(final int tabPlacement, final int tabIndex) { } // This is the preferred size - the layout manager will ignore if it has to + @Override protected int calculateTabHeight(final int tabPlacement, final int tabIndex, final int fontHeight) { // Constrain to what the Mac allows final int result = super.calculateTabHeight(tabPlacement, tabIndex, fontHeight); @@ -783,11 +800,13 @@ protected int calculateTabHeight(final int tabPlacement, final int tabIndex, fin } // JBuilder requested this - it's against HI, but then so are multiple rows + @Override protected boolean shouldRotateTabRuns(final int tabPlacement) { return false; } - protected class TabbedPanePropertyChangeHandler extends PropertyChangeHandler { + protected final class TabbedPanePropertyChangeHandler extends PropertyChangeHandler { + @Override public void propertyChange(final PropertyChangeEvent e) { final String prop = e.getPropertyName(); @@ -807,6 +826,7 @@ public void propertyChange(final PropertyChangeEvent e) { } } + @Override protected ChangeListener createChangeListener() { return new ChangeListener() { public void stateChanged(final ChangeEvent e) { @@ -818,9 +838,10 @@ public void stateChanged(final ChangeEvent e) { }; } - protected class FocusHandler extends FocusAdapter { + protected final class FocusHandler extends FocusAdapter { Rectangle sWorkingRect = new Rectangle(); + @Override public void focusGained(final FocusEvent e) { if (isDefaultFocusReceiver(tabPane) && !hasAvoidedFirstFocus) { KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(); @@ -829,6 +850,7 @@ public void focusGained(final FocusEvent e) { adjustPaintingRectForFocusRing(e); } + @Override public void focusLost(final FocusEvent e) { adjustPaintingRectForFocusRing(e); } @@ -862,7 +884,7 @@ Container getTopLevelFocusCycleRootAncestor(Container container) { } } - class MouseHandler extends MouseInputAdapter implements ActionListener { + final class MouseHandler extends MouseInputAdapter implements ActionListener { int trackingTab = -3; private final Timer popupTimer = new Timer(500, this); @@ -876,6 +898,7 @@ void dispose (){ popupTimer.stop(); } + @Override public void mousePressed(final MouseEvent e) { final JTabbedPane pane = (JTabbedPane)e.getSource(); if (!pane.isEnabled()) { @@ -898,6 +921,7 @@ public void mousePressed(final MouseEvent e) { repaint(pane, pressedTab); } + @Override public void mouseDragged(final MouseEvent e) { if (trackingTab < -2) return; @@ -917,6 +941,7 @@ public void mouseDragged(final MouseEvent e) { repaint(pane, trackingTab); } + @Override public void mouseReleased(final MouseEvent e) { if (trackingTab < -2) return; @@ -944,6 +969,7 @@ public void mouseReleased(final MouseEvent e) { trackingTab = -3; } + @Override public void actionPerformed(final ActionEvent e) { if (trackingTab != pressedTab) { return; @@ -1063,8 +1089,9 @@ public void actionPerformed(final ActionEvent ae) { } } - protected class AquaTruncatingTabbedPaneLayout extends AquaTabbedPaneCopyFromBasicUI.TabbedPaneLayout { + protected final class AquaTruncatingTabbedPaneLayout extends AquaTabbedPaneCopyFromBasicUI.TabbedPaneLayout { // fix for Radar #3346131 + @Override protected int preferredTabAreaWidth(final int tabPlacement, final int height) { // Our superclass wants to stack tabs, but we rotate them, // so when tabs are on the left or right we know that @@ -1077,6 +1104,7 @@ protected int preferredTabAreaWidth(final int tabPlacement, final int height) { return super.preferredTabAreaWidth(tabPlacement, height); } + @Override protected int preferredTabAreaHeight(final int tabPlacement, final int width) { if (tabPlacement == SwingConstants.LEFT || tabPlacement == SwingConstants.RIGHT) { return super.preferredTabAreaWidth(tabPlacement, width); @@ -1085,6 +1113,7 @@ protected int preferredTabAreaHeight(final int tabPlacement, final int width) { return super.preferredTabAreaHeight(tabPlacement, width); } + @Override protected void calculateTabRects(final int tabPlacement, final int tabCount) { if (tabCount <= 0) return; @@ -1096,6 +1125,7 @@ protected void calculateTabRects(final int tabPlacement, final int tabCount) { visibleTabState.alignRectsRunFor(rects, tabPane.getSize(), tabPlacement, AquaUtils.isLeftToRight(tabPane)); } + @Override protected void padTabRun(final int tabPlacement, final int start, final int end, final int max) { if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { super.padTabRun(tabPlacement, start, end, max); @@ -1247,6 +1277,7 @@ private void calculateVerticalTabRunRect(final Rectangle rect, final FontMetrics rect.width = maxTabWidth; } + @Override protected void layoutTabComponents() { final Container tabContainer = getTabContainer(); if (tabContainer == null) return; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderBorder.java index 04f0d08edf0..0fd3d30e8be 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderBorder.java @@ -37,7 +37,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; @SuppressWarnings("serial") // Superclass is not serializable across versions -public class AquaTableHeaderBorder extends AbstractBorder { +public final class AquaTableHeaderBorder extends AbstractBorder { protected static final int SORT_NONE = 0; protected static final int SORT_ASCENDING = 1; protected static final int SORT_DECENDING = -1; @@ -67,6 +67,7 @@ protected AquaTableHeaderBorder() { * @param height the height of the painted border */ protected boolean doPaint = true; + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { if (!doPaint) return; final JComponent jc = (JComponent)c; @@ -140,11 +141,13 @@ protected static Border getAlternateBorder() { * Returns the insets of the border. * @param c the component for which this border insets value applies */ + @Override public Insets getBorderInsets(final Component c) { // bad to create new one each time. For debugging only. return editorBorderInsets; } + @Override public Insets getBorderInsets(final Component c, final Insets insets) { insets.left = editorBorderInsets.left; insets.top = editorBorderInsets.top; @@ -158,6 +161,7 @@ public Insets getBorderInsets(final Component c, final Insets insets) { * is opaque, it is responsible for filling in it's own * background when painting. */ + @Override public boolean isBorderOpaque() { return false; } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java index af5621657de..b614ff2a5ab 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java @@ -37,7 +37,7 @@ import com.apple.laf.ClientPropertyApplicator.Property; import com.apple.laf.AquaUtils.RecyclableSingleton; -public class AquaTableHeaderUI extends BasicTableHeaderUI { +public final class AquaTableHeaderUI extends BasicTableHeaderUI { private int originalHeaderAlignment; protected int sortColumn; protected int sortOrder; @@ -46,6 +46,7 @@ public static ComponentUI createUI(final JComponent c) { return new AquaTableHeaderUI(); } + @Override public void installDefaults() { super.installDefaults(); @@ -57,6 +58,7 @@ public void installDefaults() { } } + @Override public void uninstallDefaults() { final TableCellRenderer renderer = header.getDefaultRenderer(); if (renderer instanceof UIResource && renderer instanceof DefaultTableCellRenderer) { @@ -112,7 +114,8 @@ static void tickle(final JTableHeader target, final Object selectedColumn, final } @SuppressWarnings("serial") // Superclass is not serializable across versions - class AquaTableCellRenderer extends DefaultTableCellRenderer implements UIResource { + final class AquaTableCellRenderer extends DefaultTableCellRenderer implements UIResource { + @Override public Component getTableCellRendererComponent(final JTable localTable, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { if (localTable != null) { if (header != null) { @@ -165,11 +168,13 @@ protected static AquaTableHeaderBorder getAquaBorderFrom(final JTableHeader head return (AquaTableHeaderBorder)border; } + @Override protected void installListeners() { super.installListeners(); getTableHeaderApplicators().attachAndApplyClientProperties(header); } + @Override protected void uninstallListeners() { getTableHeaderApplicators().removeFrom(header); super.uninstallListeners(); @@ -232,6 +237,7 @@ private Dimension createHeaderSizeAqua(long width) { * Return the minimum size of the header. The minimum width is the sum of the minimum widths of each column (plus * inter-cell spacing). */ + @Override public Dimension getMinimumSize(final JComponent c) { long width = 0; final Enumeration enumeration = header.getColumnModel().getColumns(); @@ -247,6 +253,7 @@ public Dimension getMinimumSize(final JComponent c) { * the components provided by the header renderers. The preferred width is the sum of the preferred widths of each * column (plus inter-cell spacing). */ + @Override public Dimension getPreferredSize(final JComponent c) { long width = 0; final Enumeration enumeration = header.getColumnModel().getColumns(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableUI.java index 5915530f77a..31702152c3c 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableUI.java @@ -38,7 +38,7 @@ * * All this does is look for a ThemeBorder and invalidate it when the focus changes */ -public class AquaTableUI extends BasicTableUI { +public final class AquaTableUI extends BasicTableUI { public static ComponentUI createUI(final JComponent c) { return new AquaTableUI(); } @@ -46,6 +46,7 @@ public static ComponentUI createUI(final JComponent c) { /** * Creates the focus listener to repaint the focus ring */ + @Override protected FocusListener createFocusListener() { return new AquaTableUI.FocusHandler(); } @@ -53,6 +54,7 @@ protected FocusListener createFocusListener() { /** * Creates the mouse listener for the JTable. */ + @Override protected MouseInputListener createMouseInputListener() { return new AquaTableUI.MouseInputHandler(); } @@ -62,12 +64,14 @@ protected MouseInputListener createMouseInputListener() { * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTableUI. */ - public class FocusHandler extends BasicTableUI.FocusHandler { + public final class FocusHandler extends BasicTableUI.FocusHandler { + @Override public void focusGained(final FocusEvent e) { super.focusGained(e); AquaBorder.repaintBorder(getComponent()); } + @Override public void focusLost(final FocusEvent e) { super.focusLost(e); AquaBorder.repaintBorder(getComponent()); @@ -81,12 +85,14 @@ public void propertyChange(final PropertyChangeEvent ev) { AquaFocusHandler.swapSelectionColors("Table", getComponent(), ev.getNewValue()); } }; + @Override protected void installListeners() { super.installListeners(); table.addFocusListener(focusHandler); table.addPropertyChangeListener(focusHandler); } + @Override protected void uninstallListeners() { table.removePropertyChangeListener(focusHandler); table.removeFocusListener(focusHandler); @@ -97,7 +103,7 @@ protected void uninstallListeners() { // Replace the mouse event with one that returns the cmd-key state when asked // for the control-key state, which super assumes is what everyone does to discontiguously extend selections - public class MouseInputHandler extends BasicTableUI.MouseInputHandler { + public final class MouseInputHandler extends BasicTableUI.MouseInputHandler { /*public void mousePressed(final MouseEvent e) { super.mousePressed(new SelectionMouseEvent(e)); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java index 76b9b276395..6ce1372c8f5 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextAreaUI.java @@ -32,7 +32,7 @@ import javax.swing.plaf.basic.BasicTextAreaUI; import javax.swing.text.*; -public class AquaTextAreaUI extends BasicTextAreaUI { +public final class AquaTextAreaUI extends BasicTextAreaUI { public static ComponentUI createUI(final JComponent c) { return new AquaTextAreaUI(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldBorder.java index 29191725d20..eb07bb25724 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldBorder.java @@ -56,11 +56,13 @@ public AquaTextFieldBorder(final AquaTextFieldBorder other) { super(other); } + @Override protected void setSize(final Size size) { super.setSize(size); painter.state.set(Size.LARGE); } + @Override public void paintBorder(final Component c, final Graphics g, int x, int y, int width, int height) { // g.setColor(Color.MAGENTA); // g.drawRect(x, y, width - 1, height - 1); @@ -122,6 +124,7 @@ protected Insets getSubInsets(final int shrinkage) { return insets; } + @Override public Insets getBorderInsets(final Component c) { if (!(c instanceof JTextComponent) || c.isOpaque()) return new InsetsUIResource(3, 7, 3, 7); return new InsetsUIResource(5, 5, 5, 5); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldFormattedUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldFormattedUI.java index 8af61850a20..0bfbc556920 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldFormattedUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldFormattedUI.java @@ -35,7 +35,7 @@ * This class exists only as a hack to work around a Sun bug which parks the * insertion caret at the beginning of a text field when it gets clicked on. */ -public class AquaTextFieldFormattedUI extends AquaTextFieldUI implements MouseListener { +public final class AquaTextFieldFormattedUI extends AquaTextFieldUI implements MouseListener { public static ComponentUI createUI(final JComponent c) { return new AquaTextFieldFormattedUI(); } @@ -45,16 +45,19 @@ protected String getPropertyPrefix() { return "FormattedTextField"; } + @Override protected void installListeners() { super.installListeners(); getComponent().addMouseListener(this); } + @Override protected void uninstallListeners() { getComponent().removeMouseListener(this); super.uninstallListeners(); } + @Override @SuppressWarnings("deprecation") public void mouseClicked(final MouseEvent e) { if (e.getClickCount() != 1) return; @@ -66,8 +69,12 @@ public void mouseClicked(final MouseEvent e) { c.setCaretPosition(viewToModel(c, e.getPoint())); } + @Override public void mouseEntered(final MouseEvent e) { } + @Override public void mouseExited(final MouseEvent e) { } + @Override public void mousePressed(final MouseEvent e) { } + @Override public void mouseReleased(final MouseEvent e) { } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java index a6be82d9ac3..20b179da7d1 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java @@ -40,7 +40,7 @@ import com.apple.laf.AquaUtilControlSize.*; import com.apple.laf.AquaUtils.*; -public class AquaTextFieldSearch { +public final class AquaTextFieldSearch { private static final String VARIANT_KEY = "JTextField.variant"; private static final String SEARCH_VARIANT_VALUE = "search"; @@ -58,7 +58,8 @@ protected static void uninstallSearchFieldListener(final JTextComponent c) { c.removePropertyChangeListener(SEARCH_FIELD_PROPERTY_LISTENER); } - static class SearchFieldPropertyListener implements PropertyChangeListener { + static final class SearchFieldPropertyListener implements PropertyChangeListener { + @Override public void propertyChange(final PropertyChangeEvent evt) { final Object source = evt.getSource(); if (!(source instanceof JTextComponent)) return; @@ -290,7 +291,7 @@ static void updateCancelIconOnEDT(final JButton button, final JTextComponent tex } // subclass of normal text border, because we still want all the normal text field behaviors - static class SearchFieldBorder extends AquaTextFieldBorder implements JComponentPainter { + static final class SearchFieldBorder extends AquaTextFieldBorder implements JComponentPainter { protected boolean reallyPaintBorder; public SearchFieldBorder() { @@ -302,6 +303,7 @@ public SearchFieldBorder(final SearchFieldBorder other) { super(other); } + @Override public void paint(final JComponent c, final Graphics g, final int x, final int y, final int w, final int h) { reallyPaintBorder = true; paintBorder(c, g, x, y, w, h); @@ -309,11 +311,13 @@ public void paint(final JComponent c, final Graphics g, final int x, final int y } // apparently without adjusting for odd height pixels, the search field "wobbles" relative to it's contents + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { if (!reallyPaintBorder) return; super.paintBorder(c, g, x, y - (height % 2), width, height); } + @Override public Insets getBorderInsets(final Component c) { if (doingLayout) return new Insets(0, 0, 0, 0); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java index 77b74e33847..6fc391c5fec 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.text.*; //[3663467] moved it to sublcass from BasicEditorPaneUI to BasicTextPaneUI. (vm) -public class AquaTextPaneUI extends BasicTextPaneUI { +public final class AquaTextPaneUI extends BasicTextPaneUI { public static ComponentUI createUI(final JComponent c) { return new AquaTextPaneUI(); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPasswordFieldUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPasswordFieldUI.java index 0cdcc9c8006..da52600075a 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPasswordFieldUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextPasswordFieldUI.java @@ -37,7 +37,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaTextPasswordFieldUI extends AquaTextFieldUI { +public final class AquaTextPasswordFieldUI extends AquaTextFieldUI { private static final RecyclableSingleton capsLockPainter = new RecyclableSingletonFromDefaultConstructor(CapsLockSymbolPainter.class); static CapsLockSymbolPainter getCapsLockPainter() { return capsLockPainter.get(); @@ -84,7 +84,7 @@ protected void paintBackgroundSafely(final Graphics g) { getCapsLockPainter().paintBorder(component, g, bounds.x, bounds.y, bounds.width, bounds.height); } - protected class AquaPasswordView extends PasswordView { + protected final class AquaPasswordView extends PasswordView { public AquaPasswordView(final Element elem) { super(elem); setupDefaultEchoCharacter(); @@ -99,7 +99,7 @@ protected void setupDefaultEchoCharacter() { } } - static class CapsLockSymbolPainter extends KeyAdapter implements Border, UIResource { + static final class CapsLockSymbolPainter extends KeyAdapter implements Border, UIResource { protected Shape capsLockShape; protected Shape getCapsLockShape() { if (capsLockShape != null) return capsLockShape; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarSeparatorUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarSeparatorUI.java index 555ea8b33a2..09bd21f8c72 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarSeparatorUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarSeparatorUI.java @@ -33,7 +33,7 @@ import com.apple.laf.AquaUtils.*; -public class AquaToolBarSeparatorUI extends BasicToolBarSeparatorUI { +public final class AquaToolBarSeparatorUI extends BasicToolBarSeparatorUI { private static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaToolBarSeparatorUI.class); public static ComponentUI createUI(final JComponent c) { @@ -46,6 +46,7 @@ public AquaToolBarSeparatorUI() { BasicStroke dashedStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[] { 1.0f, 2.0f }, 0.0f); + @Override public void paint(final Graphics g, final JComponent c) { g.setColor(c.getForeground()); ((Graphics2D)g).setStroke(dashedStroke); @@ -59,6 +60,7 @@ public void paint(final Graphics g, final JComponent c) { } } + @Override public Dimension getMinimumSize(final JComponent c) { final JToolBar.Separator sep = (JToolBar.Separator)c; if (sep.getOrientation() == SwingConstants.HORIZONTAL) { @@ -67,6 +69,7 @@ public Dimension getMinimumSize(final JComponent c) { return new Dimension(11, 1); } + @Override public Dimension getPreferredSize(final JComponent c) { final JToolBar.Separator sep = (JToolBar.Separator)c; if (sep.getOrientation() == SwingConstants.HORIZONTAL) { @@ -75,6 +78,7 @@ public Dimension getPreferredSize(final JComponent c) { return new Dimension(11, 1); } + @Override public Dimension getMaximumSize(final JComponent c) { final JToolBar.Separator sep = (JToolBar.Separator)c; if (sep.getOrientation() == SwingConstants.HORIZONTAL) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarUI.java index 0b02ae784f7..7adea86121e 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolBarUI.java @@ -34,7 +34,7 @@ import com.apple.laf.AquaUtils.*; -public class AquaToolBarUI extends BasicToolBarUI implements SwingConstants { +public final class AquaToolBarUI extends BasicToolBarUI implements SwingConstants { private static final RecyclableSingleton toolBarBorder = new RecyclableSingletonFromDefaultConstructor(ToolBarBorder.class); public static Border getToolBarBorder() { return toolBarBorder.get(); @@ -44,10 +44,14 @@ public static ComponentUI createUI(final JComponent c) { return new AquaToolBarUI(); } + @Override protected void setBorderToNonRollover(final Component c) { } + @Override protected void setBorderToNormal(final Component c) { } + @Override protected void setBorderToRollover(final Component c) { } + @Override protected RootPaneContainer createFloatingWindow(final JToolBar toolbar) { final RootPaneContainer window = super.createFloatingWindow(toolbar); window.getRootPane().putClientProperty("Window.style", "small"); @@ -56,7 +60,7 @@ protected RootPaneContainer createFloatingWindow(final JToolBar toolbar) { /* ToolBarBorder and drag-off handle, based loosely on MetalBumps */ @SuppressWarnings("serial") // Superclass is not serializable across versions - static class ToolBarBorder extends AbstractBorder implements UIResource, javax.swing.SwingConstants { + static final class ToolBarBorder extends AbstractBorder implements UIResource, javax.swing.SwingConstants { protected void fillHandle(final Graphics g, final int x1, final int y1, final int x2, final int y2, final boolean horizontal) { g.setColor(UIManager.getColor("ToolBar.borderHandleColor")); if (horizontal) { @@ -70,6 +74,7 @@ protected void fillHandle(final Graphics g, final int x1, final int y1, final in } } + @Override public void paintBorder(final java.awt.Component c, final Graphics g, int x, int y, final int w, final int h) { g.translate(x, y); @@ -100,11 +105,13 @@ public void paintBorder(final java.awt.Component c, final Graphics g, int x, int g.translate(-x, -y); } + @Override public Insets getBorderInsets(final java.awt.Component c) { final Insets borderInsets = new Insets(5, 5, 5, 5); return getBorderInsets(c, borderInsets); } + @Override public Insets getBorderInsets(final java.awt.Component c, final Insets borderInsets) { borderInsets.left = 4; borderInsets.right = 4; @@ -132,6 +139,7 @@ public Insets getBorderInsets(final java.awt.Component c, final Insets borderIns return borderInsets; } + @Override public boolean isBorderOpaque() { return true; } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolTipUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolTipUI.java index 19e9c1cb593..e872cad0b94 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaToolTipUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaToolTipUI.java @@ -33,7 +33,7 @@ import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaToolTipUI extends BasicToolTipUI { +public final class AquaToolTipUI extends BasicToolTipUI { private static final RecyclableSingletonFromDefaultConstructor sharedAquaInstance = new RecyclableSingletonFromDefaultConstructor(AquaToolTipUI.class); public static ComponentUI createUI(final JComponent c) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java index 2de5975051a..4a7aaff738e 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java @@ -45,7 +45,7 @@ * AquaTreeUI supports the client property "value-add" system of customization See MetalTreeUI * This is heavily based on the 1.3.1 AquaTreeUI implementation. */ -public class AquaTreeUI extends BasicTreeUI { +public final class AquaTreeUI extends BasicTreeUI { // Create PLAF public static ComponentUI createUI(final JComponent c) { @@ -80,6 +80,7 @@ public AquaTreeUI() { } + @Override public void installUI(final JComponent c) { super.installUI(c); @@ -88,6 +89,7 @@ public void installUI(final JComponent c) { c.addPropertyChangeListener(lineStyleListener); } + @Override public void uninstallUI(final JComponent c) { c.removePropertyChangeListener(lineStyleListener); super.uninstallUI(c); @@ -96,6 +98,7 @@ public void uninstallUI(final JComponent c) { /** * Creates the focus listener to repaint the focus ring */ + @Override protected FocusListener createFocusListener() { return new AquaTreeUI.FocusHandler(); } @@ -117,6 +120,7 @@ protected void decodeLineStyle(final Object lineStyleFlag) { } } + @Override public TreePath getClosestPathForLocation(final JTree treeLocal, final int x, final int y) { if (treeLocal == null || treeState == null) return null; @@ -125,6 +129,7 @@ public TreePath getClosestPathForLocation(final JTree treeLocal, final int x, fi return treeState.getPathClosestTo(x - i.left, y - i.top); } + @Override public void paint(final Graphics g, final JComponent c) { super.paint(g, c); @@ -156,12 +161,14 @@ protected void paintHorizontalSeparators(final Graphics g, final JComponent c) { } } + @Override protected void paintVerticalPartOfLeg(final Graphics g, final Rectangle clipBounds, final Insets insets, final TreePath path) { if (lineStyle == LEG_LINE_STYLE) { super.paintVerticalPartOfLeg(g, clipBounds, insets, path); } } + @Override protected void paintHorizontalPartOfLeg(final Graphics g, final Rectangle clipBounds, final Insets insets, final Rectangle bounds, final TreePath path, final int row, final boolean isExpanded, final boolean hasBeenExpanded, final boolean isLeaf) { if (lineStyle == LEG_LINE_STYLE) { super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); @@ -169,7 +176,8 @@ protected void paintHorizontalPartOfLeg(final Graphics g, final Rectangle clipBo } /** This class listens for changes in line style */ - class LineListener implements PropertyChangeListener { + final class LineListener implements PropertyChangeListener { + @Override public void propertyChange(final PropertyChangeEvent e) { final String name = e.getPropertyName(); if (name.equals(LINE_STYLE)) { @@ -182,6 +190,7 @@ public void propertyChange(final PropertyChangeEvent e) { * Paints the expand (toggle) part of a row. The receiver should NOT modify {@code clipBounds}, or * {@code insets}. */ + @Override protected void paintExpandControl(final Graphics g, final Rectangle clipBounds, final Insets insets, final Rectangle bounds, final TreePath path, final int row, final boolean isExpanded, final boolean hasBeenExpanded, final boolean isLeaf) { final Object value = path.getLastPathComponent(); @@ -272,6 +281,7 @@ protected State getState(final TreePath path) { * We install a motion handler that gets removed after. * See super.MouseInputHandler & super.startEditing for why */ + @Override protected void handleExpandControlClick(final TreePath path, final int mouseX, final int mouseY) { fMouseHandler = new TreeArrowMouseInputHandler(path); } @@ -279,27 +289,32 @@ protected void handleExpandControlClick(final TreePath path, final int mouseX, f /** * Returning true signifies a mouse event on the node should toggle the selection of only the row under mouse. */ + @Override protected boolean isToggleSelectionEvent(final MouseEvent event) { return SwingUtilities.isLeftMouseButton(event) && event.isMetaDown(); } - class FocusHandler extends BasicTreeUI.FocusHandler { + final class FocusHandler extends BasicTreeUI.FocusHandler { + @Override public void focusGained(final FocusEvent e) { super.focusGained(e); AquaBorder.repaintBorder(tree); } + @Override public void focusLost(final FocusEvent e) { super.focusLost(e); AquaBorder.repaintBorder(tree); } } + @Override protected PropertyChangeListener createPropertyChangeListener() { return new MacPropertyChangeHandler(); } - public class MacPropertyChangeHandler extends PropertyChangeHandler { + public final class MacPropertyChangeHandler extends PropertyChangeHandler { + @Override public void propertyChange(final PropertyChangeEvent e) { final String prop = e.getPropertyName(); if (prop.equals(AquaFocusHandler.FRAME_ACTIVE_PROPERTY)) { @@ -318,7 +333,7 @@ public void propertyChange(final PropertyChangeEvent e) { * Just like super.MouseInputHandler, this is removed once it's not needed, so they won't clash with each other */ // The Adapters take care of defining all the empties - class TreeArrowMouseInputHandler extends MouseInputAdapter { + final class TreeArrowMouseInputHandler extends MouseInputAdapter { protected Rectangle fPathBounds = new Rectangle(); // Values needed for paintOneControl @@ -362,6 +377,7 @@ class TreeArrowMouseInputHandler extends MouseInputAdapter { paintOneControl(); } + @Override public void mouseDragged(final MouseEvent e) { fIsInBounds = fPathBounds.contains(e.getX(), e.getY()); paintOneControl(); @@ -373,6 +389,7 @@ public void mouseExited(MouseEvent e) { paintOneControl(); } + @Override public void mouseReleased(final MouseEvent e) { if (tree == null) return; @@ -485,6 +502,7 @@ protected Rectangle getPathArrowBounds(final TreePath path) { return bounds; } + @Override protected void installKeyboardActions() { super.installKeyboardActions(); tree.getActionMap().put("aquaExpandNode", new KeyboardExpandCollapseAction(true, false)); @@ -494,7 +512,7 @@ protected void installKeyboardActions() { } @SuppressWarnings("serial") // Superclass is not serializable across versions - class KeyboardExpandCollapseAction extends AbstractAction { + final class KeyboardExpandCollapseAction extends AbstractAction { /** * Determines direction to traverse, 1 means expand, -1 means collapse. */ @@ -509,6 +527,7 @@ public KeyboardExpandCollapseAction(final boolean expand, final boolean recursiv this.recursive = recursive; } + @Override public void actionPerformed(final ActionEvent e) { if (tree == null || 0 > getRowCount(tree)) return; @@ -542,6 +561,7 @@ public void actionPerformed(final ActionEvent e) { } } + @Override public boolean isEnabled() { return (tree != null && tree.isEnabled()); } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java index 32479fc4854..d5974049f30 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java @@ -38,7 +38,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -public class AquaUtilControlSize { +public final class AquaUtilControlSize { protected static final String CLIENT_PROPERTY_KEY = "JComponent.sizeVariant"; protected static final String SYSTEM_PROPERTY_KEY = "swing.component.sizevariant"; @@ -127,7 +127,7 @@ private static void applyBorderForSize(final JComponent c, final Size size) { c.setBorder(derivedBorder); } - protected static class PropertySizeListener implements PropertyChangeListener { + protected static final class PropertySizeListener implements PropertyChangeListener { @Override public void propertyChange(final PropertyChangeEvent evt) { final String key = evt.getPropertyName(); @@ -204,7 +204,7 @@ public String toString() { } } - public static class SizeVariant { + public static final class SizeVariant { Size size = Size.REGULAR; Insets insets = new InsetsUIResource(0, 0, 0, 0); Insets margins = new InsetsUIResource(0, 0, 0, 0); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java index 5bb3dbf0953..610407e6160 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java @@ -162,7 +162,7 @@ void reset() { abstract T getInstance(); } - static class RecyclableSingletonFromDefaultConstructor extends RecyclableSingleton { + static final class RecyclableSingletonFromDefaultConstructor extends RecyclableSingleton { private final Class clazz; RecyclableSingletonFromDefaultConstructor(final Class clazz) { @@ -308,7 +308,7 @@ private void paintToImage(final BufferedImage img, final int x, final int y, fin } } - static class SlicedShadowBorder extends ShadowBorder { + static final class SlicedShadowBorder extends ShadowBorder { private final SlicedImageControl slices; SlicedShadowBorder(final Painter prePainter, final Painter postPainter, final int offsetX, final int offsetY, final float distance, final float intensity, final int blur, final int templateWidth, final int templateHeight, final int leftCut, final int topCut, final int rightCut, final int bottomCut) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java index 5f4ede3687c..83e37170fae 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java @@ -36,7 +36,7 @@ import static sun.awt.AWTAccessor.*; @SuppressWarnings("serial") // JDK implementation class -public class ScreenMenuBar extends MenuBar +public final class ScreenMenuBar extends MenuBar implements ContainerListener, ScreenMenuPropertyHandler, ComponentListener { @@ -53,6 +53,7 @@ public ScreenMenuBar(final JMenuBar swingBar) { fSubmenus = new Hashtable(fSwingBar.getMenuCount()); } + @Override public void addNotify() { super.addNotify(); @@ -82,6 +83,7 @@ public void addNotify() { } } + @Override public void removeNotify() { // KCH - 3974930 - We do null checks for fSwingBar and fSubmenus because some people are using // reflection to muck about with our ivars @@ -110,6 +112,7 @@ public void removeNotify() { /** * Invoked when a component has been added to the container. */ + @Override public void componentAdded(final ContainerEvent e) { final Component child = e.getChild(); if (!(child instanceof JMenu)) return; @@ -119,6 +122,7 @@ public void componentAdded(final ContainerEvent e) { /** * Invoked when a component has been removed from the container. */ + @Override public void componentRemoved(final ContainerEvent e) { final Component child = e.getChild(); if (!(child instanceof JMenu)) return; @@ -128,11 +132,13 @@ public void componentRemoved(final ContainerEvent e) { /** * Invoked when the component's size changes. */ + @Override public void componentResized(final ComponentEvent e) {} /** * Invoked when the component's position changes. */ + @Override public void componentMoved(final ComponentEvent e) {} /** @@ -140,6 +146,7 @@ public void componentMoved(final ComponentEvent e) {} * See componentHidden - we should still have a MenuItem * it just isn't inserted */ + @Override public void componentShown(final ComponentEvent e) { final Object source = e.getSource(); if (!(source instanceof JMenuItem)) return; @@ -152,6 +159,7 @@ public void componentShown(final ComponentEvent e) { * so we remove the ScreenMenuItem from the ScreenMenu * but leave it in fItems */ + @Override public void componentHidden(final ComponentEvent e) { final Object source = e.getSource(); if (!(source instanceof JMenuItem)) return; @@ -163,6 +171,7 @@ public void componentHidden(final ComponentEvent e) { * so we just add or remove the child from the ScreenMenuBar * but leave it in the list */ + @Override public void setChildVisible(final JMenuItem child, final boolean b) { if (child instanceof JMenu) { if (b) { @@ -184,9 +193,12 @@ public void removeAll() { } } + @Override public void setIcon(final Icon i) {} + @Override public void setLabel(final String s) {} + @Override public void setEnabled(final boolean b) { final int count = fSwingBar.getMenuCount(); for (int i = 0; i < count; i++) { @@ -194,10 +206,13 @@ public void setEnabled(final boolean b) { } } + @Override public void setAccelerator(final KeyStroke ks) {} + @Override public void setToolTipText(final String tooltip) {} // only check and radio items can be indeterminate + @Override public void setIndeterminate(boolean indeterminate) { } ScreenMenu addSubmenu(final JMenu m) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java index 8d0b67489b6..0e827e9b990 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java @@ -55,6 +55,7 @@ final class ScreenMenuItem extends MenuItem } } + @Override public void addNotify() { super.addNotify(); @@ -92,6 +93,7 @@ public void addNotify() { } } + @Override public void removeNotify() { super.removeNotify(); removeActionListener(this); @@ -125,6 +127,7 @@ public void setAccelerator(final KeyStroke ks) { syncLabelAndKS(this, fMenuItem.getText(), ks); } + @Override public void actionPerformed(final ActionEvent e) { fMenuItem.doClick(0); // This takes care of all the different events } @@ -132,11 +135,13 @@ public void actionPerformed(final ActionEvent e) { /** * Invoked when the component's size changes. */ + @Override public void componentResized(final ComponentEvent e) {} /** * Invoked when the component's position changes. */ + @Override public void componentMoved(final ComponentEvent e) {} /** @@ -144,6 +149,7 @@ public void componentMoved(final ComponentEvent e) {} * See componentHidden - we should still have a MenuItem * it just isn't inserted */ + @Override public void componentShown(final ComponentEvent e) { setVisible(true); } @@ -154,6 +160,7 @@ public void componentShown(final ComponentEvent e) { * so we remove the ScreenMenuItem from the ScreenMenu * but leave it in fItems */ + @Override public void componentHidden(final ComponentEvent e) { setVisible(false); } @@ -168,6 +175,7 @@ public void setVisible(final boolean b) { } } + @Override public void setToolTipText(final String text) { Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); if (!(peer instanceof CMenuItem)) return; @@ -176,6 +184,7 @@ public void setToolTipText(final String text) { cmi.setToolTipText(text); } + @Override public void setIcon(final Icon i) { Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); if (!(peer instanceof CMenuItem)) return; @@ -192,8 +201,10 @@ public void setIcon(final Icon i) { } // we have no children + @Override public void setChildVisible(final JMenuItem child, final boolean b) {} // only check and radio items can be indeterminate + @Override public void setIndeterminate(boolean indeterminate) { } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java index de38fd52b42..4528d94df38 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java @@ -61,6 +61,7 @@ public void init(final JMenuItem mi) { ScreenMenuPropertyListener fPropertyListener; + @Override public void addNotify() { super.addNotify(); @@ -104,6 +105,7 @@ public void addNotify() { } } + @Override public void removeNotify() { fMenuItem.removeComponentListener(this); fMenuItem.removePropertyChangeListener(fPropertyListener); @@ -125,6 +127,7 @@ public void setAccelerator(final KeyStroke ks) { ScreenMenuItem.syncLabelAndKS(this, fMenuItem.getText(), ks); } + @Override public void actionPerformed(final ActionEvent e) { fMenuItem.doClick(0); // This takes care of all the different events } @@ -132,11 +135,13 @@ public void actionPerformed(final ActionEvent e) { /** * Invoked when the component's size changes. */ + @Override public void componentResized(final ComponentEvent e) {} /** * Invoked when the component's position changes. */ + @Override public void componentMoved(final ComponentEvent e) {} /** @@ -144,6 +149,7 @@ public void componentMoved(final ComponentEvent e) {} * See componentHidden - we should still have a MenuItem * it just isn't inserted */ + @Override public void componentShown(final ComponentEvent e) { setVisible(true); } @@ -154,10 +160,12 @@ public void componentShown(final ComponentEvent e) { * so we remove the ScreenMenuItem from the ScreenMenu * but leave it in fItems */ + @Override public void componentHidden(final ComponentEvent e) { setVisible(false); } + @Override public void setToolTipText(final String text) { Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); if (!(peer instanceof CMenuItem)) return; @@ -165,6 +173,7 @@ public void setToolTipText(final String text) { ((CMenuItem)peer).setToolTipText(text); } + @Override public void setIcon(final Icon i) { Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); if (!(peer instanceof CMenuItem)) return; @@ -188,11 +197,13 @@ public void setVisible(final boolean b) { } // we have no children + @Override public void setChildVisible(final JMenuItem child, final boolean b) {} /** * Invoked when an item's state has been changed. */ + @Override public void itemStateChanged(final ItemEvent e) { if (e.getSource() == this) { fMenuItem.doClick(0); @@ -209,6 +220,7 @@ public void itemStateChanged(final ItemEvent e) { } } + @Override public void setIndeterminate(final boolean indeterminate) { Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); if (peer instanceof CCheckboxMenuItem) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuPropertyListener.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuPropertyListener.java index 1176a82cfc1..5d04929fad6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuPropertyListener.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuPropertyListener.java @@ -30,7 +30,7 @@ import javax.accessibility.*; import javax.swing.*; -class ScreenMenuPropertyListener implements PropertyChangeListener { +final class ScreenMenuPropertyListener implements PropertyChangeListener { ScreenMenuPropertyHandler fMenu; ScreenMenuPropertyListener(final ScreenMenuPropertyHandler mc) { @@ -42,6 +42,7 @@ class ScreenMenuPropertyListener implements PropertyChangeListener { * @param e A PropertyChangeEvent object describing the event source * and the property that has changed. */ + @Override public void propertyChange(final PropertyChangeEvent e) { final String propertyName = e.getPropertyName(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java index b08b890aa2b..2eda60c4e30 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java @@ -31,7 +31,7 @@ import sun.lwawt.macosx.CPlatformWindow; import sun.swing.SwingAccessor; -class ScreenPopupFactory extends PopupFactory { +final class ScreenPopupFactory extends PopupFactory { static final Float TRANSLUCENT = 248f/255f; static final Float OPAQUE = 1.0f; @@ -50,6 +50,7 @@ private static Window getWindow(final Component c) { return (Window)w; } + @Override public Popup getPopup(final Component comp, final Component invoker, final int x, final int y) { if (invoker == null) throw new IllegalArgumentException("Popup.getPopup must be passed non-null contents"); diff --git a/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java b/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java index 728ee39a092..97d4e444454 100644 --- a/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java +++ b/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java @@ -29,7 +29,7 @@ import java.awt.Toolkit; @SuppressWarnings({"restricted"}) -public class PlatformGraphicsInfo { +public final class PlatformGraphicsInfo { static { System.loadLibrary("awt"); diff --git a/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java b/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java index 7ce12b7d4f7..f94b8968614 100644 --- a/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java +++ b/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java @@ -30,7 +30,7 @@ import static sun.font.FontUtilities.isDefaultIgnorable; import static sun.font.FontUtilities.isIgnorableWhitespace; -public class CCharToGlyphMapper extends CharToGlyphMapper { +public final class CCharToGlyphMapper extends CharToGlyphMapper { private static native int countGlyphs(final long nativeFontPtr); private Cache cache = new Cache(); @@ -42,6 +42,7 @@ public CCharToGlyphMapper(CFont font) { missingGlyph = 0; // for getMissingGlyphCode() } + @Override public int getNumGlyphs() { if (numGlyphs == -1) { numGlyphs = countGlyphs(fFont.getNativeFontPtr()); @@ -49,16 +50,19 @@ public int getNumGlyphs() { return numGlyphs; } + @Override public boolean canDisplay(char ch) { int glyph = charToGlyph(ch, false); return glyph != missingGlyph; } + @Override public boolean canDisplay(int cp) { int glyph = charToGlyph(cp, false); return glyph != missingGlyph; } + @Override public synchronized boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { @@ -91,6 +95,7 @@ public synchronized boolean charsToGlyphsNS(int count, return false; } + @Override public synchronized int charToGlyph(char unicode) { return charToGlyph(unicode, false); } @@ -109,10 +114,12 @@ private int charToGlyph(char unicode, boolean raw) { return glyph; } + @Override public synchronized int charToGlyph(int unicode) { return charToGlyph(unicode, false); } + @Override public synchronized int charToGlyphRaw(int unicode) { return charToGlyph(unicode, true); } @@ -131,10 +138,12 @@ private int charToGlyph(int unicode, boolean raw) { } } + @Override public synchronized void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { cache.get(count, unicodes, glyphs, false); } + @Override public synchronized void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { for (int i = 0; i < count; i++) { glyphs[i] = charToGlyph(unicodes[i], false); @@ -151,7 +160,7 @@ private static native void nativeCharsToGlyphs(final long nativeFontPtr, int count, char[] unicodes, int[] glyphs); - private class Cache { + private final class Cache { private static final int FIRST_LAYER_SIZE = 256; private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128 @@ -209,7 +218,7 @@ public synchronized void put(final int index, final int value) { generalCache.put(index, value); } - private class SparseBitShiftingTwoLayerArray { + private final class SparseBitShiftingTwoLayerArray { final int[][] cache; final int shift; final int secondLayerLength; diff --git a/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java b/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java index 1897c7af642..b290d9a06e1 100644 --- a/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java +++ b/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java @@ -46,6 +46,7 @@ private CharToGlyphMapper getSlotMapper(int slot) { return mapper; } + @Override public boolean canDisplay(char ch) { int glyph = charToGlyph(ch); return glyph != missingGlyph; @@ -67,6 +68,7 @@ private int convertToGlyph(int unicode) { return missingGlyph; } + @Override public int getNumGlyphs() { int numGlyphs = 0; for (int slot=0; slot<1 /*font.numSlots*/; slot++) { @@ -80,14 +82,17 @@ public int getNumGlyphs() { return numGlyphs; } + @Override public int charToGlyph(int unicode) { return convertToGlyph(unicode); } + @Override public int charToGlyph(char unicode) { return convertToGlyph(unicode); } + @Override public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { for (int i=0; i= 0x10000) { return false; } + @Override public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { for (int i=0; i familyNames, Loc } } + @Override protected void registerFontsInDir(final String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) { @@ -201,6 +202,7 @@ void registerItalicDerived() { private boolean loadedAllFonts = false; + @Override public void loadFonts() { synchronized(waitForFontsToBeLoaded) diff --git a/src/java.desktop/macosx/classes/sun/font/CStrike.java b/src/java.desktop/macosx/classes/sun/font/CStrike.java index cfab6a9f4c3..69b53433c4f 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -136,6 +136,7 @@ public long getNativeStrikePtr() { return nativeStrikePtr; } + @Override @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (nativeStrikePtr != 0) { @@ -183,6 +184,7 @@ Point2D.Float getGlyphMetrics(final int glyphCode) { return new Point2D.Float(getGlyphAdvance(glyphCode), 0.0f); } + @Override Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { GeneralPath gp = getGlyphOutline(glyphCode, 0f, 0f); Rectangle2D r2d = gp.getBounds2D(); @@ -200,6 +202,7 @@ Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { } // pt, result in device space + @Override void getGlyphImageBounds(int glyphCode, Point2D.Float pt, Rectangle result) { Rectangle2D.Float floatRect = new Rectangle2D.Float(); @@ -221,16 +224,19 @@ private void getGlyphImageBounds(int glyphCode, float x, float y, Rectangle2D.Fl getNativeGlyphImageBounds(getNativeStrikePtr(), glyphCode, floatRect, x, y); } + @Override GeneralPath getGlyphOutline(int glyphCode, float x, float y) { return getNativeGlyphOutline(getNativeStrikePtr(), glyphCode, x, y); } // should implement, however not called though any path that is publicly exposed + @Override GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) { throw new Error("not implemented yet"); } // called from the Sun2D renderer + @Override long getGlyphImagePtr(int glyphCode) { synchronized (glyphInfoCache) { long ptr = glyphInfoCache.get(glyphCode); @@ -250,6 +256,7 @@ long getGlyphImagePtr(int glyphCode) { } // called from the Sun2D renderer + @Override void getGlyphImagePtrs(int[] glyphCodes, long[] images, int len) { synchronized (glyphInfoCache) { // fill the image pointer array with existing pointers @@ -361,7 +368,7 @@ private float getCachedNativeGlyphAdvance(int glyphCode) { // This class stores glyph pointers, and is indexed based on glyph codes, // and negative unicode values. See the comments in // CCharToGlyphMapper for more details on our glyph code strategy. - private static class GlyphInfoCache extends CStrikeDisposer { + private static final class GlyphInfoCache extends CStrikeDisposer { private static final int FIRST_LAYER_SIZE = 256; private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128 @@ -428,6 +435,7 @@ public synchronized void put(final int index, final long value) { generalCache.put(Integer.valueOf(index), Long.valueOf(value)); } + @Override public synchronized void dispose() { // rdar://problem/5204197 // Note that sun.font.Font2D.getStrike() actively disposes @@ -476,7 +484,7 @@ private static void disposeLongArray(final long[] longArray) { } } - private static class SparseBitShiftingTwoLayerArray { + private static final class SparseBitShiftingTwoLayerArray { final long[][] cache; final int shift; final int secondLayerLength; @@ -505,7 +513,7 @@ public void put(final int index, final long value) { } } - private static class GlyphAdvanceCache { + private static final class GlyphAdvanceCache { private static final int FIRST_LAYER_SIZE = 256; private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128 @@ -558,7 +566,7 @@ public synchronized void put(final int index, final float value) { generalCache.put(Integer.valueOf(index), Float.valueOf(value)); } - private static class SparseBitShiftingTwoLayerArray { + private static final class SparseBitShiftingTwoLayerArray { final float[][] cache; final int shift; final int secondLayerLength; diff --git a/src/java.desktop/macosx/classes/sun/font/CStrikeDisposer.java b/src/java.desktop/macosx/classes/sun/font/CStrikeDisposer.java index b0c8c788ec9..f032d716e90 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrikeDisposer.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrikeDisposer.java @@ -75,6 +75,7 @@ public CStrikeDisposer(Font2D font2D, FontStrikeDesc desc) { super(font2D, desc); } + @Override public synchronized void dispose() { if (!disposed) { if (pNativeScalerContext != 0L) { diff --git a/src/java.desktop/macosx/classes/sun/font/NativeFont.java b/src/java.desktop/macosx/classes/sun/font/NativeFont.java index d3203da3980..6faf4adfb53 100644 --- a/src/java.desktop/macosx/classes/sun/font/NativeFont.java +++ b/src/java.desktop/macosx/classes/sun/font/NativeFont.java @@ -37,7 +37,7 @@ * and the font is ignored. */ -public class NativeFont extends PhysicalFont { +public final class NativeFont extends PhysicalFont { /** * Verifies native font is accessible. @@ -53,6 +53,7 @@ static boolean hasExternalBitmaps(String platName) { return false; } + @Override public CharToGlyphMapper getMapper() { return null; } @@ -61,6 +62,7 @@ PhysicalFont getDelegateFont() { return null; } + @Override FontStrike createStrike(FontStrikeDesc desc) { return null; } @@ -69,16 +71,19 @@ public Rectangle2D getMaxCharBounds(FontRenderContext frc) { return null; } + @Override StrikeMetrics getFontMetrics(long pScalerContext) { return null; } + @Override public GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) { return null; } + @Override public GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) { @@ -86,20 +91,24 @@ public GeneralPath getGlyphVectorOutline(long pScalerContext, } + @Override long getGlyphImage(long pScalerContext, int glyphCode) { return 0L; } + @Override void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) { } + @Override float getGlyphAdvance(long pScalerContext, int glyphCode) { return 0f; } + @Override Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) { return new Rectangle2D.Float(0f, 0f, 0f, 0f); diff --git a/src/java.desktop/macosx/classes/sun/font/NativeStrike.java b/src/java.desktop/macosx/classes/sun/font/NativeStrike.java index de5c3aca312..d7c16150328 100644 --- a/src/java.desktop/macosx/classes/sun/font/NativeStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/NativeStrike.java @@ -48,9 +48,11 @@ public class NativeStrike extends PhysicalStrike { } + @Override void getGlyphImagePtrs(int[] glyphCodes, long[] images,int len) { } + @Override long getGlyphImagePtr(int glyphCode) { return 0L; } @@ -59,26 +61,32 @@ long getGlyphImagePtrNoCache(int glyphCode) { return 0L; } + @Override void getGlyphImageBounds(int glyphcode, Point2D.Float pt, Rectangle result) { } + @Override Point2D.Float getGlyphMetrics(int glyphCode) { return null; } + @Override float getGlyphAdvance(int glyphCode) { return 0f; } + @Override Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { return null; } + @Override GeneralPath getGlyphOutline(int glyphCode, float x, float y) { return null; } + @Override GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) { return null; } diff --git a/src/java.desktop/macosx/classes/sun/java2d/CRenderer.java b/src/java.desktop/macosx/classes/sun/java2d/CRenderer.java index fc39f5572ac..9dd2c3a0bc7 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/CRenderer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/CRenderer.java @@ -45,6 +45,7 @@ public class CRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, D native void doLine(SurfaceData sData, float x1, float y1, float x2, float y2); + @Override public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { drawLine(sg2d, (float) x1, (float) y1, (float) x2, (float) y2); } @@ -72,6 +73,7 @@ public void drawLine(SunGraphics2D sg2d, float x1, float y1, float x2, float y2) native void doRect(SurfaceData sData, float x, float y, float width, float height, boolean isfill); + @Override public void drawRect(SunGraphics2D sg2d, int x, int y, int width, int height) { drawRect(sg2d, (float) x, (float) y, (float) width, (float) height); } @@ -99,6 +101,7 @@ public void drawRect(SunGraphics2D sg2d, float x, float y, float width, float he } } + @Override public void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) { fillRect(sg2d, (float) x, (float) y, (float) width, (float) height); } @@ -112,6 +115,7 @@ public void fillRect(SunGraphics2D sg2d, float x, float y, float width, float he native void doRoundRect(SurfaceData sData, float x, float y, float width, float height, float arcW, float arcH, boolean isfill); + @Override public void drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) { drawRoundRect(sg2d, (float) x, (float) y, (float) width, (float) height, (float) arcWidth, (float) arcHeight); } @@ -139,6 +143,7 @@ public void drawRoundRect(SunGraphics2D sg2d, float x, float y, float width, flo } } + @Override public void fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) { fillRoundRect(sg2d, (float) x, (float) y, (float) width, (float) height, (float) arcWidth, (float) arcHeight); } @@ -151,6 +156,7 @@ public void fillRoundRect(SunGraphics2D sg2d, float x, float y, float width, flo native void doOval(SurfaceData sData, float x, float y, float width, float height, boolean isfill); + @Override public void drawOval(SunGraphics2D sg2d, int x, int y, int width, int height) { drawOval(sg2d, (float) x, (float) y, (float) width, (float) height); } @@ -178,6 +184,7 @@ public void drawOval(SunGraphics2D sg2d, float x, float y, float width, float he } } + @Override public void fillOval(SunGraphics2D sg2d, int x, int y, int width, int height) { fillOval(sg2d, (float) x, (float) y, (float) width, (float) height); } @@ -190,6 +197,7 @@ public void fillOval(SunGraphics2D sg2d, float x, float y, float width, float he native void doArc(SurfaceData sData, float x, float y, float width, float height, float angleStart, float angleExtent, int type, boolean isfill); + @Override public void drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) { drawArc(sg2d, x, y, width, height, startAngle, arcAngle, Arc2D.OPEN); } @@ -217,6 +225,7 @@ public void drawArc(SunGraphics2D sg2d, float x, float y, float width, float hei } } + @Override public void fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) { fillArc(sg2d, x, y, width, height, startAngle, arcAngle, Arc2D.PIE); } @@ -230,6 +239,7 @@ public void fillArc(SunGraphics2D sg2d, float x, float y, float width, float hei native void doPoly(SurfaceData sData, int[] xpoints, int[] ypoints, int npoints, boolean ispolygon, boolean isfill); + @Override public void drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); if ((sg2d.strokeState != SunGraphics2D.STROKE_CUSTOM) && (OSXSurfaceData.IsSimpleColor(sg2d.paint))) { @@ -244,6 +254,7 @@ public void drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int n } } + @Override public void drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); if ((sg2d.strokeState != SunGraphics2D.STROKE_CUSTOM) && (OSXSurfaceData.IsSimpleColor(sg2d.paint))) { @@ -259,6 +270,7 @@ public void drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int np } } + @Override public void fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); surfaceData.doPolygon(this, sg2d, xpoints, ypoints, npoints, true, true); @@ -374,6 +386,7 @@ void drawfillShape(SunGraphics2D sg2d, Shape s, boolean isfill, boolean shouldAp } } + @Override public void draw(SunGraphics2D sg2d, Shape s) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); if ((sg2d.strokeState != SunGraphics2D.STROKE_CUSTOM) && (OSXSurfaceData.IsSimpleColor(sg2d.paint))) { @@ -383,6 +396,7 @@ public void draw(SunGraphics2D sg2d, Shape s) { } } + @Override public void fill(SunGraphics2D sg2d, Shape s) { drawfillShape(sg2d, s, true, false); } @@ -527,6 +541,7 @@ protected boolean imageReady(sun.awt.image.ToolkitImage sunimg, ImageObserver ob } // copied from DrawImage.java + @Override public boolean copyImage(SunGraphics2D sg2d, Image img, int x, int y, Color bgColor, ImageObserver observer) { if (img == null) { throw new NullPointerException(); } @@ -539,6 +554,7 @@ public boolean copyImage(SunGraphics2D sg2d, Image img, int x, int y, Color bgCo } // copied from DrawImage.java + @Override public boolean copyImage(SunGraphics2D sg2d, Image img, int dx, int dy, int sx, int sy, int width, int height, Color bgColor, ImageObserver observer) { if (img == null) { throw new NullPointerException(); } @@ -551,6 +567,7 @@ public boolean copyImage(SunGraphics2D sg2d, Image img, int dx, int dy, int sx, } // copied from DrawImage.java + @Override public boolean scaleImage(SunGraphics2D sg2d, Image img, int x, int y, int width, int height, Color bgColor, ImageObserver observer) { if (img == null) { throw new NullPointerException(); } @@ -563,6 +580,7 @@ public boolean scaleImage(SunGraphics2D sg2d, Image img, int x, int y, int width } // copied from DrawImage.java + @Override public boolean scaleImage(SunGraphics2D sg2d, Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgColor, ImageObserver observer) { if (img == null) { throw new NullPointerException(); } @@ -575,6 +593,7 @@ public boolean scaleImage(SunGraphics2D sg2d, Image img, int dx1, int dy1, int d } // copied from DrawImage.java + @Override public boolean transformImage(SunGraphics2D sg2d, Image img, AffineTransform atfm, ImageObserver observer) { if (img == null) { throw new NullPointerException(); } @@ -590,6 +609,7 @@ public boolean transformImage(SunGraphics2D sg2d, Image img, AffineTransform atf } // copied from DrawImage.java + @Override public void transformImage(SunGraphics2D sg2d, BufferedImage img, BufferedImageOp op, int x, int y) { if (img != null) { transformImage(sg2d, img, x, y, op, null, null); @@ -602,42 +622,50 @@ public CRenderer traceWrap() { return new Tracer(); } - public static class Tracer extends CRenderer { + public static final class Tracer extends CRenderer { + @Override void doLine(SurfaceData sData, float x1, float y1, float x2, float y2) { GraphicsPrimitive.tracePrimitive("QuartzLine"); super.doLine(sData, x1, y1, x2, y2); } + @Override void doRect(SurfaceData sData, float x, float y, float width, float height, boolean isfill) { GraphicsPrimitive.tracePrimitive("QuartzRect"); super.doRect(sData, x, y, width, height, isfill); } + @Override void doRoundRect(SurfaceData sData, float x, float y, float width, float height, float arcW, float arcH, boolean isfill) { GraphicsPrimitive.tracePrimitive("QuartzRoundRect"); super.doRoundRect(sData, x, y, width, height, arcW, arcH, isfill); } + @Override void doOval(SurfaceData sData, float x, float y, float width, float height, boolean isfill) { GraphicsPrimitive.tracePrimitive("QuartzOval"); super.doOval(sData, x, y, width, height, isfill); } + @Override void doArc(SurfaceData sData, float x, float y, float width, float height, float angleStart, float angleExtent, int type, boolean isfill) { GraphicsPrimitive.tracePrimitive("QuartzArc"); super.doArc(sData, x, y, width, height, angleStart, angleExtent, type, isfill); } + @Override void doPoly(SurfaceData sData, int[] xpoints, int[] ypoints, int npoints, boolean ispolygon, boolean isfill) { GraphicsPrimitive.tracePrimitive("QuartzDoPoly"); super.doPoly(sData, xpoints, ypoints, npoints, ispolygon, isfill); } + @Override void doShape(SurfaceData sData, int length, FloatBuffer coordinates, IntBuffer types, int windingRule, boolean isfill, boolean shouldApplyOffset) { GraphicsPrimitive.tracePrimitive("QuartzFillOrDrawShape"); super.doShape(sData, length, coordinates, types, windingRule, isfill, shouldApplyOffset); } + @Override void doImage(SurfaceData sData, SurfaceData img, boolean fliph, boolean flipv, int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) { GraphicsPrimitive.tracePrimitive("QuartzDrawImage"); super.doImage(sData, img, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh); diff --git a/src/java.desktop/macosx/classes/sun/java2d/CompositeCRenderer.java b/src/java.desktop/macosx/classes/sun/java2d/CompositeCRenderer.java index a5e218310c5..e23bcbdbbee 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/CompositeCRenderer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/CompositeCRenderer.java @@ -34,7 +34,7 @@ import sun.java2d.loops.*; import sun.java2d.pipe.*; -public class CompositeCRenderer extends CRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, DrawImagePipe, TextPipe { +public final class CompositeCRenderer extends CRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, DrawImagePipe, TextPipe { static final int fPadding = 4; static final int fPaddingHalf = fPadding / 2; @@ -49,6 +49,7 @@ public class CompositeCRenderer extends CRenderer implements PixelDrawPipe, Pixe Ellipse2D ellipse = new Ellipse2D.Float(); Arc2D arc = new Arc2D.Float(); + @Override public synchronized void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { // create shape corresponding to this primitive line.setLine(x1, y1, x2, y2); @@ -56,6 +57,7 @@ public synchronized void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, in draw(sg2d, line); } + @Override public synchronized void drawRect(SunGraphics2D sg2d, int x, int y, int width, int height) { // create shape corresponding to this primitive rectangle.setRect(x, y, width, height); @@ -63,6 +65,7 @@ public synchronized void drawRect(SunGraphics2D sg2d, int x, int y, int width, i draw(sg2d, rectangle); } + @Override public synchronized void drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) { // create shape corresponding to this primitive roundrectangle.setRoundRect(x, y, width, height, arcWidth, arcHeight); @@ -70,6 +73,7 @@ public synchronized void drawRoundRect(SunGraphics2D sg2d, int x, int y, int wid draw(sg2d, roundrectangle); } + @Override public synchronized void drawOval(SunGraphics2D sg2d, int x, int y, int width, int height) { // create shape corresponding to this primitive ellipse.setFrame(x, y, width, height); @@ -77,6 +81,7 @@ public synchronized void drawOval(SunGraphics2D sg2d, int x, int y, int width, i draw(sg2d, ellipse); } + @Override public synchronized void drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) { // create shape corresponding to this primitive arc.setArc(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN); @@ -84,14 +89,17 @@ public synchronized void drawArc(SunGraphics2D sg2d, int x, int y, int width, in draw(sg2d, arc); } + @Override public synchronized void drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { doPolygon(sg2d, xpoints, ypoints, npoints, false, false); } + @Override public synchronized void drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { doPolygon(sg2d, xpoints, ypoints, npoints, true, false); } + @Override public synchronized void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) { // create shape corresponding to this primitive rectangle.setRect(x, y, width, height); @@ -99,6 +107,7 @@ public synchronized void fillRect(SunGraphics2D sg2d, int x, int y, int width, i fill(sg2d, rectangle); } + @Override public synchronized void fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) { // create shape corresponding to this primitive roundrectangle.setRoundRect(x, y, width, height, arcWidth, arcHeight); @@ -106,6 +115,7 @@ public synchronized void fillRoundRect(SunGraphics2D sg2d, int x, int y, int wid fill(sg2d, roundrectangle); } + @Override public synchronized void fillOval(SunGraphics2D sg2d, int x, int y, int width, int height) { // create shape corresponding to this primitive ellipse.setFrame(x, y, width, height); @@ -113,6 +123,7 @@ public synchronized void fillOval(SunGraphics2D sg2d, int x, int y, int width, i fill(sg2d, ellipse); } + @Override public synchronized void fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) { // create shape corresponding to this primitive arc.setArc(x, y, width, height, startAngle, arcAngle, Arc2D.PIE); @@ -120,6 +131,7 @@ public synchronized void fillArc(SunGraphics2D sg2d, int x, int y, int width, in fill(sg2d, arc); } + @Override public synchronized void fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) { doPolygon(sg2d, xpoints, ypoints, npoints, true, true); } @@ -140,10 +152,12 @@ public synchronized void doPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoi doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), (Shape) gp, isfill); } + @Override public synchronized void draw(SunGraphics2D sg2d, Shape shape) { doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), shape, false); } + @Override public synchronized void fill(SunGraphics2D sg2d, Shape shape) { doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), shape, true); } @@ -192,10 +206,12 @@ void doShape(SunGraphics2D sg2d, OSXSurfaceData surfaceData, Shape shape, boolea } } + @Override public synchronized void drawString(SunGraphics2D sg2d, String str, double x, double y) { drawGlyphVector(sg2d, sg2d.getFont().createGlyphVector(sg2d.getFontRenderContext(), str), x, y); } + @Override public synchronized void drawChars(SunGraphics2D sg2d, char[] data, int offset, int length, int x, int y) { drawString(sg2d, new String(data, offset, length), x, y); } @@ -204,6 +220,7 @@ public synchronized void drawGlyphVector(SunGraphics2D sg2d, GlyphVector glyphVe drawGlyphVector(sg2d, glyphVector, (float) x, (float) y); } + @Override public synchronized void drawGlyphVector(SunGraphics2D sg2d, GlyphVector glyphVector, float x, float y) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); @@ -242,6 +259,7 @@ public synchronized void drawGlyphVector(SunGraphics2D sg2d, GlyphVector glyphVe } } + @Override protected boolean blitImage(SunGraphics2D sg2d, Image img, boolean fliph, boolean flipv, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, Color bgColor) { OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData(); diff --git a/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java b/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java index f8e216f5064..3627a8f47f3 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java +++ b/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java @@ -105,6 +105,7 @@ public int[][] getBankData() { * @see #setElem(int, int) * @see #setElem(int, int, int) */ + @Override public int getElem(int i) { return data.get(i+offset); } @@ -118,6 +119,7 @@ public int getElem(int i) { * @see #setElem(int, int) * @see #setElem(int, int, int) */ + @Override public int getElem(int bank, int i) { return bankdata[bank].get(i+offsets[bank]); } @@ -131,6 +133,7 @@ public int getElem(int bank, int i) { * @see #getElem(int) * @see #getElem(int, int) */ + @Override public void setElem(int i, int val) { data.put(i+offset, val); } @@ -144,6 +147,7 @@ public void setElem(int i, int val) { * @see #getElem(int) * @see #getElem(int, int) */ + @Override public void setElem(int bank, int i, int val) { bankdata[bank].put(i+offsets[bank], val); } diff --git a/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java b/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java index a09bf9b5435..65631c0de86 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java +++ b/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java @@ -30,7 +30,7 @@ import java.nio.IntBuffer; import sun.awt.image.SunWritableRaster; -public class IntegerNIORaster extends SunWritableRaster { +public final class IntegerNIORaster extends SunWritableRaster { protected IntBuffer data; @@ -55,10 +55,12 @@ public IntegerNIORaster(SampleModel sampleModel, DataBufferNIOInt dataBuffer, Po this.data = dataBuffer.getBuffer(); } + @Override public WritableRaster createCompatibleWritableRaster() { return new IntegerNIORaster(sampleModel, new DataBufferNIOInt(sampleModel.getWidth() * sampleModel.getHeight()), new Point(0,0)); } + @Override public WritableRaster createCompatibleWritableRaster(int w, int h) { if (w <= 0 || h <=0) { throw new RasterFormatException("negative " + ((w <= 0) ? "width" : "height")); @@ -69,6 +71,7 @@ public WritableRaster createCompatibleWritableRaster(int w, int h) { return new IntegerNIORaster(sm, new DataBufferNIOInt(w * h), new Point(0,0)); } + @Override public WritableRaster createCompatibleWritableRaster(Rectangle rect) { if (rect == null) { throw new NullPointerException("Rect cannot be null"); @@ -76,6 +79,7 @@ public WritableRaster createCompatibleWritableRaster(Rectangle rect) { return createCompatibleWritableRaster(rect.x, rect.y, rect.width, rect.height); } + @Override public WritableRaster createCompatibleWritableRaster(int x, int y, int w, int h) { WritableRaster ret = createCompatibleWritableRaster(w, h); return ret.createWritableChild(0,0,w,h,x,y,null); @@ -86,6 +90,7 @@ public IntBuffer getBuffer() { return data; } + @Override public String toString() { return "IntegerNIORaster: width = " + width + " height = " + height diff --git a/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java b/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java index f2fb23f0a61..14a8231d890 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java +++ b/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java @@ -29,7 +29,7 @@ import sun.java2d.opengl.CGLGraphicsConfig; -public class MacOSFlags { +public final class MacOSFlags { /** * Description of command-line flags. All flags with [true|false] diff --git a/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java b/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java index e61ce02077c..77d7f66fed6 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java @@ -33,7 +33,7 @@ import sun.awt.image.*; import sun.java2d.loops.*; -public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements RasterListener +public final class OSXOffScreenSurfaceData extends OSXSurfaceData // implements RasterListener { private static native void initIDs(); @@ -474,6 +474,7 @@ public Object getLockObject() { /** * Performs a copyArea within this surface. */ + @Override public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { // For the Sun2D renderer we should rely on the implementation of the super class. // BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class. @@ -524,6 +525,7 @@ public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, * * Only used by compositor code (private API) */ + @Override public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage) { // create the destination image if needed if (dstImage == null) { @@ -538,6 +540,7 @@ public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, Bu return dstImage; } + @Override public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR) { int type = this.bim.getType(); @@ -549,6 +552,7 @@ public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int native boolean xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h); + @Override public void clearRect(BufferedImage bim, int w, int h) { OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) (OSXOffScreenSurfaceData.createData(bim)); // offsd.clear(); diff --git a/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java b/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java index 78fece98867..a56063c0049 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java @@ -88,6 +88,7 @@ public OSXSurfaceData(SurfaceType sType, ColorModel cm, GraphicsConfiguration co // Thread.dumpStack(); } + @Override public void validatePipe(SunGraphics2D sg2d) { if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) { @@ -121,11 +122,13 @@ protected void setPipesToQuartzComposite(SunGraphics2D sg2d) { sg2d.textpipe = sCocoaTextPipe; } + @Override public Rectangle getBounds() { // gznote: always return a copy, not the rect itself and translate into device space return new Rectangle(fBounds.x, fBounds.y, fBounds.width, fBounds.height - fBounds.y); } + @Override public GraphicsConfiguration getDeviceConfiguration() { return fConfig; } @@ -194,6 +197,7 @@ public void clearRect(BufferedImage bim, int w, int h) { // END compositing support API + @Override public void invalidate() { // always valid } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java index 6be497ee9ce..d807f954d71 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java @@ -334,7 +334,7 @@ static void IsoBlit(SurfaceData srcData, SurfaceData dstData, } } -class MTLSurfaceToSurfaceBlit extends Blit { +final class MTLSurfaceToSurfaceBlit extends Blit { MTLSurfaceToSurfaceBlit() { super(MTLSurfaceData.MTLSurface, @@ -342,6 +342,7 @@ class MTLSurfaceToSurfaceBlit extends Blit { MTLSurfaceData.MTLSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -356,7 +357,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLSurfaceToSurfaceScale extends ScaledBlit { +final class MTLSurfaceToSurfaceScale extends ScaledBlit { MTLSurfaceToSurfaceScale() { super(MTLSurfaceData.MTLSurface, @@ -364,6 +365,7 @@ class MTLSurfaceToSurfaceScale extends ScaledBlit { MTLSurfaceData.MTLSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -381,7 +383,7 @@ public void Scale(SurfaceData src, SurfaceData dst, } } -class MTLSurfaceToSurfaceTransform extends TransformBlit { +final class MTLSurfaceToSurfaceTransform extends TransformBlit { MTLSurfaceToSurfaceTransform() { super(MTLSurfaceData.MTLSurface, @@ -389,6 +391,7 @@ class MTLSurfaceToSurfaceTransform extends TransformBlit { MTLSurfaceData.MTLSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -404,7 +407,7 @@ public void Transform(SurfaceData src, SurfaceData dst, } } -class MTLRTTSurfaceToSurfaceBlit extends Blit { +final class MTLRTTSurfaceToSurfaceBlit extends Blit { MTLRTTSurfaceToSurfaceBlit() { super(MTLSurfaceData.MTLSurfaceRTT, @@ -412,6 +415,7 @@ class MTLRTTSurfaceToSurfaceBlit extends Blit { MTLSurfaceData.MTLSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -426,7 +430,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLRTTSurfaceToSurfaceScale extends ScaledBlit { +final class MTLRTTSurfaceToSurfaceScale extends ScaledBlit { MTLRTTSurfaceToSurfaceScale() { super(MTLSurfaceData.MTLSurfaceRTT, @@ -434,6 +438,7 @@ class MTLRTTSurfaceToSurfaceScale extends ScaledBlit { MTLSurfaceData.MTLSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -451,7 +456,7 @@ public void Scale(SurfaceData src, SurfaceData dst, } } -class MTLRTTSurfaceToSurfaceTransform extends TransformBlit { +final class MTLRTTSurfaceToSurfaceTransform extends TransformBlit { MTLRTTSurfaceToSurfaceTransform() { super(MTLSurfaceData.MTLSurfaceRTT, @@ -459,6 +464,7 @@ class MTLRTTSurfaceToSurfaceTransform extends TransformBlit { MTLSurfaceData.MTLSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -521,6 +527,7 @@ private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, } } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -574,7 +581,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLSwToSurfaceBlit extends Blit { +final class MTLSwToSurfaceBlit extends Blit { private int typeval; @@ -585,6 +592,7 @@ class MTLSwToSurfaceBlit extends Blit { this.typeval = typeval; } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -598,7 +606,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLSwToSurfaceScale extends ScaledBlit { +final class MTLSwToSurfaceScale extends ScaledBlit { private int typeval; @@ -609,6 +617,7 @@ class MTLSwToSurfaceScale extends ScaledBlit { this.typeval = typeval; } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -625,7 +634,7 @@ public void Scale(SurfaceData src, SurfaceData dst, } } -class MTLSwToSurfaceTransform extends TransformBlit { +final class MTLSwToSurfaceTransform extends TransformBlit { private int typeval; @@ -636,6 +645,7 @@ class MTLSwToSurfaceTransform extends TransformBlit { this.typeval = typeval; } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -649,7 +659,7 @@ public void Transform(SurfaceData src, SurfaceData dst, } } -class MTLSwToTextureBlit extends Blit { +final class MTLSwToTextureBlit extends Blit { private int typeval; @@ -660,6 +670,7 @@ class MTLSwToTextureBlit extends Blit { this.typeval = typeval; } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -673,7 +684,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLTextureToSurfaceBlit extends Blit { +final class MTLTextureToSurfaceBlit extends Blit { MTLTextureToSurfaceBlit() { super(MTLSurfaceData.MTLTexture, @@ -681,6 +692,7 @@ class MTLTextureToSurfaceBlit extends Blit { MTLSurfaceData.MTLSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -695,7 +707,7 @@ public void Blit(SurfaceData src, SurfaceData dst, } } -class MTLTextureToSurfaceScale extends ScaledBlit { +final class MTLTextureToSurfaceScale extends ScaledBlit { MTLTextureToSurfaceScale() { super(MTLSurfaceData.MTLTexture, @@ -703,6 +715,7 @@ class MTLTextureToSurfaceScale extends ScaledBlit { MTLSurfaceData.MTLSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -720,7 +733,7 @@ public void Scale(SurfaceData src, SurfaceData dst, } } -class MTLTextureToSurfaceTransform extends TransformBlit { +final class MTLTextureToSurfaceTransform extends TransformBlit { MTLTextureToSurfaceTransform() { super(MTLSurfaceData.MTLTexture, @@ -728,6 +741,7 @@ class MTLTextureToSurfaceTransform extends TransformBlit { MTLSurfaceData.MTLSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -749,7 +763,7 @@ public void Transform(SurfaceData src, SurfaceData dst, * IntArgbPre->MTLSurface/Texture loop to get the intermediate * (premultiplied) surface down to Metal using simple blit. */ -class MTLGeneralBlit extends Blit { +final class MTLGeneralBlit extends Blit { private final Blit performop; private WeakReference srcTmp; @@ -762,6 +776,7 @@ class MTLGeneralBlit extends Blit { this.performop = performop; } + @Override public synchronized void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -857,6 +872,7 @@ final class MTLAnyCompositeBlit extends Blit { this.convertresult = convertresult; } + @Override public synchronized void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBufImgOps.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBufImgOps.java index fded8f6c72b..534ab101075 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBufImgOps.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBufImgOps.java @@ -39,7 +39,7 @@ import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER; -class MTLBufImgOps extends BufferedBufImgOps { +final class MTLBufImgOps extends BufferedBufImgOps { /** * This method is called from MTLDrawImage.transformImage() only. It diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java index 516fe33fd4e..b3bcf6633c6 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java @@ -78,7 +78,7 @@ public static void setScratchSurface(long pConfigInfo) { buf.putLong(pConfigInfo); } - public static class MTLContextCaps extends ContextCapabilities { + public static final class MTLContextCaps extends ContextCapabilities { /** Indicates that the context is doublebuffered. */ @Native diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLDrawImage.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLDrawImage.java index 06ef5c4c089..cb24cfdea2c 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLDrawImage.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLDrawImage.java @@ -38,7 +38,7 @@ import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; -public class MTLDrawImage extends DrawImage { +public final class MTLDrawImage extends DrawImage { @Override protected void renderImageXform(SunGraphics2D sg, Image img, diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java index e4afec42482..0278a6bce36 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java @@ -208,11 +208,12 @@ public boolean isDoubleBuffered() { return true; } - private static class MTLGCDisposerRecord implements DisposerRecord { + private static final class MTLGCDisposerRecord implements DisposerRecord { private long pCfgInfo; public MTLGCDisposerRecord(long pCfgInfo) { this.pCfgInfo = pCfgInfo; } + @Override public void dispose() { if (pCfgInfo != 0) { MTLRenderQueue.disposeGraphicsConfig(pCfgInfo); @@ -302,7 +303,7 @@ public void flip(final LWComponentPeer peer, final Image backBuffer, } } - private static class MTLBufferCaps extends BufferCapabilities { + private static final class MTLBufferCaps extends BufferCapabilities { public MTLBufferCaps(boolean dblBuf) { super(imageCaps, imageCaps, dblBuf ? FlipContents.UNDEFINED : null); @@ -317,10 +318,11 @@ public BufferCapabilities getBufferCapabilities() { return bufferCaps; } - private static class MTLImageCaps extends ImageCapabilities { + private static final class MTLImageCaps extends ImageCapabilities { private MTLImageCaps() { super(true); } + @Override public boolean isTrueVolatile() { return true; } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java index 890c55376c7..645b2e8a2f5 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java @@ -32,7 +32,7 @@ import java.awt.GraphicsConfiguration; import java.awt.Insets; -public class MTLLayer extends CFLayer { +public final class MTLLayer extends CFLayer { private native long nativeCreateLayer(); private static native void nativeSetScale(long layerPtr, double scale); @@ -52,6 +52,7 @@ public MTLLayer(LWWindowPeer peer) { this.peer = peer; } + @Override public SurfaceData replaceSurfaceData() { if (getBounds().isEmpty()) { surfaceData = NullSurfaceData.theInstance; diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java index 15f0ada65c5..3cc61ead145 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java @@ -39,7 +39,7 @@ import static sun.java2d.loops.CompositeType.SrcOver; import static sun.java2d.loops.SurfaceType.*; -class MTLMaskBlit extends BufferedMaskBlit { +final class MTLMaskBlit extends BufferedMaskBlit { static void register() { GraphicsPrimitive[] primitives = { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java index 04b5ea90a23..a6876c919e5 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java @@ -38,7 +38,7 @@ import static sun.java2d.loops.CompositeType.SrcOver; import static sun.java2d.loops.SurfaceType.*; -class MTLMaskFill extends BufferedMaskFill { +final class MTLMaskFill extends BufferedMaskFill { static void register() { GraphicsPrimitive[] primitives = { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java index 12f789deb35..79625b875ce 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java @@ -78,7 +78,7 @@ static boolean isValid(SunGraphics2D sg2d) { /************************* GradientPaint support ****************************/ - private static class Gradient extends MTLPaints { + private static final class Gradient extends MTLPaints { private Gradient() {} /** @@ -93,7 +93,7 @@ boolean isPaintValid(SunGraphics2D sg2d) { /************************** TexturePaint support ****************************/ - private static class Texture extends MTLPaints { + private static final class Texture extends MTLPaints { private Texture() {} /** @@ -171,7 +171,7 @@ boolean isPaintValid(SunGraphics2D sg2d) { /********************** LinearGradientPaint support *************************/ - private static class LinearGradient extends MultiGradient { + private static final class LinearGradient extends MultiGradient { private LinearGradient() {} @Override @@ -193,7 +193,7 @@ boolean isPaintValid(SunGraphics2D sg2d) { /********************** RadialGradientPaint support *************************/ - private static class RadialGradient extends MultiGradient { + private static final class RadialGradient extends MultiGradient { private RadialGradient() {} } } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java index 85f9023eada..f63ed523454 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java @@ -38,7 +38,7 @@ * the queue, thus ensuring that only one thread communicates with the native * OpenGL libraries for the entire process. */ -public class MTLRenderQueue extends RenderQueue { +public final class MTLRenderQueue extends RenderQueue { private static MTLRenderQueue theInstance; private final QueueFlusher flusher; @@ -128,6 +128,7 @@ public void flushNow() { } } + @Override public void flushAndInvokeNow(Runnable r) { // assert lock.isHeldByCurrentThread(); try { @@ -153,7 +154,7 @@ private void flushBuffer() { refSet.clear(); } - private class QueueFlusher implements Runnable { + private final class QueueFlusher implements Runnable { private boolean needsFlush; private Runnable task; private Error error; @@ -192,6 +193,7 @@ public synchronized void flushAndInvokeNow(Runnable task) { flushNow(); } + @Override public synchronized void run() { boolean timedOut = false; while (true) { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderer.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderer.java index 44f8b9b6cee..9ef4dc9c3ab 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderer.java @@ -98,12 +98,13 @@ MTLRenderer traceWrap() { return new Tracer(this); } - private static class Tracer extends MTLRenderer { + private static final class Tracer extends MTLRenderer { private MTLRenderer mtlr; Tracer(MTLRenderer mtlr) { super(mtlr.rq); this.mtlr = mtlr; } + @Override public ParallelogramPipe getAAParallelogramPipe() { final ParallelogramPipe realpipe = mtlr.getAAParallelogramPipe(); return new ParallelogramPipe() { @@ -135,19 +136,23 @@ public void drawParallelogram(SunGraphics2D sg2d, } }; } + @Override protected void validateContext(SunGraphics2D sg2d) { mtlr.validateContext(sg2d); } + @Override public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { GraphicsPrimitive.tracePrimitive("MTLDrawLine"); mtlr.drawLine(sg2d, x1, y1, x2, y2); } + @Override public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("MTLDrawRect"); mtlr.drawRect(sg2d, x, y, w, h); } + @Override protected void drawPoly(SunGraphics2D sg2d, int[] xPoints, int[] yPoints, int nPoints, boolean isClosed) @@ -155,28 +160,33 @@ protected void drawPoly(SunGraphics2D sg2d, GraphicsPrimitive.tracePrimitive("MTLDrawPoly"); mtlr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed); } + @Override public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("MTLFillRect"); mtlr.fillRect(sg2d, x, y, w, h); } + @Override protected void drawPath(SunGraphics2D sg2d, Path2D.Float p2df, int transx, int transy) { GraphicsPrimitive.tracePrimitive("MTLDrawPath"); mtlr.drawPath(sg2d, p2df, transx, transy); } + @Override protected void fillPath(SunGraphics2D sg2d, Path2D.Float p2df, int transx, int transy) { GraphicsPrimitive.tracePrimitive("MTLFillPath"); mtlr.fillPath(sg2d, p2df, transx, transy); } + @Override protected void fillSpans(SunGraphics2D sg2d, SpanIterator si, int transx, int transy) { GraphicsPrimitive.tracePrimitive("MTLFillSpans"); mtlr.fillSpans(sg2d, si, transx, transy); } + @Override public void fillParallelogram(SunGraphics2D sg2d, double ux1, double uy1, double ux2, double uy2, @@ -189,6 +199,7 @@ public void fillParallelogram(SunGraphics2D sg2d, ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2); } + @Override public void drawParallelogram(SunGraphics2D sg2d, double ux1, double uy1, double ux2, double uy2, @@ -202,6 +213,7 @@ public void drawParallelogram(SunGraphics2D sg2d, ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2, lw1, lw2); } + @Override public void copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceData.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceData.java index 8dd2557743e..c8259f9056b 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceData.java @@ -291,6 +291,7 @@ public void run() { * Returns the MTLContext for the GraphicsConfig associated with this * surface. */ + @Override public final MTLContext getContext() { return graphicsConfig.getContext(); } @@ -305,6 +306,7 @@ final MTLGraphicsConfig getMTLGraphicsConfig() { /** * Returns one of the surface type constants defined above. */ + @Override public final int getType() { return type; } @@ -320,6 +322,7 @@ public final int getType() { * and remove the above restrictions, but that would require significantly * more code just to support a few uncommon cases. */ + @Override public boolean canRenderLCDText(SunGraphics2D sg2d) { return sg2d.surfaceData.getTransparency() == Transparency.OPAQUE && @@ -337,6 +340,7 @@ private boolean canHandleComposite(Composite c) { return false; } + @Override public void validatePipe(SunGraphics2D sg2d) { TextPipe textpipe; boolean validated = false; @@ -466,6 +470,7 @@ protected MaskFill getMaskFill(SunGraphics2D sg2d) { return super.getMaskFill(sg2d); } + @Override public void flush() { invalidate(); MTLRenderQueue rq = MTLRenderQueue.getInstance(); @@ -510,6 +515,7 @@ public boolean isOnScreen() { * such resource doesn't exist or can not be retrieved. * @see AccelSurface#getNativeResource */ + @Override public long getNativeResource(int resType) { if (resType == TEXTURE) { return getMTLTexturePointer(getNativeOps()); @@ -517,6 +523,7 @@ public long getNativeResource(int resType) { return 0L; } + @Override public Raster getRaster(int x, int y, int w, int h) { throw new InternalError("not implemented yet"); } @@ -531,6 +538,7 @@ public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, return true; } + @Override public Rectangle getNativeBounds() { MTLRenderQueue rq = MTLRenderQueue.getInstance(); rq.lock(); @@ -548,7 +556,7 @@ public Rectangle getNativeBounds() { * This surface serves as a buffer attached to a MTLLayer and * the layer redirects all painting to the buffer's graphics. */ - public static class MTLLayerSurfaceData extends MTLSurfaceData { + public static final class MTLLayerSurfaceData extends MTLSurfaceData { private final MTLLayer layer; @@ -589,7 +597,7 @@ public void invalidate() { /** * SurfaceData object representing an off-screen buffer */ - public static class MTLOffScreenSurfaceData extends MTLSurfaceData { + public static final class MTLOffScreenSurfaceData extends MTLSurfaceData { private final Image offscreenImage; public MTLOffScreenSurfaceData(MTLGraphicsConfig gc, int width, diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java index 5d694c56d25..a73728c7b03 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java @@ -37,7 +37,7 @@ * SurfaceData with a cached MTL Texture and the code to create * the accelerated surfaces. */ -public class MTLSurfaceDataProxy extends SurfaceDataProxy { +public final class MTLSurfaceDataProxy extends SurfaceDataProxy { public static SurfaceDataProxy createProxy(SurfaceData srcData, MTLGraphicsConfig dstConfig) { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java index b1284e0d552..ad7bd95071e 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java @@ -60,10 +60,11 @@ MTLTextRenderer traceWrap() { return new Tracer(this); } - private static class Tracer extends MTLTextRenderer { + private static final class Tracer extends MTLTextRenderer { Tracer(MTLTextRenderer mtltr) { super(mtltr.rq); } + @Override protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) { GraphicsPrimitive.tracePrimitive("MTLDrawGlyphs"); super.drawGlyphList(sg2d, gl); diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java index 4d337be1f61..e7d4b166eef 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java @@ -34,7 +34,7 @@ import java.awt.image.ColorModel; import sun.java2d.pipe.hw.AccelSurface; -public class MTLVolatileSurfaceManager extends VolatileSurfaceManager { +public final class MTLVolatileSurfaceManager extends VolatileSurfaceManager { private final boolean accelerationEnabled; @@ -49,6 +49,7 @@ public MTLVolatileSurfaceManager(SunVolatileImage vImg, Object context) { accelerationEnabled = transparency != Transparency.BITMASK; } + @Override protected boolean isAccelerationEnabled() { return accelerationEnabled; } @@ -57,6 +58,7 @@ protected boolean isAccelerationEnabled() { * Create a SurfaceData object (or init the backbuffer * of an existing window if this is a double buffered GraphicsConfig) */ + @Override protected SurfaceData initAcceleratedSurface() { try { MTLGraphicsConfig gc = diff --git a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java index 6022d516bf9..fb058fb38bf 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java @@ -210,11 +210,12 @@ public boolean isDoubleBuffered() { return isCapPresent(CAPS_DOUBLEBUFFERED); } - private static class CGLGCDisposerRecord implements DisposerRecord { + private static final class CGLGCDisposerRecord implements DisposerRecord { private long pCfgInfo; public CGLGCDisposerRecord(long pCfgInfo) { this.pCfgInfo = pCfgInfo; } + @Override public void dispose() { if (pCfgInfo != 0) { OGLRenderQueue.disposeGraphicsConfig(pCfgInfo); @@ -321,7 +322,7 @@ public void flip(final LWComponentPeer peer, final Image backBuffer, } } - private static class CGLBufferCaps extends BufferCapabilities { + private static final class CGLBufferCaps extends BufferCapabilities { public CGLBufferCaps(boolean dblBuf) { super(imageCaps, imageCaps, dblBuf ? FlipContents.UNDEFINED : null); @@ -336,10 +337,11 @@ public BufferCapabilities getBufferCapabilities() { return bufferCaps; } - private static class CGLImageCaps extends ImageCapabilities { + private static final class CGLImageCaps extends ImageCapabilities { private CGLImageCaps() { super(true); } + @Override public boolean isTrueVolatile() { return true; } diff --git a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLLayer.java b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLLayer.java index eb6629a0ae9..aa75a142e57 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLLayer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLLayer.java @@ -32,7 +32,7 @@ import sun.java2d.SurfaceData; import sun.lwawt.macosx.CFLayer; -public class CGLLayer extends CFLayer { +public final class CGLLayer extends CFLayer { private native long nativeCreateLayer(); private static native void nativeSetScale(long layerPtr, double scale); @@ -48,6 +48,7 @@ public CGLLayer(LWWindowPeer peer) { this.peer = peer; } + @Override public SurfaceData replaceSurfaceData() { if (getBounds().isEmpty()) { surfaceData = NullSurfaceData.theInstance; diff --git a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java index 667bcaad200..592d3783aba 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java @@ -110,7 +110,7 @@ public Rectangle getBounds() { * This surface serves as a buffer attached to a CGLLayer and * the layer redirects all painting to the buffer's graphics. */ - public static class CGLLayerSurfaceData extends CGLSurfaceData { + public static final class CGLLayerSurfaceData extends CGLSurfaceData { private final CGLLayer layer; @@ -152,7 +152,7 @@ public void invalidate() { * SurfaceData object representing an off-screen buffer (either a FBO or * Texture). */ - public static class CGLOffScreenSurfaceData extends CGLSurfaceData { + public static final class CGLOffScreenSurfaceData extends CGLSurfaceData { private final Image offscreenImage; diff --git a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java index 2bc1d98e1e1..86fe9387554 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java @@ -35,7 +35,7 @@ import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_EXT_FBOBJECT; -public class CGLVolatileSurfaceManager extends VolatileSurfaceManager { +public final class CGLVolatileSurfaceManager extends VolatileSurfaceManager { private final boolean accelerationEnabled; @@ -54,6 +54,7 @@ public CGLVolatileSurfaceManager(SunVolatileImage vImg, Object context) { && transparency != Transparency.BITMASK; } + @Override protected boolean isAccelerationEnabled() { return accelerationEnabled; } @@ -62,6 +63,7 @@ protected boolean isAccelerationEnabled() { * Create a FBO-based SurfaceData object (or init the backbuffer * of an existing window if this is a double buffered GraphicsConfig) */ + @Override protected SurfaceData initAcceleratedSurface() { try { CGLGraphicsConfig gc = (CGLGraphicsConfig)vImg.getGraphicsConfig(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java index b129e3b97f4..918bef702b1 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java @@ -29,7 +29,7 @@ import java.awt.Window; import sun.awt.KeyboardFocusManagerPeerImpl; -public class LWKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { +public final class LWKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { private static final LWKeyboardFocusManagerPeer inst = new LWKeyboardFocusManagerPeer(); private Window focusedWindow; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java index 41acd8ecab6..89b4a02c9d7 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -38,7 +38,7 @@ import sun.swing.JLightweightFrame; import sun.swing.SwingAccessor; -public class LWLightweightFramePeer extends LWWindowPeer implements OverrideNativeWindowHandle { +public final class LWLightweightFramePeer extends LWWindowPeer implements OverrideNativeWindowHandle { public LWLightweightFramePeer(LightweightFrame target, PlatformComponent platformComponent, diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java index a507b75a904..cd25f2328c2 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java @@ -32,7 +32,7 @@ import sun.awt.AWTAccessor; -public class LWMouseInfoPeer implements MouseInfoPeer { +public final class LWMouseInfoPeer implements MouseInfoPeer { @Override public int fillPointWithCoords(Point point) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 054e74dcef2..73e13908fbf 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -825,7 +825,7 @@ public void notifyMouseEvent(int id, long when, int button, topmostPlatformWindow != null ? topmostPlatformWindow.getPeer() : null; // topmostWindowPeer == null condition is added for the backward - // compatibility with applets. It can be removed when the + // compatibility. It can be removed when the // getTopmostPlatformWindowUnderMouse() method will be properly // implemented in CPlatformEmbeddedFrame class if (topmostWindowPeer == this || topmostWindowPeer == null) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 0017c39bfda..4947d1a109e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -72,7 +72,7 @@ import sun.lwawt.LWWindowPeer; import sun.swing.SwingAccessor; -class CAccessibility implements PropertyChangeListener { +final class CAccessibility implements PropertyChangeListener { private static Set ignoredRoles; static { @@ -104,6 +104,7 @@ private CAccessibility() { KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("focusOwner", this); } + @Override public void propertyChange(final PropertyChangeEvent evt) { Object newValue = evt.getNewValue(); if (newValue == null) return; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java index babe899296f..5be7f70b981 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java @@ -49,7 +49,7 @@ import sun.awt.AWTAccessor; -class CAccessible extends CFRetainedResource implements Accessible { +final class CAccessible extends CFRetainedResource implements Accessible { public static CAccessible getCAccessible(final Accessible a) { if (a == null) return null; @@ -111,7 +111,7 @@ public void addNotificationListeners(Component c) { } } - private class AXChangeNotifier implements PropertyChangeListener { + private final class AXChangeNotifier implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent e) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java index cee23f2f96e..1ad04eab47b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java @@ -38,7 +38,7 @@ import javax.swing.text.Element; import javax.swing.text.JTextComponent; -class CAccessibleText { +final class CAccessibleText { static AccessibleEditableText getAccessibleEditableText(final Accessible a, final Component c) { if (a == null) return null; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java index 5cc8fad2a4a..21021b2e9d0 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java @@ -31,7 +31,7 @@ import sun.awt.SunToolkit; -public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer { +public final class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer { volatile boolean fAutoToggle = true; volatile boolean fIsIndeterminate; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCustomCursor.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCustomCursor.java index 3312f6e4213..a2c749fcc79 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCustomCursor.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCustomCursor.java @@ -29,7 +29,7 @@ import java.awt.image.BufferedImage; @SuppressWarnings("serial") // JDK implementation class -public class CCustomCursor extends Cursor { +public final class CCustomCursor extends Cursor { static Dimension sMaxCursorSize; static Dimension getMaxCursorSize() { if (sMaxCursorSize != null) return sMaxCursorSize; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java index 32cd2efa795..065163adbb1 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java @@ -45,7 +45,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; -public class CDataTransferer extends DataTransferer { +public final class CDataTransferer extends DataTransferer { private static final Map predefinedClipboardNameMap; private static final Map predefinedClipboardFormatMap; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java index fe040d05bb2..35ef3c3897c 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java @@ -81,6 +81,7 @@ public static CDragSourceContextPeer createDragSourceContextPeer(DragGestureEven } // We have to overload this method just to be able to grab the drag image and its offset as shared code doesn't store it: + @Override public void startDrag(DragSourceContext dsc, Cursor cursor, Image dragImage, Point dragImageOffset) throws InvalidDnDOperationException { fDragImage = dragImage; fDragImageOffset = dragImageOffset; @@ -88,6 +89,7 @@ public void startDrag(DragSourceContext dsc, Cursor cursor, Image dragImage, Poi super.startDrag(dsc, cursor, dragImage, dragImageOffset); } + @Override protected void startDrag(Transferable transferable, long[] formats, Map formatMap) { DragGestureEvent trigger = getTrigger(); InputEvent triggerEvent = trigger.getTriggerEvent(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java index e15ad1e293c..b35eb9afd5d 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java @@ -51,6 +51,7 @@ private CDropTargetContextPeer() { super(); } + @Override protected Object getNativeData(long format) { long nativeDropTarget = this.getNativeDragContext(); @@ -153,6 +154,7 @@ protected int postDropTargetEvent(Component component, int x, int y, int dropAct } // Signal drop complete: + @Override protected void doDropDone(boolean success, int dropAction, boolean isLocal) { long nativeDropTarget = this.getNativeDragContext(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java index 049f8d0df32..fc9618ccf04 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java @@ -35,7 +35,7 @@ import sun.lwawt.LWWindowPeer; @SuppressWarnings("serial") // JDK implementation class -public class CEmbeddedFrame extends EmbeddedFrame { +public final class CEmbeddedFrame extends EmbeddedFrame { private CPlatformResponder responder; private static final Object classLock = new Object(); @@ -47,6 +47,7 @@ public CEmbeddedFrame() { show(); } + @Override public void addNotify() { if (!isDisplayable()) { LWCToolkit toolkit = (LWCToolkit)Toolkit.getDefaultToolkit(); @@ -57,8 +58,10 @@ public void addNotify() { super.addNotify(); } + @Override public void registerAccelerator(AWTKeyStroke stroke) {} + @Override public void unregisterAccelerator(AWTKeyStroke stroke) {} protected long getLayerPtr() { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java index 96879952dc3..8becf91f114 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java @@ -56,9 +56,9 @@ import sun.awt.AWTAccessor; import sun.java2d.pipe.Region; -class CFileDialog implements FileDialogPeer { +final class CFileDialog implements FileDialogPeer { - private class Task implements Runnable { + private final class Task implements Runnable { @Override public void run() { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CImage.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CImage.java index a7e9e15b02b..84cb12586e0 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CImage.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CImage.java @@ -38,7 +38,7 @@ import sun.awt.image.SunWritableRaster; -public class CImage extends CFRetainedResource { +public final class CImage extends CFRetainedResource { private static native long nativeCreateNSImageFromArray(int[] buffer, int w, int h); private static native long nativeCreateNSImageFromBytes(byte[] buffer); private static native long nativeCreateNSImageFromArrays(int[][] buffers, int[] w, int[] h); @@ -82,7 +82,7 @@ public static CImage createFromImage(final Image image, CTrayIcon.IconObserver o return getCreator().createFromImage(image, observer); } - public static class Creator { + public static final class Creator { CTrayIcon.IconObserver observer; Creator() { } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index c0804dbbbd0..fc504cc297d 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -44,7 +44,7 @@ import static sun.awt.AWTAccessor.ComponentAccessor; -public class CInputMethod extends InputMethodAdapter { +public final class CInputMethod extends InputMethodAdapter { private InputMethodContext fIMContext; private Component fAwtFocussedComponent; private LWComponentPeer fAwtFocussedComponentPeer; @@ -103,6 +103,7 @@ public CInputMethod() { * @param context the input method context for this input method * @throws NullPointerException if {@code context} is null */ + @Override public void setInputMethodContext(InputMethodContext context) { fIMContext = context; } @@ -126,6 +127,7 @@ public void setInputMethodContext(InputMethodContext context) { * @return whether the specified locale is supported * @throws NullPointerException if {@code locale} is null */ + @Override public boolean setLocale(Locale lang) { return setLocale(lang, false); } @@ -159,6 +161,7 @@ private boolean setLocale(Locale lang, boolean onActivate) { * * @return the current input locale, or null */ + @Override public Locale getLocale() { // On Mac OS X we'll ask the currently active input method what its locale is. Locale returnValue = getNativeLocale(); @@ -184,6 +187,7 @@ public Locale getLocale() { * @param subsets the subsets of the Unicode character set from which * characters may be input */ + @Override public void setCharacterSubsets(Subset[] subsets) { // -- SAK: Does mac OS X support this? } @@ -191,10 +195,12 @@ public void setCharacterSubsets(Subset[] subsets) { /** * Composition cannot be set on Mac OS X -- the input method remembers this */ + @Override public void setCompositionEnabled(boolean enable) { throw new UnsupportedOperationException("Can't adjust composition mode on Mac OS X."); } + @Override public boolean isCompositionEnabled() { throw new UnsupportedOperationException("Can't adjust composition mode on Mac OS X."); } @@ -218,6 +224,7 @@ public boolean isCompositionEnabled() { * @param event the event being dispatched to the input method * @throws NullPointerException if {@code event} is null */ + @Override public void dispatchEvent(final AWTEvent event) { // No-op for Mac OS X. } @@ -231,10 +238,12 @@ public void dispatchEvent(final AWTEvent event) { * * */ + @Override public void activate() { isActive = true; } + @Override public void deactivate(boolean isTemporary) { isActive = false; } @@ -243,6 +252,7 @@ public void deactivate(boolean isTemporary) { * Closes or hides all windows opened by this input method instance or * its class. Deactivate hides windows for us on Mac OS X. */ + @Override public void hideWindows() { } @@ -261,6 +271,7 @@ long getNativeViewPtr(LWComponentPeer peer) { * removed from its containment hierarchy, or that input method * support has been disabled for the component. */ + @Override public void removeNotify() { if (fAwtFocussedComponentPeer != null) { nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer)); @@ -275,6 +286,7 @@ public void removeNotify() { * We also take the opportunity to tell the native side that we are the input method * to talk to when responding to key events. */ + @Override protected void setAWTFocussedComponent(Component component) { LWComponentPeer peer = null; long modelPtr = 0; @@ -347,6 +359,7 @@ protected void setAWTFocussedComponent(Component component) { * {@link java.awt.im.InputContext#selectInputMethod InputContext.selectInputMethod}. * */ + @Override public void endComposition() { if (fAwtFocussedComponentPeer != null) nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer)); @@ -362,6 +375,7 @@ public void endComposition() { * The method is only called when the input method is inactive. * No method of this interface is called on this instance after dispose. */ + @Override public void dispose() { fIMContext = null; fAwtFocussedComponent = null; @@ -382,6 +396,7 @@ public void dispose() { * * @return a control object from this input method, or null */ + @Override public Object getControlObject() { return null; } @@ -784,11 +799,13 @@ public void run() { synchronized(offsetInfo) { // On Mac OS X we effectively disabled the input method when focus was lost, so // this call can be ignored. + @Override public void disableInputMethod() { // Deliberately ignored. See setAWTFocussedComponent above. } + @Override public String getNativeInputMethodInfo() { return nativeGetCurrentInputMethodInfo(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethodDescriptor.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethodDescriptor.java index 062b2e2e59f..b681efc198b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethodDescriptor.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethodDescriptor.java @@ -36,7 +36,7 @@ * The input method itself is only loaded when it is actually used. */ -public class CInputMethodDescriptor implements InputMethodDescriptor { +public final class CInputMethodDescriptor implements InputMethodDescriptor { static { nativeInit(); @@ -48,6 +48,7 @@ public CInputMethodDescriptor() { /** * @see java.awt.im.spi.InputMethodDescriptor#getAvailableLocales */ + @Override public Locale[] getAvailableLocales() { // returns a copy of internal list for public API Object[] locales = getAvailableLocalesInternal(); @@ -75,6 +76,7 @@ static Object[] getAvailableLocalesInternal() { /** * @see java.awt.im.spi.InputMethodDescriptor#hasDynamicLocaleList */ + @Override public boolean hasDynamicLocaleList() { return false; } @@ -82,6 +84,7 @@ public boolean hasDynamicLocaleList() { /** * @see java.awt.im.spi.InputMethodDescriptor#getInputMethodDisplayName */ + @Override public synchronized String getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage) { String name = "System Input Methods"; if (Locale.getDefault().equals(displayLanguage)) { @@ -93,6 +96,7 @@ public synchronized String getInputMethodDisplayName(Locale inputLocale, Locale /** * @see java.awt.im.spi.InputMethodDescriptor#getInputMethodIcon */ + @Override public Image getInputMethodIcon(Locale inputLocale) { // This should return the flag icon corresponding to the input Locale. return null; @@ -101,10 +105,12 @@ public Image getInputMethodIcon(Locale inputLocale) { /** * @see java.awt.im.spi.InputMethodDescriptor#createInputMethod */ + @Override public InputMethod createInputMethod() throws Exception { return new CInputMethod(); } + @Override public String toString() { Locale[] loc = getAvailableLocales(); String locnames = null; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMouseDragGestureRecognizer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMouseDragGestureRecognizer.java index b2d2015d191..e23dcf19f1c 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMouseDragGestureRecognizer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMouseDragGestureRecognizer.java @@ -33,7 +33,7 @@ import sun.awt.dnd.SunDragSourceContextPeer; @SuppressWarnings("serial") // JDK implementation class -class CMouseDragGestureRecognizer extends MouseDragGestureRecognizer { +final class CMouseDragGestureRecognizer extends MouseDragGestureRecognizer { // Number of pixels before drag is determined to have started: private static final int fMotionThreshold = getMotionThreshold(); @@ -84,11 +84,13 @@ protected int mapDragOperationFromModifiers(MouseEvent e) { } // Invoked when the mouse has been clicked on a component: + @Override public void mouseClicked(MouseEvent e) { // do nothing } // Invoked when a mouse button has been pressed on a component: + @Override public void mousePressed(MouseEvent e) { events.clear(); @@ -98,16 +100,19 @@ public void mousePressed(MouseEvent e) { } // Invoked when a mouse button has been released over a component: + @Override public void mouseReleased(MouseEvent e) { events.clear(); } // Invoked when the mouse enters a component: + @Override public void mouseEntered(MouseEvent e) { events.clear(); } // Invoked when the mouse exits a component: + @Override public void mouseExited(MouseEvent e) { if (!events.isEmpty()) { // gesture pending int dragAction = mapDragOperationFromModifiers(e); @@ -119,6 +124,7 @@ public void mouseExited(MouseEvent e) { } // Invoked when a mouse button is pressed on a component: + @Override public void mouseDragged(MouseEvent e) { if (!events.isEmpty()) { // gesture pending int dop = mapDragOperationFromModifiers(e); @@ -144,6 +150,7 @@ public void mouseDragged(MouseEvent e) { } // Invoked when the mouse button has been moved on a component (with no buttons no down): + @Override public void mouseMoved(MouseEvent e) { // do nothing } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index 8570ecaa97a..5b447d857f3 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -40,7 +40,7 @@ /* * Provides a lightweight implementation of the EmbeddedFrame. */ -public class CPlatformEmbeddedFrame implements PlatformWindow { +public final class CPlatformEmbeddedFrame implements PlatformWindow { private static final PlatformLogger focusLogger = PlatformLogger.getLogger( "sun.lwawt.macosx.focus.CPlatformEmbeddedFrame"); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java index fd76cf5c898..43c40647e99 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java @@ -28,7 +28,7 @@ import sun.lwawt.PlatformWindow; -class CPlatformLWComponent extends CPlatformComponent { +final class CPlatformLWComponent extends CPlatformComponent { CPlatformLWComponent() { super(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java index 9585625d9dc..460c4235075 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java @@ -28,7 +28,7 @@ import sun.java2d.SurfaceData; import sun.lwawt.LWWindowPeer; -public class CPlatformLWView extends CPlatformView { +public final class CPlatformLWView extends CPlatformView { public CPlatformLWView() { super(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java index 6a9a8d61e59..1b87b31740b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -44,7 +44,7 @@ import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; -public class CPlatformLWWindow extends CPlatformWindow { +public final class CPlatformLWWindow extends CPlatformWindow { @Override public void initialize(Window target, LWWindowPeer peer, PlatformWindow owner) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index 0501bbfab03..5cdbbded9ac 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -276,7 +276,7 @@ void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) { eventNotifier.notifyActivation(gained, opposite); } - static class DeltaAccumulator { + static final class DeltaAccumulator { double accumulatedDelta; boolean accumulate; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 615fcec9a77..baaad51d953 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -433,7 +433,6 @@ protected int getInitialStyleBits() { // If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look. if (isPopup) { styleBits = SET(styleBits, TEXTURED, false); - // Popups in applets don't activate applet's process styleBits = SET(styleBits, NONACTIVATING, true); styleBits = SET(styleBits, IS_POPUP, true); } @@ -604,6 +603,7 @@ public void setBounds(int x, int y, int w, int h) { execute(ptr -> nativeSetNSWindowBounds(ptr, x, y, w, h)); } + @Override public void setMaximizedBounds(int x, int y, int w, int h) { execute(ptr -> nativeSetNSWindowStandardFrame(ptr, x, y, w, h)); } @@ -714,7 +714,6 @@ public void setVisible(boolean visible) { boolean isPopup = (target.getType() == Window.Type.POPUP); execute(ptr -> { if (isPopup) { - // Popups in applets don't activate applet's process CWrapper.NSWindow.orderFrontRegardless(ptr); } else { CWrapper.NSWindow.orderFront(ptr); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java index 1e492b9103c..68bae1f112b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java @@ -30,7 +30,7 @@ import sun.lwawt.*; -public class CPrinterDialogPeer extends LWWindowPeer { +public final class CPrinterDialogPeer extends LWWindowPeer { static { // AWT has to be initialized for the native code to function correctly. Toolkit.getDefaultToolkit(); @@ -47,10 +47,12 @@ public CPrinterDialogPeer(CPrinterDialog target, PlatformComponent platformCompo super.initialize(); } + @Override protected void disposeImpl() { LWCToolkit.targetDisposedPeer(fTarget, this); } + @Override public void setVisible(boolean visible) { if (visible) { Runnable task = () -> { @@ -63,22 +65,31 @@ public void setVisible(boolean visible) { } // unused methods. + @Override public void toFront() {} + @Override public void toBack() {} + @Override public void setResizable(boolean resizable) {} + @Override public void setEnabled(boolean enable) {} public void setBounds(int x, int y, int width, int height) {} @SuppressWarnings("deprecation") public boolean handleEvent(Event e) { return false; } + @Override public void setForeground(Color c) {} + @Override public void setBackground(Color c) {} + @Override public void setFont(Font f) {} public boolean requestFocus(boolean temporary, boolean focusedWindowChangeAllowed) { return false; } void start() {} void invalidate(int x, int y, int width, int height) {} + @Override public void addDropTarget(DropTarget dt) {} + @Override public void removeDropTarget(DropTarget dt) {} // 1.5 peer method @@ -87,18 +98,22 @@ public boolean isRestackSupported() { } // 1.6 peer method + @Override public void updateAlwaysOnTopState() { // no-op, since we just show the native print dialog } // 1.6 peer method + @Override public void updateMinimumSize() {} // 1.6 peer method + @Override public void setModalBlocked(Dialog blocker, boolean blocked) { // I don't think we care since this is a native dialog } // 1.6 peer method + @Override public void updateFocusableWindowState() {} } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphics.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphics.java index 38d3c88f40e..c3ed089472b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphics.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphics.java @@ -30,7 +30,7 @@ import java.awt.print.*; import sun.print.*; -public class CPrinterGraphics extends ProxyGraphics2D { +public final class CPrinterGraphics extends ProxyGraphics2D { // NOTE: This is a ProxyGraphics2D, and not a PathGraphics. However // the RasterPrinterJob, upon which CPrinterJob is based, refers to // PathGraphics. However, this is not a code path that will be @@ -43,6 +43,7 @@ public CPrinterGraphics(Graphics2D graphics, PrinterJob printerJob) { super(graphics, printerJob); } + @Override public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { @@ -52,6 +53,7 @@ public boolean drawImage(Image img, int x, int y, return getDelegate().drawImage(img, x, y, bgcolor, observer); } + @Override public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, @@ -62,6 +64,7 @@ public boolean drawImage(Image img, int x, int y, return getDelegate().drawImage(img, x, y, width, height, bgcolor, observer); } + @Override public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 1ca94eb3f51..25ebc82c5f7 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -984,7 +984,7 @@ protected MediaPrintableArea getDefaultPrintableArea(PageFormat page, double w, // FlipPageFormat preserves the original PageFormat class // to pass it to Printable.print(Graphics, PageFormat, int) // method overridden by a user. - private static class FlipPageFormat extends PageFormat { + private static final class FlipPageFormat extends PageFormat { private final PageFormat original; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterSurfaceData.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterSurfaceData.java index 82f6ca98922..bad5ecdcc09 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterSurfaceData.java @@ -33,7 +33,7 @@ import sun.java2d.*; import sun.java2d.loops.SurfaceType; -public class CPrinterSurfaceData extends OSXSurfaceData{ +public final class CPrinterSurfaceData extends OSXSurfaceData{ public static final String DESC_INT_RGB_PQ = "Integer RGB Printer Quartz"; // public static final String DESC_INT_ARGB_PQ = "Integer ARGB Printer Quartz"; @@ -49,6 +49,7 @@ private CPrinterSurfaceData(GraphicsConfiguration gc, long context) { initOps(context, this.fGraphicsStates, this.fGraphicsStatesObject, gc.getBounds().width, gc.getBounds().height); } + @Override public SurfaceData getReplacement() { return this; } @@ -60,16 +61,19 @@ public void enableFlushing() { } native void _flush(); + @Override public Object getDestination() { // this should never get called for the printer surface (see BufferStrategyPaintManager for one case of usage) return null; } + @Override public Raster getRaster(int x, int y, int w, int h) { BufferedImage dstImage = new BufferedImage(x + w, y + h, BufferedImage.TYPE_INT_ARGB_PRE); return dstImage.getRaster(); } + @Override public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage) { // create the destination image if needed if (dstImage == null) { @@ -85,6 +89,7 @@ public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, Bu return dstImage; } + @Override public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR) { throw new InternalError("not implemented yet"); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CSystemTray.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CSystemTray.java index ef69a37567f..adbd79de28d 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CSystemTray.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CSystemTray.java @@ -28,7 +28,7 @@ import java.awt.Dimension; import java.awt.peer.SystemTrayPeer; -public class CSystemTray implements SystemTrayPeer { +public final class CSystemTray implements SystemTrayPeer { CSystemTray(){ } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java index 6aa36453ac0..6fdda409ce5 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java @@ -71,6 +71,7 @@ void drawTextAsShape(final SunGraphics2D sg2d, final String s, final double x, f sg2d.setRenderingHint(SunHints.KEY_ANTIALIASING, oldAliasingHint); } + @Override public void drawString(final SunGraphics2D sg2d, final String s, final double x, final double y) { final long nativeStrikePtr = getNativeStrikePtr(sg2d); if (OSXSurfaceData.IsSimpleColor(sg2d.paint) && nativeStrikePtr != 0) { @@ -141,6 +142,7 @@ private void drawGlyphVectorImpl(final SunGraphics2D sg2d, final GlyphVector gV, } } + @Override public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, final float x, final float y) { final Font prevFont = sg2d.getFont(); sg2d.setFont(gV.getFont()); @@ -167,6 +169,7 @@ public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, fina sg2d.setFont(prevFont); } + @Override public void drawChars(final SunGraphics2D sg2d, final char[] data, final int offset, final int length, final int x, final int y) { final long nativeStrikePtr = getNativeStrikePtr(sg2d); if (OSXSurfaceData.IsSimpleColor(sg2d.paint) && nativeStrikePtr != 0) { @@ -181,22 +184,25 @@ public CTextPipe traceWrap() { return new Tracer(); } - public static class Tracer extends CTextPipe { + public static final class Tracer extends CTextPipe { void doDrawString(final SurfaceData sData, final long nativeStrikePtr, final String s, final float x, final float y) { GraphicsPrimitive.tracePrimitive("QuartzDrawString"); super.doDrawString(sData, nativeStrikePtr, s, x, y); } + @Override public void doDrawGlyphs(final SurfaceData sData, final long nativeStrikePtr, final GlyphVector gV, final float x, final float y) { GraphicsPrimitive.tracePrimitive("QuartzDrawGlyphs"); super.doDrawGlyphs(sData, nativeStrikePtr, gV, x, y); } + @Override public void doUnicodes(final SurfaceData sData, final long nativeStrikePtr, final char[] unicodes, final int offset, final int length, final float x, final float y) { GraphicsPrimitive.tracePrimitive("QuartzDrawUnicodes"); super.doUnicodes(sData, nativeStrikePtr, unicodes, offset, length, x, y); } + @Override public void doOneUnicode(final SurfaceData sData, final long nativeStrikePtr, final char aUnicode, final float x, final float y) { GraphicsPrimitive.tracePrimitive("QuartzDrawUnicode"); super.doOneUnicode(sData, nativeStrikePtr, aUnicode, x, y); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java index fc32f46701a..27c4a3e5740 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java @@ -37,6 +37,7 @@ final class CToolkitThreadBlockedHandler extends Mutex implements ToolkitThreadB this.processEvents = true; } + @Override public void enter() { if (!isOwned()) { throw new IllegalMonitorStateException(); @@ -47,6 +48,7 @@ public void enter() { lock(); } + @Override public void exit() { if (!isOwned()) { throw new IllegalMonitorStateException(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java index 4ca923c75b6..3851bd18339 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java @@ -54,7 +54,7 @@ import static sun.awt.AWTAccessor.MenuComponentAccessor; import static sun.awt.AWTAccessor.getMenuComponentAccessor; -public class CTrayIcon extends CFRetainedResource implements TrayIconPeer { +public final class CTrayIcon extends CFRetainedResource implements TrayIconPeer { private final TrayIcon target; private PopupMenu popup; @@ -140,6 +140,7 @@ public long getPopupMenuModel() { * kind of window in Lion, NSPopover, so perhaps it could be used it * to implement better looking notifications. */ + @Override public void displayMessage(final String caption, final String text, final String messageType) { // obtain icon to show along the message @@ -357,7 +358,7 @@ private static Icon getIconForMessageType(String messageType) { } } - class IconObserver implements ImageObserver { + final class IconObserver implements ImageObserver { @Override public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) { if (image != target.getImage()) //if the image has been changed diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java index 5fbb825a342..177184282e0 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java @@ -39,7 +39,7 @@ * This is a part of public API and should not be renamed or moved */ @SuppressWarnings("serial") // JDK implementation class -public class CViewEmbeddedFrame extends EmbeddedFrame { +public final class CViewEmbeddedFrame extends EmbeddedFrame { private final long nsViewPtr; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java index 5c658ef8e33..118e9258531 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java @@ -37,7 +37,7 @@ import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; -public class CViewPlatformEmbeddedFrame implements PlatformWindow { +public final class CViewPlatformEmbeddedFrame implements PlatformWindow { private CPlatformView view; private LWWindowPeer peer; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 87b697cd720..5047a50303b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -216,7 +216,7 @@ protected void loadSystemColors(final int[] systemColors) { } @SuppressWarnings("serial") // JDK implementation class - private static class AppleSpecificColor extends Color { + private static final class AppleSpecificColor extends Color { private final int index; AppleSpecificColor(int index) { super(appleColors[index]); @@ -402,7 +402,7 @@ protected void platformShutdown() { // TODO Auto-generated method stub } - static class OSXPlatformFont extends sun.awt.PlatformFont { + static final class OSXPlatformFont extends sun.awt.PlatformFont { OSXPlatformFont(String name, int style) { super(name, style); diff --git a/src/java.desktop/macosx/classes/sun/print/PlatformPrinterJobProxy.java b/src/java.desktop/macosx/classes/sun/print/PlatformPrinterJobProxy.java index 15ce3ecb699..92e821f2e42 100644 --- a/src/java.desktop/macosx/classes/sun/print/PlatformPrinterJobProxy.java +++ b/src/java.desktop/macosx/classes/sun/print/PlatformPrinterJobProxy.java @@ -27,7 +27,7 @@ import java.awt.print.PrinterJob; -public class PlatformPrinterJobProxy { +public final class PlatformPrinterJobProxy { public static PrinterJob getPrinterJob() { return new sun.lwawt.macosx.CPrinterJob(); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index d26def5694f..e81335c0d9e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -49,7 +49,7 @@ * when we get a punctuation char what was the real hardware key was that * was pressed? Although '&' often comes from Shift-7 the keyboard can be * remapped! I don't think there really is a good answer, and hopefully - * all good applets are only interested in logical key typed events not + * all good applications are only interested in logical key typed events not * press/release. Meanwhile, we are hard-coding the shifted punctuation * to trigger the virtual keys that are the expected ones under a standard * keymapping. Looking at Windows & Mac, they don't actually do this, the diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/DnDUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/DnDUtilities.m index 6c7f3aee8fa..7eb7b104bcd 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/DnDUtilities.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/DnDUtilities.m @@ -43,7 +43,6 @@ Documentation for Drag and Drop (Radar 3065640) @implementation DnDUtilities // Make sure we don't let other apps see local drags by using a process unique pasteboard type. -// This may not work in the Applet case, since they are all running in the same VM + (NSString *) javaPboardType { static NSString *customJavaPboardType = nil; if (customJavaPboardType == nil) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index 54f036bdc3b..614fd7ec535 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -237,6 +237,7 @@ @implementation CGGI_GlyphCanvas { UInt32 *src = (UInt32 *)canvas->image->data; size_t srcRowWidth = canvas->image->width; + size_t srcHeight = canvas->image->height; UInt8 *dest = (UInt8 *)info->image; size_t destRowWidth = info->width; @@ -246,12 +247,12 @@ @implementation CGGI_GlyphCanvas size_t y; // fill empty glyph image with black-on-white glyph - for (y = 0; y < height; y++) { + for (y = 0; y < height && y < srcHeight; y++) { size_t destRow = y * destRowWidth * 3; size_t srcRow = y * srcRowWidth; size_t x; - for (x = 0; x < destRowWidth; x++) { + for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x], dest + destRow + x * 3); } @@ -289,6 +290,7 @@ @implementation CGGI_GlyphCanvas { UInt32 *src = (UInt32 *)canvas->image->data; size_t srcRowWidth = canvas->image->width; + size_t srcHeight = canvas->image->height; UInt8 *dest = (UInt8 *)info->image; size_t destRowWidth = info->width; @@ -298,11 +300,11 @@ @implementation CGGI_GlyphCanvas size_t y; // fill empty glyph image with black-on-white glyph - for (y = 0; y < height; y++) { + for (y = 0; y < height && y < srcHeight; y++) { size_t destRow = y * destRowWidth; size_t srcRow = y * srcRowWidth; size_t x; - for (x = 0; x < destRowWidth; x++) { + for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { UInt32 p = src[srcRow + x]; dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p); } @@ -317,6 +319,7 @@ @implementation CGGI_GlyphCanvas UInt32 *src = (UInt32 *)canvas->image->data; size_t srcRowWidth = canvas->image->width; + size_t srcHeight = canvas->image->height; UInt8 *dest = (UInt8 *)info->image; size_t destRowWidth = info->width; @@ -325,15 +328,16 @@ @implementation CGGI_GlyphCanvas size_t y; - for (y = 0; y < height; y++) { + for (y = 0; y < height && y < srcHeight; y++) { size_t srcRow = y * srcRowWidth; if (littleEndian) { - UInt16 destRowBytes = info->rowBytes; + size_t srcRowBytes = canvas->image->rowBytes; + UInt16 destRowBytes = (info->rowBytes < srcRowBytes) ? info->rowBytes : srcRowBytes; memcpy(dest, src + srcRow, destRowBytes); dest += destRowBytes; } else { size_t x; - for (x = 0; x < destRowWidth; x++) { + for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { UInt32 p = src[srcRow + x]; *dest++ = (p >> 24 & 0xFF); // blue (alpha-premultiplied) *dest++ = (p >> 16 & 0xFF); // green (alpha-premultiplied) @@ -426,8 +430,10 @@ @implementation CGGI_GlyphCanvas canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8)); if (canvas->image->data == NULL) { - [[NSException exceptionWithName:NSMallocException - reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise]; + canvas->image->width = 0; + canvas->image->height = 0; + canvas->image->rowBytes = 0; + canvas->image->data = malloc(0); } uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst; @@ -477,6 +483,10 @@ @implementation CGGI_GlyphCanvas /* * Quick and easy inline to check if this canvas is big enough. + * This function only increases the size. To get a smaller canvas, free it first. + * This function adds padding / slack multiplier to the requested size. + * So resizes must be based on the size you need, not the size of the canvas. + * The function will internally account for the multiplier it uses. */ static inline void CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, @@ -484,18 +494,31 @@ @implementation CGGI_GlyphCanvas const CGGI_RenderingMode* mode) { if (canvas->image != NULL && - width < canvas->image->width && + width < canvas->image->width && height < canvas->image->height) { return; } + vImagePixelCount w = width * CGGI_GLYPH_CANVAS_SLACK; + vImagePixelCount h = height * CGGI_GLYPH_CANVAS_SLACK; + + // Do not allow the canvas to be resized smaller. + if (canvas->image != NULL) { + if (w < canvas->image->width) { + w = canvas->image->width; + } + if (h < canvas->image->height) { + h = canvas->image->height; + } + } + // if we don't have enough space to strike the largest glyph in the // run, resize the canvas CGGI_FreeCanvas(canvas); CGGI_InitCanvas(canvas, - width * CGGI_GLYPH_CANVAS_SLACK, - height * CGGI_GLYPH_CANVAS_SLACK, + w, + h, mode); JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode); } @@ -511,6 +534,12 @@ @implementation CGGI_GlyphCanvas canvasRectToClear.data = canvas->image->data; canvasRectToClear.height = info->height; canvasRectToClear.width = info->width; + if (canvas->image->width < canvasRectToClear.width) { + canvasRectToClear.width = canvas->image->width; + } + if (canvas->image->height < canvasRectToClear.height) { + canvasRectToClear.height = canvas->image->height; + } // use the row stride of the canvas, not the info canvasRectToClear.rowBytes = canvas->image->rowBytes; @@ -870,7 +899,6 @@ @implementation CGGI_GlyphCanvas CGRect bbox = bboxes[i]; GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mainFontDescriptor); - if (maxWidth < glyphInfo->width) maxWidth = glyphInfo->width; if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height; @@ -946,26 +974,32 @@ @implementation CGGI_GlyphCanvas return; } - // just do one malloc, and carve it up for all the buffers - void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) * - sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len); - if (buffer == NULL) { + CGRect *bboxes = (CGRect*)calloc(len, sizeof(CGRect)); + CGSize *advances = (CGSize*)calloc(len, sizeof(CGSize)); + CGGlyph *glyphs = (CGGlyph*)calloc(len, sizeof(CGGlyph)); + UnicodeScalarValue *uniChars = (UnicodeScalarValue*)calloc(len, sizeof(UnicodeScalarValue)); + + if (bboxes == NULL || advances == NULL || glyphs == NULL || uniChars == NULL) { + free(bboxes); + free(advances); + free(glyphs); + free(uniChars); [[NSException exceptionWithName:NSMallocException reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise]; } - CGRect *bboxes = (CGRect *)(buffer); - CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len); - CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len); - UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len); - CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode, rawGlyphCodes, uniChars, glyphs, advances, bboxes, len); - free(buffer); + free(bboxes); + free(advances); + free(glyphs); + free(uniChars); } +#define TX_FIXED_UNSAFE(v) (isinf(v) || isnan(v) || fabs(v) >= (1<<30)) + /* * Calculates bounding boxes (for given transform) and advance (for untransformed 1pt-size font) for specified glyphs. */ @@ -977,6 +1011,27 @@ @implementation CGGI_GlyphCanvas size_t count, CGRect bboxes[], CGSize advances[]) { + + if (TX_FIXED_UNSAFE(tx->a) || TX_FIXED_UNSAFE(tx->b) || TX_FIXED_UNSAFE(tx->c) || + TX_FIXED_UNSAFE(tx->d) || TX_FIXED_UNSAFE(tx->tx) || TX_FIXED_UNSAFE(tx->tx)) { + + if (bboxes) { + for (int i = 0; i < count; i++) { + bboxes[i].origin.x = 0; + bboxes[i].origin.y = 0; + bboxes[i].size.width = 0; + bboxes[i].size.height = 0; + } + } + if (advances) { + for (int i = 0; i < count; i++) { + advances[i].width = 0; + advances[i].height = 0; + } + } + return; + } + if (IsEmojiFont(font)) { // Glyph metrics for emoji font are not strictly proportional to font size, // so we need to construct real-sized font object to calculate them. diff --git a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java index 8040120695d..277b00ba4cf 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -25,7 +25,6 @@ package com.sun.java.swing; -import java.applet.Applet; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; @@ -53,9 +52,7 @@ * releases and even patch releases. You should not rely on this class even * existing. * - * This is a second part of sun.swing.SwingUtilities2. It is required - * to provide services for JavaFX applets. - * + * This is a second part of sun.swing.SwingUtilities2. */ public class SwingUtilities3 { /** @@ -91,14 +88,12 @@ public static void setDelegateRepaintManager(JComponent component, * depends on current RepaintManager's RepaintManager.PaintManager * and on the capabilities of the graphics hardware/software and what not. * - * @param rootContainer topmost container. Should be either {@code Window} - * or {@code Applet} + * @param rootContainer topmost container. Should be {@code Window} * @param isRequested the value to set vsyncRequested state to */ - @SuppressWarnings("removal") public static void setVsyncRequested(Container rootContainer, boolean isRequested) { - assert (rootContainer instanceof Applet) || (rootContainer instanceof Window); + assert (rootContainer instanceof Window); if (isRequested) { vsyncedMap.put(rootContainer, Boolean.TRUE); } else { @@ -109,12 +104,11 @@ public static void setVsyncRequested(Container rootContainer, /** * Checks if vsync painting is requested for {@code rootContainer} * - * @param rootContainer topmost container. Should be either Window or Applet + * @param rootContainer topmost container. Should be Window * @return {@code true} if vsync painting is requested for {@code rootContainer} */ - @SuppressWarnings("removal") public static boolean isVsyncRequested(Container rootContainer) { - assert (rootContainer instanceof Applet) || (rootContainer instanceof Window); + assert (rootContainer instanceof Window); return Boolean.TRUE == vsyncedMap.get(rootContainer); } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java index d8a404f500e..0cd5591b7c0 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -561,10 +561,7 @@ private void add(Transmitter t) { private void remove(Transmitter t) { synchronized(transmitters) { - int index = transmitters.indexOf(t); - if (index >= 0) { - transmitters.remove(index); - } + transmitters.remove(t); } } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index fa90f92f0ab..6b81eaf008e 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -25,16 +25,17 @@ package com.sun.media.sound; -import java.applet.AudioClip; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; +import javax.sound.SoundClip; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaEventListener; import javax.sound.midi.MetaMessage; @@ -59,8 +60,7 @@ * @author Arthur van Hoff, Kara Kytle, Jan Borgersen * @author Florian Bomers */ -@SuppressWarnings("removal") -public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, LineListener { +public final class JavaSoundAudioClip implements MetaEventListener, LineListener { private long lastPlayCall = 0; private static final int MINIMUM_PLAY_DELAY = 30; @@ -103,24 +103,28 @@ public static JavaSoundAudioClip create(final File file) throws IOException { return clip; } - public static JavaSoundAudioClip create(final URLConnection uc) { - JavaSoundAudioClip clip = new JavaSoundAudioClip(); + /* Used [only] by sun.awt.www.content.MultiMediaContentHandlers */ + public static SoundClip create(final URLConnection uc) { + File tmpFile = null; try { - clip.init(uc.getInputStream()); - } catch (final Exception ignored) { - // Playing the clip will be a no-op if an exception occured in inititialization. + tmpFile = File.createTempFile("javaurl", ".aud"); + } catch (IOException e) { + return null; + } + + try (InputStream in = uc.getInputStream(); + FileOutputStream out = new FileOutputStream(tmpFile)) { + in.transferTo(out); + } catch (IOException e) { } - return clip; - } - public static JavaSoundAudioClip create(final URL url) { - JavaSoundAudioClip clip = new JavaSoundAudioClip(); try { - clip.init(url.openStream()); - } catch (final Exception ignored) { - // Playing the clip will be a no-op if an exception occurred in inititialization. + return SoundClip.createSoundClip(tmpFile); + } catch (IOException e) { + } finally { + tmpFile.delete(); } - return clip; + return null; } private void init(InputStream in) throws IOException { @@ -167,7 +171,6 @@ public synchronized boolean isPlaying() { return false; } - @Override public synchronized void play() { if (!success) { return; @@ -175,7 +178,6 @@ public synchronized void play() { startImpl(false); } - @Override public synchronized void loop() { if (!success) { return; @@ -184,7 +186,7 @@ public synchronized void loop() { } private synchronized void startImpl(boolean loop) { - // hack for some applets that call the start method very rapidly... + // hack for some applications that call the start method very rapidly... long currentTime = System.currentTimeMillis(); long diff = currentTime - lastPlayCall; if (diff < MINIMUM_PLAY_DELAY) { @@ -247,7 +249,6 @@ private synchronized void startImpl(boolean loop) { } } - @Override public synchronized void stop() { if (!success) { return; diff --git a/src/java.desktop/share/classes/java/applet/Applet.java b/src/java.desktop/share/classes/java/applet/Applet.java deleted file mode 100644 index 56b2392f0e2..00000000000 --- a/src/java.desktop/share/classes/java/applet/Applet.java +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (c) 1995, 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. - */ - -package java.applet; - -import java.awt.Dimension; -import java.awt.GraphicsEnvironment; -import java.awt.HeadlessException; -import java.awt.Image; -import java.awt.Panel; -import java.awt.event.ComponentEvent; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serial; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Locale; - -import javax.accessibility.AccessibleContext; -import javax.accessibility.AccessibleRole; -import javax.accessibility.AccessibleState; -import javax.accessibility.AccessibleStateSet; - -import com.sun.media.sound.JavaSoundAudioClip; - -/** - * An applet is a small program that is intended not to be run on its own, but - * rather to be embedded inside another application. - *

    - * The {@code Applet} class must be the superclass of any applet that is to be - * embedded in a Web page or viewed by the Java Applet Viewer. The - * {@code Applet} class provides a standard interface between applets and their - * environment. - * - * @author Arthur van Hoff - * @author Chris Warth - * @since 1.0 - * @deprecated The Applet API is deprecated, no replacement. - */ -@Deprecated(since = "9", forRemoval = true) -@SuppressWarnings("removal") -public class Applet extends Panel { - - /** - * Constructs a new Applet. - *

    - * Note: Many methods in {@code java.applet.Applet} may be invoked by the - * applet only after the applet is fully constructed; applet should avoid - * calling methods in {@code java.applet.Applet} in the constructor. - * - * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()} - * returns {@code true} - * @see java.awt.GraphicsEnvironment#isHeadless - * @since 1.4 - */ - public Applet() throws HeadlessException { - if (GraphicsEnvironment.isHeadless()) { - throw new HeadlessException(); - } - } - - /** - * Applets can be serialized but the following conventions MUST be followed: - *

    - * Before Serialization: An applet must be in STOPPED state. - *

    - * After Deserialization: The applet will be restored in STOPPED state (and - * most clients will likely move it into RUNNING state). The stub field will - * be restored by the reader. - */ - private transient AppletStub stub; - - /** - * Use serialVersionUID from JDK 1.0 for interoperability. - */ - @Serial - private static final long serialVersionUID = -5836846270535785031L; - - /** - * Read an applet from an object input stream. - * - * @param s the {@code ObjectInputStream} to read - * @throws ClassNotFoundException if the class of a serialized object could - * not be found - * @throws IOException if an I/O error occurs - * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()} - * returns {@code true} - * - * @see java.awt.GraphicsEnvironment#isHeadless - * @since 1.4 - */ - @Serial - private void readObject(ObjectInputStream s) - throws ClassNotFoundException, IOException, HeadlessException { - if (GraphicsEnvironment.isHeadless()) { - throw new HeadlessException(); - } - s.defaultReadObject(); - } - - /** - * Sets this applet's stub. This is done automatically by the system. - * - * @param stub the new stub - */ - public final void setStub(AppletStub stub) { - this.stub = stub; - } - - /** - * Determines if this applet is active. An applet is marked active just - * before its {@code start} method is called. It becomes inactive just - * before its {@code stop} method is called. - * - * @return {@code true} if the applet is active; {@code false} otherwise - * @see java.applet.Applet#start() - * @see java.applet.Applet#stop() - */ - public boolean isActive() { - if (stub != null) { - return stub.isActive(); - } else { // If stub field not filled in, applet never active - return false; - } - } - - /** - * Gets the {@code URL} of the document in which this applet is embedded. - * For example, suppose an applet is contained within the document: - *

    -     *    http://www.oracle.com/technetwork/java/index.html
    -     * 
    - * The document base is: - *
    -     *    http://www.oracle.com/technetwork/java/index.html
    -     * 
    - * - * @return the {@link java.net.URL} of the document that contains this - * applet - * @see java.applet.Applet#getCodeBase() - */ - public URL getDocumentBase() { - return stub.getDocumentBase(); - } - - /** - * Gets the base {@code URL}. This is the {@code URL} of the directory which - * contains this applet. - * - * @return the base {@link java.net.URL} of the directory which contains - * this applet - * @see java.applet.Applet#getDocumentBase() - */ - public URL getCodeBase() { - return stub.getCodeBase(); - } - - /** - * Returns the value of the named parameter in the HTML tag. For example, if - * this applet is specified as - *
    -     * <applet code="Clock" width=50 height=50>
    -     * <param name=Color value="blue">
    -     * </applet>
    -     * 
    - *

    - * then a call to {@code getParameter("Color")} returns the value - * {@code "blue"}. - *

    - * The {@code name} argument is case insensitive. - * - * @param name a parameter name - * @return the value of the named parameter, or {@code null} if not set - */ - public String getParameter(String name) { - return stub.getParameter(name); - } - - /** - * Determines this applet's context, which allows the applet to query and - * affect the environment in which it runs. - *

    - * This environment of an applet represents the document that contains the - * applet. - * - * @return the applet's context - */ - public AppletContext getAppletContext() { - return stub.getAppletContext(); - } - - /** - * Requests that this applet be resized. - * - * @param width the new requested width for the applet - * @param height the new requested height for the applet - */ - @SuppressWarnings("deprecation") - public void resize(int width, int height) { - Dimension d = size(); - if ((d.width != width) || (d.height != height)) { - super.resize(width, height); - if (stub != null) { - stub.appletResize(width, height); - } - } - } - - /** - * Requests that this applet be resized. - * - * @param d an object giving the new width and height - */ - @SuppressWarnings("deprecation") - public void resize(Dimension d) { - resize(d.width, d.height); - } - - /** - * Indicates if this container is a validate root. - *

    - * {@code Applet} objects are the validate roots, and, therefore, they - * override this method to return {@code true}. - * - * @return {@code true} - * @see java.awt.Container#isValidateRoot - * @since 1.7 - */ - @Override - public boolean isValidateRoot() { - return true; - } - - /** - * Requests that the argument string be displayed in the "status window". - * Many browsers and applet viewers provide such a window, where the - * application can inform users of its current state. - * - * @param msg a string to display in the status window - */ - public void showStatus(String msg) { - getAppletContext().showStatus(msg); - } - - /** - * Returns an {@code Image} object that can then be painted on the screen. - * The {@code url} that is passed as an argument must specify an absolute - * {@code URL}. - *

    - * This method always returns immediately, whether or not the image exists. - * When this applet attempts to draw the image on the screen, the data will - * be loaded. The graphics primitives that draw the image will incrementally - * paint on the screen. - * - * @param url an absolute {@code URL} giving the location of the image - * @return the image at the specified {@code URL} - * @see java.awt.Image - */ - public Image getImage(URL url) { - return getAppletContext().getImage(url); - } - - /** - * Returns an {@code Image} object that can then be painted on the screen. - * The {@code url} argument must specify an absolute {@code URL}. The - * {@code name} argument is a specifier that is relative to the {@code url} - * argument. - *

    - * This method always returns immediately, whether or not the image exists. - * When this applet attempts to draw the image on the screen, the data will - * be loaded. The graphics primitives that draw the image will incrementally - * paint on the screen. - * - * @param url an absolute URL giving the base location of the image - * @param name the location of the image, relative to the {@code url} - * argument - * @return the image at the specified {@code URL} - * @see java.awt.Image - */ - public Image getImage(URL url, String name) { - try { - @SuppressWarnings("deprecation") - var u = new URL(url, name); - return getImage(u); - } catch (MalformedURLException e) { - return null; - } - } - - /** - * Get an audio clip from the given {@code URL}. - * - * @param url points to the audio clip - * @return the audio clip at the specified {@code URL} - * @since 1.2 - */ - public static final AudioClip newAudioClip(URL url) { - return JavaSoundAudioClip.create(url); - } - - /** - * Returns the {@code AudioClip} object specified by the {@code URL} - * argument. - *

    - * This method always returns immediately, whether or not the audio clip - * exists. When this applet attempts to play the audio clip, the data will - * be loaded. - * - * @param url an absolute {@code URL} giving the location of the audio clip - * @return the audio clip at the specified {@code URL} - * @see java.applet.AudioClip - */ - public AudioClip getAudioClip(URL url) { - return getAppletContext().getAudioClip(url); - } - - /** - * Returns the {@code AudioClip} object specified by the {@code URL} and - * {@code name} arguments. - *

    - * This method always returns immediately, whether or not the audio clip - * exists. When this applet attempts to play the audio clip, the data will - * be loaded. - * - * @param url an absolute {@code URL} giving the base location of the audio - * clip - * @param name the location of the audio clip, relative to the {@code url} - * argument - * @return the audio clip at the specified {@code URL} - * @see java.applet.AudioClip - */ - public AudioClip getAudioClip(URL url, String name) { - try { - @SuppressWarnings("deprecation") - var u = new URL(url, name); - return getAudioClip(u); - } catch (MalformedURLException e) { - return null; - } - } - - /** - * Returns information about this applet. An applet should override this - * method to return a {@code String} containing information about the - * author, version, and copyright of the applet. - *

    - * The implementation of this method provided by the {@code Applet} class - * returns {@code null}. - * - * @return a string containing information about the author, version, and - * copyright of the applet - */ - public String getAppletInfo() { - return null; - } - - /** - * Gets the locale of the applet. It allows the applet to maintain its own - * locale separated from the locale of the browser or appletviewer. - * - * @return the locale of the applet; if no locale has been set, the default - * locale is returned - * @since 1.1 - */ - public Locale getLocale() { - Locale locale = super.getLocale(); - if (locale == null) { - return Locale.getDefault(); - } - return locale; - } - - /** - * Returns information about the parameters that are understood by this - * applet. An applet should override this method to return an array of - * strings describing these parameters. - *

    - * Each element of the array should be a set of three strings containing the - * name, the type, and a description. For example: - *

    -     * String pinfo[][] = {
    -     *   {"fps",    "1-10",    "frames per second"},
    -     *   {"repeat", "boolean", "repeat image loop"},
    -     *   {"imgs",   "url",     "images directory"}
    -     * };
    -     * 
    - *

    - * The implementation of this method provided by the {@code Applet} class - * returns {@code null}. - * - * @return an array describing the parameters this applet looks for - */ - public String[][] getParameterInfo() { - return null; - } - - /** - * Plays the audio clip at the specified absolute {@code URL}. Nothing - * happens if the audio clip cannot be found. - * - * @param url an absolute {@code URL} giving the location of the audio clip - */ - public void play(URL url) { - AudioClip clip = getAudioClip(url); - if (clip != null) { - clip.play(); - } - } - - /** - * Plays the audio clip given the {@code URL} and a specifier that is - * relative to it. Nothing happens if the audio clip cannot be found. - * - * @param url an absolute {@code URL} giving the base location of the audio - * clip - * @param name the location of the audio clip, relative to the {@code url} - * argument - */ - public void play(URL url, String name) { - AudioClip clip = getAudioClip(url, name); - if (clip != null) { - clip.play(); - } - } - - /** - * Called by the browser or applet viewer to inform this applet that it has - * been loaded into the system. It is always called before the first time - * that the {@code start} method is called. - *

    - * A subclass of {@code Applet} should override this method if it has - * initialization to perform. For example, an applet with threads would use - * the {@code init} method to create the threads and the {@code destroy} - * method to kill them. - *

    - * The implementation of this method provided by the {@code Applet} class - * does nothing. - * - * @see java.applet.Applet#destroy() - * @see java.applet.Applet#start() - * @see java.applet.Applet#stop() - */ - public void init() { - } - - /** - * Called by the browser or applet viewer to inform this applet that it - * should start its execution. It is called after the {@code init} method - * and each time the applet is revisited in a Web page. - *

    - * A subclass of {@code Applet} should override this method if it has any - * operation that it wants to perform each time the Web page containing it - * is visited. For example, an applet with animation might want to use the - * {@code start} method to resume animation, and the {@code stop} method to - * suspend the animation. - *

    - * Note: some methods, such as {@code getLocationOnScreen}, can only provide - * meaningful results if the applet is showing. Because {@code isShowing} - * returns {@code false} when the applet's {@code start} is first called, - * methods requiring {@code isShowing} to return {@code true} should be - * called from a {@code ComponentListener}. - *

    - * The implementation of this method provided by the {@code Applet} class - * does nothing. - * - * @see java.applet.Applet#destroy() - * @see java.applet.Applet#init() - * @see java.applet.Applet#stop() - * @see java.awt.Component#isShowing() - * @see java.awt.event.ComponentListener#componentShown(ComponentEvent) - */ - public void start() { - } - - /** - * Called by the browser or applet viewer to inform this applet that it - * should stop its execution. It is called when the Web page that contains - * this applet has been replaced by another page, and also just before the - * applet is to be destroyed. - *

    - * A subclass of {@code Applet} should override this method if it has any - * operation that it wants to perform each time the Web page containing it - * is no longer visible. For example, an applet with animation might want to - * use the {@code start} method to resume animation, and the {@code stop} - * method to suspend the animation. - *

    - * The implementation of this method provided by the {@code Applet} class - * does nothing. - * - * @see java.applet.Applet#destroy() - * @see java.applet.Applet#init() - */ - public void stop() { - } - - /** - * Called by the browser or applet viewer to inform this applet that it is - * being reclaimed and that it should destroy any resources that it has - * allocated. The {@code stop} method will always be called before - * {@code destroy}. - *

    - * A subclass of {@code Applet} should override this method if it has any - * operation that it wants to perform before it is destroyed. For example, - * an applet with threads would use the {@code init} method to create the - * threads and the {@code destroy} method to kill them. - *

    - * The implementation of this method provided by the {@code Applet} class - * does nothing. - * - * @see java.applet.Applet#init() - * @see java.applet.Applet#start() - * @see java.applet.Applet#stop() - */ - public void destroy() { - } - - // - // Accessibility support - // - - /** - * @serial The accessible context associated with this {@code Applet}. - */ - @SuppressWarnings("serial") // Not statically typed as Serializable - AccessibleContext accessibleContext = null; - - /** - * Gets the {@code AccessibleContext} associated with this {@code Applet}. - * For applets, the {@code AccessibleContext} takes the form of an - * {@code AccessibleApplet}. A new {@code AccessibleApplet} instance is - * created if necessary. - * - * @return an {@code AccessibleApplet} that serves as the - * {@code AccessibleContext} of this {@code Applet} - * @since 1.3 - */ - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleApplet(); - } - return accessibleContext; - } - - /** - * This class implements accessibility support for the {@code Applet} class. - * It provides an implementation of the Java Accessibility API appropriate - * to applet user-interface elements. - * - * @since 1.3 - */ - protected class AccessibleApplet extends AccessibleAWTPanel { - - /** - * Use serialVersionUID from JDK 1.3 for interoperability. - */ - @Serial - private static final long serialVersionUID = 8127374778187708896L; - - /** - * Constructs an {@code AccessibleApplet}. - */ - protected AccessibleApplet() {} - - /** - * Get the role of this object. - * - * @return an instance of {@code AccessibleRole} describing the role of - * the object - */ - public AccessibleRole getAccessibleRole() { - return AccessibleRole.FRAME; - } - - /** - * Get the state of this object. - * - * @return an instance of {@code AccessibleStateSet} containing the - * current state set of the object - * @see AccessibleState - */ - public AccessibleStateSet getAccessibleStateSet() { - AccessibleStateSet states = super.getAccessibleStateSet(); - states.add(AccessibleState.ACTIVE); - return states; - } - } -} diff --git a/src/java.desktop/share/classes/java/applet/AppletContext.java b/src/java.desktop/share/classes/java/applet/AppletContext.java deleted file mode 100644 index 792bfa05bfd..00000000000 --- a/src/java.desktop/share/classes/java/applet/AppletContext.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 1995, 2021, 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. - */ - -package java.applet; - -import java.awt.Image; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.Iterator; - -/** - * This interface corresponds to an applet's environment: the document - * containing the applet and the other applets in the same document. - *

    - * The methods in this interface can be used by an applet to obtain information - * about its environment. - * - * @author Arthur van Hoff - * @since 1.0 - * @deprecated The Applet API is deprecated, no replacement. - */ -@Deprecated(since = "9", forRemoval = true) -@SuppressWarnings("removal") -public interface AppletContext { - - /** - * Creates an audio clip. - * - * @param url an absolute {@code URL} giving the location of the audio clip - * @return the audio clip at the specified {@code URL} - */ - AudioClip getAudioClip(URL url); - - /** - * Returns an {@code Image} object that can then be painted on the screen. - * The {@code url} argument that is passed as an argument must specify an - * absolute {@code URL}. - *

    - * This method always returns immediately, whether or not the image exists. - * When the applet attempts to draw the image on the screen, the data will - * be loaded. The graphics primitives that draw the image will incrementally - * paint on the screen. - * - * @param url an absolute {@code URL} giving the location of the image - * @return the image at the specified {@code URL} - * @see java.awt.Image - */ - Image getImage(URL url); - - /** - * Finds and returns the applet in the document represented by this applet - * context with the given name. The name can be set in the HTML tag by - * setting the {@code name} attribute. - * - * @param name an applet name - * @return the applet with the given name, or {@code null} if not found - */ - Applet getApplet(String name); - - /** - * Finds all the applets in the document represented by this applet context. - * - * @return an enumeration of all applets in the document represented by this - * applet context - */ - Enumeration getApplets(); - - /** - * Requests that the browser or applet viewer show the Web page indicated by - * the {@code url} argument. The browser or applet viewer determines which - * window or frame to display the Web page. This method may be ignored by - * applet contexts that are not browsers. - * - * @param url an absolute {@code URL} giving the location of the document - */ - void showDocument(URL url); - - /** - * Requests that the browser or applet viewer show the Web page indicated by - * the {@code url} argument. The {@code target} argument indicates in which - * HTML frame the document is to be displayed. The target argument is - * interpreted as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Target arguments and their descriptions
    Target Argument - * Description - *
    {@code "_self"} - * Show in the window and frame that contain the applet. - *
    {@code "_parent"} - * Show in the applet's parent frame. If the applet's frame has no - * parent frame, acts the same as "_self". - *
    {@code "_top"} - * Show in the top-level frame of the applet's window. If the - * applet's frame is the top-level frame, acts the same as "_self". - *
    {@code "_blank"} - * Show in a new, unnamed top-level window. - *
    name - * Show in the frame or window named name. If a target named - * name does not already exist, a new top-level window with the - * specified name is created, and the document is shown there. - *
    - *

    - * An applet viewer or browser is free to ignore {@code showDocument}. - * - * @param url an absolute {@code URL} giving the location of the document - * @param target a {@code String} indicating where to display the page - */ - public void showDocument(URL url, String target); - - /** - * Requests that the argument string be displayed in the "status window". - * Many browsers and applet viewers provide such a window, where the - * application can inform users of its current state. - * - * @param status a string to display in the status window - */ - void showStatus(String status); - - /** - * Associates the specified stream with the specified key in this applet - * context. If the applet context previously contained a mapping for this - * key, the old value is replaced. - *

    - * For security reasons, mapping of streams and keys exists for each - * codebase. In other words, applet from one codebase cannot access the - * streams created by an applet from a different codebase - * - * @param key key with which the specified value is to be associated - * @param stream stream to be associated with the specified key. If this - * parameter is {@code null}, the specified key is removed in this - * applet context. - * @throws IOException if the stream size exceeds a certain size limit. Size - * limit is decided by the implementor of this interface. - * @since 1.4 - */ - public void setStream(String key, InputStream stream) throws IOException; - - /** - * Returns the stream to which specified key is associated within this - * applet context. Returns {@code null} if the applet context contains no - * stream for this key. - *

    - * For security reasons, mapping of streams and keys exists for each - * codebase. In other words, applet from one codebase cannot access the - * streams created by an applet from a different codebase. - * - * @param key key whose associated stream is to be returned - * @return the stream to which this applet context maps the key - * @since 1.4 - */ - public InputStream getStream(String key); - - /** - * Finds all the keys of the streams in this applet context. - *

    - * For security reasons, mapping of streams and keys exists for each - * codebase. In other words, applet from one codebase cannot access the - * streams created by an applet from a different codebase. - * - * @return an {@code Iterator} of all the names of the streams in this - * applet context - * @since 1.4 - */ - public Iterator getStreamKeys(); -} diff --git a/src/java.desktop/share/classes/java/applet/AppletStub.java b/src/java.desktop/share/classes/java/applet/AppletStub.java deleted file mode 100644 index fea295e727f..00000000000 --- a/src/java.desktop/share/classes/java/applet/AppletStub.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1995, 2021, 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. - */ - -package java.applet; - -import java.net.URL; - -/** - * When an applet is first created, an applet stub is attached to it using the - * applet's {@code setStub} method. This stub serves as the interface between - * the applet and the browser environment or applet viewer environment in which - * the application is running. - * - * @author Arthur van Hoff - * @see java.applet.Applet#setStub(java.applet.AppletStub) - * @since 1.0 - * @deprecated The Applet API is deprecated, no replacement. - */ -@Deprecated(since = "9", forRemoval = true) -@SuppressWarnings("removal") -public interface AppletStub { - - /** - * Determines if the applet is active. An applet is active just before its - * {@code start} method is called. It becomes inactive just before its - * {@code stop} method is called. - * - * @return {@code true} if the applet is active; {@code false} otherwise - */ - boolean isActive(); - - /** - * Gets the {@code URL} of the document in which the applet is embedded. For - * example, suppose an applet is contained within the document: - *

    -     *    http://www.oracle.com/technetwork/java/index.html
    -     * 
    - * The document base is: - *
    -     *    http://www.oracle.com/technetwork/java/index.html
    -     * 
    - * - * @return the {@link java.net.URL} of the document that contains the applet - * @see java.applet.AppletStub#getCodeBase() - */ - URL getDocumentBase(); - - /** - * Gets the base {@code URL}. This is the {@code URL} of the directory which - * contains the applet. - * - * @return the base {@link java.net.URL} of the directory which contains the - * applet - * @see java.applet.AppletStub#getDocumentBase() - */ - URL getCodeBase(); - - /** - * Returns the value of the named parameter in the HTML tag. For example, if - * an applet is specified as - *
    -     * <applet code="Clock" width=50 height=50>
    -     * <param name=Color value="blue">
    -     * </applet>
    -     * 
    - *

    - * then a call to {@code getParameter("Color")} returns the value - * {@code "blue"}. - * - * @param name a parameter name - * @return the value of the named parameter, or {@code null} if not set - */ - String getParameter(String name); - - /** - * Returns the applet's context. - * - * @return the applet's context - */ - AppletContext getAppletContext(); - - /** - * Called when the applet wants to be resized. - * - * @param width the new requested width for the applet - * @param height the new requested height for the applet - */ - void appletResize(int width, int height); -} diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index 55fb06247af..e78cab2a14c 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -25,7 +25,6 @@ package java.awt; -import java.applet.Applet; import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; import java.awt.event.AdjustmentEvent; @@ -237,8 +236,7 @@ public abstract class Component implements ImageObserver, MenuContainer, transient Container parent; /** - * The {@code AppContext} of the component. Applets/Plugin may - * change the AppContext. + * The {@code AppContext} of the component. */ transient AppContext appContext; @@ -3937,10 +3935,9 @@ Image getBackBuffer() { /** * Inner class for flipping buffers on a component. That component must - * be a {@code Canvas} or {@code Window} or {@code Applet}. + * be a {@code Canvas} or {@code Window}. * @see Canvas * @see Window - * @see Applet * @see java.awt.image.BufferStrategy * @author Michael Martak * @since 1.4 @@ -3988,11 +3985,9 @@ protected class FlipBufferStrategy extends BufferStrategy { /** * Creates a new flipping buffer strategy for this component. - * The component must be a {@code Canvas} or {@code Window} or - * {@code Applet}. + * The component must be a {@code Canvas} or {@code Window}. * @see Canvas * @see Window - * @see Applet * @param numBuffers the number of buffers * @param caps the capabilities of the buffers * @throws AWTException if the capabilities supplied could not be @@ -4010,11 +4005,10 @@ protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps) throws AWTException { if (!(Component.this instanceof Window) && - !(Component.this instanceof Canvas) && - !(Component.this instanceof Applet)) + !(Component.this instanceof Canvas)) { throw new ClassCastException( - "Component must be a Canvas or Window or Applet"); + "Component must be a Canvas or Window"); } this.numBuffers = numBuffers; this.caps = caps; @@ -8161,12 +8155,6 @@ final Component getNextFocusCandidate() { focusLog.finer("default component is " + toFocus); } } - if (toFocus == null) { - Applet applet = EmbeddedFrame.getAppletIfAncestorOf(this); - if (applet != null) { - toFocus = applet; - } - } candidate = toFocus; } if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java index 9bfb41a871e..683c24f9d13 100644 --- a/src/java.desktop/share/classes/java/awt/Container.java +++ b/src/java.desktop/share/classes/java/awt/Container.java @@ -1557,8 +1557,8 @@ public void layout() { * as a {@code Frame} object) should be used to restore the validity of the * component hierarchy. *

    - * The {@code Window} class and the {@code Applet} class are the validate - * roots in AWT. Swing introduces more validate roots. + * The {@code Window} class is the validate root in AWT. + * Swing introduces more validate roots. * * @return whether this container is a validate root * @see #invalidate diff --git a/src/java.desktop/share/classes/java/awt/Dialog.java b/src/java.desktop/share/classes/java/awt/Dialog.java index 95d32161b36..0fa4a74b61a 100644 --- a/src/java.desktop/share/classes/java/awt/Dialog.java +++ b/src/java.desktop/share/classes/java/awt/Dialog.java @@ -165,18 +165,11 @@ public static enum ModalityType { /** * An {@code APPLICATION_MODAL} dialog blocks all top-level windows * from the same Java application except those from its own child hierarchy. - * If there are several applets launched in a browser, they can be - * treated either as separate applications or a single one. This behavior - * is implementation-dependent. */ APPLICATION_MODAL, /** * A {@code TOOLKIT_MODAL} dialog blocks all top-level windows run - * from the same toolkit except those from its own child hierarchy. If there - * are several applets launched in a browser, all of them run with the same - * toolkit; thus, a toolkit-modal dialog displayed by an applet may affect - * other applets and all windows of the browser instance which embeds the - * Java runtime environment for this toolkit. + * from the same toolkit except those from its own child hierarchy. */ TOOLKIT_MODAL } diff --git a/src/java.desktop/share/classes/java/awt/EventQueue.java b/src/java.desktop/share/classes/java/awt/EventQueue.java index f79ff285a79..be13548e998 100644 --- a/src/java.desktop/share/classes/java/awt/EventQueue.java +++ b/src/java.desktop/share/classes/java/awt/EventQueue.java @@ -67,15 +67,6 @@ * dispatched before event A. * *

    - * Some browsers partition applets in different code bases into - * separate contexts, and establish walls between these contexts. - * In such a scenario, there will be one {@code EventQueue} - * per context. Other browsers place all applets into the same - * context, implying that there will be only a single, global - * {@code EventQueue} for all applets. This behavior is - * implementation-dependent. Consult your browser's documentation - * for more information. - *

    * For information on the threading issues of the event dispatch * machinery, see AWT Threading Issues. diff --git a/src/java.desktop/share/classes/java/awt/Frame.java b/src/java.desktop/share/classes/java/awt/Frame.java index fcdb4d5e032..85ccf3efa45 100644 --- a/src/java.desktop/share/classes/java/awt/Frame.java +++ b/src/java.desktop/share/classes/java/awt/Frame.java @@ -1123,8 +1123,6 @@ public int getCursorType() { /** * Returns an array of all {@code Frame}s created by this application. - * If called from an applet, the array includes only the {@code Frame}s - * accessible by that applet. *

    * Warning: this method may return system created frames, such * as a shared, hidden frame which is used by Swing. Applications diff --git a/src/java.desktop/share/classes/java/awt/GraphicsDevice.java b/src/java.desktop/share/classes/java/awt/GraphicsDevice.java index ed331e4915a..63b9543014e 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsDevice.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,7 +27,6 @@ import java.awt.image.ColorModel; -import sun.awt.AppContext; import sun.awt.SunToolkit; /** @@ -75,13 +74,7 @@ */ public abstract class GraphicsDevice { - private Window fullScreenWindow; - private AppContext fullScreenAppContext; // tracks which AppContext - // created the FS window - // this lock is used for making synchronous changes to the AppContext's - // current full screen window - private final Object fsAppContextLock = new Object(); - + private volatile Window fullScreenWindow; private Rectangle windowedModeBounds; /** @@ -303,15 +296,7 @@ public void setFullScreenWindow(Window w) { fullScreenWindow.setBounds(windowedModeBounds); } // Set the full screen window - synchronized (fsAppContextLock) { - // Associate fullscreen window with current AppContext - if (w == null) { - fullScreenAppContext = null; - } else { - fullScreenAppContext = AppContext.getAppContext(); - } - fullScreenWindow = w; - } + fullScreenWindow = w; if (fullScreenWindow != null) { windowedModeBounds = fullScreenWindow.getBounds(); // Note that we use the graphics configuration of the device, @@ -319,7 +304,7 @@ public void setFullScreenWindow(Window w) { // this device. final GraphicsConfiguration gc = getDefaultConfiguration(); final Rectangle screenBounds = gc.getBounds(); - if (SunToolkit.isDispatchThreadForAppContext(fullScreenWindow)) { + if (EventQueue.isDispatchThread()) { // Update graphics configuration here directly and do not wait // asynchronous notification from the peer. Note that // setBounds() will reset a GC, if it was set incorrectly. @@ -342,15 +327,7 @@ public void setFullScreenWindow(Window w) { * @since 1.4 */ public Window getFullScreenWindow() { - Window returnWindow = null; - synchronized (fsAppContextLock) { - // Only return a handle to the current fs window if we are in the - // same AppContext that set the fs window - if (fullScreenAppContext == AppContext.getAppContext()) { - returnWindow = fullScreenWindow; - } - } - return returnWindow; + return fullScreenWindow; } /** diff --git a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java index 4936d5d396d..ecaf5ae4e27 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java @@ -292,8 +292,7 @@ public abstract GraphicsDevice getDefaultScreenDevice() * be used in constructing new {@code Font}s by name or family name, * and is enumerated by {@link #getAvailableFontFamilyNames} and * {@link #getAllFonts} within the execution context of this - * application or applet. This means applets cannot register fonts in - * a way that they are visible to other applets. + * application. *

    * Reasons that this method might not register the font and therefore * return {@code false} are: diff --git a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java index ede4d385a80..6c6e4044131 100644 --- a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java +++ b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java @@ -71,16 +71,6 @@ * dispatcher for all FocusEvents, WindowEvents related to focus, and * KeyEvents. *

    - * Some browsers partition applets in different code bases into separate - * contexts, and establish walls between these contexts. In such a scenario, - * there will be one KeyboardFocusManager per context. Other browsers place all - * applets into the same context, implying that there will be only a single, - * global KeyboardFocusManager for all applets. This behavior is - * implementation-dependent. Consult your browser's documentation for more - * information. No matter how many contexts there may be, however, there can - * never be more than one focus owner, focused Window, or active Window, per - * ClassLoader. - *

    * Please see * * How to Use the Focus Subsystem, @@ -1177,7 +1167,7 @@ void setGlobalCurrentFocusCycleRootPriv(final Container newFocusCycleRoot) { * following: *

      *
    • whether the KeyboardFocusManager is currently managing focus - * for this application or applet's browser context + * for this application * ("managingFocus")
    • *
    • the focus owner ("focusOwner")
    • *
    • the permanent focus owner ("permanentFocusOwner")
    • @@ -1262,7 +1252,7 @@ public synchronized PropertyChangeListener[] getPropertyChangeListeners() { * following: *
        *
      • whether the KeyboardFocusManager is currently managing focus - * for this application or applet's browser context + * for this application * ("managingFocus")
      • *
      • the focus owner ("focusOwner")
      • *
      • the permanent focus owner ("permanentFocusOwner")
      • diff --git a/src/java.desktop/share/classes/java/awt/Polygon.java b/src/java.desktop/share/classes/java/awt/Polygon.java index e74ce5cb10f..3c91aaba90f 100644 --- a/src/java.desktop/share/classes/java/awt/Polygon.java +++ b/src/java.desktop/share/classes/java/awt/Polygon.java @@ -160,7 +160,7 @@ public Polygon(int[] xpoints, int[] ypoints, int npoints) { if (npoints < 0) { throw new NegativeArraySizeException("npoints < 0"); } - // Fix 6343431: Applet compatibility problems if arrays are not + // Fix 6343431: compatibility problems if arrays are not // exactly npoints in length this.npoints = npoints; this.xpoints = Arrays.copyOf(xpoints, npoints); diff --git a/src/java.desktop/share/classes/java/awt/SystemTray.java b/src/java.desktop/share/classes/java/awt/SystemTray.java index abf8c97abda..b51702bd125 100644 --- a/src/java.desktop/share/classes/java/awt/SystemTray.java +++ b/src/java.desktop/share/classes/java/awt/SystemTray.java @@ -306,10 +306,7 @@ public void remove(TrayIcon trayIcon) { /** * Returns an array of all icons added to the tray by this * application. You can't access the icons added by another - * application. Some browsers partition applets in different - * code bases into separate contexts, and establish walls between - * these contexts. In such a scenario, only the tray icons added - * from this context will be returned. + * application. * *

        The returned array is a copy of the actual array and may be * modified in any way without affecting the system tray. To diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index d3d8fa2e268..1ca5cdd8112 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -1350,22 +1350,16 @@ public static String getProperty(String key, String defaultValue) { } /** - * Get the application's or applet's EventQueue instance. - * Depending on the Toolkit implementation, different EventQueues - * may be returned for different applets. Applets should - * therefore not assume that the EventQueue instance returned - * by this method will be shared by other applets or the system. - * - * @return the {@code EventQueue} object + * {@return the {@code EventQueue} for this application} */ public final EventQueue getSystemEventQueue() { return getSystemEventQueueImpl(); } /** - * Gets the application's or applet's {@code EventQueue} - * instance, without checking access. For security reasons, - * this can only be called from a {@code Toolkit} subclass. + * A method used by toolkit subclasses to get the {@code EventQueue}. + * This may be more direct or more efficient than calling + * {@code getSystemEventQueue()}. * @return the {@code EventQueue} object */ protected abstract EventQueue getSystemEventQueueImpl(); diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index 329e2574473..b41409a138e 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -1520,8 +1520,6 @@ private static Window[] getWindows(AppContext appContext) { /** * Returns an array of all {@code Window}s, both owned and ownerless, * created by this application. - * If called from an applet, the array includes only the {@code Window}s - * accessible by that applet. *

        * Warning: this method may return system created windows, such * as a print dialog. Applications should not assume the existence of @@ -1543,8 +1541,6 @@ public static Window[] getWindows() { * Returns an array of all {@code Window}s created by this application * that have no owner. They include {@code Frame}s and ownerless * {@code Dialog}s and {@code Window}s. - * If called from an applet, the array includes only the {@code Window}s - * accessible by that applet. *

        * Warning: this method may return system created windows, such * as a print dialog. Applications should not assume the existence of @@ -3865,7 +3861,7 @@ private static void setLayersOpaque(Component component, boolean isOpaque) { if (content != null) { content.setOpaque(isOpaque); - // Iterate down one level to see whether we have a JApplet + // Iterate down one level to see whether we have (eg) a JInternalFrame // (which is also a RootPaneContainer) which requires processing int numChildren = content.getComponentCount(); if (numChildren > 0) { diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index c641e469972..3793b138a96 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -799,31 +799,19 @@ private interface BuiltInProfile { */ public static ICC_Profile getInstance(byte[] data) { ProfileDataVerifier.verify(data); + verifyHeader(data); Profile p; try { - byte[] theHeader = new byte[HEADER_SIZE]; - System.arraycopy(data, 0, theHeader, 0, HEADER_SIZE); - verifyHeader(theHeader); - p = CMSManager.getModule().loadProfile(data); } catch (CMMException c) { throw new IllegalArgumentException("Invalid ICC Profile Data"); } try { - if (getColorSpaceType(data) == ColorSpace.TYPE_GRAY - && getData(p, icSigMediaWhitePointTag) != null - && getData(p, icSigGrayTRCTag) != null) { + int type = getColorSpaceType(data); + if (type == ColorSpace.TYPE_GRAY) { return new ICC_ProfileGray(p); - } - if (getColorSpaceType(data) == ColorSpace.TYPE_RGB - && getData(p, icSigMediaWhitePointTag) != null - && getData(p, icSigRedColorantTag) != null - && getData(p, icSigGreenColorantTag) != null - && getData(p, icSigBlueColorantTag) != null - && getData(p, icSigRedTRCTag) != null - && getData(p, icSigGreenTRCTag) != null - && getData(p, icSigBlueTRCTag) != null) { + } else if (type == ColorSpace.TYPE_RGB) { return new ICC_ProfileRGB(p); } } catch (CMMException c) { @@ -969,7 +957,7 @@ private Profile cmmProfile() { * @return the major version of the profile */ public int getMajorVersion() { - return getData(icSigHead)[8]; + return getData(cmmProfile(), icSigHead)[8]; } /** @@ -978,7 +966,7 @@ public int getMajorVersion() { * @return the minor version of the profile */ public int getMinorVersion() { - return getData(icSigHead)[9]; + return getData(cmmProfile(), icSigHead)[9]; } /** @@ -991,12 +979,12 @@ public int getProfileClass() { if (info != null) { return info.profileClass; } - byte[] theHeader = getData(icSigHead); + byte[] theHeader = getData(cmmProfile(), icSigHead); return getProfileClass(theHeader); } - private static int getProfileClass(byte[] theHeader) { - int theClassSig = intFromBigEndian(theHeader, icHdrDeviceClass); + private static int getProfileClass(byte[] data) { + int theClassSig = intFromBigEndian(data, icHdrDeviceClass); return switch (theClassSig) { case icSigInputClass -> CLASS_INPUT; case icSigDisplayClass -> CLASS_DISPLAY; @@ -1032,8 +1020,8 @@ public int getColorSpaceType() { return getColorSpaceType(theHeader); } - private static int getColorSpaceType(byte[] theHeader) { - int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); + private static int getColorSpaceType(byte[] data) { + int theColorSpaceSig = intFromBigEndian(data, icHdrColorSpace); return iccCStoJCS(theColorSpaceSig); } @@ -1051,13 +1039,13 @@ private static int getColorSpaceType(byte[] theHeader) { * {@code ColorSpace} class */ public int getPCSType() { - byte[] theHeader = getData(icSigHead); + byte[] theHeader = getData(cmmProfile(), icSigHead); return getPCSType(theHeader); } - private static int getPCSType(byte[] theHeader) { - int thePCSSig = intFromBigEndian(theHeader, icHdrPcs); - int theDeviceClass = intFromBigEndian(theHeader, icHdrDeviceClass); + private static int getPCSType(byte[] data) { + int thePCSSig = intFromBigEndian(data, icHdrPcs); + int theDeviceClass = intFromBigEndian(data, icHdrDeviceClass); if (theDeviceClass == icSigLinkClass) { return iccCStoJCS(thePCSSig); @@ -1120,18 +1108,27 @@ public byte[] getData() { * @see #setData(int, byte[]) */ public byte[] getData(int tagSignature) { - byte[] t = getData(cmmProfile(), tagSignature); - return t != null ? t.clone() : null; - } - - private static byte[] getData(Profile p, int tagSignature) { try { - return CMSManager.getModule().getTagData(p, tagSignature); + return getData(cmmProfile(), tagSignature).clone(); } catch (CMMException c) { return null; } } + /** + * Returns a particular tagged data element from the profile as a non-null + * byte array. The returned byte array is not cloned. It must not be exposed + * to or used by public APIs. It is intended strictly for internal use only. + * + * @param p the CMM profile from which to retrieve the tag data + * @param tagSignature the ICC tag signature for the data to retrieve + * @return a non-null byte array containing the tag data + * @throws CMMException if the specified tag doesn't exist + */ + static byte[] getData(Profile p, int tagSignature) { + return CMSManager.getModule().getTagData(p, tagSignature); + } + /** * Sets a particular tagged data element in the profile from a byte array. * The array should contain data in a format, corresponded to the @@ -1183,7 +1180,7 @@ private static void verifyHeader(byte[] data) { checkRenderingIntent(data); } - private static void checkRenderingIntent(byte[] header) { + private static void checkRenderingIntent(byte[] data) { int index = ICC_Profile.icHdrRenderingIntent; /* * ICC spec: only the least-significant 16 bits encode the rendering @@ -1191,7 +1188,7 @@ private static void checkRenderingIntent(byte[] header) { * https://www.color.org/specification/ICC.1-2022-05.pdf, section 7.2.15 */ // Extract 16-bit unsigned rendering intent (0–65535) - int intent = (header[index + 2] & 0xff) << 8 | header[index + 3] & 0xff; + int intent = (data[index + 2] & 0xff) << 8 | data[index + 3] & 0xff; // Only check upper bound since intent can't be negative if (intent > icICCAbsoluteColorimetric) { throw new IllegalArgumentException( @@ -1212,7 +1209,7 @@ public int getNumComponents() { if (info != null) { return info.numComponents; } - byte[] theHeader = getData(icSigHead); + byte[] theHeader = getData(cmmProfile(), icSigHead); int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); return switch (theColorSpaceSig) { case icSigGrayData -> 1; @@ -1251,7 +1248,7 @@ float[] getMediaWhitePoint() { * encoded in an XYZType tag. */ final float[] getXYZTag(int tagSignature) { - byte[] theData = getData(tagSignature); + byte[] theData = getData(cmmProfile(), tagSignature); float[] theXYZNumber = new float[3]; /* array to return */ /* convert s15Fixed16Number to float */ @@ -1275,7 +1272,7 @@ final float[] getXYZTag(int tagSignature) { * single gamma value */ float getGamma(int tagSignature) { - byte[] theTRCData = getData(tagSignature); + byte[] theTRCData = getData(cmmProfile(), tagSignature); if (intFromBigEndian(theTRCData, icCurveCount) != 1) { throw new ProfileDataException("TRC is not a gamma"); } @@ -1306,7 +1303,7 @@ float getGamma(int tagSignature) { * table */ short[] getTRC(int tagSignature) { - byte[] theTRCData = getData(tagSignature); + byte[] theTRCData = getData(cmmProfile(), tagSignature); int nElements = intFromBigEndian(theTRCData, icCurveCount); if (nElements == 1) { throw new ProfileDataException("TRC is not a table"); diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java index b248e996c81..523668d37ec 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -74,10 +74,15 @@ public final class ICC_ProfileGray extends ICC_Profile { private static final long serialVersionUID = -1124721290732002649L; /** - * Constructs a new {@code ICC_ProfileGray} from a CMM ID. + * Constructs a new {@code ICC_ProfileGray} from the specified CMM profile. + * + * @param p the CMM profile used to create this ICC profile + * @throws CMMException if the required tags are missing */ ICC_ProfileGray(Profile p) { super(p); + getData(p, icSigMediaWhitePointTag); + getData(p, icSigGrayTRCTag); } /** diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java index f1166e81636..d46852380f3 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -104,12 +104,20 @@ public final class ICC_ProfileRGB extends ICC_Profile { public static final int BLUECOMPONENT = 2; /** - * Constructs an new {@code ICC_ProfileRGB} from a CMM ID. + * Constructs a new {@code ICC_ProfileRGB} from the specified CMM profile. * - * @param p the CMM ID for the profile. + * @param p the CMM profile used to create this ICC profile + * @throws CMMException if the required tags are missing */ ICC_ProfileRGB(Profile p) { super(p); + getData(p, icSigMediaWhitePointTag); + getData(p, icSigRedColorantTag); + getData(p, icSigGreenColorantTag); + getData(p, icSigBlueColorantTag); + getData(p, icSigRedTRCTag); + getData(p, icSigGreenTRCTag); + getData(p, icSigBlueTRCTag); } /** diff --git a/src/java.desktop/share/classes/java/awt/doc-files/FocusSpec.html b/src/java.desktop/share/classes/java/awt/doc-files/FocusSpec.html index 9e9dc8dcca2..22df108b91a 100644 --- a/src/java.desktop/share/classes/java/awt/doc-files/FocusSpec.html +++ b/src/java.desktop/share/classes/java/awt/doc-files/FocusSpec.html @@ -81,7 +81,6 @@

        The AWT Focus Subsystem

        across platforms. This document has the following sections:
        • Overview of KeyboardFocusManager -
        • KeyboardFocusManager and Browser Contexts
        • KeyEventDispatcher
        • FocusEvent and WindowEvent
        • Event Delivery @@ -213,22 +212,6 @@

          Overview of KeyboardFocusManager

          implementation in the DefaultKeyboardFocusManager class. - -

          KeyboardFocusManager and Browser Contexts

          -

          -Some browsers partition applets in different code bases into separate -contexts, and establish walls between these contexts. Each thread and -each Component is associated with a particular context and cannot -interfere with threads or access Components in other contexts. In such -a scenario, there will be one KeyboardFocusManager per context. Other -browsers place all applets into the same context, implying that there -will be only a single, global KeyboardFocusManager for all -applets. This behavior is implementation-dependent. Consult your -browser's documentation for more information. No matter how many -contexts there may be, however, there can never be more than one focus -owner, focused Window, or active Window, per ClassLoader. - -

          KeyEventDispatcher and KeyEventPostProcessor

          diff --git a/src/java.desktop/share/classes/java/awt/doc-files/Modality.html b/src/java.desktop/share/classes/java/awt/doc-files/Modality.html index df8131c0fc5..94491dd3edc 100644 --- a/src/java.desktop/share/classes/java/awt/doc-files/Modality.html +++ b/src/java.desktop/share/classes/java/awt/doc-files/Modality.html @@ -117,16 +117,9 @@

          Modality types

        • Application-modal dialogs
          An application-modal dialog blocks all windows from the same application except for those from its child hierarchy. - If there are several applets launched in a browser, they can be - treated either as separate applications or a single application. - This behavior is implementation-dependent.
        • Toolkit-modal dialogs
          A toolkit-modal dialog blocks all windows that run in the same - toolkit except those from its child hierarchy. If there - are several applets launched all of them run with the same toolkit, - so a toolkit-modal dialog shown from an applet may affect other - applets and all windows of the browser instance which embeds the - Java runtime environment for this toolkit. + toolkit except those from its child hierarchy.
        • Modality priority is arranged by the strength of blocking: modeless, @@ -356,8 +349,8 @@

          Compatibility

          calls: Dialog.setModal(true), Dialog(owner, true), etc. Prior to JDK 6 the default type was toolkit-modal, - but the only distinction between application- and toolkit-modality is for - applets and applications launched from Java Web Start. + and now with single application per-VM there is no + distinction between application- and toolkit-modality.

          Examples

          diff --git a/src/java.desktop/share/classes/java/beans/AppletInitializer.java b/src/java.desktop/share/classes/java/beans/AppletInitializer.java deleted file mode 100644 index 36f89836c28..00000000000 --- a/src/java.desktop/share/classes/java/beans/AppletInitializer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 1997, 2021, 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. - */ - -package java.beans; - -import java.applet.Applet; - -import java.beans.beancontext.BeanContext; - -/** - * This interface is designed to work in collusion with java.beans.Beans.instantiate. - * The interface is intended to provide mechanism to allow the proper - * initialization of JavaBeans that are also Applets, during their - * instantiation by java.beans.Beans.instantiate(). - * - * @see java.beans.Beans#instantiate - * - * @since 1.2 - * - * @deprecated The Applet API is deprecated. See the - * java.applet package - * documentation for further information. - */ -@Deprecated(since = "9", forRemoval = true) -public interface AppletInitializer { - - /** - *

          - * If passed to the appropriate variant of java.beans.Beans.instantiate - * this method will be called in order to associate the newly instantiated - * Applet (JavaBean) with its AppletContext, AppletStub, and Container. - *

          - *

          - * Conformant implementations shall: - *

            - *
          1. Associate the newly instantiated Applet with the appropriate - * AppletContext. - * - *
          2. Instantiate an AppletStub() and associate that AppletStub with - * the Applet via an invocation of setStub(). - * - *
          3. If BeanContext parameter is null, then it shall associate the - * Applet with its appropriate Container by adding that Applet to its - * Container via an invocation of add(). If the BeanContext parameter is - * non-null, then it is the responsibility of the BeanContext to associate - * the Applet with its Container during the subsequent invocation of its - * addChildren() method. - *
          - * - * @param newAppletBean The newly instantiated JavaBean - * @param bCtxt The BeanContext intended for this Applet, or - * null. - */ - @SuppressWarnings("removal") - void initialize(Applet newAppletBean, BeanContext bCtxt); - - /** - *

          - * Activate, and/or mark Applet active. Implementors of this interface - * shall mark this Applet as active, and optionally invoke its start() - * method. - *

          - * - * @param newApplet The newly instantiated JavaBean - */ - @SuppressWarnings("removal") - void activate(Applet newApplet); -} diff --git a/src/java.desktop/share/classes/java/beans/Beans.java b/src/java.desktop/share/classes/java/beans/Beans.java index 5320d12ecd2..313bfe98515 100644 --- a/src/java.desktop/share/classes/java/beans/Beans.java +++ b/src/java.desktop/share/classes/java/beans/Beans.java @@ -27,11 +27,6 @@ import com.sun.beans.finder.ClassFinder; -import java.applet.Applet; -import java.applet.AppletContext; -import java.applet.AppletStub; -import java.applet.AudioClip; - import java.awt.Image; import java.beans.beancontext.BeanContext; @@ -82,7 +77,7 @@ public Beans() {} */ public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException { - return Beans.instantiate(cls, beanName, null, null); + return Beans.instantiate(cls, beanName, null); } /** @@ -109,73 +104,6 @@ public static Object instantiate(ClassLoader cls, String beanName) throws IOExce public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException { - return Beans.instantiate(cls, beanName, beanContext, null); - } - - /** - * Instantiate a bean. - *

          - * The bean is created based on a name relative to a class-loader. - * This name should be a dot-separated name such as "a.b.c". - *

          - * In Beans 1.0 the given name can indicate either a serialized object - * or a class. Other mechanisms may be added in the future. In - * beans 1.0 we first try to treat the beanName as a serialized object - * name then as a class name. - *

          - * When using the beanName as a serialized object name we convert the - * given beanName to a resource pathname and add a trailing ".ser" suffix. - * We then try to load a serialized object from that resource. - *

          - * For example, given a beanName of "x.y", Beans.instantiate would first - * try to read a serialized object from the resource "x/y.ser" and if - * that failed it would try to load the class "x.y" and create an - * instance of that class. - *

          - * If the bean is a subtype of java.applet.Applet, then it is given - * some special initialization. First, it is supplied with a default - * AppletStub and AppletContext. Second, if it was instantiated from - * a classname the applet's "init" method is called. (If the bean was - * deserialized this step is skipped.) - *

          - * Note that for beans which are applets, it is the caller's responsibility - * to call "start" on the applet. For correct behaviour, this should be done - * after the applet has been added into a visible AWT container. - *

          - * Note that applets created via beans.instantiate run in a slightly - * different environment than applets running inside browsers. In - * particular, bean applets have no access to "parameters", so they may - * wish to provide property get/set methods to set parameter values. We - * advise bean-applet developers to test their bean-applets against both - * the JDK appletviewer (for a reference browser environment) and the - * BDK BeanBox (for a reference bean container). - * - * @return a JavaBean - * @param cls the class-loader from which we should create - * the bean. If this is null, then the system - * class-loader is used. - * @param beanName the name of the bean within the class-loader. - * For example "sun.beanbox.foobah" - * @param beanContext The BeanContext in which to nest the new bean - * @param initializer The AppletInitializer for the new bean - * - * @throws ClassNotFoundException if the class of a serialized - * object could not be found. - * @throws IOException if an I/O error occurs. - * @since 1.2 - * - * @deprecated It is recommended to use - * {@link #instantiate(ClassLoader, String, BeanContext)}, - * because the Applet API is deprecated. See the - * java.applet package - * documentation for further information. - */ - @Deprecated(since = "9", forRemoval = true) - @SuppressWarnings("removal") - public static Object instantiate(ClassLoader cls, String beanName, - BeanContext beanContext, - AppletInitializer initializer) - throws IOException, ClassNotFoundException { InputStream ins; ObjectInputStream oins = null; @@ -249,101 +177,7 @@ public static Object instantiate(ClassLoader cls, String beanName, } if (result != null) { - - // Ok, if the result is an applet initialize it. - - AppletStub stub = null; - - if (result instanceof Applet) { - Applet applet = (Applet) result; - boolean needDummies = initializer == null; - - if (needDummies) { - - // Figure our the codebase and docbase URLs. We do this - // by locating the URL for a known resource, and then - // massaging the URL. - - // First find the "resource name" corresponding to the bean - // itself. So a serialized bean "a.b.c" would imply a - // resource name of "a/b/c.ser" and a classname of "x.y" - // would imply a resource name of "x/y.class". - - final String resourceName; - - if (serialized) { - // Serialized bean - resourceName = beanName.replace('.','/').concat(".ser"); - } else { - // Regular class - resourceName = beanName.replace('.','/').concat(".class"); - } - - URL objectUrl = null; - URL codeBase = null; - URL docBase = null; - - // Now get the URL corresponding to the resource name. - if (cls == null) { - objectUrl = ClassLoader.getSystemResource(resourceName); - } else - objectUrl = cls.getResource(resourceName); - - // If we found a URL, we try to locate the docbase by taking - // of the final path name component, and the code base by taking - // of the complete resourceName. - // So if we had a resourceName of "a/b/c.class" and we got an - // objectURL of "file://bert/classes/a/b/c.class" then we would - // want to set the codebase to "file://bert/classes/" and the - // docbase to "file://bert/classes/a/b/" - - if (objectUrl != null) { - String s = objectUrl.toExternalForm(); - - if (s.endsWith(resourceName)) { - int ix = s.length() - resourceName.length(); - codeBase = newURL(s.substring(0,ix)); - docBase = codeBase; - - ix = s.lastIndexOf('/'); - - if (ix >= 0) { - docBase = newURL(s.substring(0,ix+1)); - } - } - } - - // Setup a default context and stub. - BeansAppletContext context = new BeansAppletContext(applet); - - stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase); - applet.setStub(stub); - } else { - initializer.initialize(applet, beanContext); - } - - // now, if there is a BeanContext, add the bean, if applicable. - - if (beanContext != null) { - unsafeBeanContextAdd(beanContext, result); - } - - // If it was deserialized then it was already init-ed. - // Otherwise we need to initialize it. - - if (!serialized) { - // We need to set a reasonable initial size, as many - // applets are unhappy if they are started without - // having been explicitly sized. - applet.setSize(100,100); - applet.init(); - } - - if (needDummies) { - ((BeansAppletStub)stub).active = true; - } else initializer.activate(applet); - - } else if (beanContext != null) unsafeBeanContextAdd(beanContext, result); + if (beanContext != null) unsafeBeanContextAdd(beanContext, result); } return result; @@ -482,138 +316,3 @@ protected Class resolveClass(ObjectStreamClass classDesc) return ClassFinder.resolveClass(cname, this.loader); } } - -/** - * Package private support class. This provides a default AppletContext - * for beans which are applets. - */ -@Deprecated(since = "9", forRemoval = true) -@SuppressWarnings("removal") -class BeansAppletContext implements AppletContext { - Applet target; - Hashtable imageCache = new Hashtable<>(); - - BeansAppletContext(Applet target) { - this.target = target; - } - - public AudioClip getAudioClip(URL url) { - // We don't currently support audio clips in the Beans.instantiate - // applet context, unless by some luck there exists a URL content - // class that can generate an AudioClip from the audio URL. - try { - return (AudioClip) url.getContent(); - } catch (Exception ex) { - return null; - } - } - - public synchronized Image getImage(URL url) { - Object o = imageCache.get(url); - if (o != null) { - return (Image)o; - } - try { - o = url.getContent(); - if (o == null) { - return null; - } - if (o instanceof Image) { - imageCache.put(url, o); - return (Image) o; - } - // Otherwise it must be an ImageProducer. - Image img = target.createImage((java.awt.image.ImageProducer)o); - imageCache.put(url, img); - return img; - - } catch (Exception ex) { - return null; - } - } - - public Applet getApplet(String name) { - return null; - } - - public Enumeration getApplets() { - Vector applets = new Vector<>(); - applets.addElement(target); - return applets.elements(); - } - - public void showDocument(URL url) { - // We do nothing. - } - - public void showDocument(URL url, String target) { - // We do nothing. - } - - public void showStatus(String status) { - // We do nothing. - } - - public void setStream(String key, InputStream stream)throws IOException{ - // We do nothing. - } - - public InputStream getStream(String key){ - // We do nothing. - return null; - } - - public Iterator getStreamKeys(){ - // We do nothing. - return null; - } -} - -/** - * Package private support class. This provides an AppletStub - * for beans which are applets. - */ -@Deprecated(since = "9", forRemoval = true) -@SuppressWarnings("removal") -class BeansAppletStub implements AppletStub { - transient boolean active; - transient Applet target; - transient AppletContext context; - transient URL codeBase; - transient URL docBase; - - BeansAppletStub(Applet target, - AppletContext context, URL codeBase, - URL docBase) { - this.target = target; - this.context = context; - this.codeBase = codeBase; - this.docBase = docBase; - } - - public boolean isActive() { - return active; - } - - public URL getDocumentBase() { - // use the root directory of the applet's class-loader - return docBase; - } - - public URL getCodeBase() { - // use the directory where we found the class or serialized object. - return codeBase; - } - - public String getParameter(String name) { - return null; - } - - public AppletContext getAppletContext() { - return context; - } - - public void appletResize(int width, int height) { - // we do nothing. - } -} diff --git a/src/java.desktop/share/classes/java/beans/DesignMode.java b/src/java.desktop/share/classes/java/beans/DesignMode.java index bcc9f756848..36cff7a41e1 100644 --- a/src/java.desktop/share/classes/java/beans/DesignMode.java +++ b/src/java.desktop/share/classes/java/beans/DesignMode.java @@ -34,7 +34,7 @@ * The JavaBeans specification defines the notion of design time as is a * mode in which JavaBeans instances should function during their composition * and customization in a interactive design, composition or construction tool, - * as opposed to runtime when the JavaBean is part of an applet, application, + * as opposed to runtime when the JavaBean is part of an application, * or other live Java executable abstraction. * * @author Laurence P. G. Cable diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java index ed9444b83af..9f47a582e5b 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java @@ -952,7 +952,7 @@ private String getResource(String key, Locale locale) { * are intended to be delivered by the subclasser - ie supplier of the * metadataformat. For the standard format and all standard plugins that * is the JDK. For 3rd party plugins that they will supply their own. - * This includes plugins bundled with applets/applications. + * This includes plugins bundled with applications. * In all cases this means it is sufficient to search for those resource * in the module that is providing the MetadataFormatImpl subclass. */ diff --git a/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java index 18a73ebce1f..5286464617a 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java @@ -110,9 +110,7 @@ private IIORegistry() { * the Image I/O API. This instance should be used for all * registry functions. * - *

          Each {@code ThreadGroup} will receive its own - * instance; this allows different {@code Applet}s in the - * same browser (for example) to each have their own registry. + *

          Each {@code ThreadGroup} will receive its own instance. * * @return the default registry for the current * {@code ThreadGroup}. diff --git a/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java b/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java index 2cb6a0cbb67..02df96b435d 100644 --- a/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java @@ -534,8 +534,7 @@ private Container fetchRoot(JComponent c) { Container root = c; xOffset = yOffset = 0; while (root != null && - (!(root instanceof Window) && - !SunToolkit.isInstanceOf(root, "java.applet.Applet"))) { + (!(root instanceof Window))) { xOffset += root.getX(); yOffset += root.getY(); root = root.getParent(); @@ -687,7 +686,7 @@ public boolean isInSync() { } /** - * Returns the Root (Window or Applet) that this BufferInfo references. + * Returns the Root (Window) that this BufferInfo references. */ public Container getRoot() { return (root == null) ? null : root.get(); @@ -793,30 +792,14 @@ private BufferStrategy createBufferStrategy(Container root, null); } BufferStrategy bs = null; - if (SunToolkit.isInstanceOf(root, "java.applet.Applet")) { - try { - AWTAccessor.ComponentAccessor componentAccessor - = AWTAccessor.getComponentAccessor(); - componentAccessor.createBufferStrategy(root, 2, caps); - bs = componentAccessor.getBufferStrategy(root); - } catch (AWTException e) { - // Type is not supported - if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) { - LOGGER.finer("createBufferStrategy failed", - e); - } - } - } - else { - try { - ((Window)root).createBufferStrategy(2, caps); - bs = ((Window)root).getBufferStrategy(); - } catch (AWTException e) { - // Type not supported - if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) { - LOGGER.finer("createBufferStrategy failed", - e); - } + try { + ((Window)root).createBufferStrategy(2, caps); + bs = ((Window)root).getBufferStrategy(); + } catch (AWTException e) { + // Type not supported + if (LOGGER.isLoggable(PlatformLogger.Level.FINER)) { + LOGGER.finer("createBufferStrategy failed", + e); } } return bs; diff --git a/src/java.desktop/share/classes/javax/swing/JApplet.java b/src/java.desktop/share/classes/javax/swing/JApplet.java deleted file mode 100644 index d5169f0df11..00000000000 --- a/src/java.desktop/share/classes/javax/swing/JApplet.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 1997, 2021, 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. - */ - -package javax.swing; - -import java.applet.Applet; -import java.awt.AWTEvent; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Graphics; -import java.awt.HeadlessException; -import java.awt.LayoutManager; -import java.beans.BeanProperty; -import java.beans.JavaBean; - -import javax.accessibility.Accessible; -import javax.accessibility.AccessibleContext; - -/** - * An extended version of java.applet.Applet that adds support for - * the JFC/Swing component architecture. - * You can find task-oriented documentation about using JApplet - * in The Java Tutorial, - * in the section - * How to Make Applets. - *

          - * The JApplet class is slightly incompatible with - * java.applet.Applet. JApplet contains a - * JRootPane as its only child. The contentPane - * should be the parent of any children of the JApplet. - * As a convenience, the {@code add}, {@code remove}, and {@code setLayout} - * methods of this class are overridden, so that they delegate calls - * to the corresponding methods of the {@code ContentPane}. - * For example, you can add a child component to an applet as follows: - *

          - *       applet.add(child);
          - * 
          - * - * And the child will be added to the contentPane. - * The contentPane will always be non-null. - * Attempting to set it to null will cause the - * JApplet to throw an exception. The default - * contentPane will have a BorderLayout - * manager set on it. - * Refer to {@link javax.swing.RootPaneContainer} - * for details on adding, removing and setting the LayoutManager - * of a JApplet. - *

          - * Please see the JRootPane documentation for a - * complete description of the contentPane, glassPane, - * and layeredPane properties. - *

          - * Warning: Swing is not thread safe. For more - * information see Swing's Threading - * Policy. - *

          - * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeans - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @see javax.swing.RootPaneContainer - * - * @author Arnaud Weber - * @since 1.2 - * - * @deprecated The Applet API is deprecated, no replacement. - */ -@Deprecated(since = "9", forRemoval = true) -@JavaBean(defaultProperty = "JMenuBar", description = "Swing's Applet subclass.") -@SwingContainer(delegate = "getContentPane") -@SuppressWarnings({"serial", "removal"}) // Same-version serialization only -public class JApplet extends Applet implements Accessible, - RootPaneContainer, - TransferHandler.HasGetTransferHandler -{ - /** - * The JRootPane instance that manages the - * contentPane. - * - * @see #getRootPane - * @see #setRootPane - */ - protected JRootPane rootPane; - - /** - * If true then calls to add and setLayout - * will be forwarded to the contentPane. This is initially - * false, but is set to true when the JApplet is constructed. - * - * @see #isRootPaneCheckingEnabled - * @see #setRootPaneCheckingEnabled - * @see javax.swing.RootPaneContainer - */ - protected boolean rootPaneCheckingEnabled = false; - - /** - * The TransferHandler for this applet. - */ - private TransferHandler transferHandler; - - /** - * Creates a swing applet instance. - *

          - * This constructor sets the component's locale property to the value - * returned by JComponent.getDefaultLocale. - * - * @throws HeadlessException if GraphicsEnvironment.isHeadless() - * returns true. - * @see java.awt.GraphicsEnvironment#isHeadless - * @see JComponent#getDefaultLocale - */ - public JApplet() throws HeadlessException { - super(); - // Check the timerQ and restart if necessary. - TimerQueue q = TimerQueue.sharedInstance(); - if(q != null) { - q.startIfNeeded(); - } - - /* Workaround for bug 4155072. The shared double buffer image - * may hang on to a reference to this applet; unfortunately - * Image.getGraphics() will continue to call JApplet.getForeground() - * and getBackground() even after this applet has been destroyed. - * So we ensure that these properties are non-null here. - */ - setForeground(Color.black); - setBackground(Color.white); - - setLocale( JComponent.getDefaultLocale() ); - setLayout(new BorderLayout()); - setRootPane(createRootPane()); - setRootPaneCheckingEnabled(true); - - setFocusTraversalPolicyProvider(true); - sun.awt.SunToolkit.checkAndSetPolicy(this); - - enableEvents(AWTEvent.KEY_EVENT_MASK); - } - - /** - * Called by the constructor methods to create the default rootPane. - * - * @return a new {@code JRootPane} - */ - protected JRootPane createRootPane() { - JRootPane rp = new JRootPane(); - // NOTE: this uses setOpaque vs LookAndFeel.installProperty as there - // is NO reason for the RootPane not to be opaque. For painting to - // work the contentPane must be opaque, therefore the RootPane can - // also be opaque. - rp.setOpaque(true); - return rp; - } - - /** - * Sets the {@code transferHandler} property, which is a mechanism to - * support transfer of data into this component. Use {@code null} - * if the component does not support data transfer operations. - *

          - * If the system property {@code suppressSwingDropSupport} is {@code false} - * (the default) and the current drop target on this component is either - * {@code null} or not a user-set drop target, this method will change the - * drop target as follows: If {@code newHandler} is {@code null} it will - * clear the drop target. If not {@code null} it will install a new - * {@code DropTarget}. - *

          - * Note: When used with {@code JApplet}, {@code TransferHandler} only - * provides data import capability, as the data export related methods - * are currently typed to {@code JComponent}. - *

          - * Please see - * - * How to Use Drag and Drop and Data Transfer, a section in - * The Java Tutorial, for more information. - * - * @param newHandler the new {@code TransferHandler} - * - * @see TransferHandler - * @see #getTransferHandler - * @see java.awt.Component#setDropTarget - * @since 1.6 - */ - @BeanProperty(hidden = true, description - = "Mechanism for transfer of data into the component") - public void setTransferHandler(TransferHandler newHandler) { - TransferHandler oldHandler = transferHandler; - transferHandler = newHandler; - SwingUtilities.installSwingDropTargetAsNecessary(this, transferHandler); - firePropertyChange("transferHandler", oldHandler, newHandler); - } - - /** - * Gets the transferHandler property. - * - * @return the value of the transferHandler property - * - * @see TransferHandler - * @see #setTransferHandler - * @since 1.6 - */ - public TransferHandler getTransferHandler() { - return transferHandler; - } - - /** - * Just calls paint(g). This method was overridden to - * prevent an unnecessary call to clear the background. - */ - public void update(Graphics g) { - paint(g); - } - - /** - * Sets the menubar for this applet. - * @param menuBar the menubar being placed in the applet - * - * @see #getJMenuBar - */ - @BeanProperty(bound = false, hidden = true, description - = "The menubar for accessing pulldown menus from this applet.") - public void setJMenuBar(final JMenuBar menuBar) { - getRootPane().setJMenuBar(menuBar); - } - - /** - * Returns the menubar set on this applet. - * - * @return the menubar set on this applet - * @see #setJMenuBar - */ - public JMenuBar getJMenuBar() { - return getRootPane().getJMenuBar(); - } - - - /** - * Returns whether calls to add and - * setLayout are forwarded to the contentPane. - * - * @return true if add and setLayout - * are forwarded; false otherwise - * - * @see #addImpl - * @see #setLayout - * @see #setRootPaneCheckingEnabled - * @see javax.swing.RootPaneContainer - */ - protected boolean isRootPaneCheckingEnabled() { - return rootPaneCheckingEnabled; - } - - - /** - * Sets whether calls to add and - * setLayout are forwarded to the contentPane. - * - * @param enabled true if add and setLayout - * are forwarded, false if they should operate directly on the - * JApplet. - * - * @see #addImpl - * @see #setLayout - * @see #isRootPaneCheckingEnabled - * @see javax.swing.RootPaneContainer - */ - @BeanProperty(hidden = true, description - = "Whether the add and setLayout methods are forwarded") - protected void setRootPaneCheckingEnabled(boolean enabled) { - rootPaneCheckingEnabled = enabled; - } - - - /** - * Adds the specified child Component. - * This method is overridden to conditionally forward calls to the - * contentPane. - * By default, children are added to the contentPane instead - * of the frame, refer to {@link javax.swing.RootPaneContainer} for - * details. - * - * @param comp the component to be enhanced - * @param constraints the constraints to be respected - * @param index the index - * @throws IllegalArgumentException if index is invalid - * @throws IllegalArgumentException if adding the container's parent - * to itself - * @throws IllegalArgumentException if adding a window to a container - * - * @see #setRootPaneCheckingEnabled - * @see javax.swing.RootPaneContainer - */ - protected void addImpl(Component comp, Object constraints, int index) - { - if(isRootPaneCheckingEnabled()) { - getContentPane().add(comp, constraints, index); - } - else { - super.addImpl(comp, constraints, index); - } - } - - /** - * Removes the specified component from the container. If - * comp is not the rootPane, this will forward - * the call to the contentPane. This will do nothing if - * comp is not a child of the JFrame or - * contentPane. - * - * @param comp the component to be removed - * @throws NullPointerException if comp is null - * @see #add - * @see javax.swing.RootPaneContainer - */ - public void remove(Component comp) { - if (comp == rootPane) { - super.remove(comp); - } else { - getContentPane().remove(comp); - } - } - - - /** - * Sets the LayoutManager. - * Overridden to conditionally forward the call to the - * contentPane. - * Refer to {@link javax.swing.RootPaneContainer} for - * more information. - * - * @param manager the LayoutManager - * @see #setRootPaneCheckingEnabled - * @see javax.swing.RootPaneContainer - */ - public void setLayout(LayoutManager manager) { - if(isRootPaneCheckingEnabled()) { - getContentPane().setLayout(manager); - } - else { - super.setLayout(manager); - } - } - - - /** - * Returns the rootPane object for this applet. - * - * @see #setRootPane - * @see RootPaneContainer#getRootPane - */ - @BeanProperty(bound = false, hidden = true, description - = "the RootPane object for this applet.") - public JRootPane getRootPane() { - return rootPane; - } - - - /** - * Sets the rootPane property. This method is called by the constructor. - * @param root the rootPane object for this applet - * - * @see #getRootPane - */ - protected void setRootPane(JRootPane root) { - if(rootPane != null) { - remove(rootPane); - } - rootPane = root; - if(rootPane != null) { - boolean checkingEnabled = isRootPaneCheckingEnabled(); - try { - setRootPaneCheckingEnabled(false); - add(rootPane, BorderLayout.CENTER); - } - finally { - setRootPaneCheckingEnabled(checkingEnabled); - } - } - } - - - /** - * Returns the contentPane object for this applet. - * - * @see #setContentPane - * @see RootPaneContainer#getContentPane - */ - public Container getContentPane() { - return getRootPane().getContentPane(); - } - - /** - * Sets the contentPane property. This method is called by the constructor. - * @param contentPane the contentPane object for this applet - * - * @throws java.awt.IllegalComponentStateException (a runtime - * exception) if the content pane parameter is null - * @see #getContentPane - * @see RootPaneContainer#setContentPane - */ - @BeanProperty(bound = false, hidden = true, description - = "The client area of the applet where child components are normally inserted.") - public void setContentPane(Container contentPane) { - getRootPane().setContentPane(contentPane); - } - - /** - * Returns the layeredPane object for this applet. - * - * @throws java.awt.IllegalComponentStateException (a runtime - * exception) if the layered pane parameter is null - * @see #setLayeredPane - * @see RootPaneContainer#getLayeredPane - */ - public JLayeredPane getLayeredPane() { - return getRootPane().getLayeredPane(); - } - - /** - * Sets the layeredPane property. This method is called by the constructor. - * @param layeredPane the layeredPane object for this applet - * - * @see #getLayeredPane - * @see RootPaneContainer#setLayeredPane - */ - @BeanProperty(bound = false, hidden = true, description - = "The pane which holds the various applet layers.") - public void setLayeredPane(JLayeredPane layeredPane) { - getRootPane().setLayeredPane(layeredPane); - } - - /** - * Returns the glassPane object for this applet. - * - * @see #setGlassPane - * @see RootPaneContainer#getGlassPane - */ - public Component getGlassPane() { - return getRootPane().getGlassPane(); - } - - /** - * Sets the glassPane property. - * This method is called by the constructor. - * @param glassPane the glassPane object for this applet - * - * @see #getGlassPane - * @see RootPaneContainer#setGlassPane - */ - @BeanProperty(bound = false, hidden = true, description - = "A transparent pane used for menu rendering.") - public void setGlassPane(Component glassPane) { - getRootPane().setGlassPane(glassPane); - } - - /** - * {@inheritDoc} - * - * @since 1.6 - */ - @BeanProperty(bound = false) - public Graphics getGraphics() { - JComponent.getGraphicsInvoked(this); - return super.getGraphics(); - } - - /** - * Repaints the specified rectangle of this component within - * time milliseconds. Refer to RepaintManager - * for details on how the repaint is handled. - * - * @param time maximum time in milliseconds before update - * @param x the x coordinate - * @param y the y coordinate - * @param width the width - * @param height the height - * @see RepaintManager - * @since 1.6 - */ - public void repaint(long time, int x, int y, int width, int height) { - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) { - RepaintManager.currentManager(this).addDirtyRegion( - this, x, y, width, height); - } - else { - super.repaint(time, x, y, width, height); - } - } - - /** - * Returns a string representation of this JApplet. This method - * is intended to be used only for debugging purposes, and the - * content and format of the returned string may vary between - * implementations. The returned string may be empty but may not - * be null. - * - * @return a string representation of this JApplet. - */ - protected String paramString() { - String rootPaneString = (rootPane != null ? - rootPane.toString() : ""); - String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ? - "true" : "false"); - - return super.paramString() + - ",rootPane=" + rootPaneString + - ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString; - } - - - -///////////////// -// Accessibility support -//////////////// - - /** - * {@code AccessibleContext} associated with this {@code JApplet} - */ - protected AccessibleContext accessibleContext = null; - - /** - * Gets the AccessibleContext associated with this JApplet. - * For JApplets, the AccessibleContext takes the form of an - * AccessibleJApplet. - * A new AccessibleJApplet instance is created if necessary. - * - * @return an AccessibleJApplet that serves as the - * AccessibleContext of this JApplet - */ - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleJApplet(); - } - return accessibleContext; - } - - /** - * This class implements accessibility support for the - * JApplet class. - */ - protected class AccessibleJApplet extends AccessibleApplet { - - /** - * Constructs an {@code AccessibleJApplet}. - */ - protected AccessibleJApplet() {} - - // everything moved to new parent, AccessibleApplet - } -} diff --git a/src/java.desktop/share/classes/javax/swing/JComponent.java b/src/java.desktop/share/classes/javax/swing/JComponent.java index 92f3f01ab3e..de3d7d128e9 100644 --- a/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -25,7 +25,6 @@ package javax.swing; -import java.applet.Applet; import java.awt.AWTEvent; import java.awt.AWTKeyStroke; import java.awt.Color; @@ -106,8 +105,7 @@ * you must place the component in a containment hierarchy * whose root is a top-level Swing container. * Top-level Swing containers -- - * such as JFrame, JDialog, - * and JApplet -- + * such as JFrame and JDialog -- * are specialized components * that provide a place for other Swing components to paint themselves. * For an explanation of containment hierarchies, see @@ -609,7 +607,6 @@ public void setComponentPopupMenu(JPopupMenu popup) { * @see #setComponentPopupMenu * @since 1.5 */ - @SuppressWarnings("removal") public JPopupMenu getComponentPopupMenu() { if(!getInheritsPopupMenu()) { @@ -623,8 +620,7 @@ public JPopupMenu getComponentPopupMenu() { if(parent instanceof JComponent) { return ((JComponent)parent).getComponentPopupMenu(); } - if(parent instanceof Window || - parent instanceof Applet) { + if(parent instanceof Window) { // Reached toplevel, break and return null break; } @@ -2838,11 +2834,6 @@ public void setFont(Font font) { * Returns the default locale used to initialize each JComponent's * locale property upon creation. * - * The default locale has "AppContext" scope so that applets (and - * potentially multiple lightweight applications running in a single VM) - * can have their own setting. An applet can safely alter its default - * locale because it will have no affect on other applets (or the browser). - * * @return the default Locale. * @see #setDefaultLocale * @see java.awt.Component#getLocale @@ -2865,10 +2856,6 @@ public static Locale getDefaultLocale() { * Sets the default locale used to initialize each JComponent's locale * property upon creation. The initial value is the VM's default locale. * - * The default locale has "AppContext" scope so that applets (and - * potentially multiple lightweight applications running in a single VM) - * can have their own setting. An applet can safely alter its default - * locale because it will have no affect on other applets (or the browser). * Passing {@code null} will reset the current locale back * to VM's default locale. * @@ -2978,7 +2965,7 @@ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, * @param pressed true if the key is pressed * @return true if there is a key binding for e */ - @SuppressWarnings({"deprecation", "removal"}) + @SuppressWarnings("deprecation") boolean processKeyBindings(KeyEvent e, boolean pressed) { if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) { return false; @@ -3015,8 +3002,7 @@ boolean processKeyBindings(KeyEvent e, boolean pressed) { * asking the same component twice. */ Container parent = this; - while (parent != null && !(parent instanceof Window) && - !(parent instanceof Applet)) { + while (parent != null && !(parent instanceof Window)) { if(parent instanceof JComponent) { if(ksE != null && ((JComponent)parent).processKeyBinding(ksE, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed)) @@ -4534,12 +4520,11 @@ boolean rectangleIsObscured(int x,int y,int width,int height) * return value for this method * @see #getVisibleRect */ - @SuppressWarnings("removal") static final void computeVisibleRect(Component c, Rectangle visibleRect) { Container p = c.getParent(); Rectangle bounds = c.getBounds(); - if (p == null || p instanceof Window || p instanceof Applet) { + if (p == null || p instanceof Window) { visibleRect.setBounds(0, 0, bounds.width, bounds.height); } else { computeVisibleRect(p, visibleRect); @@ -4694,8 +4679,8 @@ public synchronized VetoableChangeListener[] getVetoableChangeListeners() { /** - * Returns the top-level ancestor of this component (either the - * containing Window or Applet), + * Returns the top-level ancestor of this component (the + * containing Window) * or null if this component has not * been added to any container. * @@ -4703,10 +4688,9 @@ public synchronized VetoableChangeListener[] getVetoableChangeListeners() { * or null if not in any container */ @BeanProperty(bound = false) - @SuppressWarnings("removal") public Container getTopLevelAncestor() { for(Container p = this; p != null; p = p.getParent()) { - if(p instanceof Window || p instanceof Applet) { + if(p instanceof Window) { return p; } } @@ -5126,7 +5110,7 @@ void _paintImmediately(int x, int y, int w, int h) { JComponent paintingComponent = this; RepaintManager repaintManager = RepaintManager.currentManager(this); - // parent Container's up to Window or Applet. First container is + // parent Container's up to Window. First container is // the direct parent. Note that in testing it was faster to // alloc a new Vector vs keeping a stack of them around, and gc // seemed to have a minimal effect on this. @@ -5156,7 +5140,7 @@ void _paintImmediately(int x, int y, int w, int h) { } Component child; for (c = this, child = null; - c != null && !(c instanceof Window) && !(c instanceof Applet); + c != null && !(c instanceof Window); child = c, c = c.getParent()) { JComponent jc = (c instanceof JComponent) ? (JComponent)c : null; diff --git a/src/java.desktop/share/classes/javax/swing/JEditorPane.java b/src/java.desktop/share/classes/javax/swing/JEditorPane.java index ff23b4f5589..e715b88603f 100644 --- a/src/java.desktop/share/classes/javax/swing/JEditorPane.java +++ b/src/java.desktop/share/classes/javax/swing/JEditorPane.java @@ -1339,8 +1339,7 @@ private static Hashtable getKitRegistry() { /** * This is invoked every time the registries are accessed. Loading * is done this way instead of via a static as the static is only - * called once when running in plugin resulting in the entries only - * appearing in the first applet. + * called once when running in an AppContext. */ private static void loadDefaultKitsIfNecessary() { if (SwingUtilities.appContextGet(kitTypeRegistryKey) == null) { diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 1c1f3ee9ba3..bff597dd22c 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -1316,11 +1316,7 @@ public static int showInternalOptionDialog(Component parentComponent, /* Since all input will be blocked until this dialog is dismissed, * make sure its parent containers are visible first (this component - * is tested below). This is necessary for JApplets, because - * because an applet normally isn't made visible until after its - * start() method returns -- if this method is called from start(), - * the applet will appear to hang while an invisible modal frame - * waits for input. + * is tested below). */ if (dialog.isVisible() && !dialog.isShowing()) { Container parent = dialog.getParent(); @@ -1460,11 +1456,7 @@ public static Object showInternalInputDialog(Component parentComponent, /* Since all input will be blocked until this dialog is dismissed, * make sure its parent containers are visible first (this component - * is tested below). This is necessary for JApplets, because - * because an applet normally isn't made visible until after its - * start() method returns -- if this method is called from start(), - * the applet will appear to hang while an invisible modal frame - * waits for input. + * is tested below). */ if (dialog.isVisible() && !dialog.isShowing()) { Container parent = dialog.getParent(); diff --git a/src/java.desktop/share/classes/javax/swing/JRootPane.java b/src/java.desktop/share/classes/javax/swing/JRootPane.java index 44eb41248e6..61d3b3e707e 100644 --- a/src/java.desktop/share/classes/javax/swing/JRootPane.java +++ b/src/java.desktop/share/classes/javax/swing/JRootPane.java @@ -34,7 +34,7 @@ /** * A lightweight container used behind the scenes by * JFrame, JDialog, JWindow, - * JApplet, and JInternalFrame. + * and JInternalFrame. * For task-oriented information on functionality provided by root panes * see How to Use Root Panes, * a section in The Java Tutorial. @@ -42,21 +42,18 @@ *

          * The following image shows the relationships between * the classes that use root panes. - *

          The following text describes this graphic.

          + * HEIGHT=600 WIDTH=850>

          * The "heavyweight" components (those that delegate to a peer, or native - * component on the host system) are shown with a darker, heavier box. The four - * heavyweight JFC/Swing containers (JFrame, JDialog, - * JWindow, and JApplet) are - * shown in relation to the AWT classes they extend. - * These four components are the - * only heavyweight containers in the Swing library. The lightweight container - * JInternalFrame is also shown. - * All five of these JFC/Swing containers implement the - * RootPaneContainer interface, - * and they all delegate their operations to a - * JRootPane (shown with a little "handle" on top). + * component on the host system) are shown with a heavier box. AWT components in red, + * Swing heavyweights in blue. + * The three heavyweight JFC/Swing containers ({@code JFrame}, {@code JDialog}, and + * {@code JWindow}) are shown in relation to the AWT classes they extend. + * These three components are the only heavyweight containers in the Swing library. + * The lightweight container {@code JInternalFrame} is also shown in green with thin outline. + * All four of these JFC/Swing containers implement the {@code RootPaneContainer} interface, + * and they all delegate their operations to a {@code JRootPane}. *
          * Note: The JComponent method getRootPane * can be used to obtain the JRootPane that contains @@ -179,7 +176,6 @@ * @see JWindow * @see JFrame * @see JDialog - * @see JApplet * @see JInternalFrame * @see JComponent * @see BoxLayout diff --git a/src/java.desktop/share/classes/javax/swing/JTable.java b/src/java.desktop/share/classes/javax/swing/JTable.java index 3760bdac9ee..653466318a7 100644 --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java @@ -25,7 +25,6 @@ package javax.swing; -import java.applet.Applet; import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -6122,7 +6121,6 @@ public CellEditorRemover(KeyboardFocusManager fm) { this.focusManager = fm; } - @SuppressWarnings("removal") public void propertyChange(PropertyChangeEvent ev) { if (!isEditing() || getClientProperty("terminateEditOnFocusLost") != Boolean.TRUE) { return; @@ -6133,8 +6131,7 @@ public void propertyChange(PropertyChangeEvent ev) { if (c == JTable.this) { // focus remains inside the table return; - } else if ((c instanceof Window) || - (c instanceof Applet && c.getParent() == null)) { + } else if (c instanceof Window) { if (c == SwingUtilities.getRoot(JTable.this)) { if (!getCellEditor().stopCellEditing()) { getCellEditor().cancelCellEditing(); diff --git a/src/java.desktop/share/classes/javax/swing/JViewport.java b/src/java.desktop/share/classes/javax/swing/JViewport.java index f7c27314750..e7b1e1eacf0 100644 --- a/src/java.desktop/share/classes/javax/swing/JViewport.java +++ b/src/java.desktop/share/classes/javax/swing/JViewport.java @@ -378,7 +378,7 @@ public void remove(Component child) { * To avoid excessive validation when the containment hierarchy is * being created this will not validate if one of the ancestors does not * have a peer, or there is no validate root ancestor, or one of the - * ancestors is not a Window or Applet. + * ancestors is not a Window. *

          * Note that this method will not scroll outside of the * valid viewport; for example, if contentRect is larger diff --git a/src/java.desktop/share/classes/javax/swing/KeyboardManager.java b/src/java.desktop/share/classes/javax/swing/KeyboardManager.java index 2ba5749dcdc..42a6403ddb5 100644 --- a/src/java.desktop/share/classes/javax/swing/KeyboardManager.java +++ b/src/java.desktop/share/classes/javax/swing/KeyboardManager.java @@ -28,7 +28,6 @@ import java.util.*; import java.awt.*; import java.awt.event.*; -import java.applet.*; import sun.awt.EmbeddedFrame; /** @@ -130,13 +129,12 @@ public void registerKeyStroke(KeyStroke k, JComponent c) { } /** - * Find the top focusable Window, Applet, or InternalFrame + * Find the top focusable Window, or InternalFrame */ - @SuppressWarnings("removal") private static Container getTopAncestor(JComponent c) { for(Container p = c.getParent(); p != null; p = p.getParent()) { if (p instanceof Window && ((Window)p).isFocusableWindow() || - p instanceof Applet || p instanceof JInternalFrame) { + p instanceof JInternalFrame) { return p; } diff --git a/src/java.desktop/share/classes/javax/swing/PopupFactory.java b/src/java.desktop/share/classes/javax/swing/PopupFactory.java index 682cdbd005b..2b274c816b1 100644 --- a/src/java.desktop/share/classes/javax/swing/PopupFactory.java +++ b/src/java.desktop/share/classes/javax/swing/PopupFactory.java @@ -25,7 +25,6 @@ package javax.swing; -import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; @@ -274,7 +273,6 @@ else if (popupType == LIGHT_WEIGHT_POPUP && * Obtains the appropriate Popup based on * popupType. */ - @SuppressWarnings("removal") private Popup getPopup(Component owner, Component contents, int ownerX, int ownerY, int popupType) { if (GraphicsEnvironment.isHeadless()) { @@ -288,10 +286,6 @@ private Popup getPopup(Component owner, Component contents, return getMediumWeightPopup(owner, contents, ownerX, ownerY); case HEAVY_WEIGHT_POPUP: Popup popup = getHeavyWeightPopup(owner, contents, ownerX, ownerY); - if ((OSInfo.getOSType() == OSInfo.OSType.MACOSX) && (owner != null) && - (EmbeddedFrame.getAppletIfAncestorOf(owner) != null)) { - ((HeavyWeightPopup)popup).setCacheEnabled(false); - } return popup; } return null; @@ -626,7 +620,6 @@ boolean overlappedByOwnedWindow() { * Returns true if popup can fit the screen and the owner's top parent. * It determines can popup be lightweight or mediumweight. */ - @SuppressWarnings("removal") boolean fitsOnScreen() { boolean result = false; Component component = getComponent(); @@ -656,12 +649,6 @@ boolean fitsOnScreen() { result = parentBounds .contains(x, y, popupWidth, popupHeight); } - } else if (parent instanceof JApplet) { - Rectangle parentBounds = parent.getBounds(); - Point p = parent.getLocationOnScreen(); - parentBounds.x = p.x; - parentBounds.y = p.y; - result = parentBounds.contains(x, y, popupWidth, popupHeight); } } return result; @@ -795,7 +782,6 @@ public void hide() { recycleLightWeightPopup(this); } - @SuppressWarnings("removal") public void show() { Container parent = null; @@ -817,11 +803,6 @@ public void show() { parent = p; } break; - } else if (p instanceof JApplet) { - // Painting code stops at Applets, we don't want - // to add to a Component above an Applet otherwise - // you'll never see it painted. - break; } } @@ -948,7 +929,6 @@ public void hide() { recycleMediumWeightPopup(this); } - @SuppressWarnings("removal") public void show() { Component component = getComponent(); Container parent = null; @@ -961,7 +941,7 @@ public void show() { if it has a layered pane, add to that, otherwise add to the window. */ - while (!(parent instanceof Window || parent instanceof Applet) && + while (!(parent instanceof Window) && (parent!=null)) { parent = parent.getParent(); } diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index 8d9548d19e5..dcc755cb4bc 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -30,7 +30,6 @@ import java.awt.image.VolatileImage; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.applet.*; import sun.awt.AWTAccessor; import sun.awt.AppContext; @@ -52,8 +51,8 @@ * requests into a single repaint for members of a component tree. *

          * As of 1.6 RepaintManager handles repaint requests - * for Swing's top level components (JApplet, - * JWindow, JFrame and JDialog). + * for Swing's top level components + * (JWindow, JFrame and JDialog). * Any calls to repaint on one of these will call into the * appropriate addDirtyRegion method. * @@ -390,11 +389,8 @@ public synchronized void removeInvalidComponent(JComponent component) { delegate.removeInvalidComponent(component); return; } - if(invalidComponents != null) { - int index = invalidComponents.indexOf(component); - if(index != -1) { - invalidComponents.remove(index); - } + if (invalidComponents != null) { + invalidComponents.remove(component); } } @@ -406,7 +402,6 @@ public synchronized void removeInvalidComponent(JComponent component) { * * @see JComponent#repaint */ - @SuppressWarnings("removal") private void addDirtyRegion0(Container c, int x, int y, int w, int h) { /* Special cases we don't have to bother with. */ @@ -424,7 +419,7 @@ private void addDirtyRegion0(Container c, int x, int y, int w, int h) { return; } - /* Make sure that c and all it ancestors (up to an Applet or + /* Make sure that c and all it ancestors (up to a * Window) are visible. This loop has the same effect as * checking c.isShowing() (and note that it's still possible * that c is completely obscured by an opaque ancestor in @@ -440,7 +435,7 @@ private void addDirtyRegion0(Container c, int x, int y, int w, int h) { if (!p.isVisible() || !p.isDisplayable()) { return; } - if ((p instanceof Window) || (p instanceof Applet)) { + if (p instanceof Window) { // Iconified frames are still visible! if (p instanceof Frame && (((Frame)p).getExtendedState() & Frame.ICONIFIED) == @@ -508,29 +503,6 @@ public void addDirtyRegion(Window window, int x, int y, int w, int h) { addDirtyRegion0(window, x, y, w, h); } - /** - * Adds applet to the list of Components that - * need to be repainted. - * - * @param applet Applet to repaint, null results in nothing happening. - * @param x X coordinate of the region to repaint - * @param y Y coordinate of the region to repaint - * @param w Width of the region to repaint - * @param h Height of the region to repaint - * @see JApplet#repaint - * @since 1.6 - * - * @deprecated The Applet API is deprecated. See the - * java.applet package - * documentation for further information. - */ - @Deprecated(since = "9", forRemoval = true) - @SuppressWarnings("removal") - public void addDirtyRegion(Applet applet, int x, int y, int w, int h) { - addDirtyRegion0(applet, x, y, w, h); - } - - @SuppressWarnings("removal") void scheduleHeavyWeightPaints() { Map hws; @@ -547,10 +519,6 @@ void scheduleHeavyWeightPaints() { addDirtyRegion((Window)hw, dirty.x, dirty.y, dirty.width, dirty.height); } - else if (hw instanceof Applet) { - addDirtyRegion((Applet)hw, dirty.x, dirty.y, - dirty.width, dirty.height); - } else { // SwingHeavyWeight addDirtyRegion0(hw, dirty.x, dirty.y, dirty.width, dirty.height); diff --git a/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java b/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java index b05e0c52e55..b81c80dbf35 100644 --- a/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java +++ b/src/java.desktop/share/classes/javax/swing/RootPaneContainer.java @@ -31,7 +31,7 @@ /** * This interface is implemented by components that have a single - * JRootPane child: JDialog, JFrame, JWindow, JApplet, JInternalFrame. + * JRootPane child: JDialog, JFrame, JWindow, JInternalFrame. * The methods in this interface are just covers for the JRootPane * properties, e.g. getContentPane() is generally implemented * like this:

          @@ -46,7 +46,7 @@
            * as frame.getContentPane().add(child).
            * 

          * As a convenience, the standard classes that implement this interface - * (such as {@code JFrame}, {@code JDialog}, {@code JWindow}, {@code JApplet}, + * (such as {@code JFrame}, {@code JDialog}, {@code JWindow}, * and {@code JInternalFrame}) have their {@code add}, {@code remove}, * and {@code setLayout} methods overridden, so that they delegate calls * to the corresponding methods of the {@code ContentPane}. @@ -62,7 +62,7 @@ * The behavior of the add and * setLayout methods for * JFrame, JDialog, JWindow, - * JApplet and JInternalFrame is controlled by + * and JInternalFrame is controlled by * the rootPaneCheckingEnabled property. If this property is * true (the default), then calls to these methods are * forwarded to the contentPane; if false, these @@ -73,7 +73,6 @@ * @see JFrame * @see JDialog * @see JWindow - * @see JApplet * @see JInternalFrame * * @author Hans Muller diff --git a/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java b/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java index 6bd0400fd8d..329fe52ade5 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java +++ b/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java @@ -34,7 +34,7 @@ /** * Swing's PaintEventDispatcher. If the component specified by the PaintEvent - * is a top level Swing component (JFrame, JWindow, JDialog, JApplet), this + * is a top level Swing component (JFrame, JWindow, JDialog), this * will forward the request to the RepaintManager for eventual painting. * */ diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index c5b5bd051ff..ebf39ac0283 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -27,8 +27,6 @@ import sun.swing.SwingUtilities2; import sun.swing.UIAction; -import java.applet.*; - import java.awt.*; import java.awt.event.*; import java.awt.dnd.DropTarget; @@ -416,7 +414,6 @@ else if (sourceEvent instanceof MenuDragMouseEvent) { * @param p a Point object (converted to the new coordinate system) * @param c a Component object */ - @SuppressWarnings("removal") public static void convertPointToScreen(Point p,Component c) { Rectangle b; int x,y; @@ -425,8 +422,7 @@ public static void convertPointToScreen(Point p,Component c) { if(c instanceof JComponent) { x = c.getX(); y = c.getY(); - } else if(c instanceof java.applet.Applet || - c instanceof java.awt.Window) { + } else if(c instanceof java.awt.Window) { try { Point pp = c.getLocationOnScreen(); x = pp.x; @@ -443,7 +439,7 @@ public static void convertPointToScreen(Point p,Component c) { p.x += x; p.y += y; - if(c instanceof java.awt.Window || c instanceof java.applet.Applet) + if(c instanceof java.awt.Window) break; c = c.getParent(); } while(c != null); @@ -456,7 +452,6 @@ public static void convertPointToScreen(Point p,Component c) { * @param p a Point object (converted to the new coordinate system) * @param c a Component object */ - @SuppressWarnings("removal") public static void convertPointFromScreen(Point p,Component c) { Rectangle b; int x,y; @@ -465,8 +460,7 @@ public static void convertPointFromScreen(Point p,Component c) { if(c instanceof JComponent) { x = c.getX(); y = c.getY(); - } else if(c instanceof java.applet.Applet || - c instanceof java.awt.Window) { + } else if (c instanceof java.awt.Window) { try { Point pp = c.getLocationOnScreen(); x = pp.x; @@ -483,7 +477,7 @@ public static void convertPointFromScreen(Point p,Component c) { p.x -= x; p.y -= y; - if(c instanceof java.awt.Window || c instanceof java.applet.Applet) + if(c instanceof java.awt.Window) break; c = c.getParent(); } while(c != null); @@ -1655,20 +1649,15 @@ public static JRootPane getRootPane(Component c) { * Returns the root component for the current component tree. * * @param c the component - * @return the first ancestor of c that's a Window or the last Applet ancestor + * @return the first ancestor of c that's a Window */ - @SuppressWarnings("removal") public static Component getRoot(Component c) { - Component applet = null; for(Component p = c; p != null; p = p.getParent()) { if (p instanceof Window) { return p; } - if (p instanceof Applet) { - applet = p; - } } - return applet; + return null; } static JComponent getPaintingOrigin(JComponent c) { @@ -1698,7 +1687,6 @@ static JComponent getPaintingOrigin(JComponent c) { * @return true if a binding has found and processed * @since 1.4 */ - @SuppressWarnings("removal") public static boolean processKeyBindings(KeyEvent event) { if (event != null) { if (event.isConsumed()) { @@ -1718,9 +1706,8 @@ public static boolean processKeyBindings(KeyEvent event) { return ((JComponent)component).processKeyBindings( event, pressed); } - if ((component instanceof Applet) || - (component instanceof Window)) { - // No JComponents, if Window or Applet parent, process + if (component instanceof Window) { + // No JComponents, if Window parent, process // WHEN_IN_FOCUSED_WINDOW bindings. return JComponent.processKeyBindingsForAllComponents( event, (Container)component, pressed); @@ -2202,8 +2189,7 @@ public static Component getUnwrappedView(JViewport viewport) { * CellRendererPane}. *

          * The component hierarchy must be displayable up to the toplevel component - * (either a {@code Frame} or an {@code Applet} object.) Otherwise this - * method returns {@code null}. + * (a {@code Frame}). Otherwise this method returns {@code null}. *

          * If the {@code visibleOnly} argument is {@code true}, the found validate * root and all its parents up to the toplevel component must also be @@ -2214,7 +2200,6 @@ public static Component getUnwrappedView(JViewport viewport) { * @see java.awt.Component#isVisible() * @since 1.7 */ - @SuppressWarnings("removal") static Container getValidateRoot(Container c, boolean visibleOnly) { Container root = null; @@ -2237,7 +2222,7 @@ static Container getValidateRoot(Container c, boolean visibleOnly) { if (!c.isDisplayable() || (visibleOnly && !c.isVisible())) { return null; } - if (c instanceof Window || c instanceof Applet) { + if (c instanceof Window) { return root; } } diff --git a/src/java.desktop/share/classes/javax/swing/Timer.java b/src/java.desktop/share/classes/javax/swing/Timer.java index e5f17af2c05..38ced6f3102 100644 --- a/src/java.desktop/share/classes/javax/swing/Timer.java +++ b/src/java.desktop/share/classes/javax/swing/Timer.java @@ -174,7 +174,7 @@ public class Timer implements Serializable // This field is maintained by TimerQueue. // eventQueued can also be reset by the TimerQueue, but will only ever - // happen in applet case when TimerQueues thread is destroyed. + // happen in an AppContext case when TimerQueues thread is destroyed. // access to this field is synchronized on getLock() lock. transient TimerQueue.DelayedTimer delayedTimer = null; diff --git a/src/java.desktop/share/classes/javax/swing/ToolTipManager.java b/src/java.desktop/share/classes/javax/swing/ToolTipManager.java index 84d62e67c54..1f77980f896 100644 --- a/src/java.desktop/share/classes/javax/swing/ToolTipManager.java +++ b/src/java.desktop/share/classes/javax/swing/ToolTipManager.java @@ -794,7 +794,6 @@ public void focusLost(FocusEvent evt){ // Returns: 0 no adjust // -1 can't fit // >0 adjust value by amount returned - @SuppressWarnings("removal") private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){ if (invoker != null){ Container parent; @@ -803,7 +802,7 @@ private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){ if(parent instanceof JFrame || parent instanceof JDialog || parent instanceof JWindow) { // no check for awt.Frame since we use Heavy tips return getWidthAdjust(parent.getBounds(),popupRectInScreen); - } else if (parent instanceof JApplet || parent instanceof JInternalFrame) { + } else if (parent instanceof JInternalFrame) { if (popupFrameRect == null){ popupFrameRect = new Rectangle(); } @@ -828,7 +827,7 @@ private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){ if(parent instanceof JFrame || parent instanceof JDialog || parent instanceof JWindow) { return getHeightAdjust(parent.getBounds(),popupRectInScreen); - } else if (parent instanceof JApplet || parent instanceof JInternalFrame) { + } else if (parent instanceof JInternalFrame) { if (popupFrameRect == null){ popupFrameRect = new Rectangle(); } diff --git a/src/java.desktop/share/classes/javax/swing/UIManager.java b/src/java.desktop/share/classes/javax/swing/UIManager.java index 752b37a5238..e86d9caee6d 100644 --- a/src/java.desktop/share/classes/javax/swing/UIManager.java +++ b/src/java.desktop/share/classes/javax/swing/UIManager.java @@ -180,10 +180,8 @@ public class UIManager implements Serializable * Swing applications the fields in this class could just as well * be static members of UIManager however we give them * "AppContext" - * scope instead so that applets (and potentially multiple lightweight - * applications running in a single VM) have their own state. For example, - * an applet can alter its look and feel, see setLookAndFeel. - * Doing so has no affect on other applets (or the browser). + * scope instead so that potentially multiple lightweight + * applications running in a single VM have their own state. */ private static class LAFState { @@ -1455,8 +1453,8 @@ private static void initializeSystemDefaults(Properties swingProps) { /* * This method is called before any code that depends on the - * AppContext specific LAFState object runs. When the AppContext - * corresponds to a set of applets it's possible for this method + * AppContext specific LAFState object runs. + * In some AppContext cases, it's possible for this method * to be re-entered, which is why we grab a lock before calling * initialize(). */ diff --git a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor16.gif b/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor16.gif deleted file mode 100644 index 6de0a1f14ad..00000000000 Binary files a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor16.gif and /dev/null differ diff --git a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor32.gif b/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor32.gif deleted file mode 100644 index 464ee9dce11..00000000000 Binary files a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor32.gif and /dev/null differ diff --git a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono16.gif b/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono16.gif deleted file mode 100644 index 1112f96cdd7..00000000000 Binary files a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono16.gif and /dev/null differ diff --git a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono32.gif b/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono32.gif deleted file mode 100644 index 80b2a08efb9..00000000000 Binary files a/src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono32.gif and /dev/null differ diff --git a/src/java.desktop/share/classes/javax/swing/border/LineBorder.java b/src/java.desktop/share/classes/javax/swing/border/LineBorder.java index 9116731eaf0..7fcb644a261 100644 --- a/src/java.desktop/share/classes/javax/swing/border/LineBorder.java +++ b/src/java.desktop/share/classes/javax/swing/border/LineBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,6 +37,8 @@ import com.sun.java.swing.SwingUtilities3; +import static sun.java2d.pipe.Region.clipRound; + /** * A class which implements a line border of arbitrary thickness * and of a single color. @@ -161,7 +163,7 @@ private void paintUnscaledBorder(Component c, Graphics g, Shape outer; Shape inner; - int offs = this.thickness * (int) scaleFactor; + int offs = clipRound(this.thickness * scaleFactor); int size = offs + offs; if (this.roundedCorners) { float arc = .2f * offs; diff --git a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java index 706ae9ab320..3115b768263 100644 --- a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java +++ b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -738,6 +738,10 @@ private Color getColor(Component c) { } private JLabel getLabel(Component c) { + if (c instanceof JComponent comp) { + this.label.putClientProperty("html.disable", + comp.getClientProperty("html.disable")); + } this.label.setText(getTitle()); this.label.setFont(getFont(c)); this.label.setForeground(getColor(c)); diff --git a/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.gif b/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.gif deleted file mode 100644 index 2c4cca175c8..00000000000 Binary files a/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.gif and /dev/null differ diff --git a/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.svg b/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.svg new file mode 100644 index 00000000000..aed766b841f --- /dev/null +++ b/src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + Window + + + + + Frame + + + + + Dialog + + + + + JFrame + + + + + JDialog + + + + + JWindow + + + + + JInternalFrame + + + + + JRootPane + + + + + + + + + + + + + + + + + + + + + + + + AWT classes + Swing classes + implementing the + RootPaneContainer + interface + + diff --git a/src/java.desktop/share/classes/javax/swing/package-info.java b/src/java.desktop/share/classes/javax/swing/package-info.java index 3723c5a66e9..a1492cb7b28 100644 --- a/src/java.desktop/share/classes/javax/swing/package-info.java +++ b/src/java.desktop/share/classes/javax/swing/package-info.java @@ -44,10 +44,10 @@ * developers are not impacted by the restriction. *

          * Where the impact lies, however, is in constructing and showing a Swing - * application. Calls to an application's {@code main} method, or methods in - * {@code Applet}, are not invoked on the event dispatching thread. As such, + * application. Calls to an application's {@code main} method, + * are not invoked on the event dispatching thread. As such, * care must be taken to transfer control to the event dispatching thread when - * constructing and showing an application or applet. The preferred way to + * constructing and showing an application. The preferred way to * transfer control and begin working with Swing is to use {@code invokeLater}. * The {@code invokeLater} method schedules a {@code Runnable} to be processed * on the event dispatching thread. The following two examples work equally well diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index 07036eedbf6..a6d2a448186 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -468,6 +468,10 @@ protected void addMessageComponents(Container container, } JLabel label; label = new JLabel(s, JLabel.LEADING); + if (Boolean.TRUE.equals( + this.optionPane.getClientProperty("html.disable"))) { + label.putClientProperty("html.disable", true); + } label.setName("OptionPane.label"); configureMessageLabel(label); addMessageComponents(container, cons, label, maxll, true); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index 3869da4ee2b..e518f509c5a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -29,8 +29,6 @@ import javax.swing.event.*; import javax.swing.plaf.*; -import java.applet.Applet; - import java.awt.Component; import java.awt.ComponentOrientation; import java.awt.KeyboardFocusManager; @@ -916,10 +914,9 @@ public void eventDispatched(AWTEvent ev) { } } - @SuppressWarnings("removal") boolean isInPopup(Component src) { for (Component c=src; c!=null; c=c.getParent()) { - if (c instanceof Applet || c instanceof Window) { + if (c instanceof Window) { break; } else if (c instanceof JPopupMenu) { return true; @@ -1131,7 +1128,6 @@ void removeUIActionMap(JComponent c, ActionMap map) { } } - @SuppressWarnings("removal") public void stateChanged(ChangeEvent ev) { if (!(UIManager.getLookAndFeel() instanceof BasicLookAndFeel)) { uninstall(); @@ -1171,8 +1167,6 @@ public void stateChanged(ChangeEvent ev) { invoker = ((JFrame)c).getRootPane(); } else if(c instanceof JDialog) { invoker = ((JDialog)c).getRootPane(); - } else if(c instanceof JApplet) { - invoker = ((JApplet)c).getRootPane(); } else { while (!(c instanceof JComponent)) { if (c == null) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 3f4712cda08..59799f4d91a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -495,7 +495,11 @@ protected void installListeners() { } tabPane.addContainerListener(getHandler()); if (tabPane.getTabCount()>0) { - htmlViews = createHTMLVector(); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); + if (!(Boolean.TRUE.equals(htmlDisabled))) { + htmlViews = createHTMLVector(); + } } } @@ -4065,8 +4069,10 @@ else if (name =="indexForTitle") { private void updateHtmlViews(int index, boolean inserted) { String title = tabPane.getTitleAt(index); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { + if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { if (htmlViews==null) { // Initialize vector htmlViews = createHTMLVector(); } else { // Vector already exists diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 094f5be68c5..391cfdf0b65 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1029,14 +1029,17 @@ public Dimension getMaximumSize(JComponent c) { /** - * Gets the allocation to give the root View. Due - * to an unfortunate set of historical events this - * method is inappropriately named. The Rectangle - * returned has nothing to do with visibility. + * Gets the allocation (that is the allocated size) for the root view. + *

          + * The returned rectangle is unrelated to visibility. + * It is used to set the size of the root view. + *

          * The component must have a non-zero positive size for * this translation to be computed. * * @return the bounding box for the root view + * @see View#paint + * @see View#setSize */ protected Rectangle getVisibleEditorRect() { Rectangle alloc = editor.getBounds(); diff --git a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java index e7d6f996cbe..7bc3ad94866 100644 --- a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -408,7 +408,7 @@ public DocumentFilter getDocumentFilter() { /** * This allows the model to be safely rendered in the presence - * of currency, if the model supports being updated asynchronously. + * of concurrency, if the model supports being updated asynchronously. * The given runnable will be executed in a way that allows it * to safely read the model with no changes while the runnable * is being executed. The runnable itself may not diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java index 884ac624956..6d34d934194 100644 --- a/src/java.desktop/share/classes/module-info.java +++ b/src/java.desktop/share/classes/module-info.java @@ -61,7 +61,6 @@ requires transitive java.datatransfer; requires transitive java.xml; - exports java.applet; exports java.awt; exports java.awt.color; exports java.awt.desktop; diff --git a/src/java.desktop/share/classes/sun/awt/AppContext.java b/src/java.desktop/share/classes/sun/awt/AppContext.java index 3b93f1d2755..040861ce8a4 100644 --- a/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -53,7 +53,7 @@ * The AppContext is a table referenced by ThreadGroup which stores * application service instances. (If you are not writing an application * service, or don't know what one is, please do not use this class.) - * The AppContext allows applet access to what would otherwise be + * The AppContext allows a context access to what would otherwise be * potentially dangerous services, such as the ability to peek at * EventQueues or change the look-and-feel of a Swing application.

          * @@ -79,7 +79,7 @@ * }

          * * The problem with the above is that the Foo service is global in scope, - * so that applets and other untrusted code can execute methods on the + * so that untrusted code can execute methods on the * single, shared Foo instance. The Foo service therefore either needs * to block its use by untrusted code using a SecurityManager test, or * restrict its capabilities so that it doesn't matter if untrusted code @@ -104,20 +104,14 @@ * Since a separate AppContext can exist for each ThreadGroup, trusted * and untrusted code have access to different Foo instances. This allows * untrusted code access to "system-wide" services -- the service remains - * within the AppContext "sandbox". For example, say a malicious applet + * within the AppContext "sandbox". For example, say malicious code * wants to peek all of the key events on the EventQueue to listen for * passwords; if separate EventQueues are used for each ThreadGroup - * using AppContexts, the only key events that applet will be able to - * listen to are its own. A more reasonable applet request would be to + * using AppContexts, the only key events that code will be able to + * listen to are its own. A more reasonable request would be to * change the Swing default look-and-feel; with that default stored in - * an AppContext, the applet's look-and-feel will change without - * disrupting other applets or potentially the browser itself.

          - * - * Because the AppContext is a facility for safely extending application - * service support to applets, none of its methods may be blocked by a - * a SecurityManager check in a valid Java implementation. Applets may - * therefore safely invoke any of its methods without worry of being - * blocked. + * an AppContext, the look-and-feel will change without + * disrupting other contexts. * * @author Thomas Ball * @author Fred Ecks @@ -155,7 +149,7 @@ public static Set getAppContexts() { /* The main "system" AppContext, used by everything not otherwise contained in another AppContext. It is implicitly created for - standalone apps only (i.e. not applets) + standalone apps only. */ private static volatile AppContext mainAppContext; @@ -283,9 +277,7 @@ public static AppContext getAppContext() { ThreadGroup threadGroup = currentThreadGroup; // Special case: we implicitly create the main app context - // if no contexts have been created yet. This covers standalone apps - // and excludes applets because by the time applet starts - // a number of contexts have already been created by the plugin. + // if no contexts have been created yet. synchronized (getAppContextLock) { if (numAppContexts.get() == 0) { if (System.getProperty("javaplugin.version") == null && diff --git a/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java b/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java index 8c0669fa386..654cd04ff93 100644 --- a/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java +++ b/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java @@ -25,7 +25,6 @@ package sun.awt; -import java.applet.Applet; import java.awt.AWTKeyStroke; import java.awt.Component; import java.awt.Container; @@ -49,11 +48,11 @@ import java.util.Set; /** - * A generic container used for embedding Java components, usually applets. + * A generic container used for embedding Java components. * An EmbeddedFrame has two related uses: * * . Within a Java-based application, an EmbeddedFrame serves as a sort of - * firewall, preventing the contained components or applets from using + * firewall, preventing the contained components from using * getParent() to find parent components, such as menubars. * * . Within a C-based application, an EmbeddedFrame contains a window handle @@ -71,7 +70,7 @@ public abstract class EmbeddedFrame extends Frame private boolean isCursorAllowed = true; private boolean supportsXEmbed = false; @SuppressWarnings("serial") // Not statically typed as Serializable - private KeyboardFocusManager appletKFM; + private KeyboardFocusManager appKFM; /** * Use serialVersionUID from JDK 1.1 for interoperability. @@ -139,12 +138,12 @@ public void propertyChange(PropertyChangeEvent evt) { return; } - // should be the same as appletKFM + // should be the same as appKFM removeTraversingOutListeners((KeyboardFocusManager)evt.getSource()); - appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + appKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); if (isVisible()) { - addTraversingOutListeners(appletKFM); + addTraversingOutListeners(appKFM); } } @@ -169,44 +168,44 @@ private void removeTraversingOutListeners(KeyboardFocusManager kfm) { * EmbeddedFrame is first created or shown, we can't automatically determine * the correct KeyboardFocusManager to attach to as KeyEventDispatcher. * Those who want to use the functionality of traversing out of the EmbeddedFrame - * must call this method on the Applet's AppContext. After that, all the changes + * must call this method on the AppContext. After that, all the changes * can be handled automatically, including possible replacement of * KeyboardFocusManager. */ public void registerListeners() { - if (appletKFM != null) { - removeTraversingOutListeners(appletKFM); + if (appKFM != null) { + removeTraversingOutListeners(appKFM); } - appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + appKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager(); if (isVisible()) { - addTraversingOutListeners(appletKFM); + addTraversingOutListeners(appKFM); } } /** * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with - * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep + * KeyboardFocusManager of an AppContext. We don't want the KFM to keep * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we * add listeners in show() and remove them in hide(). */ @SuppressWarnings("deprecation") public void show() { - if (appletKFM != null) { - addTraversingOutListeners(appletKFM); + if (appKFM != null) { + addTraversingOutListeners(appKFM); } super.show(); } /** * Needed to avoid memory leak: we register this EmbeddedFrame as a listener with - * KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep + * KeyboardFocusManager of an AppContext. We don't want the KFM to keep * reference to our EmbeddedFrame forever if the Frame is no longer in use, so we * add listeners in show() and remove them in hide(). */ @SuppressWarnings("deprecation") public void hide() { - if (appletKFM != null) { - removeTraversingOutListeners(appletKFM); + if (appKFM != null) { + removeTraversingOutListeners(appKFM); } super.hide(); } @@ -511,31 +510,6 @@ public void toBack() {} public abstract void registerAccelerator(AWTKeyStroke stroke); public abstract void unregisterAccelerator(AWTKeyStroke stroke); - /** - * Checks if the component is in an EmbeddedFrame. If so, - * returns the applet found in the hierarchy or null if - * not found. - * @return the parent applet or {@code null} - * @since 1.6 - * - * @deprecated The Applet API is deprecated. See the - * java.applet package - * documentation for further information. - */ - @Deprecated(since = "9", forRemoval = true) - @SuppressWarnings("removal") - public static Applet getAppletIfAncestorOf(Component comp) { - Container parent = comp.getParent(); - Applet applet = null; - while (parent != null && !(parent instanceof EmbeddedFrame)) { - if (parent instanceof Applet) { - applet = (Applet)parent; - } - parent = parent.getParent(); - } - return parent == null ? null : applet; - } - /** * This method should be overridden in subclasses. It is * called when window this frame is within should be blocked diff --git a/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/src/java.desktop/share/classes/sun/awt/SunToolkit.java index 9bf805a5808..0f1edaf6a0e 100644 --- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -267,8 +267,7 @@ public static final boolean isAWTLockHeldByCurrentThread() { /* * Create a new AppContext, along with its EventQueue, for a - * new ThreadGroup. Browser code, for example, would use this - * method to create an AppContext & EventQueue for an Applet. + * new ThreadGroup. */ public static AppContext createNewAppContext() { ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); @@ -1635,9 +1634,6 @@ private void fireDesktopFontPropertyChanges() { * But GTK currently has an additional test based on locale which is * not applied by Metal. So mixing GTK in a few locales with Metal * would mean the last one wins. - * This could be stored per-app context which would work - * for different applets, but wouldn't help for a single application - * using GTK and some other L&F concurrently. * But it is expected this will be addressed within GTK and the font * system so is a temporary and somewhat unlikely harmless corner case. */ diff --git a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java index df7167c1dd3..ae7ee6618bf 100644 --- a/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/GifImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -31,6 +31,7 @@ */ package sun.awt.image; +import java.util.Arrays; import java.util.Hashtable; import java.io.InputStream; import java.io.IOException; @@ -569,6 +570,9 @@ private boolean readImage(boolean first, int disposal_method, int delay) 0, 0); } } + if (model.getTransparentPixel() > 0) { + Arrays.fill(saved_image, (byte) model.getTransparentPixel()); + } } int hints = (interlace ? interlaceflags : normalflags); diff --git a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java index e57bf169275..117ff4bec2a 100644 --- a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java +++ b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java @@ -44,12 +44,12 @@ * analysis is interesting; this class is merely a central container * for those timing values. * Note that, due to the variables in this class being static, - * use of particular time values by multiple applets will cause - * confusing results. For example, if plugin runs two applets - * simultaneously, the initTime for those applets will collide + * use of particular time values by multiple AppContexts will cause + * confusing results. For example, if two contexts run + * simultaneously, the initTime for those will collide * and the results may be undefined. *

          - * To automatically track startup performance in an app or applet, + * To automatically track startup performance in an app * use the command-line parameter sun.perflog as follows:
          *

          {@code
            *     -Dsun.perflog[=file:]
          @@ -167,9 +167,9 @@ private static long getCurrentTime() {
           
               /**
                * Sets the start time.  Ideally, this is the earliest time available
          -     * during the startup of a Java applet or application.  This time is
          +     * during the startup of an application.  This time is
                * later used to analyze the difference between the initial startup
          -     * time and other events in the system (such as an applet's init time).
          +     * time and other events in the system.
                */
               public static void setStartTime(String message) {
                   if (loggingEnabled()) {
          diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java
          index 2831cae2573..1194a1c5816 100644
          --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java
          +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java
          @@ -2481,7 +2481,7 @@ private Font2D findFont2DAllLocales(String name, int style) {
                * performed normally. There may be some duplication of effort, but
                * that code is already written to be able to perform properly if called
                * to duplicate work. The main difference is that if we detect we are
          -     * running in an applet/browser/Java plugin environment these new fonts
          +     * in an AppContext environment these new fonts
                * are not placed in the "default" maps but into an AppContext instance.
                * The font lookup mechanism in java.awt.Font.getFont2D() is also updated
                * so that look-up for composite fonts will in that case always
          @@ -2502,7 +2502,7 @@ private Font2D findFont2DAllLocales(String name, int style) {
                * Calling the methods below is "heavyweight" but it is expected that
                * these methods will be called very rarely.
                *
          -     * If _usingAlternateComposites is true, we are not in an "applet"
          +     * If _usingAlternateComposites is true, we are not in an "AppContext"
                * environment and the (single) application has selected
                * an alternate composite font behaviour.
                *
          diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java
          index 78b14bc605d..7165b1701fa 100644
          --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java
          +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java
          @@ -1441,7 +1441,7 @@ public Point getLocationOnScreen() {
                           comp = AWTAccessor.getComponentAccessor().getParent(comp);
                       }
           
          -            // applets, embedded, etc - translate directly
          +            // embedded, etc - translate directly
                       // XXX: override in subclass?
                       if (comp == null || comp instanceof sun.awt.EmbeddedFrame) {
                           return toGlobal(0, 0);
          diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
          index 77a67103fc3..ff25120b659 100644
          --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
          +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
          @@ -333,7 +333,7 @@ depth, getConfigColormap(0, screen),
           
               private static native void enterFullScreenExclusive(long window);
               private static native void exitFullScreenExclusive(long window);
          -    private static native boolean initXrandrExtension();
          +    private static native boolean initXrandrExtension(boolean useOldConfigDisplayMode);
               private static native DisplayMode getCurrentDisplayMode(int screen);
               private static native void enumDisplayModes(int screen,
                                                           ArrayList modes);
          @@ -350,10 +350,11 @@ private static native void configDisplayMode(int screen,
                */
               private static synchronized boolean isXrandrExtensionSupported() {
                   if (xrandrExtSupported == null) {
          -            xrandrExtSupported =
          -                Boolean.valueOf(initXrandrExtension());
          +            boolean useOldConfigDisplayMode =
          +                    Boolean.getBoolean("awt.x11useOldConfigDisplayMode");
          +            xrandrExtSupported = initXrandrExtension(useOldConfigDisplayMode);
                   }
          -        return xrandrExtSupported.booleanValue();
          +        return xrandrExtSupported;
               }
           
               @Override
          diff --git a/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h b/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
          index da6ae0c8117..82e956d4074 100644
          --- a/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
          +++ b/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h
          @@ -62,4 +62,11 @@ struct X11GraphicsConfigIDs {
               jfieldID bitsPerPixel;
           };
           
          +#define MAX_DISPLAY_MODES 256
          +typedef struct {
          +    unsigned int width;
          +    unsigned int height;
          +    jint refresh;
          +} DisplayMode;
          +
           #endif /* _AWT_GRAPHICSENV_H_ */
          diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
          index c7fe9c879ff..05d2eb4d0e3 100644
          --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
          +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
          @@ -55,6 +55,7 @@
           #include "gdefs.h"
           #include 
           #include "Trace.h"
          +#include 
           
           int awt_numScreens;     /* Xinerama-aware number of screens */
           
          @@ -76,6 +77,8 @@ jmethodID awtNotifyMID = NULL;
           jmethodID awtNotifyAllMID = NULL;
           jboolean awtLockInited = JNI_FALSE;
           
          +static Bool useNewConfigDisplayMode = True;
          +
           /** Convenience macro for loading the lock-related method IDs. */
           #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
               do { \
          @@ -1505,6 +1508,20 @@ typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
           
           typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
           
          +typedef void (*XRRSetScreenSizeType)(Display *dpy, Window window,
          +                                     int width, int height,
          +                                     int mmWidth, int mmHeight);
          +
          +typedef Status (*XRRSetCrtcConfigType)(Display *dpy,
          +                                       XRRScreenResources *resources,
          +                                       RRCrtc crtc,
          +                                       Time timestamp,
          +                                       int x, int y,
          +                                       RRMode mode,
          +                                       Rotation rotation,
          +                                       RROutput *outputs,
          +                                       int noutputs);
          +
           static XRRQueryVersionType               awt_XRRQueryVersion;
           static XRRGetScreenInfoType              awt_XRRGetScreenInfo;
           static XRRFreeScreenConfigInfoType       awt_XRRFreeScreenConfigInfo;
          @@ -1520,6 +1537,8 @@ static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
           static XRRFreeOutputInfoType             awt_XRRFreeOutputInfo;
           static XRRGetCrtcInfoType                awt_XRRGetCrtcInfo;
           static XRRFreeCrtcInfoType               awt_XRRFreeCrtcInfo;
          +static XRRSetScreenSizeType              awt_XRRSetScreenSize;
          +static XRRSetCrtcConfigType              awt_XRRSetCrtcConfig;
           
           #define LOAD_XRANDR_FUNC(f) \
               do { \
          @@ -1597,6 +1616,8 @@ X11GD_InitXrandrFuncs(JNIEnv *env)
               LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
               LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
               LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
          +    LOAD_XRANDR_FUNC(XRRSetScreenSize);
          +    LOAD_XRANDR_FUNC(XRRSetCrtcConfig);
           
               return JNI_TRUE;
           }
          @@ -1697,11 +1718,11 @@ X11GD_SetFullscreenMode(Window win, jboolean enabled)
           /*
            * Class:     sun_awt_X11GraphicsDevice
            * Method:    initXrandrExtension
          - * Signature: ()Z
          + * Signature: (Z)Z
            */
           JNIEXPORT jboolean JNICALL
           Java_sun_awt_X11GraphicsDevice_initXrandrExtension
          -    (JNIEnv *env, jclass x11gd)
          +    (JNIEnv *env, jclass x11gd, jboolean useOldConfigDisplayMode)
           {
           #if defined(NO_XRANDR)
               return JNI_FALSE;
          @@ -1717,10 +1738,304 @@ Java_sun_awt_X11GraphicsDevice_initXrandrExtension
               }
               AWT_FLUSH_UNLOCK();
           
          +    useNewConfigDisplayMode = !useOldConfigDisplayMode;
          +
               return ret;
           #endif /* NO_XRANDR */
           }
           
          +// ---------------------------------------------------
          +// display mode change via XRRSetCrtcConfig
          +// ---------------------------------------------------
          +
          +static jint refreshRateFromModeInfo(const XRRModeInfo *modeInfo) {
          +    if (!modeInfo->hTotal || !modeInfo->vTotal) {
          +        return 0;
          +    }
          +
          +    double vTotal = modeInfo->vTotal;
          +
          +    if (modeInfo->modeFlags & RR_Interlace) {
          +        vTotal /= 2;
          +    }
          +
          +    if (modeInfo->modeFlags & RR_DoubleScan) {
          +        vTotal *= 2;
          +    }
          +
          +    return (jint) round((double) modeInfo->dotClock / (vTotal * (double) modeInfo->hTotal));
          +}
          +
          +static inline Bool isLandscapeOrientation(XRRCrtcInfo* info) {
          +    if (!info) {
          +        return True;
          +    }
          +    return info->rotation == RR_Rotate_0 || info->rotation == RR_Rotate_180;
          +}
          +
          +static Bool xrrGetInfoForScreen(XRRScreenResources *res,
          +                                int screen,
          +                                XRRCrtcInfo **outCrtcInfo,
          +                                XRROutputInfo **outOutputInfo) {
          +    if (!res) {
          +        return False;
          +    }
          +
          +    int screenX = 0;
          +    int screenY = 0;
          +
          +    if (usingXinerama) {
          +        int nscreens = 0;
          +        XineramaScreenInfo *screens = XineramaQueryScreens(awt_display, &nscreens);
          +
          +        if (!screens) {
          +            return False;
          +        }
          +
          +        if (screen >= nscreens) {
          +            XFree(screens);
          +            return False;
          +        }
          +
          +        XineramaScreenInfo xScreenInfo = screens[screen];
          +
          +        screenX = xScreenInfo.x_org;
          +        screenY= xScreenInfo.y_org;
          +
          +        XFree(screens);
          +    }
          +
          +    for (int i = 0; i < res->noutput; ++i) {
          +        XRROutputInfo *output = awt_XRRGetOutputInfo(awt_display, res, res->outputs[i]);
          +        if (!output) {
          +            continue;
          +        }
          +        if (output->connection == RR_Connected && output->crtc) {
          +            // output is connected and has an active mode
          +            XRRCrtcInfo *crtcInfo = awt_XRRGetCrtcInfo(awt_display, res, output->crtc);
          +            if (crtcInfo) {
          +                if (crtcInfo->mode != None
          +                    && crtcInfo->x == screenX
          +                    && crtcInfo->y == screenY) {
          +                    if (outCrtcInfo) {
          +                        *outCrtcInfo = crtcInfo;
          +                    } else {
          +                        awt_XRRFreeCrtcInfo(crtcInfo);
          +                    }
          +                    if (outOutputInfo) {
          +                        *outOutputInfo = output;
          +                    } else {
          +                        awt_XRRFreeOutputInfo(output);
          +                    }
          +                    return True;
          +                }
          +                awt_XRRFreeCrtcInfo(crtcInfo);
          +            }
          +        }
          +        awt_XRRFreeOutputInfo(output);
          +    }
          +
          +    return False;
          +}
          +
          +static jobject xrrGetCurrentDisplayMode(JNIEnv* env, int screen) {
          +    XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display));
          +    if (!res) {
          +        return NULL;
          +    }
          +
          +    XRRCrtcInfo* currentCrtcInfo = NULL;
          +    if (!xrrGetInfoForScreen(res, screen, ¤tCrtcInfo, NULL)) {
          +        goto cleanup;
          +    }
          +
          +    if (!currentCrtcInfo || currentCrtcInfo->mode == None) {
          +        goto cleanup;
          +    }
          +
          +    for (int i = 0; i < res->nmode; ++i) {
          +        if (res->modes[i].id == currentCrtcInfo->mode) {
          +            XRRModeInfo mode = res->modes[i];
          +            DisplayMode dm = {
          +                    mode.width,
          +                    mode.height,
          +                    refreshRateFromModeInfo(&mode)
          +            };
          +
          +            Bool isLandscape =  isLandscapeOrientation(currentCrtcInfo);
          +
          +            jint resultWidth = isLandscape ? (jint)  dm.width : (jint) dm.height;
          +            jint resultHeight = isLandscape ? (jint)  dm.height : (jint) dm.width;
          +
          +            jobject displayMode = X11GD_CreateDisplayMode(env,
          +                                                          resultWidth,
          +                                                          resultHeight,
          +                                                          BIT_DEPTH_MULTI,
          +                                                          dm.refresh);
          +
          +            awt_XRRFreeCrtcInfo(currentCrtcInfo);
          +            awt_XRRFreeScreenResources(res);
          +
          +            return displayMode;
          +        }
          +    }
          +
          +    cleanup:
          +        if (currentCrtcInfo) {
          +            awt_XRRFreeCrtcInfo(currentCrtcInfo);
          +        }
          +        awt_XRRFreeScreenResources(res);
          +    return NULL;
          +}
          +
          +static Bool isUniqueDisplayMode(DisplayMode seen[], int count, unsigned int width, unsigned int height, int refresh) {
          +    for (int i = 0; i < count; ++i) {
          +        if (seen[i].width == width &&
          +            seen[i].height == height &&
          +            seen[i].refresh == refresh) {
          +            return False;
          +        }
          +    }
          +    return True;
          +}
          +
          +static void xrrEnumDisplayModes(JNIEnv *env, jobject arrayList, jint screen) {
          +    XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display));
          +    if (!res) {
          +        return;
          +    }
          +
          +    XRRCrtcInfo *crtcInfo = NULL;
          +    XRROutputInfo *outputInfo = NULL;
          +    if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) {
          +        goto cleanup;
          +    }
          +
          +    DisplayMode seenModes[MAX_DISPLAY_MODES];
          +    int seenCount = 0;
          +
          +    Bool isLandscape = isLandscapeOrientation(crtcInfo);
          +
          +    for (int i = 0; i < outputInfo->nmode; ++i) {
          +        RRMode mode_id = outputInfo->modes[i];
          +
          +        for (int j = 0; j < res->nmode; ++j) {
          +            if (res->modes[j].id == mode_id) {
          +                XRRModeInfo mode = res->modes[j];
          +                jint rr = refreshRateFromModeInfo(&mode);
          +
          +                // The refresh rate is stored as an integer in Java, so we need to round the double value.
          +                // Because of this rounding, duplicate modes may appear. We only keep the first one encountered.
          +                if (isUniqueDisplayMode(seenModes, seenCount, mode.width, mode.height, rr)) {
          +                    seenModes[seenCount++] = (DisplayMode) {
          +                            mode.width,
          +                            mode.height,
          +                            rr
          +                    };
          +                    X11GD_AddDisplayMode(env, arrayList,
          +                                         isLandscape ? (jint) mode.width : (jint) mode.height,
          +                                         isLandscape ? (jint) mode.height : (jint) mode.width,
          +                                         BIT_DEPTH_MULTI,
          +                                         rr);
          +                    if ((*env)->ExceptionCheck(env)) {
          +                        goto cleanup;
          +                    }
          +                }
          +                break;
          +            }
          +        }
          +    }
          +
          +    cleanup:
          +        if (outputInfo) {
          +            awt_XRRFreeOutputInfo(outputInfo);
          +        }
          +        if (crtcInfo) {
          +            awt_XRRFreeCrtcInfo(crtcInfo);
          +        }
          +        awt_XRRFreeScreenResources(res);
          +}
          +
          +static void xrrChangeDisplayMode(jint screen, jint width, jint height, jint refreshRate) {
          +    Drawable root = DefaultRootWindow(awt_display);
          +
          +
          +    XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, root);
          +    if (!res) {
          +        return;
          +    }
          +
          +    XRRCrtcInfo *crtcInfo = NULL;
          +    XRROutputInfo *outputInfo = NULL;
          +
          +    if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) {
          +        goto cleanup;
          +    }
          +
          +    RRMode new_mode = None;
          +
          +    Bool isLandscape = isLandscapeOrientation(crtcInfo);
          +
          +    for (int i = 0; i < res->nmode; ++i) {
          +        XRRModeInfo mode = res->modes[i];
          +        jint rr = refreshRateFromModeInfo(&mode);
          +
          +        Bool matchW = (isLandscape ? mode.width : mode.height) == (unsigned int) width;
          +        Bool matchH = (isLandscape ? mode.height : mode.width) == (unsigned int) height;
          +
          +        if (matchW && matchH && rr == refreshRate) {
          +            for (int j = 0; j < outputInfo->nmode; ++j) {
          +                if (mode.id == outputInfo->modes[j]) {
          +                    // belongs to our output
          +                    new_mode = mode.id;
          +                    break;
          +                }
          +            }
          +            if (new_mode != None) {
          +                break;
          +            }
          +        }
          +    }
          +
          +    if (new_mode == None) {
          +        goto cleanup;
          +    }
          +
          +    awt_XRRSetCrtcConfig (awt_display, res, outputInfo->crtc, CurrentTime,
          +                          0, 0, None, RR_Rotate_0, NULL, 0);
          +
          +    int resultMmWidth = outputInfo->mm_width
          +                        ? (int) outputInfo->mm_width
          +                        : DisplayWidthMM(awt_display, DefaultScreen(awt_display));
          +
          +    int resultMmHeight = outputInfo->mm_height
          +                         ? (int) outputInfo->mm_height
          +                         : XDisplayHeightMM(awt_display, DefaultScreen(awt_display));
          +
          +    awt_XRRSetScreenSize(awt_display, root,
          +                         width, height,
          +                         resultMmWidth, resultMmHeight);
          +
          +    Status s = awt_XRRSetCrtcConfig(awt_display, res, outputInfo->crtc,
          +                         CurrentTime,
          +                         crtcInfo->x, crtcInfo->y,
          +                         new_mode, crtcInfo->rotation,
          +                         crtcInfo->outputs, crtcInfo->noutput);
          +
          +    cleanup:
          +        if (crtcInfo) {
          +            awt_XRRFreeCrtcInfo(crtcInfo);
          +        }
          +        if (outputInfo) {
          +            awt_XRRFreeOutputInfo(outputInfo);
          +        }
          +        awt_XRRFreeScreenResources(res);
          +}
          +
          +// ---------------------------------------------------
          +// display mode change via XRRSetCrtcConfig
          +// ---------------------------------------------------
          +
           /*
            * Class:     sun_awt_X11GraphicsDevice
            * Method:    getCurrentDisplayMode
          @@ -1733,9 +2048,17 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
           #if defined(NO_XRANDR)
               return NULL;
           #else
          -    XRRScreenConfiguration *config;
               jobject displayMode = NULL;
           
          +    if (useNewConfigDisplayMode) {
          +        AWT_LOCK();
          +        displayMode = xrrGetCurrentDisplayMode(env, screen);
          +        AWT_FLUSH_UNLOCK();
          +        return displayMode;
          +    }
          +
          +    XRRScreenConfiguration *config;
          +
               AWT_LOCK();
           
               if (screen < ScreenCount(awt_display)) {
          @@ -1786,7 +2109,12 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes
           {
           #if !defined(NO_XRANDR)
           
          -    AWT_LOCK();
          +    if (useNewConfigDisplayMode) {
          +        AWT_LOCK();
          +        xrrEnumDisplayModes(env, arrayList, screen);
          +        AWT_FLUSH_UNLOCK();
          +        return;
          +    }
           
               if (XScreenCount(awt_display) > 0) {
           
          @@ -1836,6 +2164,15 @@ Java_sun_awt_X11GraphicsDevice_configDisplayMode
                jint screen, jint width, jint height, jint refreshRate)
           {
           #if !defined(NO_XRANDR)
          +    if (useNewConfigDisplayMode) {
          +        AWT_LOCK();
          +        XGrabServer(awt_display);
          +        xrrChangeDisplayMode(screen, width, height, refreshRate);
          +        XUngrabServer(awt_display);
          +        AWT_FLUSH_UNLOCK();
          +        return;
          +    }
          +
               jboolean success = JNI_FALSE;
               XRRScreenConfiguration *config;
               Drawable root;
          diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
          index ea921d3f636..e29c6bc4319 100644
          --- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
          +++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
          @@ -33,6 +33,7 @@
           
           #ifndef _AIX
           #include "screencast_pipewire.h"
          +#include "java_awt_event_KeyEvent.h"
           
           struct pw_buffer *(*fp_pw_stream_dequeue_buffer)(struct pw_stream *stream);
           const char * (*fp_pw_stream_state_as_string)(enum pw_stream_state state);
          @@ -1197,6 +1198,24 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
               return result ? RESULT_OK : pw.pwFd;
           }
           
          +static int getNumpadKey(jint jkey) {
          +    switch (jkey) {
          +        case java_awt_event_KeyEvent_VK_NUMPAD0: return XK_KP_Insert;
          +        case java_awt_event_KeyEvent_VK_NUMPAD1: return XK_KP_End;
          +        case java_awt_event_KeyEvent_VK_NUMPAD2: return XK_KP_Down;
          +        case java_awt_event_KeyEvent_VK_NUMPAD3: return XK_KP_Page_Down;
          +        case java_awt_event_KeyEvent_VK_NUMPAD4: return XK_KP_Left;
          +        case java_awt_event_KeyEvent_VK_NUMPAD5: return XK_KP_Begin;
          +        case java_awt_event_KeyEvent_VK_NUMPAD6: return XK_KP_Right;
          +        case java_awt_event_KeyEvent_VK_NUMPAD7: return XK_KP_Home;
          +        case java_awt_event_KeyEvent_VK_NUMPAD8: return XK_KP_Up;
          +        case java_awt_event_KeyEvent_VK_NUMPAD9: return XK_KP_Prior;
          +        case java_awt_event_KeyEvent_VK_DECIMAL:
          +        case java_awt_event_KeyEvent_VK_SEPARATOR: return XK_KP_Delete;
          +        default: return 0;
          +    }
          +}
          +
           /*
            * Class:     sun_awt_screencast_ScreencastHelper
            * Method:    remoteDesktopKeyImpl
          @@ -1205,9 +1224,12 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
           JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl
                   (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) {
           
          -    AWT_LOCK();
          -    int key = awt_getX11KeySym(jkey);
          -    AWT_UNLOCK();
          +    int key = getNumpadKey(jkey);
          +    if (!key) {
          +        AWT_LOCK();
          +        key = awt_getX11KeySym(jkey);
          +        AWT_UNLOCK();
          +    }
           
               if (key == NoSymbol || (*env)->ExceptionCheck(env)) {
                   return RESULT_ERROR;
          diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java
          index ad0745a2733..dcdee830edc 100644
          --- a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java
          +++ b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java
          @@ -253,8 +253,8 @@ public void unregisterAccelerator(AWTKeyStroke stroke) {}
                *     super.notifyModalBlocked(blocker, blocked) must be present
                *     when overriding.
                * It may occur that embedded frame is not put into its
          -     *     container at the moment when it is blocked, for example,
          -     *     when running an applet in IE. Then the call to this method
          +     *     container at the moment when it is blocked.
          +     *     Then the call to this method
                *     should be delayed until embedded frame is reparented.
                *
                * NOTE: This method may be called by privileged threads.
          diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.h b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.h
          index 52e28e4cc57..91886c46a9a 100644
          --- a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.h
          +++ b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.h
          @@ -128,8 +128,7 @@ class AwtDialog : public AwtFrame {
               static LRESULT CALLBACK MouseHookProc(int code,
                                                     WPARAM wParam, LPARAM lParam);
               // WM_MOUSE hook procedure used in modality, similar to
          -    // MouseHookProc but installed on non-toolkit threads, for
          -    // example on browser's thread when running in Java Plugin
          +    // MouseHookProc but installed on non-toolkit threads
               static LRESULT CALLBACK MouseHookProc_NonTT(int code,
                                                           WPARAM wParam, LPARAM lParam);
           
          diff --git a/src/java.desktop/windows/native/libawt/windows/awt_GDIObject.cpp b/src/java.desktop/windows/native/libawt/windows/awt_GDIObject.cpp
          index b396538455a..90d7854d0c8 100644
          --- a/src/java.desktop/windows/native/libawt/windows/awt_GDIObject.cpp
          +++ b/src/java.desktop/windows/native/libawt/windows/awt_GDIObject.cpp
          @@ -49,7 +49,6 @@
            * Set our limit much lower than that to allow a buffer for objects
            * created beyond the per-thread HDC/Brush/Pen objects we are
            * counting here, including objects created by the overall process
          - * (which could include the browser, in the case of applets)
            */
           #define MAX_GDI_OBJECTS 9000
           
          diff --git a/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp b/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp
          index 9f126bded94..9abe32e0fcc 100644
          --- a/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp
          +++ b/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp
          @@ -1786,8 +1786,8 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WEmbeddedFrame_printBand
           //     ::PatBlt(hDC, destX+1, destY+1, destWidth-2, destHeight-2, PATCOPY);
           //     ::SelectObject(hDC, oldBrush);
           
          -    /* This code is rarely used now. It used to be invoked by Java plugin browser
          -     * printing. Today embedded frames are used only when a toolkit such as SWT
          +    /* This code is rarely used now.
          +     * Today embedded frames are used only when a toolkit such as SWT
                * needs to embed
                */
               TRY;
          diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
          index d5bbdc51b0b..0e7e27b5e8c 100644
          --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
          +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp
          @@ -2498,32 +2498,22 @@ jint AwtWindow::_GetScreenImOn(void *param)
           
               jobject self = (jobject)param;
           
          -    // It's entirely possible that our native resources have been destroyed
          -    // before our java peer - if we're dispose()d, for instance.
          -    // Alert caller w/ IllegalComponentStateException.
          -    if (self == NULL) {
          -        JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
          -                        "Peer null in JNI");
          -        return 0;
          -    }
          -    PDATA pData = JNI_GET_PDATA(self);
          -    if (pData == NULL) {
          -        JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
          -                        "Native resources unavailable");
          -        env->DeleteGlobalRef(self);
          -        return 0;
          -    }
          +    jint result = -1;
          +    AwtWindow* window = NULL;
           
          -    jint result = 0;
          -    AwtWindow *w = (AwtWindow *)pData;
          -    if (::IsWindow(w->GetHWnd()))
          +    // Our native resources may have been destroyed before the Java peer,
          +    // e.g., if dispose() was called. In that case, return the default screen.
          +    PDATA pData;
          +    JNI_CHECK_PEER_GOTO(self, ret);
          +    window = (AwtWindow *)pData;
          +    if (::IsWindow(window->GetHWnd()))
               {
          -        result = (jint)w->GetScreenImOn();
          +        result = (jint)window->GetScreenImOn();
               }
           
          +  ret:
               env->DeleteGlobalRef(self);
          -
          -    return result;
          +    return (result != -1) ? result : AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
           }
           
           void AwtWindow::_SetFocusableWindow(void *param)
          diff --git a/src/java.management/share/classes/javax/management/AttributeList.java b/src/java.management/share/classes/javax/management/AttributeList.java
          index 932c4974244..c85b119f3a0 100644
          --- a/src/java.management/share/classes/javax/management/AttributeList.java
          +++ b/src/java.management/share/classes/javax/management/AttributeList.java
          @@ -1,5 +1,5 @@
           /*
          - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
          + * Copyright (c) 1999, 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
          @@ -37,13 +37,9 @@
            * {@link MBeanServerConnection#setAttributes setAttributes} methods of
            * {@link MBeanServer} and {@link MBeanServerConnection}.

          * - *

          For compatibility reasons, it is possible, though - * highly discouraged, to add objects to an {@code AttributeList} that are - * not instances of {@code Attribute}. However, an {@code AttributeList} - * can be made type-safe, which means that an attempt to add - * an object that is not an {@code Attribute} will produce an {@code - * IllegalArgumentException}. An {@code AttributeList} becomes type-safe - * when the method {@link #asList()} is called on it.

          + *

          It is not permitted to add objects to an {@code AttributeList} that are + * not instances of {@code Attribute}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

          * * @since 1.5 */ @@ -64,9 +60,6 @@ the asList() method so you can write */ public class AttributeList extends ArrayList { - private transient volatile boolean typeSafe; - private transient volatile boolean tainted; - /* Serial version */ private static final long serialVersionUID = -4077085769279709076L; @@ -145,14 +138,6 @@ public AttributeList(List list) { * @return a {@code List} whose contents * reflect the contents of this {@code AttributeList}. * - *

          If this method has ever been called on a given - * {@code AttributeList} instance, a subsequent attempt to add - * an object to that instance which is not an {@code Attribute} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, an {@code AttributeList} on which this method has never - * been called does allow objects other than {@code Attribute}s to - * be added.

          - * * @throws IllegalArgumentException if this {@code AttributeList} contains * an element that is not an {@code Attribute}. * @@ -160,9 +145,7 @@ public AttributeList(List list) { */ @SuppressWarnings("unchecked") public List asList() { - typeSafe = true; - if (tainted) - adding((Collection) this); // will throw IllegalArgumentException + adding((Collection) this); return (List) (List) this; } @@ -257,15 +240,12 @@ public boolean addAll(int index, AttributeList list) { /* * Override all of the methods from ArrayList that might add - * a non-Attribute to the List, and disallow that if asList has ever - * been called on this instance. + * a non-Attribute to the List, and disallow. */ /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public boolean add(Object element) { @@ -275,9 +255,7 @@ public boolean add(Object element) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public void add(int index, Object element) { @@ -287,9 +265,7 @@ public void add(int index, Object element) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code c} contains an - * element that is not an {@code Attribute}. + * @throws IllegalArgumentException if {@code c} contains an element that is not an {@code Attribute}. */ @Override public boolean addAll(Collection c) { @@ -299,9 +275,7 @@ public boolean addAll(Collection c) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code c} contains an - * element that is not an {@code Attribute}. + * @throws IllegalArgumentException if {@code c} contains an element that is not an {@code Attribute}. */ @Override public boolean addAll(int index, Collection c) { @@ -311,9 +285,7 @@ public boolean addAll(int index, Collection c) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public Object set(int index, Object element) { @@ -324,10 +296,7 @@ public Object set(int index, Object element) { private void adding(Object x) { if (x == null || x instanceof Attribute) return; - if (typeSafe) - throw new IllegalArgumentException("Not an Attribute: " + x); - else - tainted = true; + throw new IllegalArgumentException("Not an Attribute: " + x); } private void adding(Collection c) { diff --git a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java index ff90068958f..731dd619d26 100644 --- a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java +++ b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java @@ -138,6 +138,7 @@ private Object readResolve() throws InvalidObjectException { if (names == null || values == null || names.length != values.length) bad = true; if (!bad) { + hashCode = -1; // Force recalculation if (names.length == 0 && getClass() == ImmutableDescriptor.class) return EMPTY_DESCRIPTOR; final Comparator compare = String.CASE_INSENSITIVE_ORDER; @@ -441,12 +442,14 @@ public Descriptor clone() { */ public final void setFields(String[] fieldNames, Object[] fieldValues) throws RuntimeOperationsException { + if (fieldNames == null || fieldValues == null) illegal("Null argument"); if (fieldNames.length != fieldValues.length) illegal("Different array sizes"); for (int i = 0; i < fieldNames.length; i++) checkIllegalFieldName(fieldNames[i]); + hashCode = -1; // Force recalculation for (int i = 0; i < fieldNames.length; i++) setField(fieldNames[i], fieldValues[i]); } @@ -462,10 +465,12 @@ public final void setFields(String[] fieldNames, Object[] fieldValues) */ public final void setField(String fieldName, Object fieldValue) throws RuntimeOperationsException { + checkIllegalFieldName(fieldName); int i = fieldIndex(fieldName); if (i < 0) unsupported(); + hashCode = -1; // Force recalculation Object value = values[i]; if ((value == null) ? (fieldValue != null) : @@ -485,6 +490,7 @@ public final void setField(String fieldName, Object fieldValue) * be an {@link UnsupportedOperationException}. */ public final void removeField(String fieldName) { + hashCode = -1; // Force recalculation if (fieldName != null && fieldIndex(fieldName) >= 0) unsupported(); } diff --git a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java index 71f8f61bedb..cd5cd29c4d8 100644 --- a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -174,137 +174,6 @@ public DescriptorSupport(DescriptorSupport inDescr) { init(inDescr.descriptorMap); } - - /** - *

          Descriptor constructor taking an XML String.

          - * - *

          The format of the XML string is not defined, but an - * implementation must ensure that the string returned by - * {@link #toXMLString() toXMLString()} on an existing - * descriptor can be used to instantiate an equivalent - * descriptor using this constructor.

          - * - *

          In this implementation, all field values will be created - * as Strings. If the field values are not Strings, the - * programmer will have to reset or convert these fields - * correctly.

          - * - * @param inStr An XML-formatted string used to populate this - * Descriptor. The format is not defined, but any - * implementation must ensure that the string returned by - * method {@link #toXMLString toXMLString} on an existing - * descriptor can be used to instantiate an equivalent - * descriptor when instantiated using this constructor. - * - * @exception RuntimeOperationsException If the String inStr - * passed in parameter is null - * @exception XMLParseException XML parsing problem while parsing - * the input String - * @exception MBeanException Wraps a distributed communication Exception. - * @deprecated This constructor exists for historical reasons. If - * reading from XML is required, it should be implemented externally. - */ - /* At some stage we should rewrite this code to be cleverer. Using - a StringTokenizer as we do means, first, that we accept a lot of - bogus strings without noticing they are bogus, and second, that we - split the string being parsed at characters like > even if they - occur in the middle of a field value. */ - @Deprecated(since="25", forRemoval=true) - @SuppressWarnings("removal") - public DescriptorSupport(String inStr) - throws MBeanException, RuntimeOperationsException, - XMLParseException { - /* parse an XML-formatted string and populate internal - * structure with it */ - if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { - MODELMBEAN_LOGGER.log(Level.TRACE, - "Descriptor(String = '" + inStr + "') Constructor"); - } - if (inStr == null) { - if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { - MODELMBEAN_LOGGER.log(Level.TRACE, - "Descriptor(String = null) Illegal arguments"); - } - final String msg = "String in parameter is null"; - final RuntimeException iae = new IllegalArgumentException(msg); - throw new RuntimeOperationsException(iae, msg); - } - - final String lowerInStr = inStr.toLowerCase(Locale.ENGLISH); - if (!lowerInStr.startsWith("") - || !lowerInStr.endsWith("")) { - throw new XMLParseException("No , pair"); - // XMLParseException is deprecated for removal. - } - - // parse xmlstring into structures - init(null); - // create dummy descriptor: should have same size - // as number of fields in xmlstring - // loop through structures and put them in descriptor - - StringTokenizer st = new StringTokenizer(inStr, "<> \t\n\r\f"); - - boolean inFld = false; - boolean inDesc = false; - String fieldName = null; - String fieldValue = null; - - - while (st.hasMoreTokens()) { // loop through tokens - String tok = st.nextToken(); - - if (tok.equalsIgnoreCase("FIELD")) { - inFld = true; - } else if (tok.equalsIgnoreCase("/FIELD")) { - if ((fieldName != null) && (fieldValue != null)) { - fieldName = - fieldName.substring(fieldName.indexOf('"') + 1, - fieldName.lastIndexOf('"')); - final Object fieldValueObject = - parseQuotedFieldValue(fieldValue); - setField(fieldName, fieldValueObject); - } - fieldName = null; - fieldValue = null; - inFld = false; - } else if (tok.equalsIgnoreCase("DESCRIPTOR")) { - inDesc = true; - } else if (tok.equalsIgnoreCase("/DESCRIPTOR")) { - inDesc = false; - fieldName = null; - fieldValue = null; - inFld = false; - } else if (inFld && inDesc) { - // want kw=value, eg, name="myname" value="myvalue" - int eq_separator = tok.indexOf('='); - if (eq_separator > 0) { - String kwPart = tok.substring(0,eq_separator); - String valPart = tok.substring(eq_separator+1); - if (kwPart.equalsIgnoreCase("NAME")) - fieldName = valPart; - else if (kwPart.equalsIgnoreCase("VALUE")) - fieldValue = valPart; - else { // xml parse exception - final String msg = - "Expected `name' or `value', got `" + tok + "'"; - throw new XMLParseException(msg); - // XMLParseException is deprecated for removal. - } - } else { // xml parse exception - final String msg = - "Expected `keyword=value', got `" + tok + "'"; - throw new XMLParseException(msg); - // XMLParseException is deprecated for removal. - } - } - } // while tokens - if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { - MODELMBEAN_LOGGER.log(Level.TRACE, - "Descriptor(XMLString) Exit"); - } - } - /** * Constructor taking field names and field values. Neither array * can be null. @@ -899,231 +768,6 @@ private boolean validateField(String fldName, Object fldValue) { return true; } - - - /** - *

          Returns an XML String representing the descriptor.

          - * - *

          The format is not defined, but an implementation must - * ensure that the string returned by this method can be - * used to build an equivalent descriptor when instantiated - * using the constructor {@link #DescriptorSupport(String) - * DescriptorSupport(String inStr)}.

          - * - *

          Fields which are not String objects will have toString() - * called on them to create the value. The value will be - * enclosed in parentheses. It is not guaranteed that you can - * reconstruct these objects unless they have been - * specifically set up to support toString() in a meaningful - * format and have a matching constructor that accepts a - * String in the same format.

          - * - *

          If the descriptor is empty the following String is - * returned: <Descriptor></Descriptor>

          - * - * @return the XML string. - * - * @exception RuntimeOperationsException for illegal value for - * field Names or field Values. If the XML formatted string - * construction fails for any reason, this exception will be - * thrown. - * @deprecated This method exists for historical reasons. If - * writing to XML is required, it should be implemented externally. - */ - @Deprecated(since="25", forRemoval=true) - public synchronized String toXMLString() { - final StringBuilder buf = new StringBuilder(""); - Set> returnedSet = descriptorMap.entrySet(); - for (Map.Entry currElement : returnedSet) { - final String name = currElement.getKey(); - Object value = currElement.getValue(); - String valueString = null; - /* Set valueString to non-null if and only if this is a string that - cannot be confused with the encoding of an object. If it - could be so confused (surrounded by parentheses) then we - call makeFieldValue as for any non-String object and end - up with an encoding like "(java.lang.String/(thing))". */ - if (value instanceof String) { - final String svalue = (String) value; - if (!svalue.startsWith("(") || !svalue.endsWith(")")) - valueString = quote(svalue); - } - if (valueString == null) - valueString = makeFieldValue(value); - buf.append(""); - } - buf.append(""); - return buf.toString(); - } - - private static final String[] entities = { - " ", - "\""", - "<<", - ">>", - "&&", - "\r ", - "\t ", - "\n ", - "\f ", - }; - private static final Map entityToCharMap = - new HashMap<>(); - private static final String[] charToEntityMap; - - static { - char maxChar = 0; - for (int i = 0; i < entities.length; i++) { - final char c = entities[i].charAt(0); - if (c > maxChar) - maxChar = c; - } - charToEntityMap = new String[maxChar + 1]; - for (int i = 0; i < entities.length; i++) { - final char c = entities[i].charAt(0); - final String entity = entities[i].substring(1); - charToEntityMap[c] = entity; - entityToCharMap.put(entity, c); - } - } - - private static boolean isMagic(char c) { - return (c < charToEntityMap.length && charToEntityMap[c] != null); - } - - /* - * Quote the string so that it will be acceptable to the (String) - * constructor. Since the parsing code in that constructor is fairly - * stupid, we're obliged to quote apparently innocuous characters like - * space, <, and >. In a future version, we should rewrite the parser - * and only quote " plus either \ or & (depending on the quote syntax). - */ - private static String quote(String s) { - boolean found = false; - for (int i = 0; i < s.length(); i++) { - if (isMagic(s.charAt(i))) { - found = true; - break; - } - } - if (!found) - return s; - final StringBuilder buf = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (isMagic(c)) - buf.append(charToEntityMap[c]); - else - buf.append(c); - } - return buf.toString(); - } - - @SuppressWarnings("removal") - private static String unquote(String s) throws XMLParseException { - if (!s.startsWith("\"") || !s.endsWith("\"")) { - throw new XMLParseException("Value must be quoted: <" + s + ">"); - // XMLParseException is deprecated for removal. - } - final StringBuilder buf = new StringBuilder(); - final int len = s.length() - 1; - for (int i = 1; i < len; i++) { - final char c = s.charAt(i); - final int semi; - final Character quoted; - if (c == '&' - && (semi = s.indexOf(';', i + 1)) >= 0 - && ((quoted = entityToCharMap.get(s.substring(i, semi+1))) - != null)) { - buf.append(quoted); - i = semi; - } else - buf.append(c); - } - return buf.toString(); - } - - /** - * Make the string that will go inside "..." for a value that is not - * a plain String. - * @throws RuntimeOperationsException if the value cannot be encoded. - */ - private static String makeFieldValue(Object value) { - if (value == null) - return "(null)"; - - Class valueClass = value.getClass(); - try { - valueClass.getConstructor(String.class); - } catch (NoSuchMethodException e) { - final String msg = - "Class " + valueClass + " does not have a public " + - "constructor with a single string arg"; - final RuntimeException iae = new IllegalArgumentException(msg); - throw new RuntimeOperationsException(iae, - "Cannot make XML descriptor"); - } catch (SecurityException e) { - // OK: we'll pretend the constructor is there - // too bad if it's not: we'll find out when we try to - // reconstruct the DescriptorSupport - } - - final String quotedValueString = quote(value.toString()); - - return "(" + valueClass.getName() + "/" + quotedValueString + ")"; - } - - /* - * Parse a field value from the XML produced by toXMLString(). - * Given a descriptor XML containing , - * the argument to this method will be "vvv" (a string including the - * containing quote characters). If vvv begins and ends with parentheses, - * then it may contain: - * - the characters "null", in which case the result is null; - * - a value of the form "some.class.name/xxx", in which case the - * result is equivalent to `new some.class.name("xxx")'; - * - some other string, in which case the result is that string, - * without the parentheses. - */ - @SuppressWarnings("removal") - private static Object parseQuotedFieldValue(String s) - throws XMLParseException { - s = unquote(s); - if (s.equalsIgnoreCase("(null)")) - return null; - if (!s.startsWith("(") || !s.endsWith(")")) - return s; - final int slash = s.indexOf('/'); - if (slash < 0) { - // compatibility: old code didn't include class name - return s.substring(1, s.length() - 1); - } - final String className = s.substring(1, slash); - - final Constructor constr; - try { - final ClassLoader contextClassLoader = - Thread.currentThread().getContextClassLoader(); - final Class c = - Class.forName(className, false, contextClassLoader); - constr = c.getConstructor(new Class[] {String.class}); - } catch (Exception e) { - throw new XMLParseException(e, "Cannot parse value: <" + s + ">"); - // XMLParseException is deprecated for removal. - } - final String arg = s.substring(slash + 1, s.length() - 1); - try { - return constr.newInstance(new Object[] {arg}); - } catch (Exception e) { - final String msg = - "Cannot construct instance of " + className + - " with arg: <" + s + ">"; - throw new XMLParseException(e, msg); - // XMLParseException is deprecated for removal. - } - } - /** * Returns a human readable string representing the * descriptor. The string will be in the format of diff --git a/src/java.management/share/classes/javax/management/modelmbean/XMLParseException.java b/src/java.management/share/classes/javax/management/modelmbean/XMLParseException.java deleted file mode 100644 index efcfdf54d67..00000000000 --- a/src/java.management/share/classes/javax/management/modelmbean/XMLParseException.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2000, 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. - */ -/* - * @author IBM Corp. - * - * Copyright IBM Corp. 1999-2000. All rights reserved. - */ - - -package javax.management.modelmbean; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamField; - -/** -* This exception is thrown when an XML formatted string is being parsed into ModelMBean objects -* or when XML formatted strings are being created from ModelMBean objects. -* -* It is also used to wrapper exceptions from XML parsers that may be used. -* -*

          The serialVersionUID of this class is 3176664577895105181L. -* -* @deprecated This class exists only to support XML parsing implemented privately in this module, -* in DescriptorSupport. That feature is deprecated for removal. -* -* @since 1.5 -*/ -@Deprecated(since="25", forRemoval=true) -public class XMLParseException -extends Exception -{ - private static final long serialVersionUID = 3176664577895105181L; - - /** - * Default constructor . - */ - public XMLParseException () - { - super("XML Parse Exception."); - } - - /** - * Constructor taking a string. - * - * @param s the detail message. - */ - public XMLParseException (String s) - { - super("XML Parse Exception: " + s); - } - /** - * Constructor taking a string and an exception. - * - * @param e the nested exception. - * @param s the detail message. - */ - public XMLParseException (Exception e, String s) - { - super("XML Parse Exception: " + s + ":" + e.toString()); - } - - /** - * Deserializes an {@link XMLParseException} from an {@link ObjectInputStream}. - */ - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { - // New serial form ignores extra field "msgStr" - in.defaultReadObject(); - } - - - /** - * Serializes an {@link XMLParseException} to an {@link ObjectOutputStream}. - */ - private void writeObject(ObjectOutputStream out) - throws IOException { - out.defaultWriteObject(); - } -} diff --git a/src/java.management/share/classes/javax/management/relation/RoleList.java b/src/java.management/share/classes/javax/management/relation/RoleList.java index fbbc3df6436..f16a441ad46 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -35,6 +35,10 @@ * parameter when creating a relation, and when trying to set several roles in * a relation (via 'setRoles()' method). It is returned as part of a * RoleResult, to provide roles successfully retrieved. + + *

          It is not permitted to add objects to a {@code RoleList} that are + * not instances of {@code Role}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

          * * @since 1.5 */ @@ -55,9 +59,6 @@ the asList() method so you can write */ public class RoleList extends ArrayList { - private transient boolean typeSafe; - private transient boolean tainted; - /* Serial version */ private static final long serialVersionUID = 5568344346499649313L; @@ -121,25 +122,13 @@ public RoleList(List list) throws IllegalArgumentException { * @return a {@code List} whose contents * reflect the contents of this {@code RoleList}. * - *

          If this method has ever been called on a given - * {@code RoleList} instance, a subsequent attempt to add - * an object to that instance which is not a {@code Role} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, a {@code RoleList} on which this method has never - * been called does allow objects other than {@code Role}s to - * be added.

          - * * @throws IllegalArgumentException if this {@code RoleList} contains * an element that is not a {@code Role}. * * @since 1.6 */ public List asList() { - if (!typeSafe) { - if (tainted) - checkTypeSafe(this); - typeSafe = true; - } + checkTypeSafe(this); return Util.cast(this); } @@ -158,8 +147,7 @@ public void add(Role role) throws IllegalArgumentException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } super.add(role); } @@ -183,10 +171,8 @@ public void add(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - super.add(index, role); } @@ -208,11 +194,8 @@ public void set(int index, IndexOutOfBoundsException { if (role == null) { - // Revisit [cebro] Localize message - String excMsg = "Invalid parameter."; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - super.set(index, role); } @@ -236,7 +219,6 @@ public boolean addAll(RoleList roleList) if (roleList == null) { return true; } - return (super.addAll(roleList)); } @@ -263,9 +245,7 @@ public boolean addAll(int index, IndexOutOfBoundsException { if (roleList == null) { - // Revisit [cebro] Localize message - String excMsg = "Invalid parameter."; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } return (super.addAll(index, roleList)); @@ -277,48 +257,53 @@ public boolean addAll(int index, * been called on this instance. */ + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code o} is not a {@code Role}. + */ @Override public boolean add(Object o) { - if (!tainted) - tainted = isTainted(o); - if (typeSafe) - checkTypeSafe(o); + checkTypeSafe(o); return super.add(o); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code Role}. + */ @Override public void add(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); super.add(index, element); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code Role}. + */ @Override public boolean addAll(Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code Role}. + */ @Override public boolean addAll(int index, Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(index, c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code Role}. + */ @Override public Object set(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); return super.set(index, element); } @@ -345,28 +330,4 @@ private static void checkTypeSafe(Collection c) { throw new IllegalArgumentException(e); } } - - /** - * Returns true if o is a non-Role object. - */ - private static boolean isTainted(Object o) { - try { - checkTypeSafe(o); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } - - /** - * Returns true if c contains any non-Role objects. - */ - private static boolean isTainted(Collection c) { - try { - checkTypeSafe(c); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } } diff --git a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java index dae506e5e5f..3d1e4223cba 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -35,6 +35,10 @@ * representing roles not retrieved from a relation due to a problem * encountered when trying to access (read or write) the roles. * + *

          It is not permitted to add objects to a {@code RoleUnresolvedList} that are + * not instances of {@code RoleUnresolved}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

          + * * @since 1.5 */ /* We cannot extend ArrayList because our legacy @@ -54,9 +58,6 @@ the asList() method so you can write */ public class RoleUnresolvedList extends ArrayList { - private transient boolean typeSafe; - private transient boolean tainted; - /* Serial version */ private static final long serialVersionUID = 4054902803091433324L; @@ -121,25 +122,13 @@ public RoleUnresolvedList(List list) * @return a {@code List} whose contents * reflect the contents of this {@code RoleUnresolvedList}. * - *

          If this method has ever been called on a given - * {@code RoleUnresolvedList} instance, a subsequent attempt to add - * an object to that instance which is not a {@code RoleUnresolved} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, a {@code RoleUnresolvedList} on which this method has never - * been called does allow objects other than {@code RoleUnresolved}s to - * be added.

          - * * @throws IllegalArgumentException if this {@code RoleUnresolvedList} * contains an element that is not a {@code RoleUnresolved}. * * @since 1.6 */ public List asList() { - if (!typeSafe) { - if (tainted) - checkTypeSafe(this); - typeSafe = true; - } + checkTypeSafe(this); return Util.cast(this); } @@ -158,8 +147,7 @@ public void add(RoleUnresolved role) throws IllegalArgumentException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } super.add(role); } @@ -184,10 +172,8 @@ public void add(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - super.add(index, role); } @@ -210,10 +196,8 @@ public void set(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - super.set(index, role); } @@ -236,7 +220,6 @@ public boolean addAll(RoleUnresolvedList roleList) if (roleList == null) { return true; } - return (super.addAll(roleList)); } @@ -261,10 +244,8 @@ public boolean addAll(int index, IndexOutOfBoundsException { if (roleList == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - return (super.addAll(index, roleList)); } @@ -274,48 +255,53 @@ public boolean addAll(int index, * ever been called on this instance. */ + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code o} is not a {@code RoleUnresolved}. + */ @Override public boolean add(Object o) { - if (!tainted) - tainted = isTainted(o); - if (typeSafe) - checkTypeSafe(o); + checkTypeSafe(o); return super.add(o); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code RoleUnresolved}. + */ @Override public void add(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); super.add(index, element); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code RoleUnresolved}. + */ @Override public boolean addAll(Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code RoleUnresolved}. + */ @Override public boolean addAll(int index, Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(index, c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code RoleUnresolved}. + */ @Override public Object set(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); return super.set(index, element); } @@ -342,28 +328,4 @@ private static void checkTypeSafe(Collection c) { throw new IllegalArgumentException(e); } } - - /** - * Returns true if o is a non-RoleUnresolved object. - */ - private static boolean isTainted(Object o) { - try { - checkTypeSafe(o); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } - - /** - * Returns true if c contains any non-RoleUnresolved objects. - */ - private static boolean isTainted(Collection c) { - try { - checkTypeSafe(c); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java index 52037ba497f..088e8c66b04 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java @@ -41,7 +41,7 @@ import jdk.internal.net.http.common.SSLTube; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Utils; -import static jdk.internal.net.http.common.Utils.ServerName; +import sun.net.util.IPAddressUtil; /** * Asynchronous version of SSLConnection. @@ -63,6 +63,10 @@ */ abstract class AbstractAsyncSSLConnection extends HttpConnection { + + private record ServerName(String name, boolean isLiteral) { + } + protected final SSLEngine engine; protected final SSLParameters sslParameters; private final List sniServerNames; @@ -71,17 +75,19 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection private static final boolean disableHostnameVerification = Utils.isHostnameVerificationDisabled(); - AbstractAsyncSSLConnection(InetSocketAddress addr, + AbstractAsyncSSLConnection(Origin originServer, + InetSocketAddress addr, HttpClientImpl client, - ServerName serverName, int port, String[] alpn, String label) { - super(addr, client, label); + super(originServer, addr, client, label); + assert originServer != null : "origin server is null"; + final ServerName serverName = getServerName(originServer); this.sniServerNames = formSNIServerNames(serverName, client); SSLContext context = client.theSSLContext(); sslParameters = createSSLParameters(client, this.sniServerNames, alpn); Log.logParams(sslParameters); - engine = createEngine(context, serverName.name(), port, sslParameters); + engine = createEngine(context, serverName.name(), originServer.port(), sslParameters); } abstract SSLTube getConnectionFlow(); @@ -187,6 +193,23 @@ private static SSLEngine createEngine(SSLContext context, String peerHost, int p return engine; } + /** + * Analyse the given {@linkplain Origin origin server} and determine + * if the origin server's host is a literal or not, returning the server's + * address in String form. + */ + private static ServerName getServerName(final Origin originServer) { + final String host = originServer.host(); + byte[] literal = IPAddressUtil.textToNumericFormatV4(host); + if (literal == null) { + // not IPv4 literal. Check IPv6 + literal = IPAddressUtil.textToNumericFormatV6(host); + return new ServerName(host, literal != null); + } else { + return new ServerName(host, true); + } + } + @Override final boolean isSecure() { return true; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java index 56477e9604e..c02cd145cf8 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java @@ -42,12 +42,13 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection { final PlainHttpPublisher writePublisher; private volatile SSLTube flow; - AsyncSSLConnection(InetSocketAddress addr, + AsyncSSLConnection(Origin originServer, + InetSocketAddress addr, HttpClientImpl client, String[] alpn, String label) { - super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn, label); - plainConnection = new PlainHttpConnection(addr, client, label); + super(originServer, addr, client, alpn, label); + plainConnection = new PlainHttpConnection(originServer, addr, client, label); writePublisher = new PlainHttpPublisher(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java index 1210f4dd62b..a81d8de328e 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java @@ -43,15 +43,17 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection { final PlainHttpPublisher writePublisher; volatile SSLTube flow; - AsyncSSLTunnelConnection(InetSocketAddress addr, + AsyncSSLTunnelConnection(Origin originServer, + InetSocketAddress addr, HttpClientImpl client, String[] alpn, InetSocketAddress proxy, ProxyHeaders proxyHeaders, String label) { - super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn, label); - this.plainConnection = new PlainTunnelingConnection(addr, proxy, client, proxyHeaders, label); + super(originServer, addr, client, alpn, label); + this.plainConnection = new PlainTunnelingConnection(originServer, addr, proxy, client, + proxyHeaders, label); this.writePublisher = new PlainHttpPublisher(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java index dd8f6652290..07cfc4dbdf6 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java @@ -100,7 +100,11 @@ abstract class HttpConnection implements Closeable { */ private final String label; - HttpConnection(InetSocketAddress address, HttpClientImpl client, String label) { + private final Origin originServer; + + HttpConnection(Origin originServer, InetSocketAddress address, HttpClientImpl client, + String label) { + this.originServer = originServer; this.address = address; this.client = client; trailingOperations = new TrailingOperations(); @@ -244,6 +248,14 @@ final boolean checkOpen() { return false; } + /** + * {@return the {@link Origin} server against which this connection communicates. + * Returns {@code null} if the connection is a plain connection to a proxy} + */ + final Origin getOriginServer() { + return this.originServer; + } + interface HttpPublisher extends FlowTube.TubePublisher { void enqueue(List buffers) throws IOException; void enqueueUnordered(List buffers) throws IOException; @@ -334,13 +346,20 @@ private static HttpConnection getSSLConnection(InetSocketAddress addr, String[] alpn, HttpRequestImpl request, HttpClientImpl client) { - String label = nextLabel(); + final String label = nextLabel(); + final Origin originServer; + try { + originServer = Origin.from(request.uri()); + } catch (IllegalArgumentException iae) { + // should never happen + throw new AssertionError("failed to determine origin server from request URI", iae); + } if (proxy != null) - return new AsyncSSLTunnelConnection(addr, client, alpn, proxy, + return new AsyncSSLTunnelConnection(originServer, addr, client, alpn, proxy, proxyTunnelHeaders(request), label); else - return new AsyncSSLConnection(addr, client, alpn, label); + return new AsyncSSLConnection(originServer, addr, client, alpn, label); } /** @@ -414,14 +433,21 @@ private static HttpConnection getPlainConnection(InetSocketAddress addr, InetSocketAddress proxy, HttpRequestImpl request, HttpClientImpl client) { - String label = nextLabel(); + final String label = nextLabel(); + final Origin originServer; + try { + originServer = Origin.from(request.uri()); + } catch (IllegalArgumentException iae) { + // should never happen + throw new AssertionError("failed to determine origin server from request URI", iae); + } if (request.isWebSocket() && proxy != null) - return new PlainTunnelingConnection(addr, proxy, client, + return new PlainTunnelingConnection(originServer, addr, proxy, client, proxyTunnelHeaders(request), label); if (proxy == null) - return new PlainHttpConnection(addr, client, label); + return new PlainHttpConnection(originServer, addr, client, label); else return new PlainProxyConnection(proxy, client, label); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java index bb794031508..81c693ea192 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -39,16 +39,17 @@ import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; +import java.util.function.BiPredicate; import jdk.internal.net.http.common.Alpns; import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.websocket.WebSocketRequest; -import static java.net.Authenticator.RequestorType.PROXY; import static java.net.Authenticator.RequestorType.SERVER; import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS; import static jdk.internal.net.http.common.Utils.ProxyHeaders; +import static jdk.internal.net.http.common.Utils.copyProxy; public class HttpRequestImpl extends HttpRequest implements WebSocketRequest { @@ -127,15 +128,7 @@ public HttpRequestImpl(HttpRequest request, ProxySelector ps) { this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT); } this.uri = requestURI; - if (isWebSocket) { - // WebSocket determines and sets the proxy itself - this.proxy = ((HttpRequestImpl) request).proxy; - } else { - if (ps != null) - this.proxy = retrieveProxy(ps, uri); - else - this.proxy = null; - } + this.proxy = retrieveProxy(request, ps, uri); this.expectContinue = request.expectContinue(); this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); this.requestPublisher = request.bodyPublisher().orElse(null); @@ -156,7 +149,11 @@ public static HttpRequestImpl newInstanceForRedirection(URI uri, String method, HttpRequestImpl other, boolean mayHaveBody) { - return new HttpRequestImpl(uri, method, other, mayHaveBody); + if (uri.getScheme().equalsIgnoreCase(other.uri.getScheme()) && + uri.getRawAuthority().equals(other.uri.getRawAuthority())) { + return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.empty()); + } + return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.of(Utils.ALLOWED_REDIRECT_HEADERS)); } /** Returns a new instance suitable for authentication. */ @@ -176,9 +173,19 @@ private HttpRequestImpl(URI uri, String method, HttpRequestImpl other, boolean mayHaveBody) { + this(uri, method, other, mayHaveBody, Optional.empty()); + } + + private HttpRequestImpl(URI uri, + String method, + HttpRequestImpl other, + boolean mayHaveBody, + Optional> redirectHeadersFilter) { assert method == null || Utils.isValidName(method); - this.method = method == null? "GET" : method; - this.userHeaders = other.userHeaders; + this.method = method == null ? "GET" : method; + HttpHeaders userHeaders = redirectHeadersFilter.isPresent() ? + HttpHeaders.of(other.userHeaders.map(), redirectHeadersFilter.get()) : other.userHeaders; + this.userHeaders = userHeaders; this.isWebSocket = other.isWebSocket; this.systemHeadersBuilder = new HttpHeadersBuilder(); if (userHeaders.firstValue("User-Agent").isEmpty()) { @@ -292,16 +299,27 @@ void setH2Upgrade(Exchange exchange) { @Override public boolean expectContinue() { return expectContinue; } - /** Retrieves the proxy, from the given ProxySelector, if there is one. */ - private static Proxy retrieveProxy(ProxySelector ps, URI uri) { - Proxy proxy = null; - List pl = ps.select(uri); - if (!pl.isEmpty()) { - Proxy p = pl.get(0); - if (p.type() == Proxy.Type.HTTP) - proxy = p; + /** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */ + private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) { + + // WebSocket determines and sets the proxy itself + if (request instanceof HttpRequestImpl requestImpl && requestImpl.isWebSocket) { + return requestImpl.proxy; } - return proxy; + + // Try to find a matching one from the `ProxySelector` + if (ps != null) { + List pl = ps.select(uri); + if (!pl.isEmpty()) { + Proxy p = pl.getFirst(); + if (p.type() == Proxy.Type.HTTP) { + return copyProxy(p); + } + } + } + + return null; + } InetSocketAddress proxy() { @@ -317,7 +335,7 @@ InetSocketAddress proxy() { @Override public void setProxy(Proxy proxy) { assert isWebSocket; - this.proxy = proxy; + this.proxy = copyProxy(proxy); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Origin.java b/src/java.net.http/share/classes/jdk/internal/net/http/Origin.java new file mode 100644 index 00000000000..adbee565297 --- /dev/null +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Origin.java @@ -0,0 +1,146 @@ +/* + * 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. + */ + +package jdk.internal.net.http; + +import java.net.URI; +import java.util.Locale; +import java.util.Objects; + +import sun.net.util.IPAddressUtil; + +/** + * Represents an origin server to which a HTTP request is targeted. + * + * @param scheme The scheme of the origin (for example: https). Unlike the application layer + * protocol (which can be a finer grained protocol like h2, h3 etc...), + * this is actually a scheme. Only {@code http} and {@code https} literals are + * supported. Cannot be null. + * @param host The host of the origin, cannot be null. If the host is an IPv6 address, + * then it must not be enclosed in square brackets ({@code '['} and {@code ']'}). + * If the host is a DNS hostname, then it must be passed as a lower case String. + * @param port The port of the origin. Must be greater than 0. + */ +public record Origin(String scheme, String host, int port) { + public Origin { + Objects.requireNonNull(scheme); + Objects.requireNonNull(host); + if (!isValidScheme(scheme)) { + throw new IllegalArgumentException("Unsupported scheme: " + scheme); + } + if (host.startsWith("[") && host.endsWith("]")) { + throw new IllegalArgumentException("Invalid host: " + host); + } + // expect DNS hostname to be passed as lower case + if (isDNSHostName(host) && !host.toLowerCase(Locale.ROOT).equals(host)) { + throw new IllegalArgumentException("non-lowercase hostname: " + host); + } + if (port <= 0) { + throw new IllegalArgumentException("Invalid port: " + port); + } + } + + @Override + public String toString() { + return scheme + "://" + toAuthority(host, port); + } + + /** + * {@return Creates and returns an Origin from an URI} + * + * @param uri The URI of the origin + * @throws IllegalArgumentException if a Origin cannot be constructed from + * the given {@code uri} + */ + public static Origin from(final URI uri) throws IllegalArgumentException { + Objects.requireNonNull(uri); + final String scheme = uri.getScheme(); + if (scheme == null) { + throw new IllegalArgumentException("missing scheme in URI"); + } + final String lcaseScheme = scheme.toLowerCase(Locale.ROOT); + if (!isValidScheme(lcaseScheme)) { + throw new IllegalArgumentException("Unsupported scheme: " + scheme); + } + final String host = uri.getHost(); + if (host == null) { + throw new IllegalArgumentException("missing host in URI"); + } + String effectiveHost; + if (host.startsWith("[") && host.endsWith("]")) { + // strip the square brackets from IPv6 host + effectiveHost = host.substring(1, host.length() - 1); + } else { + effectiveHost = host; + } + assert !effectiveHost.isEmpty() : "unexpected URI host: " + host; + // If the host is a DNS hostname, then convert the host to lower case. + // The DNS hostname is expected to be ASCII characters and is case-insensitive. + // + // Its usage in areas like SNI too match this expectation - RFC-6066, section 3: + // "HostName" contains the fully qualified DNS hostname of the server, + // as understood by the client. The hostname is represented as a byte + // string using ASCII encoding without a trailing dot. ... DNS hostnames + // are case-insensitive. + if (isDNSHostName(effectiveHost)) { + effectiveHost = effectiveHost.toLowerCase(Locale.ROOT); + } + int port = uri.getPort(); + if (port == -1) { + port = switch (lcaseScheme) { + case "http" -> 80; + case "https" -> 443; + // we have already verified that this is a valid scheme, so this + // should never happen + default -> throw new AssertionError("Unsupported scheme: " + scheme); + }; + } + return new Origin(lcaseScheme, effectiveHost, port); + } + + static String toAuthority(final String host, final int port) { + assert port > 0 : "invalid port: " + port; + // borrowed from code in java.net.URI + final boolean needBrackets = host.indexOf(':') >= 0 + && !host.startsWith("[") + && !host.endsWith("]"); + if (needBrackets) { + return "[" + host + "]:" + port; + } + return host + ":" + port; + } + + private static boolean isValidScheme(final String scheme) { + // only "http" and "https" literals allowed + return "http".equals(scheme) || "https".equals(scheme); + } + + private static boolean isDNSHostName(final String host) { + final boolean isLiteral = IPAddressUtil.isIPv4LiteralAddress(host) + || IPAddressUtil.isIPv6LiteralAddress(host); + + return !isLiteral; + } +} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index 190df8a00ba..d0d64312f1f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -36,12 +36,10 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Function; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.MinimalFuture; -import jdk.internal.net.http.common.TimeSource; import jdk.internal.net.http.common.Utils; /** @@ -57,16 +55,9 @@ class PlainHttpConnection extends HttpConnection { private volatile boolean connected; private volatile boolean closed; private volatile ConnectTimerEvent connectTimerEvent; // may be null - private volatile int unsuccessfulAttempts; private final ReentrantLock stateLock = new ReentrantLock(); private final AtomicReference errorRef = new AtomicReference<>(); - // Indicates whether a connection attempt has succeeded or should be retried. - // If the attempt failed, and shouldn't be retried, there will be an exception - // instead. - private enum ConnectState { SUCCESS, RETRY } - - /** * Returns a ConnectTimerEvent iff there is a connect timeout duration, * otherwise null. @@ -115,10 +106,10 @@ Throwable getError(Throwable cause) { } final class ConnectEvent extends AsyncEvent { - private final CompletableFuture cf; + private final CompletableFuture cf; private final Exchange exchange; - ConnectEvent(CompletableFuture cf, Exchange exchange) { + ConnectEvent(CompletableFuture cf, Exchange exchange) { this.cf = cf; this.exchange = exchange; } @@ -147,15 +138,10 @@ public void handle() { assert finished || exchange.multi.requestCancelled() : "Expected channel to be connected"; if (connectionOpened()) { // complete async since the event runs on the SelectorManager thread - cf.completeAsync(() -> ConnectState.SUCCESS, client().theExecutor()); + if (debug.on()) debug.log("%s has been connected asynchronously", label()); + cf.completeAsync(() -> null, client().theExecutor()); } else throw new ConnectException("Connection closed"); } catch (Throwable e) { - if (canRetryConnect(e)) { - unsuccessfulAttempts++; - // complete async since the event runs on the SelectorManager thread - cf.completeAsync(() -> ConnectState.RETRY, client().theExecutor()); - return; - } Throwable t = getError(Utils.toConnectException(e)); // complete async since the event runs on the SelectorManager thread client().theExecutor().execute( () -> cf.completeExceptionally(t)); @@ -174,7 +160,7 @@ public void abort(IOException ioe) { @Override public CompletableFuture connectAsync(Exchange exchange) { - CompletableFuture cf = new MinimalFuture<>(); + CompletableFuture cf = new MinimalFuture<>(); try { assert !connected : "Already connected"; assert !chan.isBlocking() : "Unexpected blocking channel"; @@ -212,7 +198,8 @@ public CompletableFuture connectAsync(Exchange exchange) { if (finished) { if (debug.on()) debug.log("connect finished without blocking"); if (connectionOpened()) { - cf.complete(ConnectState.SUCCESS); + if (debug.on()) debug.log("%s has been connected", label()); + cf.complete(null); } else throw getError(new ConnectException("connection closed")); } else { if (debug.on()) debug.log("registering connect event"); @@ -232,8 +219,7 @@ public CompletableFuture connectAsync(Exchange exchange) { debug.log("Failed to close channel after unsuccessful connect"); } } - return cf.handle((r,t) -> checkRetryConnect(r, t, exchange)) - .thenCompose(Function.identity()); + return cf; } boolean connectionOpened() { @@ -254,42 +240,6 @@ boolean connectionOpened() { return !closed; } - /** - * On some platforms, a ConnectEvent may be raised and a ConnectionException - * may occur with the message "Connection timed out: no further information" - * before our actual connection timeout has expired. In this case, this - * method will be called with a {@code connect} state of {@code ConnectState.RETRY)} - * and we will retry once again. - * @param connect indicates whether the connection was successful or should be retried - * @param failed the failure if the connection failed - * @param exchange the exchange - * @return a completable future that will take care of retrying the connection if needed. - */ - private CompletableFuture checkRetryConnect(ConnectState connect, Throwable failed, Exchange exchange) { - // first check if the connection failed - if (failed != null) return MinimalFuture.failedFuture(failed); - // then check if the connection should be retried - if (connect == ConnectState.RETRY) { - int attempts = unsuccessfulAttempts; - assert attempts <= 1; - if (debug.on()) - debug.log("Retrying connect after %d attempts", attempts); - return connectAsync(exchange); - } - // Otherwise, the connection was successful; - assert connect == ConnectState.SUCCESS; - return MinimalFuture.completedFuture(null); - } - - private boolean canRetryConnect(Throwable e) { - if (!MultiExchange.RETRY_CONNECT) return false; - if (!(e instanceof ConnectException)) return false; - if (unsuccessfulAttempts > 0) return false; - ConnectTimerEvent timer = connectTimerEvent; - if (timer == null) return true; - return timer.deadline().isAfter(TimeSource.now()); - } - @Override public CompletableFuture finishConnect() { assert connected == false; @@ -310,8 +260,9 @@ final FlowTube getConnectionFlow() { return tube; } - PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client, String label) { - super(addr, client, label); + PlainHttpConnection(Origin originServer, InetSocketAddress addr, HttpClientImpl client, + String label) { + super(originServer, addr, client, label); try { this.chan = SocketChannel.open(); chan.configureBlocking(false); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java index c11fd489177..c4b1b14a4d2 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java @@ -30,7 +30,9 @@ class PlainProxyConnection extends PlainHttpConnection { PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client, String label) { - super(proxy, client, label); + // we don't track the origin server for a plain proxy connection, since it + // can be used to serve requests against several different origin servers. + super(null, proxy, client, label); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java index 7a8eb9c79c5..147d5938fe5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java @@ -51,15 +51,16 @@ final class PlainTunnelingConnection extends HttpConnection { final InetSocketAddress proxyAddr; private volatile boolean connected; - protected PlainTunnelingConnection(InetSocketAddress addr, + protected PlainTunnelingConnection(Origin originServer, + InetSocketAddress addr, InetSocketAddress proxy, HttpClientImpl client, ProxyHeaders proxyHeaders, String label) { - super(addr, client, label); + super(originServer, addr, client, label); this.proxyAddr = proxy; this.proxyHeaders = proxyHeaders; - delegate = new PlainHttpConnection(proxy, client, label); + delegate = new PlainHttpConnection(originServer, proxy, client, label); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index d035a8c8da1..b10c7cd5957 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -38,6 +38,7 @@ import java.lang.System.Logger.Level; import java.net.ConnectException; import java.net.InetSocketAddress; +import java.net.Proxy; import java.net.URI; import java.net.http.HttpHeaders; import java.net.http.HttpTimeoutException; @@ -73,12 +74,10 @@ import jdk.internal.net.http.HttpRequestImpl; import sun.net.NetProperties; -import sun.net.util.IPAddressUtil; import sun.net.www.HeaderParser; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.util.stream.Collectors.joining; import static java.net.Authenticator.RequestorType.PROXY; import static java.net.Authenticator.RequestorType.SERVER; @@ -188,6 +187,18 @@ private static Set getDisallowedHeaders() { public static final BiPredicate ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header); + private static final Set DISALLOWED_REDIRECT_HEADERS_SET = getDisallowedRedirectHeaders(); + + private static Set getDisallowedRedirectHeaders() { + Set headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + headers.addAll(Set.of("Authorization", "Cookie", "Origin", "Referer", "Host")); + + return Collections.unmodifiableSet(headers); + } + + public static final BiPredicate + ALLOWED_REDIRECT_HEADERS = (header, _) -> !DISALLOWED_REDIRECT_HEADERS_SET.contains(header); + public static final BiPredicate VALIDATE_USER_HEADER = (name, value) -> { assert name != null : "null header name"; @@ -309,6 +320,17 @@ public static boolean proxyHasDisabledSchemes(boolean tunnel) { : ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty(); } + /** + * Creates a new {@link Proxy} instance for the given proxy iff it is + * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a + * {@code Proxy} instance. + */ + public static Proxy copyProxy(Proxy proxy) { + return proxy == null || proxy.getClass() == Proxy.class + ? proxy + : new Proxy(proxy.type(), proxy.address()); + } + // WebSocket connection Upgrade headers private static final String HEADER_CONNECTION = "Connection"; private static final String HEADER_UPGRADE = "Upgrade"; @@ -487,39 +509,6 @@ public static boolean isValidName(String token) { return !token.isEmpty(); } - public record ServerName (String name, boolean isLiteral) { - } - - /** - * Analyse the given address and determine if it is literal or not, - * returning the address in String form. - */ - public static ServerName getServerName(InetSocketAddress addr) { - String host = addr.getHostString(); - byte[] literal = IPAddressUtil.textToNumericFormatV4(host); - if (literal == null) { - // not IPv4 literal. Check IPv6 - literal = IPAddressUtil.textToNumericFormatV6(host); - return new ServerName(host, literal != null); - } else { - return new ServerName(host, true); - } - } - - private static boolean isLoopbackLiteral(byte[] bytes) { - if (bytes.length == 4) { - return bytes[0] == 127; - } else if (bytes.length == 16) { - for (int i=0; i<14; i++) - if (bytes[i] != 0) - return false; - if (bytes[15] != 1) - return false; - return true; - } else - throw new InternalError(); - } - /* * Validates an RFC 7230 field-value. * @@ -895,33 +884,6 @@ public static Logger getDebugLogger(Supplier dbgTag, boolean on) { return DebugLogger.createHttpLogger(dbgTag, config); } - /** - * Return the host string from a HttpRequestImpl - * - * @param request - * @return - */ - public static String hostString(HttpRequestImpl request) { - URI uri = request.uri(); - int port = uri.getPort(); - String host = uri.getHost(); - - boolean defaultPort; - if (port == -1) { - defaultPort = true; - } else if (uri.getScheme().equalsIgnoreCase("https")) { - defaultPort = port == 443; - } else { - defaultPort = port == 80; - } - - if (defaultPort) { - return host; - } else { - return host + ":" + port; - } - } - /** * Get a logger for debug HPACK traces.The logger should only be used * with levels whose severity is {@code <= DEBUG}. diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java index 6e76a272cd0..09bfecefcab 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java @@ -59,6 +59,7 @@ import java.util.concurrent.CompletableFuture; import static java.lang.String.format; +import static jdk.internal.net.http.common.Utils.copyProxy; import static jdk.internal.net.http.common.Utils.isValidName; import static jdk.internal.net.http.common.Utils.stringOf; import static jdk.internal.util.Exceptions.filterNonSocketInfo; @@ -369,7 +370,7 @@ private static Proxy proxyFor(Optional selector, URI uri) { if (proxy.type() != Proxy.Type.HTTP) { return null; } - return proxy; + return copyProxy(proxy); } } diff --git a/src/java.sql/share/classes/java/sql/Connection.java b/src/java.sql/share/classes/java/sql/Connection.java index f1de63bd51b..19f283f5762 100644 --- a/src/java.sql/share/classes/java/sql/Connection.java +++ b/src/java.sql/share/classes/java/sql/Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -27,6 +27,7 @@ import java.util.Properties; import java.util.concurrent.Executor; +import java.util.Map; /** *

          A connection (session) with a specific @@ -82,7 +83,7 @@ * @see DatabaseMetaData * @since 1.1 */ -public interface Connection extends Wrapper, AutoCloseable { +public interface Connection extends Wrapper, AutoCloseable { /** * Creates a {@code Statement} object for sending @@ -136,8 +137,7 @@ public interface Connection extends Wrapper, AutoCloseable { * @throws SQLException if a database access error occurs * or this method is called on a closed connection */ - PreparedStatement prepareStatement(String sql) - throws SQLException; + PreparedStatement prepareStatement(String sql) throws SQLException; /** * Creates a {@code CallableStatement} object for calling @@ -498,7 +498,6 @@ PreparedStatement prepareStatement(String sql) */ void clearWarnings() throws SQLException; - //--------------------------JDBC 2.0----------------------------- /** @@ -529,8 +528,7 @@ PreparedStatement prepareStatement(String sql) * set type and result set concurrency. * @since 1.2 */ - Statement createStatement(int resultSetType, int resultSetConcurrency) - throws SQLException; + Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException; /** * @@ -626,7 +624,7 @@ CallableStatement prepareCall(String sql, int resultSetType, * @since 1.2 * @see #setTypeMap */ - java.util.Map> getTypeMap() throws SQLException; + Map> getTypeMap() throws SQLException; /** * Installs the given {@code TypeMap} object as the type map for @@ -654,11 +652,10 @@ CallableStatement prepareCall(String sql, int resultSetType, * @since 1.2 * @see #getTypeMap */ - void setTypeMap(java.util.Map> map) throws SQLException; + void setTypeMap(Map> map) throws SQLException; //--------------------------JDBC 3.0----------------------------- - /** * Changes the default holdability of {@code ResultSet} objects * created using this {@code Connection} object to the given @@ -894,7 +891,6 @@ CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException; - /** * Creates a default {@code PreparedStatement} object that has * the capability to retrieve auto-generated keys. The given constant @@ -937,8 +933,7 @@ CallableStatement prepareCall(String sql, int resultSetType, * this method with a constant of Statement.RETURN_GENERATED_KEYS * @since 1.4 */ - PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) - throws SQLException; + PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException; /** * Creates a default {@code PreparedStatement} object capable @@ -985,8 +980,7 @@ PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) * * @since 1.4 */ - PreparedStatement prepareStatement(String sql, int columnIndexes[]) - throws SQLException; + PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException; /** * Creates a default {@code PreparedStatement} object capable @@ -1033,8 +1027,7 @@ PreparedStatement prepareStatement(String sql, int columnIndexes[]) * * @since 1.4 */ - PreparedStatement prepareStatement(String sql, String columnNames[]) - throws SQLException; + PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException; /** * Constructs an object that implements the {@code Clob} interface. The object @@ -1099,87 +1092,86 @@ PreparedStatement prepareStatement(String sql, String columnNames[]) */ SQLXML createSQLXML() throws SQLException; - /** - * Returns true if the connection has not been closed and is still valid. - * The driver shall submit a query on the connection or use some other - * mechanism that positively verifies the connection is still valid when - * this method is called. - *

          - * The query submitted by the driver to validate the connection shall be - * executed in the context of the current transaction. - * - * @param timeout The time in seconds to wait for the database operation - * used to validate the connection to complete. If the - * timeout period expires before the operationcompletes, - * this method returns false. A value of 0 indicates a - * timeout is not applied to the database operation. - * - * @return true if the connection is valid, false otherwise - * @throws SQLException if the value supplied for {@code timeout} - * is less than 0 - * @since 1.6 - * - * @see java.sql.DatabaseMetaData#getClientInfoProperties - */ - boolean isValid(int timeout) throws SQLException; - - /** - * Sets the value of the client info property specified by name to the - * value specified by value. - *

          - * Applications may use the {@code DatabaseMetaData.getClientInfoProperties} - * method to determine the client info properties supported by the driver - * and the maximum length that may be specified for each property. - *

          - * The driver stores the value specified in a suitable location in the - * database. For example in a special register, session parameter, or - * system table column. For efficiency the driver may defer setting the - * value in the database until the next time a statement is executed or - * prepared. Other than storing the client information in the appropriate - * place in the database, these methods shall not alter the behavior of - * the connection in anyway. The values supplied to these methods are - * used for accounting, diagnostics and debugging purposes only. - *

          - * The driver shall generate a warning if the client info name specified - * is not recognized by the driver. - *

          - * If the value specified to this method is greater than the maximum - * length for the property the driver may either truncate the value and - * generate a warning or generate a {@code SQLClientInfoException}. If the driver - * generates a {@code SQLClientInfoException}, the value specified was not set on the - * connection. - *

          - * The following are standard client info properties. Drivers are not - * required to support these properties however if the driver supports a - * client info property that can be described by one of the standard - * properties, the standard property name should be used. - * - *

            - *
          • ApplicationName - The name of the application currently utilizing - * the connection
          • - *
          • ClientUser - The name of the user that the application using - * the connection is performing work for. This may - * not be the same as the user name that was used - * in establishing the connection.
          • - *
          • ClientHostname - The hostname of the computer the application - * using the connection is running on.
          • - *
          - * - * @param name The name of the client info property to set - * @param value The value to set the client info property to. If the - * value is null, the current value of the specified - * property is cleared. - * - * @throws SQLClientInfoException if the database server returns an error while - * setting the client info value on the database server or this method - * is called on a closed connection - * - * @since 1.6 - */ - void setClientInfo(String name, String value) - throws SQLClientInfoException; - - /** + /** + * Returns true if the connection has not been closed and is still valid. + * The driver shall submit a query on the connection or use some other + * mechanism that positively verifies the connection is still valid when + * this method is called. + *

          + * The query submitted by the driver to validate the connection shall be + * executed in the context of the current transaction. + * + * @param timeout The time in seconds to wait for the database operation + * used to validate the connection to complete. If the + * timeout period expires before the operationcompletes, + * this method returns false. A value of 0 indicates a + * timeout is not applied to the database operation. + * + * @return true if the connection is valid, false otherwise + * @throws SQLException if the value supplied for {@code timeout} + * is less than 0 + * @since 1.6 + * + * @see java.sql.DatabaseMetaData#getClientInfoProperties + */ + boolean isValid(int timeout) throws SQLException; + + /** + * Sets the value of the client info property specified by name to the + * value specified by value. + *

          + * Applications may use the {@code DatabaseMetaData.getClientInfoProperties} + * method to determine the client info properties supported by the driver + * and the maximum length that may be specified for each property. + *

          + * The driver stores the value specified in a suitable location in the + * database. For example in a special register, session parameter, or + * system table column. For efficiency the driver may defer setting the + * value in the database until the next time a statement is executed or + * prepared. Other than storing the client information in the appropriate + * place in the database, these methods shall not alter the behavior of + * the connection in anyway. The values supplied to these methods are + * used for accounting, diagnostics and debugging purposes only. + *

          + * The driver shall generate a warning if the client info name specified + * is not recognized by the driver. + *

          + * If the value specified to this method is greater than the maximum + * length for the property the driver may either truncate the value and + * generate a warning or generate a {@code SQLClientInfoException}. If the driver + * generates a {@code SQLClientInfoException}, the value specified was not set on the + * connection. + *

          + * The following are standard client info properties. Drivers are not + * required to support these properties however if the driver supports a + * client info property that can be described by one of the standard + * properties, the standard property name should be used. + * + *

            + *
          • ApplicationName - The name of the application currently utilizing + * the connection
          • + *
          • ClientUser - The name of the user that the application using + * the connection is performing work for. This may + * not be the same as the user name that was used + * in establishing the connection.
          • + *
          • ClientHostname - The hostname of the computer the application + * using the connection is running on.
          • + *
          + * + * @param name The name of the client info property to set + * @param value The value to set the client info property to. If the + * value is null, the current value of the specified + * property is cleared. + * + * @throws SQLClientInfoException if the database server returns an error while + * setting the client info value on the database server or this method + * is called on a closed connection + * + * @since 1.6 + */ + void setClientInfo(String name, String value) throws SQLClientInfoException; + + /** * Sets the value of the connection's client info properties. The * {@code Properties} object contains the names and values of the client info * properties to be set. The set of client info properties contained in @@ -1209,97 +1201,92 @@ void setClientInfo(String name, String value) * is called on a closed connection * */ - void setClientInfo(Properties properties) - throws SQLClientInfoException; - - /** - * Returns the value of the client info property specified by name. This - * method may return null if the specified client info property has not - * been set and does not have a default value. This method will also - * return null if the specified client info property name is not supported - * by the driver. - *

          - * Applications may use the {@code DatabaseMetaData.getClientInfoProperties} - * method to determine the client info properties supported by the driver. - * - * @param name The name of the client info property to retrieve - * - * @return The value of the client info property specified - * - * @throws SQLException if the database server returns an error when - * fetching the client info value from the database - * or this method is called on a closed connection - * - * @since 1.6 - * - * @see java.sql.DatabaseMetaData#getClientInfoProperties - */ - String getClientInfo(String name) - throws SQLException; - - /** - * Returns a list containing the name and current value of each client info - * property supported by the driver. The value of a client info property - * may be null if the property has not been set and does not have a - * default value. - * - * @return A {@code Properties} object that contains the name and current value of - * each of the client info properties supported by the driver. - * - * @throws SQLException if the database server returns an error when - * fetching the client info values from the database - * or this method is called on a closed connection - * - * @since 1.6 - */ - Properties getClientInfo() - throws SQLException; + void setClientInfo(Properties properties) throws SQLClientInfoException; -/** - * Factory method for creating Array objects. - *

          - * Note: When {@code createArrayOf} is used to create an array object - * that maps to a primitive data type, then it is implementation-defined - * whether the {@code Array} object is an array of that primitive - * data type or an array of {@code Object}. - *

          - * Note: The JDBC driver is responsible for mapping the elements - * {@code Object} array to the default JDBC SQL type defined in - * java.sql.Types for the given class of {@code Object}. The default - * mapping is specified in Appendix B of the JDBC specification. If the - * resulting JDBC type is not the appropriate type for the given typeName then - * it is implementation defined whether an {@code SQLException} is - * thrown or the driver supports the resulting conversion. - * - * @param typeName the SQL name of the type the elements of the array map to. The typeName is a - * database-specific name which may be the name of a built-in type, a user-defined type or a standard SQL type supported by this database. This - * is the value returned by {@code Array.getBaseTypeName} - * @param elements the elements that populate the returned object - * @return an Array object whose elements map to the specified SQL type - * @throws SQLException if a database error occurs, the JDBC type is not - * appropriate for the typeName and the conversion is not supported, the typeName is null or this method is called on a closed connection - * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type - * @since 1.6 - */ - Array createArrayOf(String typeName, Object[] elements) throws -SQLException; + /** + * Returns the value of the client info property specified by name. This + * method may return null if the specified client info property has not + * been set and does not have a default value. This method will also + * return null if the specified client info property name is not supported + * by the driver. + *

          + * Applications may use the {@code DatabaseMetaData.getClientInfoProperties} + * method to determine the client info properties supported by the driver. + * + * @param name The name of the client info property to retrieve + * + * @return The value of the client info property specified + * + * @throws SQLException if the database server returns an error when + * fetching the client info value from the database + * or this method is called on a closed connection + * + * @since 1.6 + * + * @see java.sql.DatabaseMetaData#getClientInfoProperties + */ + String getClientInfo(String name) throws SQLException; -/** - * Factory method for creating Struct objects. - * - * @param typeName the SQL type name of the SQL structured type that this {@code Struct} - * object maps to. The typeName is the name of a user-defined type that - * has been defined for this database. It is the value returned by - * {@code Struct.getSQLTypeName}. - - * @param attributes the attributes that populate the returned object - * @return a Struct object that maps to the given SQL type and is populated with the given attributes - * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection - * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type - * @since 1.6 - */ - Struct createStruct(String typeName, Object[] attributes) -throws SQLException; + /** + * Returns a list containing the name and current value of each client info + * property supported by the driver. The value of a client info property + * may be null if the property has not been set and does not have a + * default value. + * + * @return A {@code Properties} object that contains the name and current value of + * each of the client info properties supported by the driver. + * + * @throws SQLException if the database server returns an error when + * fetching the client info values from the database + * or this method is called on a closed connection + * + * @since 1.6 + */ + Properties getClientInfo() throws SQLException; + + /** + * Factory method for creating Array objects. + *

          + * Note: When {@code createArrayOf} is used to create an array object + * that maps to a primitive data type, then it is implementation-defined + * whether the {@code Array} object is an array of that primitive + * data type or an array of {@code Object}. + *

          + * Note: The JDBC driver is responsible for mapping the elements + * {@code Object} array to the default JDBC SQL type defined in + * java.sql.Types for the given class of {@code Object}. The default + * mapping is specified in Appendix B of the JDBC specification. If the + * resulting JDBC type is not the appropriate type for the given typeName then + * it is implementation defined whether an {@code SQLException} is + * thrown or the driver supports the resulting conversion. + * + * @param typeName the SQL name of the type the elements of the array map to. The typeName is a + * database-specific name which may be the name of a built-in type, a user-defined type or a standard SQL type supported by this database. This + * is the value returned by {@code Array.getBaseTypeName} + * @param elements the elements that populate the returned object + * @return an Array object whose elements map to the specified SQL type + * @throws SQLException if a database error occurs, the JDBC type is not + * appropriate for the typeName and the conversion is not supported, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + * @since 1.6 + */ + Array createArrayOf(String typeName, Object[] elements) throws SQLException; + + /** + * Factory method for creating Struct objects. + * + * @param typeName the SQL type name of the SQL structured type that this {@code Struct} + * object maps to. The typeName is the name of a user-defined type that + * has been defined for this database. It is the value returned by + * {@code Struct.getSQLTypeName}. + * + * @param attributes the attributes that populate the returned object + * @return a Struct object that maps to the given SQL type and is populated with the given attributes + * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + * @since 1.6 + */ + Struct createStruct(String typeName, Object[] attributes) throws SQLException; //--------------------------JDBC 4.1 ----------------------------- @@ -1463,7 +1450,7 @@ Struct createStruct(String typeName, Object[] attributes) // JDBC 4.3 - /** + /** * Hints to the driver that a request, an independent unit of work, is beginning * on this connection. Each request is independent of all other requests * with regard to state local to the connection either on the client or the @@ -1534,7 +1521,7 @@ default void beginRequest() throws SQLException { * marks the request completed and subsequent calls are treated as * a no-op. If {@code endRequest} is called without an initial call to * {@code beginRequest} is a no-op. - *

          + *

          * The exact behavior of this method is vendor specific. In particular * implementations may detect conditions that indicate dependence on * other work such as an open transaction. It is recommended though not @@ -1565,7 +1552,7 @@ default void beginRequest() throws SQLException { * @see javax.sql.PooledConnection */ default void endRequest() throws SQLException { - // Default method takes no action + // Default method takes no action } /** @@ -1686,8 +1673,8 @@ default void setShardingKey(ShardingKey shardingKey, ShardingKey superShardingKe * @see ShardingKey * @see ShardingKeyBuilder */ - default void setShardingKey(ShardingKey shardingKey) - throws SQLException { + default void setShardingKey(ShardingKey shardingKey) throws SQLException { throw new SQLFeatureNotSupportedException("setShardingKey not implemented"); } + } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 1144488773e..87ac233b6c7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: Content des Elements ''{0}'' ist nicht vollständig. ''{1}'' wird erwartet. cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: Übereinstimmungsplatzhalter ist streng, aber es kann keine Deklaration für Element ''{0}'' gefunden werden. cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Ungültiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element erwartet. + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: Ungültiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element ''{1}'' erwartet. cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: "{0}" darf maximal "{2}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde überschritten. An dieser Stelle wird eines von "{1}" erwartet. cvc-complex-type.2.4.f = cvc-complex-type.2.4.e: "{0}" darf maximal "{1}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde überschritten. An dieser Stelle wird kein untergeordnetes Element erwartet. cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Ungültigen Inhalt gefunden, der mit Element "{0}" beginnt. "{1}" soll erwartungsgemäß mindestens "{2}"-mal in der aktuellen Abfolge auftreten. Eine weitere Instanz ist erforderlich, um diesen Constraint zu erfüllen. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties index 05e945bed9b..ad82476b1e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: 要素''{0}''のコンテンツは不完全です。''{1}''のいずれかが必要です。 cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: ワイルドカードの一致は厳密ですが、要素''{0}''で宣言が見つかりません。 cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: 要素''{0}''で始まる無効なコンテンツが見つかりました。ここでは子要素を使用できません。 + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: 要素''{0}''で始まる無効なコンテンツが見つかりました。ここでは子要素''{1}''を使用できません。 cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}''は現在のシーケンスで最大''{2}''回発生することがあります。この制限を超えました。ここでは''{1}''のいずれかが必要です。 cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}''は現在のシーケンスで最大''{1}''回発生することがあります。この制限を超えました。ここでは子要素は使用できません。 cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: 要素''{0}''で始まる無効なコンテンツが見つかりました。''{1}''は現在のシーケンスで少なくとも''{2}''回発生する必要があります。この制約を満たすインスタンスがもう1つ必要です。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties index f366acbb174..238cb63c869 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: 元素 ''{0}'' 的内容不完整。应为 ''{1}'' 之一。 cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 ''{0}'' 的声明。 cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: 发现了以元素 ''{0}'' 开头的无效内容。此处不应含有子元素。 + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: 发现了以元素 ''{0}'' 开头的无效内容。此处不应含有子元素 ''{1}''。 cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' 在当前序列中最多可以出现 ''{2}'' 次。已超过此限制。此处预期为 ''{1}'' 之一。 cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' 在当前序列中最多可以出现 ''{1}'' 次。已超过此限制。此处预期没有子元素。 cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: 发现了以元素 ''{0}'' 开头的无效内容。''{1}'' 预期在当前序列中最少出现 ''{2}'' 次。另外一个实例必须满足此约束条件。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java index 272dca058d3..eacc96e70fb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_de extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_de extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_de extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "Erweiterungsfunktion \"{0}\" kann nicht aufgerufen werden, wenn das Feature \"XMLConstants.FEATURE_SECURE_PROCESSING\" auf \"true\" gesetzt ist."}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java index 1b707cd7820..8d8d5828da1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_ja extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "\u62E1\u5F35\u95A2\u6570: XMLConstants.FEATURE_SECURE_PROCESSING\u6A5F\u80FD\u304Ctrue\u306B\u8A2D\u5B9A\u3055\u308C\u308B\u3068''{0}''\u3092\u8D77\u52D5\u3067\u304D\u307E\u305B\u3093\u3002"}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java index dd9e507a8f0..3e1969357fb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_zh_CN extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "\u5F53 XMLConstants.FEATURE_SECURE_PROCESSING \u529F\u80FD\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u65F6, \u4E0D\u80FD\u8C03\u7528\u6269\u5C55\u51FD\u6570 ''{0}''\u3002"}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java index 87bc64c4e19..6214c3775d3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java @@ -272,8 +272,6 @@ void clear() { ((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear(); Types.instance(this).newRound(); Check.instance(this).newRound(); - Check.instance(this).clear(); //clear mandatory warning handlers - Preview.instance(this).clear(); //clear mandatory warning handlers Modules.instance(this).newRound(); Annotate.instance(this).newRound(); CompileStates.instance(this).clear(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java index 2634d218af0..242ba3752b7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java @@ -261,7 +261,7 @@ public static EnumSet asFlagSet(long flags) { /** * Flag that marks either a default method or an interface containing default methods. */ - public static final long DEFAULT = 1L<<43; + public static final long DEFAULT = 1L<<43; // part of ExtendedStandardFlags, cannot be reused /** * Flag that marks class as auxiliary, ie a non-public class following @@ -289,9 +289,10 @@ public static EnumSet asFlagSet(long flags) { */ public static final long THROWS = 1L<<47; - /* - * Currently available: Bit 48. + /** + * Flag to indicate sealed class/interface declaration. */ + public static final long SEALED = 1L<<48; // part of ExtendedStandardFlags, cannot be reused /** * Flag that marks a synthetic method body for a lambda expression @@ -405,11 +406,6 @@ public static EnumSet asFlagSet(long flags) { */ public static final int GENERATED_MEMBER = 1<<24; // MethodSymbols and VarSymbols - /** - * Flag to indicate sealed class/interface declaration. - */ - public static final long SEALED = 1L<<62; // ClassSymbols - /** * Flag to indicate restricted method declaration. */ @@ -428,7 +424,7 @@ public static EnumSet asFlagSet(long flags) { /** * Flag to indicate that the class/interface was declared with the non-sealed modifier. */ - public static final long NON_SEALED = 1L<<63; // ClassSymbols + public static final long NON_SEALED = 1L<<63; // part of ExtendedStandardFlags, cannot be reused /** * Flag to indicate that a class has at least one strict field @@ -469,6 +465,7 @@ public static String toSource(long flags) { RecordMethodFlags = AccessFlags | ABSTRACT | STATIC | SYNCHRONIZED | FINAL | STRICTFP; public static final long + //NOTE: flags in ExtendedStandardFlags cannot be overlayed across Symbol kinds: ExtendedStandardFlags = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED | VALUE_CLASS, ExtendedMemberClassFlags = (long)MemberClassFlags | SEALED | NON_SEALED | VALUE_CLASS, ExtendedMemberStaticClassFlags = (long) MemberStaticClassFlags | SEALED | NON_SEALED | VALUE_CLASS, @@ -586,7 +583,7 @@ public String toString() { DEPRECATED_ANNOTATION(Flags.DEPRECATED_ANNOTATION), DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL), HAS_RESOURCE(Flags.HAS_RESOURCE), - // Bit 48 is currently available + SEALED(Flags.SEALED), ANONCONSTR_BASED(Flags.ANONCONSTR_BASED), NAME_FILLED(Flags.NAME_FILLED), PREVIEW_API(Flags.PREVIEW_API), @@ -595,7 +592,7 @@ public String toString() { MATCH_BINDING_TO_OUTER(Flags.MATCH_BINDING_TO_OUTER), RECORD(Flags.RECORD), RECOVERABLE(Flags.RECOVERABLE), - SEALED(Flags.SEALED), + RESTRICTED(Flags.RESTRICTED), NON_SEALED(Flags.NON_SEALED) { @Override public String toString() { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java index 922aeabed24..74a6528db69 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java @@ -183,9 +183,9 @@ private void initializeRootIfNeeded() { // Look for specific overrides for (LintCategory lc : LintCategory.values()) { - if (options.isExplicitlyEnabled(Option.XLINT, lc)) { + if (options.isLintExplicitlyEnabled(lc)) { values.add(lc); - } else if (options.isExplicitlyDisabled(Option.XLINT, lc)) { + } else if (options.isLintExplicitlyDisabled(lc)) { values.remove(lc); } } @@ -535,7 +535,9 @@ private EnumSet suppressionsFrom(Attribute.Compound suppressWarnin EnumSet result = LintCategory.newEmptySet(); Attribute.Array values = (Attribute.Array)suppressWarnings.member(names.value); for (Attribute value : values.values) { - Optional.of((String)((Attribute.Constant)value).value) + Optional.of(value) + .filter(val -> val instanceof Attribute.Constant) + .map(val -> (String) ((Attribute.Constant) val).value) .flatMap(LintCategory::get) .filter(lc -> lc.annotationSuppression) .ifPresent(result::add); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index f325eae1555..09f9a571f56 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -40,7 +40,6 @@ import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.Warning; import com.sun.tools.javac.util.Log; -import com.sun.tools.javac.util.MandatoryWarningHandler; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Options; @@ -71,9 +70,6 @@ public class Preview { /** flag: is the "preview" lint category enabled? */ private final boolean verbose; - /** the diag handler to manage preview feature usage diagnostics */ - private final MandatoryWarningHandler previewHandler; - /** test flag: should all features be considered as preview features? */ private final boolean forcePreview; @@ -105,7 +101,6 @@ protected Preview(Context context) { log = Log.instance(context); source = Source.instance(context); verbose = Lint.instance(context).isEnabled(LintCategory.PREVIEW); - previewHandler = new MandatoryWarningHandler(log, source, verbose, true, LintCategory.PREVIEW); forcePreview = options.isSet("forcePreview"); majorVersionToSource = initMajorVersionToSourceMap(); } @@ -176,7 +171,8 @@ public void warnPreview(DiagnosticPosition pos, Feature feature) { Assert.check(isEnabled()); Assert.check(isPreview(feature)); markUsesPreview(pos); - previewHandler.report(pos, feature.isPlural() ? + log.mandatoryWarning(pos, + feature.isPlural() ? LintWarnings.PreviewFeatureUsePlural(feature.nameFragment()) : LintWarnings.PreviewFeatureUse(feature.nameFragment())); } @@ -203,10 +199,6 @@ public void markUsesPreview(DiagnosticPosition pos) { sourcesWithPreviewFeatures.add(log.currentSourceFile()); } - public void reportPreviewWarning(DiagnosticPosition pos, LintWarning warnKey) { - previewHandler.report(pos, warnKey); - } - public boolean usesPreview(JavaFileObject file) { return sourcesWithPreviewFeatures.contains(file); } @@ -270,25 +262,13 @@ public boolean declaredUsingPreviewFeature(Symbol sym) { return false; } - /** - * Report any deferred diagnostics. - */ - public void reportDeferredDiagnostics() { - previewHandler.reportDeferredDiagnostic(); - } - - public void clear() { - previewHandler.clear(); - } - public void checkSourceLevel(DiagnosticPosition pos, Feature feature) { if (isPreview(feature) && !isEnabled()) { //preview feature without --preview flag, error - log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos, disabledError(feature)); + log.error(pos, disabledError(feature)); } else { if (!feature.allowedInSource(source)) { - log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos, - feature.error(source.name)); + log.error(pos, feature.error(source.name)); } if (isEnabled() && isPreview(feature)) { warnPreview(pos, feature); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index d60cfcccb25..33d23eec103 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -43,7 +43,6 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; -import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; import com.sun.tools.javac.code.TypeMetadata.Annotations; import com.sun.tools.javac.comp.AttrContext; @@ -2249,60 +2248,64 @@ public Type visitErrorType(ErrorType t, Symbol sym) { }; /** - * Return the base type of t or any of its outer types that starts - * with the given symbol. If none exists, return null. + * This method returns the first type in a sequence (starting at `t`) that is + * a subclass of `sym`. The next type in the sequence is obtained by calling + * `getEnclosingType()` on the previous type in the sequence. Note, this is + * typically used to compute the implicit qualifier in a method/field access + * expression. Example: * - * @param t a type - * @param sym a symbol + * static class Sup { public F f; } + * class Outer { + * static class Sub extends Sup { + * class I { + * void test() { + * String f2 = f; // Sup::f + * } + * } + * } + * } + * + * @param t a type + * @param sym a symbol */ public Type asOuterSuper(Type t, Symbol sym) { - switch (t.getTag()) { - case CLASS: - do { - Type s = asSuper(t, sym); - if (s != null) return s; - t = t.getEnclosingType(); - } while (t.hasTag(CLASS)); - return null; - case ARRAY: - return isSubtype(t, sym.type) ? sym.type : null; - case TYPEVAR: - return asSuper(t, sym); - case ERROR: - return t; - default: - return null; + Type t1 = t; + while (!t1.hasTag(NONE)) { + Type s = asSuper(t1, sym); + if (s != null) return s; + t1 = t1.getEnclosingType(); } + return null; } /** - * Return the base type of t or any of its enclosing types that - * starts with the given symbol. If none exists, return null. + * This method returns the first type in a sequence (starting at `t`) that is + * a subclass of `sym`. The next type in the sequence is obtained by obtaining + * innermost lexically enclosing class type of the previous type in the sequence. + * Note, this is typically used to compute the implicit qualifier in + * a type expression. Example: + * + * class A { class B { } } + * + * class C extends A { + * static class D { + * B b; // A.B + * } + * } * * @param t a type * @param sym a symbol */ public Type asEnclosingSuper(Type t, Symbol sym) { - switch (t.getTag()) { - case CLASS: - do { - Type s = asSuper(t, sym); - if (s != null) return s; - Type outer = t.getEnclosingType(); - t = (outer.hasTag(CLASS)) ? outer : - (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type : - Type.noType; - } while (t.hasTag(CLASS)); - return null; - case ARRAY: - return isSubtype(t, sym.type) ? sym.type : null; - case TYPEVAR: - return asSuper(t, sym); - case ERROR: - return t; - default: - return null; + Type t1 = t; + while (!t1.hasTag(NONE)) { + Type s = asSuper(t1, sym); + if (s != null) return s; + t1 = (t1.tsym.owner.enclClass() != null) + ? t1.tsym.owner.enclClass().type + : noType; } + return null; } // @@ -4527,7 +4530,7 @@ private boolean sideCast(Type from, Type to, Warner warn) { to = from; from = target; } - List commonSupers = superClosure(to, erasure(from)); + List commonSupers = supertypeClosure(to, erasure(from)); boolean giveWarning = commonSupers.isEmpty(); // The arguments to the supers could be unified here to // get a more accurate analysis @@ -4585,13 +4588,13 @@ private boolean giveWarning(Type from, Type to) { return false; } - private List superClosure(Type t, Type s) { + private List supertypeClosure(Type t, Type s) { List cl = List.nil(); for (List l = interfaces(t); l.nonEmpty(); l = l.tail) { if (isSubtype(s, erasure(l.head))) { cl = insert(cl, l.head); } else { - cl = union(cl, superClosure(l.head, s)); + cl = union(cl, supertypeClosure(l.head, s)); } } return cl; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index f908d445d5d..6acf197c687 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -79,7 +79,6 @@ import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.WILDCARD; import static com.sun.tools.javac.tree.JCTree.Tag.*; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; /** This is the main context-dependent analysis phase in GJC. It * encompasses name resolution, type checking and constant folding as @@ -1230,8 +1229,8 @@ public void visitMethodDef(JCMethodDecl tree) { annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m, null); annotate.flush(); - // Start of constructor prologue - localEnv.info.ctorPrologue = isConstructor; + // Start of constructor prologue (if not in java.lang.Object constructor) + localEnv.info.ctorPrologue = isConstructor && owner.type != syms.objectType; // Attribute method body. attribStat(tree.body, localEnv); @@ -1269,6 +1268,7 @@ class CtorPrologueVisitor extends TreeScanner { Env localEnv; CtorPrologueVisitor(Env localEnv) { this.localEnv = localEnv; + currentClassSym = localEnv.enclClass.sym; } boolean insideLambdaOrClassDef = false; @@ -1284,14 +1284,19 @@ public void visitLambda(JCLambda lambda) { } } + ClassSymbol currentClassSym; + @Override public void visitClassDef(JCClassDecl classDecl) { boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef; + ClassSymbol previousClassSym = currentClassSym; try { insideLambdaOrClassDef = true; + currentClassSym = classDecl.sym; super.visitClassDef(classDecl); } finally { insideLambdaOrClassDef = previousInsideLambdaOrClassDef; + currentClassSym = previousClassSym; } } @@ -1384,6 +1389,10 @@ public void visitMethodDef(JCMethodDecl tree) { void analyzeSymbol(JCTree tree) { Symbol sym = TreeInfo.symbolFor(tree); + // make sure that there is a symbol and it is not static + if (sym == null || sym.isStatic()) { + return; + } if (isInLHS && !insideLambdaOrClassDef) { // Check instance field assignments that appear in constructor prologues if (isEarlyReference(localEnv, tree, sym)) { @@ -1392,7 +1401,6 @@ void analyzeSymbol(JCTree tree) { log.error(tree, Errors.CantRefBeforeCtorCalled(sym)); return; } - // Field may not have an initializer if ((sym.flags() & HASINIT) != 0) { log.error(tree, Errors.CantAssignInitializedBeforeCtorCalled(sym)); @@ -1402,47 +1410,45 @@ void analyzeSymbol(JCTree tree) { return; } tree = TreeInfo.skipParens(tree); - if (sym != null) { - if (!sym.isStatic() && sym.kind == VAR && sym.owner.kind == TYP) { - if (sym.name == names._this || sym.name == names._super) { - // are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`? - if (TreeInfo.isExplicitThisReference( - types, - (ClassType)localEnv.enclClass.sym.type, - tree)) { - reportPrologueError(tree, sym); - } - } else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only - if (sym.owner != localEnv.enclClass.sym) { - if (localEnv.enclClass.sym.isSubClass(sym.owner, types) && - sym.isInheritedIn(localEnv.enclClass.sym, types)) { - /* if we are dealing with a field that doesn't belong to the current class, but the - * field is inherited, this is an error. Unless, the super class is also an outer - * class and the field's qualifier refers to the outer class - */ - if (tree.hasTag(IDENT) || - TreeInfo.isExplicitThisReference( - types, - (ClassType)localEnv.enclClass.sym.type, - ((JCFieldAccess)tree).selected)) { - reportPrologueError(tree, sym); - } - } - } else if (isEarlyReference(localEnv, tree, sym)) { - /* now this is a `proper` instance field of the current class - * references to fields of identity classes which happen to have initializers are - * not allowed in the prologue + if (sym.kind == VAR && sym.owner.kind == TYP) { + if (sym.name == names._this || sym.name == names._super) { + // are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`? + if (TreeInfo.isExplicitThisReference( + types, + (ClassType)localEnv.enclClass.sym.type, + tree)) { + reportPrologueError(tree, sym); + } + } else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only + if (sym.owner != localEnv.enclClass.sym) { + if (localEnv.enclClass.sym.isSubClass(sym.owner, types) && + sym.isInheritedIn(localEnv.enclClass.sym, types)) { + /* if we are dealing with a field that doesn't belong to the current class, but the + * field is inherited, this is an error. Unless, the super class is also an outer + * class and the field's qualifier refers to the outer class */ - if (insideLambdaOrClassDef || - (!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0)) + if (tree.hasTag(IDENT) || + TreeInfo.isExplicitThisReference( + types, + (ClassType)localEnv.enclClass.sym.type, + ((JCFieldAccess)tree).selected)) { + reportPrologueError(tree, sym); + } + } + } else if (isEarlyReference(localEnv, tree, sym)) { + /* now this is a `proper` instance field of the current class + * references to fields of identity classes which happen to have initializers are + * not allowed in the prologue + */ + if (insideLambdaOrClassDef || + (!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0)) + reportPrologueError(tree, sym); + // we will need to generate a proxy for this field later on + if (!isInLHS) { + if (allowValueClasses) { + localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym); + } else { reportPrologueError(tree, sym); - // we will need to generate a proxy for this field later on - if (!isInLHS) { - if (allowValueClasses) { - localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym); - } else { - reportPrologueError(tree, sym); - } } } } @@ -1468,6 +1474,14 @@ private boolean isEarlyReference(Env env, JCTree tree, Symbol sym) // Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance if (tree instanceof JCFieldAccess fa) { return TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, fa.selected); + } else if (currentClassSym != env.enclClass.sym) { + /* so we are inside a class, CI, in the prologue of an outer class, CO, and the symbol being + * analyzed has no qualifier. So if the symbol is a member of CI the reference is allowed, + * otherwise it is not. + * It could be that the reference to CI's member happens inside CI's own prologue, but that + * will be checked separately, when CI's prologue is analyzed. + */ + return !sym.isMemberOf(currentClassSym, types); } return true; } @@ -3090,7 +3104,7 @@ public void visitNewClass(final JCNewClass tree) { resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; boolean skipNonDiamondPath = false; // Check that class is not abstract - if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy + if (cdef == null && !tree.classDeclRemoved() && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { log.error(tree.pos(), Errors.AbstractCantBeInstantiated(clazztype.tsym)); @@ -4402,8 +4416,7 @@ public void visitTypeTest(JCInstanceOf tree) { !exprtype.isErroneous() && !clazztype.isErroneous() && tree.pattern.getTag() != RECORDPATTERN) { if (!allowUnconditionalPatternsInstanceOf) { - log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), - Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName)); + log.error(tree.pos(), Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName)); } } typeTree = TreeInfo.primaryPatternTypeTree((JCPattern) tree.pattern); @@ -4423,8 +4436,7 @@ public void visitTypeTest(JCInstanceOf tree) { if (allowReifiableTypesInInstanceof) { valid = checkCastablePattern(tree.expr.pos(), exprtype, clazztype); } else { - log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), - Feature.REIFIABLE_TYPES_INSTANCEOF.error(this.sourceName)); + log.error(tree.pos(), Feature.REIFIABLE_TYPES_INSTANCEOF.error(this.sourceName)); allowReifiableTypesInInstanceof = true; } if (!valid) { @@ -4933,11 +4945,8 @@ Type checkIdInternal(JCTree tree, // // Then the type of the last expression above is // Tree.Visitor. - else if (ownOuter.hasTag(CLASS) && site != ownOuter) { - Type normOuter = site; - if (normOuter.hasTag(CLASS)) { - normOuter = types.asEnclosingSuper(site, ownOuter.tsym); - } + else if ((ownOuter.hasTag(CLASS) || ownOuter.hasTag(TYPEVAR)) && site != ownOuter) { + Type normOuter = types.asEnclosingSuper(site, ownOuter.tsym); if (normOuter == null) // perhaps from an import normOuter = types.erasure(ownOuter); if (normOuter != ownOuter) @@ -5323,8 +5332,8 @@ public void visitTypeApply(JCTypeApply tree) { site = ((JCFieldAccess) clazz).selected.type; } else throw new AssertionError(""+tree); if (clazzOuter.hasTag(CLASS) && site != clazzOuter) { - if (site.hasTag(CLASS)) - site = types.asOuterSuper(site, clazzOuter.tsym); + if (site.hasTag(CLASS) || site.hasTag(TYPEVAR)) + site = types.asEnclosingSuper(site, clazzOuter.tsym); if (site == null) site = types.erasure(clazzOuter); clazzOuter = site; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index c9400d2e78e..f3c9b3be4e6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -164,18 +164,6 @@ protected Check(Context context) { profile = Profile.instance(context); preview = Preview.instance(context); - boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); - boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL); - boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); - boolean enforceMandatoryWarnings = true; - - deprecationHandler = new MandatoryWarningHandler(log, null, verboseDeprecated, - enforceMandatoryWarnings, LintCategory.DEPRECATION, "deprecated"); - removalHandler = new MandatoryWarningHandler(log, null, verboseRemoval, - enforceMandatoryWarnings, LintCategory.REMOVAL); - uncheckedHandler = new MandatoryWarningHandler(log, null, verboseUnchecked, - enforceMandatoryWarnings, LintCategory.UNCHECKED); - deferredLintHandler = DeferredLintHandler.instance(context); allowModules = Feature.MODULES.allowedInSource(source); @@ -194,18 +182,6 @@ protected Check(Context context) { */ private Map,ClassSymbol> compiled = new HashMap<>(); - /** A handler for messages about deprecated usage. - */ - private MandatoryWarningHandler deprecationHandler; - - /** A handler for messages about deprecated-for-removal usage. - */ - private MandatoryWarningHandler removalHandler; - - /** A handler for messages about unchecked or unsafe usage. - */ - private MandatoryWarningHandler uncheckedHandler; - /** A handler for deferred lint warnings. */ private DeferredLintHandler deferredLintHandler; @@ -259,21 +235,24 @@ MethodSymbol setMethod(MethodSymbol newMethod) { * @param sym The deprecated symbol. */ void warnDeprecated(DiagnosticPosition pos, Symbol sym) { + LintWarning warningKey = null; if (sym.isDeprecatedForRemoval()) { if (!lint.isSuppressed(LintCategory.REMOVAL)) { if (sym.kind == MDL) { - removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemovalModule(sym)); + warningKey = LintWarnings.HasBeenDeprecatedForRemovalModule(sym); } else { - removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location())); + warningKey = LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location()); } } } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) { if (sym.kind == MDL) { - deprecationHandler.report(pos, LintWarnings.HasBeenDeprecatedModule(sym)); + warningKey = LintWarnings.HasBeenDeprecatedModule(sym); } else { - deprecationHandler.report(pos, LintWarnings.HasBeenDeprecated(sym, sym.location())); + warningKey = LintWarnings.HasBeenDeprecated(sym, sym.location()); } } + if (warningKey != null) + log.mandatoryWarning(pos, warningKey); } /** Log a preview warning. @@ -282,7 +261,7 @@ void warnDeprecated(DiagnosticPosition pos, Symbol sym) { */ public void warnPreviewAPI(DiagnosticPosition pos, LintWarning warnKey) { if (!importSuppression && !lint.isSuppressed(LintCategory.PREVIEW)) - preview.reportPreviewWarning(pos, warnKey); + log.mandatoryWarning(pos, warnKey); } /** Log a preview warning. @@ -299,25 +278,15 @@ public void warnRestrictedAPI(DiagnosticPosition pos, Symbol sym) { */ public void warnUnchecked(DiagnosticPosition pos, LintWarning warnKey) { if (!lint.isSuppressed(LintCategory.UNCHECKED)) - uncheckedHandler.report(pos, warnKey); + log.mandatoryWarning(pos, warnKey); } - /** - * Report any deferred diagnostics. - */ - public void reportDeferredDiagnostics() { - deprecationHandler.reportDeferredDiagnostic(); - removalHandler.reportDeferredDiagnostic(); - uncheckedHandler.reportDeferredDiagnostic(); - } - - /** Report a failure to complete a class. * @param pos Position to be used for error reporting. * @param ex The failure to report. */ public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { - log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue())); + log.error(DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue())); return syms.errType; } @@ -480,12 +449,6 @@ public void newRound() { localClassNameIndexes.clear(); } - public void clear() { - deprecationHandler.clear(); - removalHandler.clear(); - uncheckedHandler.clear(); - } - public void putCompiled(ClassSymbol csym) { compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym); } @@ -3901,7 +3864,7 @@ void checkDeprecated(Supplier pos, final Symbol other, final void checkSunAPI(final DiagnosticPosition pos, final Symbol s) { if ((s.flags() & PROPRIETARY) != 0) { deferredLintHandler.report(_l -> { - log.mandatoryWarning(pos, Warnings.SunProprietary(s)); + log.warning(pos, Warnings.SunProprietary(s)); }); } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index d037ccc6506..9b6b8fe2707 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2849,47 +2849,55 @@ public void visitTypeCast(JCTypeCast tree) { */ public void visitTypeTest(JCInstanceOf tree) { if (tree.expr.type.isPrimitive() || tree.pattern.type.isPrimitive()) { - JCExpression exactnessCheck = null; + JCStatement prefixStatement; + JCExpression exactnessCheck; JCExpression instanceOfExpr = translate(tree.expr); - // preserving the side effects of the value - VarSymbol dollar_s = new VarSymbol(FINAL | SYNTHETIC, - names.fromString("tmp" + variableIndex++ + this.target.syntheticNameChar()), - types.erasure(tree.expr.type), - currentMethodSym); - JCStatement var = make.at(tree.pos()) - .VarDef(dollar_s, instanceOfExpr); - if (types.isUnconditionallyExact(tree.expr.type, tree.pattern.type)) { + // instanceOfExpr; true + prefixStatement = make.Exec(instanceOfExpr); exactnessCheck = make.Literal(BOOLEAN, 1).setType(syms.booleanType.constType(1)); - } - else if (tree.expr.type.isReference()) { - JCExpression nullCheck = - makeBinary(NE, - make.Ident(dollar_s), - makeNull()); - + } else if (tree.expr.type.isPrimitive()) { + // ExactConversionSupport.isXxxExact(instanceOfExpr) + prefixStatement = null; + exactnessCheck = getExactnessCheck(tree, instanceOfExpr); + } else if (tree.expr.type.isReference()) { if (types.isUnconditionallyExact(types.unboxedType(tree.expr.type), tree.pattern.type)) { - exactnessCheck = nullCheck; - } else if (types.unboxedType(tree.expr.type).isPrimitive()) { - exactnessCheck = - makeBinary(AND, - nullCheck, - getExactnessCheck(tree, boxIfNeeded(make.Ident(dollar_s), types.unboxedType(tree.expr.type)))); + // instanceOfExpr != null + prefixStatement = null; + exactnessCheck = makeBinary(NE, instanceOfExpr, makeNull()); } else { - exactnessCheck = - makeBinary(AND, - nullCheck, - make.at(tree.pos()) - .TypeTest(make.Ident(dollar_s), make.Type(types.boxedClass(tree.pattern.type).type)) - .setType(syms.booleanType)); + // We read the result of instanceOfExpr, so create variable + VarSymbol dollar_s = new VarSymbol(FINAL | SYNTHETIC, + names.fromString("tmp" + variableIndex++ + this.target.syntheticNameChar()), + types.erasure(tree.expr.type), + currentMethodSym); + prefixStatement = make.at(tree.pos()) + .VarDef(dollar_s, instanceOfExpr); + + JCExpression nullCheck = + makeBinary(NE, + make.Ident(dollar_s), + makeNull()); + + if (types.unboxedType(tree.expr.type).isPrimitive()) { + exactnessCheck = + makeBinary(AND, + nullCheck, + getExactnessCheck(tree, boxIfNeeded(make.Ident(dollar_s), types.unboxedType(tree.expr.type)))); + } else { + exactnessCheck = + makeBinary(AND, + nullCheck, + make.at(tree.pos()) + .TypeTest(make.Ident(dollar_s), make.Type(types.boxedClass(tree.pattern.type).type)) + .setType(syms.booleanType)); + } } + } else { + throw Assert.error("Non primitive or reference type: " + tree.expr.type); } - else if (tree.expr.type.isPrimitive()) { - exactnessCheck = getExactnessCheck(tree, make.Ident(dollar_s)); - } - - result = make.LetExpr(List.of(var), exactnessCheck) + result = (prefixStatement == null ? exactnessCheck : make.LetExpr(List.of(prefixStatement), exactnessCheck)) .setType(syms.booleanType); } else { tree.expr = translate(tree.expr); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index a159793fe32..47066b24de9 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -205,7 +205,7 @@ protected Modules(Context context) { allowAccessIntoSystem = options.isUnset(Option.RELEASE); - lintOptions = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.OPTIONS); + lintOptions = !options.isLintDisabled(LintCategory.OPTIONS); multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); ClassWriter classWriter = ClassWriter.instance(context); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index 675809db7ba..862c02ea5f0 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1142,9 +1142,7 @@ public void visitTypeApply(JCTypeApply tree) { } public void visitTypeIntersection(JCTypeIntersection tree) { - tree.bounds = translate(tree.bounds, null); - tree.type = erasure(tree.type); - result = tree; + result = translate(tree.bounds.head, null); } /* ************************************************************************ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 4e93f82fd99..8a0c692a1ed 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -812,6 +812,11 @@ public CondItem genCond(JCTree _tree, boolean markBranches) { } CondItem result = genCond(tree.expr, markBranches); code.endScopes(limit); + //make sure variables defined in the let expression are not included + //in the defined variables for jumps that go outside of this let + //expression: + undefineVariablesInChain(result.falseJumps, limit); + undefineVariablesInChain(result.trueJumps, limit); return result; } else { CondItem result = genExpr(_tree, syms.booleanType).mkCond(); @@ -819,6 +824,13 @@ public CondItem genCond(JCTree _tree, boolean markBranches) { return result; } } + //where: + private void undefineVariablesInChain(Chain toClear, int limit) { + while (toClear != null) { + toClear.state.defined.excludeFrom(limit); + toClear = toClear.next; + } + } public Code getCode() { return code; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/MemoryContext.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/MemoryContext.java index 5fa76c14d3f..3f3f5e2f27b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/MemoryContext.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/MemoryContext.java @@ -28,11 +28,12 @@ import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskListener; import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.code.Preview; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.resources.LauncherProperties.Errors; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context.Factory; +import com.sun.tools.javac.util.Log; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; @@ -120,8 +121,11 @@ void compileProgram() throws Fault { } var opts = options.forProgramCompilation(); var context = new Context(); - MemoryPreview.registerInstance(context); var task = compiler.getTask(out, memoryFileManager, null, opts, null, units, context); + + // This suppresses diagnostics like "Note: Recompile with -Xlint:preview for details." + Log.instance(context).suppressAggregatedWarningNotes(LintCategory.PREVIEW); + var ok = task.call(); if (!ok) { throw new Fault(Errors.CompilationFailed); @@ -269,19 +273,4 @@ private void enableNativeAccess(ModuleLayer.Controller controller, boolean shoul controller.enableNativeAccess(module); } } - - static class MemoryPreview extends Preview { - static void registerInstance(Context context) { - context.put(previewKey, (Factory)MemoryPreview::new); - } - - MemoryPreview(Context context) { - super(context); - } - - @Override - public void reportDeferredDiagnostics() { - // suppress diagnostics like "Note: Recompile with -Xlint:preview for details." - } - } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java index 9e3a978c3bc..7aa1cc473b5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java @@ -503,7 +503,7 @@ public boolean validate() { } } else { // single-module or legacy mode - boolean lintPaths = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.PATH); + boolean lintPaths = !options.isLintDisabled(LintCategory.PATH); if (lintPaths) { Path outDirParent = outDir.getParent(); if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) { @@ -576,7 +576,7 @@ public boolean validate() { reportDiag(Errors.SourcepathModulesourcepathConflict); } - boolean lintOptions = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.OPTIONS); + boolean lintOptions = !options.isLintDisabled(LintCategory.OPTIONS); if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) { if (fm instanceof BaseFileManager baseFileManager) { if (source.compareTo(Source.JDK8) <= 0) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 6ff698c1d31..e53bf638f0d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -55,10 +55,10 @@ import com.sun.source.util.TaskEvent; import com.sun.tools.javac.api.MultiTaskListener; import com.sun.tools.javac.code.*; -import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.comp.*; import com.sun.tools.javac.comp.CompileStates.CompileState; @@ -85,8 +85,6 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; -import com.sun.tools.javac.code.Symbol.ModuleSymbol; - import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Notes; @@ -272,10 +270,6 @@ else if (option.equals("class")) */ protected Source source; - /** The preview language version. - */ - protected Preview preview; - /** The module for code generation. */ protected Gen gen; @@ -411,7 +405,6 @@ public JavaCompiler(Context context) { log.error(Errors.CantAccess(ex.sym, ex.getDetailValue())); } source = Source.instance(context); - preview = Preview.instance(context); attr = Attr.instance(context); analyzer = Analyzer.instance(context); chk = Check.instance(context); @@ -1857,8 +1850,7 @@ public void reportDeferredDiagnostics() { else log.warning(Warnings.ProcUseProcOrImplicit); } - chk.reportDeferredDiagnostics(); - preview.reportDeferredDiagnostics(); + log.reportOutstandingNotes(); if (log.compressedOutput) { log.mandatoryNote(null, Notes.CompressedDiags); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java index d799975a76a..f3d0837398c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java @@ -181,10 +181,10 @@ protected JavaTokenizer(ScannerFactory fac, char[] array, int length) { protected void checkSourceLevel(int pos, Feature feature) { if (preview.isPreview(feature) && !preview.isEnabled()) { //preview feature without --preview flag, error - lexError(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature)); + lexError(pos, preview.disabledError(feature)); } else if (!feature.allowedInSource(source)) { //incompatible source level, error - lexError(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name)); + lexError(pos, feature.error(source.name)); } else if (preview.isPreview(feature)) { //use of preview feature, warn preview.warnPreview(pos, feature); @@ -199,20 +199,7 @@ protected void checkSourceLevel(int pos, Feature feature) { */ protected void lexError(int pos, JCDiagnostic.Error key) { log.error(pos, key); - tk = TokenKind.ERROR; - errPos = pos; - } - - /** - * Report an error at the given position using the provided arguments. - * - * @param flags diagnostic flags. - * @param pos position in input buffer. - * @param key error key to report. - */ - protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) { - log.error(flags, pos, key); - if (flags != DiagnosticFlag.SOURCE_LEVEL) { + if (!key.hasFlag(DiagnosticFlag.SOURCE_LEVEL)) { tk = TokenKind.ERROR; } errPos = pos; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index d00fef8562e..ceaf2bfeed7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -5668,10 +5668,10 @@ void checkSourceLevel(Feature feature) { protected void checkSourceLevel(int pos, Feature feature) { if (preview.isPreview(feature) && !preview.isEnabled()) { //preview feature without --preview flag, error - log.error(DiagnosticFlag.SOURCE_LEVEL, pos, preview.disabledError(feature)); + log.error(pos, preview.disabledError(feature)); } else if (!feature.allowedInSource(source)) { //incompatible source level, error - log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name)); + log.error(pos, feature.error(source.name)); } else if (preview.isPreview(feature)) { //use of preview feature, warn preview.warnPreview(pos, feature); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 5d3af2320be..b6ddbec8fda 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1923,16 +1923,19 @@ compiler.warn.incubating.modules=\ # 0: symbol, 1: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated=\ {0} in {1} has been deprecated # 0: symbol, 1: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal=\ {0} in {1} has been deprecated and marked for removal # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview=\ {0} is a preview API and may be removed in a future release. @@ -1943,6 +1946,7 @@ compiler.err.is.preview=\ # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview.reflective=\ {0} is a reflective preview API and may be removed in a future release. @@ -1954,15 +1958,18 @@ compiler.warn.restricted.method=\ # 0: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated.module=\ module {0} has been deprecated # 0: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal.module=\ module {0} has been deprecated and marked for removal # 0: symbol +# flags: strict compiler.warn.sun.proprietary=\ {0} is internal proprietary API and may be removed in a future release @@ -2365,11 +2372,13 @@ compiler.warn.unchecked.assign=\ # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.assign.to.var=\ unchecked assignment to variable {0} as member of raw type {1} # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.call.mbr.of.raw.type=\ unchecked call to {0} as a member of the raw type {1} @@ -2379,6 +2388,7 @@ compiler.warn.unchecked.cast.to.type=\ # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked +# flags: aggregate compiler.warn.unchecked.meth.invocation.applied=\ unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\ required: {2}\n\ @@ -2386,11 +2396,13 @@ compiler.warn.unchecked.meth.invocation.applied=\ # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.generic.array.creation=\ unchecked generic array creation for varargs parameter of type {0} # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.varargs.non.reifiable.type=\ Possible heap pollution from parameterized vararg type {0} @@ -2789,6 +2801,7 @@ compiler.misc.prob.found.req=\ # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.prob.found.req=\ {0}\n\ required: {2}\n\ @@ -3188,12 +3201,14 @@ compiler.err.override.incompatible.ret=\ # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.ret=\ {0}\n\ return type requires unchecked conversion from {1} to {2} # 0: message segment, 1: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.thrown=\ {0}\n\ overridden method does not throw {1} @@ -3257,11 +3272,13 @@ compiler.misc.inapplicable.method=\ ######################################## # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source=\ {0} is not supported in -source {1}\n\ (use -source {2} or higher to enable {0}) # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source.plural=\ {0} are not supported in -source {1}\n\ (use -source {2} or higher to enable {0}) @@ -3277,11 +3294,13 @@ compiler.misc.feature.not.supported.in.source.plural=\ (use -source {2} or higher to enable {0}) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled=\ {0} is a preview feature and is disabled by default.\n\ (use --enable-preview to enable {0}) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled.plural=\ {0} are a preview feature and are disabled by default.\n\ (use --enable-preview to enable {0}) @@ -3293,11 +3312,13 @@ compiler.err.preview.feature.disabled.classfile=\ # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use=\ {0} is a preview feature and may be removed in a future release. # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use.plural=\ {0} are a preview feature and may be removed in a future release. @@ -4285,6 +4306,7 @@ compiler.err.incorrect.number.of.nested.patterns=\ # 0: kind name, 1: symbol # lint: preview +# flags: aggregate compiler.warn.declared.using.preview=\ {0} {1} is declared using a preview feature, which may be removed in a future release. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index 8761d334157..538b5a6c03b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst=Funktionsschnittstellendeskriptor compiler.misc.bad.intersection.target.for.functional.expr=Ungültiges Schnittmengentypziel für Lambda oder Methodenreferenz\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=Komponententyp {0} ist keine Schnittstelle +compiler.misc.not.an.intf.component=Komponententyp {0} ist keine Schnittstelle oder kein java.lang.Object # 0: kind name, 1: message segment compiler.err.invalid.mref=Ungültige {0}-Referenz\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=Doppelte Klasse: {0} # 0: string compiler.err.bad.file.name=Ungültiger Dateiname: {0} -compiler.err.implicit.class.should.not.have.package.declaration=Implizit deklarierte Klasse darf keine Packagedeklaration aufweisen +compiler.err.implicit.class.should.not.have.package.declaration=Kompakte Quelldatei darf keine Packagedeklaration aufweisen -compiler.err.implicit.class.does.not.have.main.method=Implizit deklarierte Klasse weist keine Hauptmethode im Format "void main()" oder "void main(String[] args)" auf +compiler.err.implicit.class.does.not.have.main.method=Kompakte Quelldatei weist keine Hauptmethode im Format "void main()" oder "void main(String[] args)" auf # 0: name, 1: name compiler.err.same.binary.name=Klassen {0} und {1} haben denselben binären Namen @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=Unzulässige Kombination aus Modif compiler.err.illegal.enum.static.ref=Unzulässige Referenz zu statischem Feld aus Initializer +compiler.err.illegal.char.literal.multiple.surrogates=Zeichenliteral enthält mehrere UTF-16-Codeeinheiten + compiler.err.illegal.esc.char=Unzulässiges Escapezeichen compiler.err.illegal.forward.ref=Unzulässige Vorwärtsreferenz @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0} ist in Profil "{1}" nicht verfügbar # 0: symbol compiler.warn.forward.ref=Referenz zu Variable "{0}", bevor sie initialisiert wurde +# lint: this-escape compiler.warn.possible.this.escape=Mögliches "this"-Escape vor vollständiger Initialisierung der Unterklasse +# lint: this-escape compiler.warn.possible.this.escape.location=Vorheriges mögliches "This"-Escape erfolgt hier per Aufruf compiler.err.illegal.self.ref=Selbstreferenz in Initializer @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=Unzulässiges Zeilenende in Zeichenlit compiler.err.illegal.text.block.open=Unzulässige Sequenz für Öffnungstrennzeichen von Textblock. Zeilenabschlusszeichen fehlt +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=Inkonsistenter Leerzeicheneinzug +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=Nachgestelltes Leerzeichen wird entfernt compiler.err.illegal.nonascii.digit=Unzulässige Nicht-ASCII-Ziffer @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file=Lesen nicht möglich: {0} compiler.err.plugin.not.found=Plug-in nicht gefunden: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=Unbekannte Datei in Modulpfad: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar=Modulname für {0} kann nicht bes compiler.err.multi-module.outdir.cannot.be.exploded.module=Im Modus für mehrere Module kann das Ausgabeverzeichnis kein entpacktes Modul sein: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=Das Ausgabeverzeichnis befindet sich in einem entpackten Modul: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=Runde {0}:\n\tEingabedateien: {1}\n\tAnnotationen: compiler.warn.file.from.future=Änderungsdatum liegt in der Zukunft für Datei {0} # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=Ausgabedatei mehrmals geschrieben: {0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=Warnung:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUID muss Konstante in Klasse {0} sein +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=Dokumentationskommentar ist an keine Deklaration angehängt # 0: path +# lint: path compiler.warn.dir.path.element.not.found=Ungültiges Pfadelement "{0}": Verzeichnis nicht vorhanden # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=Ungültiges Pfadelement "{0}": kein Verzeichnis # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=Klasse {0} in exportiertem Package {1} deklariert keine expliziten Konstruktoren und stellt daher einen Standardkonstruktor für Clients des Moduls {2} bereit +# lint: strictfp compiler.warn.strictfp=Ab Release 17 werden alle Gleitkommaausdrücke streng ausgewertet. Daher ist "strictfp" nicht erforderlich +# lint: finally compiler.warn.finally.cannot.complete=Finally-Klausel kann nicht normal abgeschlossen werden # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=Modulnamenskomponente {0} darf keine Ziffern am Ende enthalten # 0: string +# lint: incubating compiler.warn.incubating.modules=Inkubatormodul(e) verwendet: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={0} in {1} ist veraltet # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={0} in {1} ist veraltet und wurde zum Entfernen markiert # 0: symbol +# lint: preview compiler.warn.is.preview={0} ist eine Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol compiler.err.is.preview={0} ist eine Vorschau-API, die standardmäßig deaktiviert ist.\n(Verwenden Sie --enable-preview, um Vorschau-APIs zu aktivieren) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0} ist eine reflektive Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1} ist eine eingeschränkte Methode.\n(Eingeschränkte Methoden sind nicht sicher und können bei falscher Verwendung die JRE zum Absturz bringen oder den Arbeitsspeicher beschädigen) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=Modul {0} ist veraltet # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=Modul {0} ist veraltet und wurde zum Entfernen markiert # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0} ist eine interne proprietäre API, die in eine compiler.warn.illegal.char.for.encoding=Nicht zuordenbares Zeichen für Codierung {0} # 0: symbol +# lint: serial compiler.warn.improper.SVUID=serialVersionUID muss als "static final" in Klasse {0} deklariert sein +# lint: serial compiler.warn.improper.SPF=serialPersistentFields muss als "private static final" deklariert sein, um in Kraft zu treten +# lint: serial compiler.warn.SPF.null.init=serialPersistentFields tritt bei Initialisierung als Null nicht in Kraft.\nFühren Sie die Initialisierung zu einem leeren Array aus, um keine Felder anzugeben @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=Nicht erreichbare Catch-Klausel\nAusgelöster Ty compiler.warn.unreachable.catch.1=Nicht erreichbare Catch-Klausel\nAusgelöste Typen {0} wurden bereits abgefangen # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUID muss den Typ "long" in Klasse {0} aufweisen +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFields muss den Typ "java.io.ObjectStreamField[]" aufweisen, um in Kraft zu treten # 0: symbol +# lint: serial compiler.warn.missing.SVUID=Serialisierbare Klasse {0} enthält keine Definition von serialVersionUID # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=Zugriff auf einen no-arg-Konstruktor in der ersten nicht serialisierbaren Superklasse {0} nicht möglich # 0: name +# lint: serial compiler.warn.serial.method.not.private=Serialisierungsbezogene Methode {0} nicht als privat deklariert # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=Serialisierungsbezogene Methode {0} muss eine konkrete Instanzmethode sein, um in Kraft zu treten. Sie darf nicht abstrakt oder statisch sein # 0: name +# lint: serial compiler.warn.serial.method.static=Serialisierungsbezogene Methode {0} ist als statisch deklariert. Sie muss stattdessen eine Instanzmethode sein, um in Kraft zu treten. # 0: name +# lint: serial compiler.warn.serial.method.no.args=Serialisierungsbezogene Methode {0} darf keine Parameter aufweisen, um in Kraft zu treten # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=Serialisierungsbezogene Methode {0} muss genau einen Parameter aufweisen, um in Kraft zu treten. Sie darf nicht {1} Parameter enthalten # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=Der einzige Parameter der serialisierungsbezogenen Methode {0} muss den Typ {1} haben, um in Kraft zu treten. Er darf nicht den Typ {2} aufweisen # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=Serialisierungsbezogene Methode {0} wurde mit dem Rückgabetyp {1} und nicht dem erwarteten Typ {2} deklariert.\nMit dieser Deklaration ist die Methode ungültig für die Serialisierung # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=Serialisierungsbezogene Methode {0} wurde zum Auslösen eines unerwarteten Typs {1} deklariert +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFields ist in einer Schnittstelle nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=Serialisierungsbezogenes Feld {0} ist in einer Enum-Klasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=Serialisierungsbezogene Methode {0} ist in einer Enum-Klasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=Externalisierungsbezogene Methode {0} ist in einer Enum-Klasse nicht effektiv +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFields ist in einer Datensatzklasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=Serialisierungsbezogene Methode {0} ist in einer Datensatzklasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=Externalisierungsbezogene Methode {0} ist in einer Datensatzklasse nicht effektiv # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=Serialisierungsbezogene Methode {0} ist in einer externalisierbaren Klasse nicht effektiv +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields ist in einer externalisierbaren Klasse nicht effektiv +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=Eine externalisierbare Klasse erfordert einen öffentlichen no-arg-Konstruktor +# lint: serial compiler.warn.non.serializable.instance.field=Nicht transientes Instanzfeld einer serialisierbaren Klasse mit einem nicht serialisierbaren Typ deklariert # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=Nicht transientes Instanzfeld einer serialisierbaren Klasse wurde mit einem Array mit einem nicht serialisierbaren Basiskomponententyp {0} deklariert +# lint: serial compiler.warn.non.private.method.weaker.access=Serialisierungsbezogene Methode, die in einer Schnittstelle als nicht privat deklariert ist, verhindert,\ndass Klassen, die die Schnittstelle implementieren, die Methode als privat deklarieren +# lint: serial compiler.warn.default.ineffective=Serialisierungsbezogene Standardmethode aus einer Schnittstelle wird nicht von der Serialisierung für eine implementierende Klasse ausgeführt # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={0} in {1} ist möglicherweise mehrdeutig mit {2} in {3} # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}. Außer Kraft gesetzte Methode umfasst kein "..." # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}. In außer Kraft setzender Methode fehlt "..." # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}. Außer Kraft setzende Methode ist eine Bridge compiler.warn.pkg-info.already.seen=Die Datei package-info.java wurde bereits für Package {0} gefunden # 0: path +# lint: path compiler.warn.path.element.not.found=Ungültiges Pfadelement "{0}": Datei oder Verzeichnis nicht vorhanden +# lint: fallthrough compiler.warn.possible.fall-through.into.case=Möglicher Fallthrough in Case # 0: type +# lint: cast compiler.warn.redundant.cast=Redundantes Casting in {0} # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: Hauptversion {1} ist neuer als {2}, die hö compiler.warn.invalid.utf8.in.classfile={0}: Klassendatei enthält ungültige UTF-8-Codierung: {1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=Statische {0} muss mit Typname {1} anstelle eines Ausdrucks qualifiziert werden # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2={0} (statisch) darf nicht als Member einer anonymen Klasse verwendet werden # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=Bootstrap Classpath ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=Systemmodulpfad ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=Wenn Sie den Bootstrap Classpa compiler.misc.source.no.system.modules.path.with.target=Wenn Sie den Speicherort der Systemmodule nicht festlegen, kann dies zu Klassendateien führen, die auf JDK {0} nicht ausgeführt werden können\n--release {0} wird anstelle von -source {0} -target {1} empfohlen, weil dadurch der Speicherort der Systemmodule automatisch festgelegt wird # 0: string +# lint: options compiler.warn.option.obsolete.source=Quellwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: target +# lint: options compiler.warn.option.obsolete.target=Zielwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=Quelloption {0} wird nicht mehr unterstützt. # 0: target, 1: target compiler.err.option.removed.target=Zieloption {0} wird nicht mehr unterstützt. Verwenden Sie {1} oder höher. +# lint: options compiler.warn.option.obsolete.suppression=Verwenden Sie -Xlint:-options, um Warnungen zu veralteten Optionen zu unterdrücken. # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr={0}-Attribut, das in Klassendateien der Version {1}.{2} eingeführt wurde, wird in Klassendateien der Version {3}.{4} ignoriert +# lint: requires-automatic compiler.warn.requires.automatic=Erfordert Direktive für ein automatisches Modul +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=Erfordert transitive-Direktive für ein automatisches Modul # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=Erfordert transitive-Direktive für compiler.warn.proc.package.does.not.exist=Package {0} ist nicht vorhanden # 0: string +# lint: processing compiler.warn.proc.file.reopening=Versuch, mehrmals eine Datei für "{0}" zu erstellen # 0: string +# lint: processing compiler.warn.proc.type.already.exists=Es ist bereits eine Datei für Typ "{0}" im Quellpfad oder Classpath vorhanden # 0: string +# lint: processing compiler.warn.proc.type.recreate=Versuch, mehrmals eine Datei für Typ "{0}" zu erstellen # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=Datei kann nicht für unzulässigen Namen "{0}" erstellt werden. # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=Datei für einen Typ, dessen Name mit {1} endet, wird erstellt: "{0}" # 0: string compiler.warn.proc.file.create.last.round=Datei für Typ "{0}", die in der letzten Runde erstellt wurde, wird keiner Annotationsverarbeitung unterzogen. # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=Nicht wohlgeformte Zeichenfolge "{0}" für eine unterstützte Annotationsschnittstelle von Prozessor "{1}" zurückgegeben # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=Diese Annotationen wurden von keinem Prozessor beansprucht: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=Unterstützte Quellversion "{0}" von Annotationsprozessor "{1}" kleiner als -source "{2}" # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=Doppelte unterstützte Option "{0}" von Annotationsprozessor "{1}" zurückgegeben # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=Doppelte unterstützte Annotationsschnittstelle "{0}" von Annotationsprozessor "{1}" zurückgegeben # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=Annotationsprozessor "{0}" unterstützt redundant sowohl "*" als auch andere Annotationsschnittstellen compiler.warn.proc.proc-only.requested.no.procs=Annotationsverarbeitung ohne Kompilierung angefordert, aber keine Prozessoren gefunden. @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=Nicht geschlossene Dateien für die Typen # 0: string compiler.warn.proc.unmatched.processor.options=Die folgenden Optionen wurden von keinem Prozessor erkannt: "{0}" +# lint: try compiler.warn.try.explicit.close.call=Expliziter Aufruf von close() für eine automatisch schließbare Ressource # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=Automatisch schließbare Ressource {0} wird nie im Body der entsprechenden try-Anweisung referenziert # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=Automatisch schließbare Ressource {0} umfasst die Mitgliedsmethode close(), die InterruptedException auslösen könnte +# lint: unchecked compiler.warn.unchecked.assign=Nicht geprüfte Zuweisung: {0} zu {1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=Nicht geprüfte Zuweisung zu Variable {0} als Mitglied des Raw-Typs {1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=Nicht geprüfter Aufruf von {0} als Mitglied des Raw-Typs {1} +# lint: unchecked compiler.warn.unchecked.cast.to.type=Nicht geprüftes Casting zu Typ {0} # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=Nicht geprüfter Methodenaufruf: {0} {1} in {4} {5} wird auf die angegebenen Typen angewendet\nErforderlich: {2}\nErmittelt: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=Nicht geprüfte Erstellung eines generischen Arrays für varargs-Parameter des Typs {0} # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=Möglich Heap-Beschädigung aus parametrisiertem vararg-Typ {0} # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=Varargs-Methode könnte Heap-Beschädigung aus nicht reifizierbarem varargs-Parameter {0} verursachen +# lint: dep-ann compiler.warn.missing.deprecated.annotation=Veraltetes Element ist nicht mit @Deprecated-Annotation versehen # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated-Annotation hat keine Auswirkung auf diese {0}-Deklaration # 0: string +# lint: path compiler.warn.invalid.path=Ungültiger Dateiname: {0} compiler.warn.doclint.not.available=Kein Serviceprovider für doclint verfügbar @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=Ungültiger Dateiname: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=Unerwartete Datei in Pfad: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=Unerwartete Erweiterung für Archivdatei: {0} # 0: path compiler.err.no.zipfs.for.archive=Kein Dateisystemprovider zur Verarbeitung dieser Datei verfügbar: {0} +# lint: divzero compiler.warn.div.zero=Division durch Null +# lint: empty compiler.warn.empty.if=Leere Anweisung nach "if" # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden: {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=Unbekannte Enum-Konstante {1}.{2} compiler.warn.unknown.enum.constant.reason=Unbekannte Enum-Konstante {1}.{2}\nGrund: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=Raw-Typ gefunden: {0}\nTypargumente für generische Klasse {1} fehlen compiler.warn.diamond.redundant.args=Redundante Typargumente in neuem Ausdruck (verwenden Sie stattdessen den Rautenoperator). @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=Die Erstellung dieser anonymen inneren Klas compiler.warn.method.redundant.typeargs=Redundante Typargumente in Methodenaufruf. # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno=Redundante {0}-Annotation. {1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=Zugriff auf Mitglied {0} aus serialisierbarem Element kann öffentlich für nicht vertrauenswürdigen Code zugänglich sein # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=Zugriff auf Mitglied {0} aus serialisierbarem Lambda kann öffentlich für nicht vertrauenswürdigen Code zugänglich sein ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class=Ungültige einschließende Klasse für {0}: {1 compiler.misc.bad.enclosing.method=Ungültiges einschließendes Methodenattribut für Klasse {0} # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch=Die Längen der Parameter im RuntimeVisibleParameterAnnotations-Attribut und RuntimeInvisibleParameterAnnotations-Attribut in {0} stimmen nicht überein. Beide Attribute werden ignoriert # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations=Die Attribute RuntimeVisibleParameterAnnotations und RuntimeInvisibleParameterAnnotations in {0} können nicht den Parametern der Methode zugeordnet werden compiler.misc.bad.const.pool.tag=Ungültiges Konstantenpooltag: {0} @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=Inkompatible Typen: {0} compiler.misc.prob.found.req=Inkompatible Typen: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0} kann nicht in {1} konvertiert werden compiler.misc.possible.loss.of.precision=Möglicher Verlust bei Konvertierung von {0} in {1} # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=Möglicher Verlust eines impliziten Cast von {0} bis {1} in zusammengesetzter Zuweisung compiler.misc.unchecked.assign=Nicht geprüfte Konvertierung @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=Keine übereinstimmenden varargs; {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file=Auf Auxiliary-Klasse {0} in {1} darf nicht von außerhalb der eigenen Quelldatei zugegriffen werden ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\nVersuch, niedrigere Zugriffsberechtigun compiler.err.override.incompatible.ret={0}\nRückgabetyp {1} ist nicht mit {2} kompatibel # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\nRückgabetyp erfordert eine nicht geprüfte Konvertierung von {1} in {2} # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\nAußer Kraft gesetzte Methode löst nicht {1} aus # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=Klasse {0} setzt Gleichwertige außer Kraft. hashCode-Methode wird aber weder von der Klasse noch einer Superklasse außer Kraft gesetzt ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0} sind ein Vorschaufeature, das s compiler.err.preview.feature.disabled.classfile=Klassendatei für {0} verwendet Vorschaufeatures von Java SE {1}.\n(Verwenden Sie --enable-preview, um das Laden von Klassendateien mit Vorschaufeatures zu ermöglichen) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0} ist ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0} sind ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile=Klassendatei für {0} verwendet Vorschaufeatures von Java SE {1}. compiler.misc.feature.modules=Module @@ -2515,6 +2630,7 @@ compiler.err.expected.module="module" erwartet compiler.err.module.not.found=Modul nicht gefunden: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=Modul nicht gefunden: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=Der "no argum compiler.err.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} compiler.err.no.output.dir=Kein Klassenausgabeverzeichnis angegeben @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option=Ungültiger Name im Wert für {0}-Option: "{1} compiler.err.bad.name.for.option=Ungültiger Name im Wert für {0}-Option: "{1}" # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found=Modulname in {0}-Option nicht gefunden: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH kann nur beim Kompilieren des unbenannten Moduls oder beim Kompilieren im Kontext eines automatischen Moduls verwendet werden @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=Export eines Packages aus Systemmodul {0} # 0: symbol compiler.err.add.reads.with.release=Hinzufügen von Lese-Edges für Systemmodul {0} ist mit --release nicht zulässig +# lint: options compiler.warn.addopens.ignored=--add-opens hat zur Kompilierungszeit keine Auswirkungen compiler.misc.locn.module_source_path=Modulquellpfad @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=Modulbezeichner nicht zulässig: {0} compiler.warn.service.provided.but.not.exported.or.used=Serviceschnittstelle angegeben, aber nicht exportiert oder verwendet # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible={0} {1} in Modul {2} ist nicht zugänglich für Clients, die dieses Modul benötigen # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported={0} {1} in Modul {2} wird nicht exportiert # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive={0} {1} in Modul {2} wird nicht indirekt mit "requires transitive" exportiert # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified={0} {1} in Modul {2} ist möglichweise nicht für alle Clients, die dieses Modul benötigen, sichtbar ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=Darf keine Typvariablen enthalten: {0} compiler.misc.is.duplicated=Darf keine Duplikate enthalten: {0} # 0: type -compiler.misc.doesnt.extend.sealed=Unterklasse {0} muss verschlüsselte Klasse erweitern +compiler.misc.doesnt.extend.sealed=Klasse {0} muss verschlüsselte Klasse erweitern + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1} muss verschlüsselte Klasse erweitern compiler.misc.must.not.be.same.class=Unzulässige Selbstreferenz in PERMITS-Klausel @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=Dekonstruktionsmuster könne compiler.err.incorrect.number.of.nested.patterns=Falsche Anzahl verschachtelter Muster\nErforderlich: {0}\nGefunden: {1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zukünftigen Release entfernt werden kann. +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=Versuch der Synchronisierung für eine Instanz einer wertbasierten Klasse +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=Verwendung einer wertbasierten Klasse mit einem Vorgang, der eine zuverlässige Identität erwartet + # 0: type compiler.err.enclosing.class.type.non.denotable=Einschließender Klassentyp: {0}\nist nicht deklarierbar. Führen Sie das Casting in einen deklarierbaren Typ aus diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 9ab2862407f..aa501fd6c11 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst={0}の機能インタフェース compiler.misc.bad.intersection.target.for.functional.expr=ラムダまたはメソッド参照の交差タイプ・ターゲットが不正です\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=コンポーネント・タイプ{0}はインタフェースではありません +compiler.misc.not.an.intf.component=コンポーネント・タイプ{0}はインタフェースまたはjava.lang.Objectではありません # 0: kind name, 1: message segment compiler.err.invalid.mref={0}参照が無効です\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=クラス{0}が重複しています # 0: string compiler.err.bad.file.name=不正なファイル名: {0} -compiler.err.implicit.class.should.not.have.package.declaration=暗黙的に宣言されたクラスにパッケージ宣言を含めることはできません +compiler.err.implicit.class.should.not.have.package.declaration=コンパクト・ソース・ファイルにパッケージ宣言を含めることはできません -compiler.err.implicit.class.does.not.have.main.method=暗黙的に宣言されたクラスにvoid main()またはvoid main(String[] args)という形式のmainメソッドがありません +compiler.err.implicit.class.does.not.have.main.method=コンパクト・ソース・ファイルにvoid main()またはvoid main(String[] args)という形式のmainメソッドがありません # 0: name, 1: name compiler.err.same.binary.name=クラス: {0}と{1}のバイナリ名が同じです @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=修飾子{0}と{1}の組合せは compiler.err.illegal.enum.static.ref=初期化子からstaticフィールドへの参照が不正です +compiler.err.illegal.char.literal.multiple.surrogates=文字リテラルに複数のUTF-16コード・ユニットが含まれています + compiler.err.illegal.esc.char=エスケープ文字が不正です compiler.err.illegal.forward.ref=前方参照が不正です @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0}はプロファイル''{1}''で使用できませ # 0: symbol compiler.warn.forward.ref=初期化される前の変数''{0}''を参照しようとしました +# lint: this-escape compiler.warn.possible.this.escape=サブクラスが初期化される前の''this''エスケープの可能性があります +# lint: this-escape compiler.warn.possible.this.escape.location=事前の''this''エスケープはこの呼び出しで出現する可能性があります compiler.err.illegal.self.ref=初期化子内の自己参照 @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=文字リテラルの行末が不正 compiler.err.illegal.text.block.open=テキスト・ブロックの開始区切り文字のシーケンスが無効です。行の終了文字がありません +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=空白のインデントに一貫性がありません +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=末尾の空白は除去されます compiler.err.illegal.nonascii.digit=不正な非ASCII数字です @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file={0}を読み込めません compiler.err.plugin.not.found=プラグインが見つかりません: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=モジュール・パスのファイルが不明です: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar={0}のモジュール名を判別 compiler.err.multi-module.outdir.cannot.be.exploded.module=複数モジュール・モードで、出力ディレクトリは展開したモジュールにすることはできません: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=出力ディレクトリは展開したモジュール内です: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=往復{0}:\n\t入力ファイル: {1}\n\t注釈: {2 compiler.warn.file.from.future=ファイル{0}の変更日が将来の日付です # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=出力ファイルへの書込みが複数回ありました: {0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=警告:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUIDはクラス{0}の定数である必要があります +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=どの宣言にもドキュメンテーション・コメントが添付されていません # 0: path +# lint: path compiler.warn.dir.path.element.not.found=不正なパス要素"{0}": そのディレクトリは存在しません # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=不正なパス要素"{0}": ディレクトリは存在しません # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=エクスポートされたパッケージ{1}のクラス{0}は明示的なコンストラクタを宣言しないため、デフォルト・コンストラクタをモジュール{2}のクライアントに公開します +# lint: strictfp compiler.warn.strictfp=リリース17以降、すべての浮動小数点式は厳密に評価され、''strictfp''は必要ありません +# lint: finally compiler.warn.finally.cannot.complete=finally節が正常に完了できません # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=モジュール名コンポーネント{0}の末尾は数字にしないでください # 0: string +# lint: incubating compiler.warn.incubating.modules=実験的なモジュールを使用しています: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={1}の{0}は推奨されません # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={1}の{0}は推奨されておらず、削除用にマークされています # 0: symbol +# lint: preview compiler.warn.is.preview={0}はプレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol compiler.err.is.preview={0}はプレビューAPIであり、デフォルトで無効になっています。\n(プレビューAPIを有効にするには--enable-previewを使用します) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0}はリフレクティブ・プレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1}は制限されたメソッドです。\n(制限されたメソッドは安全ではありません。不適切に使用した場合、Javaランタイムがクラッシュまたはメモリーが破損する場合があります) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=モジュール{0}は推奨されません # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=モジュール{0}は推奨されておらず、削除用にマークされています # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0}は内部所有のAPIであり、今後のリ compiler.warn.illegal.char.for.encoding=この文字は、エンコーディング{0}にマップできません # 0: symbol +# lint: serial compiler.warn.improper.SVUID=serialVersionUIDは、クラス{0}にstatic finalを宣言する必要があります +# lint: serial compiler.warn.improper.SPF=serialPersistentFieldsを有効にするには、private static finalとして宣言する必要があります +# lint: serial compiler.warn.SPF.null.init=nullに初期化するとserialPersistentFieldsは無効になります。\nフィールドがないことを示すには、空の配列に初期化します @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=catch句に移すことができません\nス compiler.warn.unreachable.catch.1=catch句に移すことができません\nスローされたタイプ{0}はすでに捕捉されています # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUIDは、クラス{0}のlong型である必要があります +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFieldsを有効にするには、タイプをjava.io.ObjectStreamField[]にする必要があります # 0: symbol +# lint: serial compiler.warn.missing.SVUID=直列化可能なクラス{0}には、serialVersionUIDが定義されていません # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=シリアライズ不可のスーパークラス{0}で引数なしのコンストラクタにアクセスできません # 0: name +# lint: serial compiler.warn.serial.method.not.private=シリアライズ関連メソッド{0}はprivateとして宣言されていません # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=シリアライズ関連メソッド{0}を有効にするには、concreteインスタンス・メソッドである必要があります。abstractでもstaticでもありません # 0: name +# lint: serial compiler.warn.serial.method.static=シリアライズ関連メソッド{0}がstaticとして宣言されています。有効にするには、かわりにインスタンス・メソッドにする必要があります # 0: name +# lint: serial compiler.warn.serial.method.no.args=有効にするには、シリアライズ関連メソッド{0}にパラメータを指定しないでください # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=有効にするには、シリアライズ関連メソッド{0}に、{1}のパラメータではなく、パラメータを1つのみ指定する必要があります # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=有効にするには、シリアライズ関連メソッド{0}の1つのパラメータに、型{2}ではなく、型{1}を指定する必要があります # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=シリアライズ関連メソッド{0}は、必要な型{2}ではなく、{1}の戻り型で宣言されています。\n宣言されているように、メソッドはシリアライズが無効になります # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=シリアライズ関連メソッド{0}は予期しない型{1}をスローするように宣言されています +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFieldsはインタフェースで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=シリアライズ関連フィールド{0}は列挙クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=シリアライズ関連メソッド{0}は列挙クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=外部化関連メソッド{0}は列挙クラスで有効ではありません +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFieldsはレコード・クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=シリアライズ関連メソッド{0}はレコード・ラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=外部化関連メソッド{0}はレコード・クラスで有効ではありません # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=シリアライズ関連メソッド{0}は外部化可能なクラスで有効ではありません +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFieldsは外部化可能なクラスで有効ではありません +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=外部化可能なクラスには引数なしでパブリックのコンストラクタが必要です +# lint: serial compiler.warn.non.serializable.instance.field=直列化可能なクラスの常駐インスタンス・フィールドは直列不可タイプで宣言されています # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=直列化可能なクラスの常駐インスタンス・フィールドは、直列不可のベース・コンポーネント・タイプ{0}を持つ配列で宣言されています +# lint: serial compiler.warn.non.private.method.weaker.access=インタフェースでprivateとして宣言されたシリアライズ関連メソッドによって、\nそのインタフェースを実装するクラスがメソッドをprivateとして宣言できなくなります +# lint: serial compiler.warn.default.ineffective=インタフェースのシリアライズ関連のデフォルト・メソッドは、クラスを実装するためのシリアライズで実行されません # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={1}内の{0}は{3}内の{2}と矛盾する可能性があります # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}。オーバーライドされたメソッドには''...''がありません # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}。オーバーライドしているメソッドには''...''がありません # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}。オーバーライドされたメソッド compiler.warn.pkg-info.already.seen=package-info.javaファイルがすでにパッケージ{0}用に表示されています # 0: path +# lint: path compiler.warn.path.element.not.found=不正なパス要素"{0}": そのファイルまたはディレクトリはありません +# lint: fallthrough compiler.warn.possible.fall-through.into.case=caseにfall-throughする可能性があります # 0: type +# lint: cast compiler.warn.redundant.cast={0}への冗長なキャストです # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: メジャー・バージョン{1}は、こ compiler.warn.invalid.utf8.in.classfile={0}: クラス・ファイルに無効なUTF-8が含まれています: {1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=static {0}は式ではなく型名{1}で修飾する必要があります # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2=static {0}を匿名クラスのメンバーとして使用しないでください # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=ブートストラップ・クラス・パスが-source {0}と一緒に設定されていません\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=システム・モジュールの場所が-source {0}と一緒に設定されていません\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=ブートストラップ・ク compiler.misc.source.no.system.modules.path.with.target=システム・モジュールの場所を設定しないと、クラス・ファイルがJDK {0}で実行できない場合があります\nシステム・モジュールの場所を自動的に設定するため、-source {0} -target {1}のかわりに--release {0}をお薦めします # 0: string +# lint: options compiler.warn.option.obsolete.source=ソース値{0}は廃止されていて、今後のリリースで削除される予定です # 0: target +# lint: options compiler.warn.option.obsolete.target=ターゲット値{0}は廃止されていて、今後のリリースで削除される予定です # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=ソース・オプション{0}は現在サポ # 0: target, 1: target compiler.err.option.removed.target=ターゲット・オプション{0}は現在サポートされていません。{1}以降を使用してください。 +# lint: options compiler.warn.option.obsolete.suppression=廃止されたオプションについての警告を表示しないようにするには、-Xlint:オプションを使用します。 # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr=バージョン{1}.{2}のクラス・ファイルで導入された{0}属性は、バージョン{3}.{4}のクラス・ファイルでは無視されます +# lint: requires-automatic compiler.warn.requires.automatic=自動モジュールにはディレクティブが必要です +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=自動モジュールには推移的ディレクティブが必要です # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=自動モジュールには推移的 compiler.warn.proc.package.does.not.exist=パッケージ{0}は存在しません # 0: string +# lint: processing compiler.warn.proc.file.reopening=''{0}''用のファイルを複数回作成しようとしています # 0: string +# lint: processing compiler.warn.proc.type.already.exists=タイプ''{0}''のファイルはすでにソース・パスまたはクラスパスに存在します # 0: string +# lint: processing compiler.warn.proc.type.recreate=タイプ''{0}''のファイルを複数回作成しようとしています # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=無効な名前''{0}''のファイルは作成できません。 # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=名前が{1}で終わる型のファイルを作成しています: ''{0}'' # 0: string compiler.warn.proc.file.create.last.round=最後に作成されたタイプ''{0}''のファイルは注釈処理に渡されません。 # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=プロセッサ''{1}''が返したサポートされる注釈インタフェースの文字列''{0}''が不正です # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=これらの注釈を要求するプロセッサはありませんでした: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=注釈プロセッサ''{1}''から-source ''{2}''より小さいソース・バージョン''{0}''がサポートされています # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=重複するサポート対象オプション''{0}''が注釈プロセッサ''{1}''によって返されました # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=重複するサポート対象注釈インタフェース''{0}''が注釈プロセッサ''{1}''によって返されました # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=注釈プロセッサ''{0}''は''*''と他の注釈インタフェースを重複してサポートします compiler.warn.proc.proc-only.requested.no.procs=コンパイルなしの注釈処理がリクエストされましたが、プロセッサが見つかりませんでした。 @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=タイプ''{0}''のファイルが閉じ # 0: string compiler.warn.proc.unmatched.processor.options=次のオプションはどのプロセッサでも認識されませんでした: ''{0}'' +# lint: try compiler.warn.try.explicit.close.call=自動クローズ可能なリソースにおけるclose()の明示的呼出し # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=自動クローズ可能なリソース{0}は対応するtry文の本体では参照されません # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=自動クローズ可能なリソース{0}に、InterruptedExceptionをスローする可能性があるメンバー・メソッドclose()があります +# lint: unchecked compiler.warn.unchecked.assign={0}から{1}への無検査代入です # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=raw型{1}のメンバーとして変数{0}への無検査代入です # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=raw型{1}のメンバーとしての{0}への無検査呼出しです +# lint: unchecked compiler.warn.unchecked.cast.to.type=型{0}への無検査キャストです # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=無検査メソッド呼出し: {4} {5}の{0} {1}は指定された型に適用されます\n期待値: {2}\n検出値: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=型{0}の可変引数パラメータに対する総称型配列の無検査作成です # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=パラメータ化された可変引数型{0}からのヒープ汚染の可能性があります # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=可変引数メソッドは、型情報保持可能でない可変引数パラメータ{0}からのヒープ汚染の原因となる可能性があります +# lint: dep-ann compiler.warn.missing.deprecated.annotation=推奨されない項目は@Deprecatedで注釈が付けられていません # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated注釈は、この{0}宣言には影響しません # 0: string +# lint: path compiler.warn.invalid.path=ファイル名が無効です: {0} compiler.warn.doclint.not.available=使用可能なdoclintのサービス・プロバイダはありません @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=ファイル名が無効です: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=パス上の予期しないファイル: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=アーカイブ・ファイルの予期しない拡張子: {0} # 0: path compiler.err.no.zipfs.for.archive=このファイルの処理に使用できるファイル・システム・プロバイダがありません: {0} +# lint: divzero compiler.warn.div.zero=ゼロで除算 +# lint: empty compiler.warn.empty.if=if以降が空の文です # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=タイプ''{0}''内に注釈メソッド''{1}()''が見つかりません # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=タイプ''{0}''内に注釈メソッド''{1}()''が見つかりません: {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=不明な列挙型定数です{1}.{2} compiler.warn.unknown.enum.constant.reason=不明な列挙型定数です{1}.{2}\n理由: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=raw型が見つかりました: {0}\n汎用クラス{1}の型引数がありません compiler.warn.diamond.redundant.args=新しい式の型引数が重複しています(かわりにダイヤモンド演算子を使用します)。 @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=この匿名内部クラスをラムダ式 compiler.warn.method.redundant.typeargs=メソッド呼出しの型引数が重複しています。 # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno={0}注釈が冗長です。{1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=直列化可能要素からメンバー{0}へのアクセスは、信頼できないコードからパブリックにアクセス可能である可能性があります # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=直列化可能ラムダからメンバー{0}へのアクセスは、信頼できないコードからパブリックにアクセス可能である可能性があります ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class={0}の内部クラスが不正です: {1} compiler.misc.bad.enclosing.method=クラス{0}の囲んでいるメソッド属性が不正です # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0}内のRuntimeVisibleParameterAnnotations属性およびRuntimeInvisibleParameterAnnotations属性内のパラメータの長さが一致しません。両方の属性を無視します # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations={0}内のRuntimeVisibleParameterAnnotationsおよびRuntimeInvisibleParameterAnnotations属性をメソッドのパラメータにマップできません compiler.misc.bad.const.pool.tag=定数プール・タグ{0}が不正です @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=不適合な型: {0} compiler.misc.prob.found.req=不適合な型: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\n期待値: {2}\n検出値: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0}を{1}に変換できません: compiler.misc.possible.loss.of.precision=精度が失われる可能性がある{0}から{1}への変換 # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=複合代入における{0}から{1}への暗黙的キャストは、精度が失われる可能性があります compiler.misc.unchecked.assign=無検査変換 @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=可変引数の不一致: {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file={1}の補助クラス{0}にソース・ファイル外からアクセスできません ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\n({1})より弱いアクセス権限を compiler.err.override.incompatible.ret={0}\n戻り値の型{1}は{2}と互換性がありません # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\n戻り値の型は{1}から{2}への無検査変換が必要です # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\nオーバーライドされたメソッドは{1}をスローしません # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=クラス{0}はequalsをオーバーライドしますが、このクラスも、また、いかなるスーパークラスも、hashCodeメソッドをオーバーライドしません ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0}はプレビュー機能であ compiler.err.preview.feature.disabled.classfile={0}のクラス・ファイルはJava SE {1}のプレビュー機能を使用します。\n(プレビュー機能を含むクラス・ファイルをロードできるようにするには、--enable-previewを使用します) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile={0}のクラス・ファイルはJava SE {1}のプレビュー機能を使用します。 compiler.misc.feature.modules=モジュール @@ -2515,6 +2630,7 @@ compiler.err.expected.module=''モジュール''が必要です compiler.err.module.not.found=モジュールが見つかりません: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=モジュールが見つかりません: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=サービス compiler.err.package.empty.or.not.found=パッケージは空であるか、または存在しません {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=パッケージは空であるか、または存在しません {0} compiler.err.no.output.dir=クラス出力ディレクトリが指定されていません @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option={0}オプションの値に含まれる名前 compiler.err.bad.name.for.option={0}オプションの値に含まれる名前が不正です: ''{1}'' # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found={0}オプション内にモジュール名が見つかりません: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATHは、名前のないモジュールのコンパイル時または自動モジュールのコンテキストでのコンパイル時のみ使用できます @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=システム・モジュール{0}からの # 0: symbol compiler.err.add.reads.with.release=システム・モジュール{0}の読取りエッジの追加は--releaseを指定して実行できません +# lint: options compiler.warn.addopens.ignored=--add-opensは、コンパイル時には無効です compiler.misc.locn.module_source_path=モジュール・ソース・パス @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=モジュール指定子は許可されま compiler.warn.service.provided.but.not.exported.or.used=サービス・インタフェースが指定されましたが、エクスポートまたは使用されていません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible=モジュール{2}の{0} {1}は、このモジュールを必要とするクライアントからアクセスできません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported=モジュール{2}の{0} {1}はエクスポートされません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive=モジュール{2}の{0} {1}は、''requires transitive''を使用して間接的にエクスポートされません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified=モジュール{2}の{0} {1}は、このモジュールを必要とするすべてのクライアントに表示されない可能性があります ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=型変数を含めることはできません: compiler.misc.is.duplicated=重複を含めることはできません: {0} # 0: type -compiler.misc.doesnt.extend.sealed=サブクラス{0}はシール・クラスを拡張する必要があります +compiler.misc.doesnt.extend.sealed=クラス{0}はシール・クラスを拡張する必要があります + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1}はシール・インタフェースを拡張する必要があります compiler.misc.must.not.be.same.class=permits句の自己参照が不正です @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=デコンストラクショ compiler.err.incorrect.number.of.nested.patterns=ネスト・パターンの数が正しくありません\n期待値: {0}\n検出値: {1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1}はプレビュー機能を使用して宣言されており、今後のリリースで削除される可能性があります。 +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=値ベース・クラスのインスタンスで同期しようとしました +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=信頼できるアイデンティティを必要とする操作での値ベース・クラスの使用 + # 0: type compiler.err.enclosing.class.type.non.denotable=包含するクラス型: {0}\nは非型指定です。型指定型にキャストしてみてください diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 52a6ec23e51..d25110f6532 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst=无法推断{0}的函数接口描 compiler.misc.bad.intersection.target.for.functional.expr=lambda 或方法引用的交叉类型目标错误\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=组件类型{0}不是接口 +compiler.misc.not.an.intf.component=组件类型 {0} 不是接口或 java.lang.Object # 0: kind name, 1: message segment compiler.err.invalid.mref={0}引用无效\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=类重复: {0} # 0: string compiler.err.bad.file.name=文件名错误:{0} -compiler.err.implicit.class.should.not.have.package.declaration=隐式声明的类不应有程序包声明 +compiler.err.implicit.class.should.not.have.package.declaration=压缩源文件不应有程序包声明 -compiler.err.implicit.class.does.not.have.main.method=隐式声明的类没有 void main() 或 void main(String[] args) 形式的 main 方法 +compiler.err.implicit.class.does.not.have.main.method=压缩源文件没有 void main() 或 void main(String[] args) 形式的 main 方法 # 0: name, 1: name compiler.err.same.binary.name=类:{0} 和 {1} 具有相同的二进制名称 @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=非法的修饰符组合: {0}和{1 compiler.err.illegal.enum.static.ref=初始化程序中对静态字段的引用不合法 +compiler.err.illegal.char.literal.multiple.surrogates=字符文字包含多个 UTF-16 代码单元 + compiler.err.illegal.esc.char=非法逃逸 符 compiler.err.illegal.forward.ref=非法前向引用 @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0}在配置文件 ''{1}'' 中不可用 # 0: symbol compiler.warn.forward.ref=先引用变量 ''{0}'', 然后再对其初始化 +# lint: this-escape compiler.warn.possible.this.escape=可能在完全初始化子类之前逃逸了 ''this'' +# lint: this-escape compiler.warn.possible.this.escape.location=此处以前可能通过调用逃逸 了 ''this'' compiler.err.illegal.self.ref=初始化程序中存在自引用 @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=字符文字的行结尾不合法 compiler.err.illegal.text.block.open=文本块起始分隔符序列非法,缺少行终止符 +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=空格缩进不一致 +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=将删除尾随空格 compiler.err.illegal.nonascii.digit=非法的非 ASCII 数字 @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file=无法读取: {0} compiler.err.plugin.not.found=找不到插件: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=模块路径中的未知文件: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar=无法确定 {0} 的模块名称 compiler.err.multi-module.outdir.cannot.be.exploded.module=在多模块模式下, 输出目录不能是展开的模块: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=输出目录位于展开的模块中: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=循环 {0}:\n\t输入文件: {1}\n\t批注: {2}\n\t compiler.warn.file.from.future=文件 {0} 的修改日期是未来的日期 # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=多次写入输出文件:{0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=警告:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUID 在类{0}中必须是常量 +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=文档注释未附加到任何声明 # 0: path +# lint: path compiler.warn.dir.path.element.not.found=错误的路径元素 "{0}": 没有这种目录 # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=错误的路径元素 "{0}": 不是目录 # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=导出的程序包 {1} 中的类 {0} 未声明显式构造器,因此将向模块 {2} 的客户机公开默认构造器 +# lint: strictfp compiler.warn.strictfp=从发行版 17 开始,所有浮点表达式都经过严格计算,不需要 ''strictfp'' +# lint: finally compiler.warn.finally.cannot.complete=finally 子句无法正常完成 # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=模块名称组成部分 {0} 应避免以数字结尾 # 0: string +# lint: incubating compiler.warn.incubating.modules=使用 incubating 模块: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={1}中的{0}已过时 # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={1} 中的 {0} 已过时, 且标记为待删除 # 0: symbol +# lint: preview compiler.warn.is.preview={0} 是预览 API,可能会在未来发行版中删除。 # 0: symbol compiler.err.is.preview={0} 是预览 API,默认情况下处于禁用状态。\n(请使用 --enable-preview 以启用预览 API) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0} 是反射预览 API,可能会在未来发行版中删除。 # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1} 是受限制的方法。\n(受限制的方法不安全,如果使用不当,可能会导致 Java 运行时崩溃或内存损坏) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=模块 {0} 已过时 # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=模块 {0} 已过时, 且标记为待删除 # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0}是内部专用 API, 可能会在未来发行 compiler.warn.illegal.char.for.encoding=编码{0}的不可映射字符 # 0: symbol +# lint: serial compiler.warn.improper.SVUID=必须在类{0}中将 serialVersionUID 声明为 static final +# lint: serial compiler.warn.improper.SPF=serialPersistentFields 必须声明为 private static final 才能生效 +# lint: serial compiler.warn.SPF.null.init=serialPersistentFields 如果初始化为空值,则无效。\n请初始化为空数组以指示没有字段 @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=catch 子句无法访问\n已捕获到抛出的 compiler.warn.unreachable.catch.1=catch 子句无法访问\n已捕获到抛出的类型{0} # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUID 在类{0}中必须是 long 类型 +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFields 的类型必须为 java.io.ObjectStreamField[] 才能生效 # 0: symbol +# lint: serial compiler.warn.missing.SVUID=可序列化类{0}没有 serialVersionUID 的定义 # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=无法访问第一个不可序列化超类 {0} 中的无参数构造器 # 0: name +# lint: serial compiler.warn.serial.method.not.private=与序列化相关的方法 {0} 未声明为 private # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=与序列化相关的方法 {0} 必须是具体的实例方法才能生效,既不能是抽象方法也不能是静态方法 # 0: name +# lint: serial compiler.warn.serial.method.static=与序列化相关的方法 {0} 声明为 static;必须改为实例方法才能有效 # 0: name +# lint: serial compiler.warn.serial.method.no.args=与序列化相关的方法 {0} 必须没有参数才能生效 # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=与序列化相关的方法 {0} 必须只有一个参数(而非 {1} 个参数)才能生效 # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=与序列化相关的方法 {0} 的唯一参数的类型必须为 {1}(而非 {2})才能生效 # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=与序列化相关的方法 {0} 是用返回类型 {1}(而不是预期类型 {2})声明的。\n如声明的那样,该方法对序列化无效 # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=与序列化相关的方法 {0} 声明为抛出意外类型 {1} +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFields 在接口中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=与序列化相关的字段 {0} 在枚举类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=与序列化相关的方法 {0} 在枚举类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=与外部化相关的方法 {0} 在枚举类中无效 +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFields 在记录类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=与序列化相关的方法 {0} 在记录类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=与外部化相关的方法 {0} 在记录类中无效 # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=与序列化相关的方法 {0} 在可外部化的类中无效 +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields 在可外部化的类中无效 +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=可外部化的类需要一个公共的无参数构造器 +# lint: serial compiler.warn.non.serializable.instance.field=可序列化类的非瞬时实例字段是用不可序列化的类型声明的 # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=可序列化类的非瞬时实例字段是用具有不可序列化基本组件类型 {0} 的数组声明的 +# lint: serial compiler.warn.non.private.method.weaker.access=在接口中声明为 non-private 的序列化相关方法将阻止\n实现接口的类将方法声明为 private +# lint: serial compiler.warn.default.ineffective=实现类的序列化不会运行接口中与序列化相关的默认方法 # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={1} 中的 {0} 可能与 {3} 中的 {2} 混淆 # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}; 被覆盖的方法没有 ''...'' # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}; 覆盖的方法缺少 ''...'' # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}; 被覆盖的方法为 bridge 方法 compiler.warn.pkg-info.already.seen=已找到程序包{0}的 package-info.java 文件 # 0: path +# lint: path compiler.warn.path.element.not.found=错误的路径元素 "{0}": 没有这种文件或目录 +# lint: fallthrough compiler.warn.possible.fall-through.into.case=可能无法实现 case # 0: type +# lint: cast compiler.warn.redundant.cast=出现冗余的到{0}的转换 # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: 主版本 {1} 比 {2} 新, 此编译器支 compiler.warn.invalid.utf8.in.classfile={0}:类文件包含无效 UTF-8:{1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=static {0}应由类型名称{1}而不是表达式限定 # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2=static {0} 不应用作匿名类的成员 # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=未与 -source {0} 一起设置引导类路径\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=未与 -source {0} 一起设置系统模块的位置\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=不设置引导类路径可能 compiler.misc.source.no.system.modules.path.with.target=不设置系统模块的位置可能会导致类文件无法在 JDK {0} 上运行\n建议使用 --release {0} 而不是 -source {0} -target {1},因为它会自动设置系统模块的位置 # 0: string +# lint: options compiler.warn.option.obsolete.source=源值 {0} 已过时,将在未来发行版中删除 # 0: target +# lint: options compiler.warn.option.obsolete.target=目标值 {0} 已过时,将在未来发行版中删除 # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=不再支持源选项 {0}。请使用 {1} 或 # 0: target, 1: target compiler.err.option.removed.target=不再支持目标选项 {0}。请使用 {1} 或更高版本。 +# lint: options compiler.warn.option.obsolete.suppression=要隐藏有关已过时选项的警告, 请使用 -Xlint:-options。 # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr={1}.{2} 版类文件中引入的 {0} 属性在 {3}.{4} 版类文件中被忽略 +# lint: requires-automatic compiler.warn.requires.automatic=需要自动模块的指令 +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=需要自动模块的过渡指令 # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=需要自动模块的过渡指令 compiler.warn.proc.package.does.not.exist=程序包{0}不存在 # 0: string +# lint: processing compiler.warn.proc.file.reopening=尝试多次为 ''{0}'' 创建文件 # 0: string +# lint: processing compiler.warn.proc.type.already.exists=类型 ''{0}'' 的文件已经存在于源路径或类路径中 # 0: string +# lint: processing compiler.warn.proc.type.recreate=尝试多次创建类型 ''{0}'' 的文件 # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=无法创建带有非法名称 ''{0}'' 的文件。 # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=正在为名称以{1}结尾的类型创建文件: ''{0}'' # 0: string compiler.warn.proc.file.create.last.round=将不对在最后一个循环中创建的类型为 ''{0}'' 的文件进行批注处理。 # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=处理程序 ''{1}'' 为支持的批注接口返回格式错误的字符串 ''{0}'' # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=没有处理程序要使用以下任何批注: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=来自批注处理程序 ''{1}'' 的受支持 source 版本 ''{0}'' 低于 -source ''{2}'' # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=批注处理程序 ''{1}'' 返回重复的支持的选项 ''{0}'' # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=批注处理程序 ''{1}'' 返回重复的受支持批注接口 ''{0}'' # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=批注处理程序 ''{0}'' 重复支持 ''*'' 和其他批注接口 compiler.warn.proc.proc-only.requested.no.procs=在未请求编译的情况下进行批注处理, 但找不到处理程序。 @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=类型 ''{0}'' 的文件未关闭; 将不 # 0: string compiler.warn.proc.unmatched.processor.options=以下选项未被任何处理程序识别: ''{0}'' +# lint: try compiler.warn.try.explicit.close.call=在可自动结束的资源上显式调用 close() # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=不能在相应的 try 语句的正文中引用可自动结束的资源{0} # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=可自动关闭的资源{0}包含的成员方法 close() 可能抛出 InterruptedException +# lint: unchecked compiler.warn.unchecked.assign=未经检查的分配: 将{0}分配给{1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=对作为原始类型{1}的成员的变量{0}的分配未经过检查 # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=对作为原始类型{1}的成员的{0}的调用未经过检查 +# lint: unchecked compiler.warn.unchecked.cast.to.type=向类型{0}的转换未经过检查 # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=方法调用未经过检查: 将{4} {5}中的{0} {1}应用到给定的类型\n需要: {2}\n找到: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=对于类型为{0}的 varargs 参数, 泛型数组创建未经过检查 # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=参数化 vararg 类型{0}的堆可能已受污染 # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=Varargs 方法可能导致来自不可具体化 varargs 参数 {0} 的堆污染 +# lint: dep-ann compiler.warn.missing.deprecated.annotation=未使用 @Deprecated 对已过时的项目进行批注 # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated 批注对此 {0} 声明没有任何效果 # 0: string +# lint: path compiler.warn.invalid.path=无效文件名: {0} compiler.warn.doclint.not.available=没有 doclint 服务提供方可用 @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=无效文件名: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=以下路径中存在意外的文件: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=以下档案文件存在意外的扩展名: {0} # 0: path compiler.err.no.zipfs.for.archive=没有任何文件系统提供方可处理此文件: {0} +# lint: divzero compiler.warn.div.zero=除数为零 +# lint: empty compiler.warn.empty.if=if 之后没有语句 # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=无法找到类型 ''{0}'' 的批注方法 ''{1}()'' # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=无法找到类型 ''{0}'' 的批注方法 ''{1}()'': {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=未知的枚举常量 {1}.{2} compiler.warn.unknown.enum.constant.reason=未知的枚举常量 {1}.{2}\n原因: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=找到原始类型: {0}\n缺少泛型类{1}的类型参数 compiler.warn.diamond.redundant.args=新表达式中存在冗余类型参数 (改用 diamond 运算符)。 @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=可将此匿名内部类创建转换为 lam compiler.warn.method.redundant.typeargs=方法调用中存在冗余类型参数。 # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno=冗余的 {0} 批注。{1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=可串行化元素对成员 {0} 的访问可以由不受信任的代码公开执行 # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=可串行化 lambda 对成员 {0} 的访问可以由不受信任的代码公开执行 ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class={0}的封闭类错误: {1} compiler.misc.bad.enclosing.method=类 {0} 的封闭方法属性错误 # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0} 中 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性中的参数长度不匹配,将忽略这两个属性 # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations={0} 中的 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性无法映射到方法的参数 compiler.misc.bad.const.pool.tag=错误的常量池标记: {0} @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=不兼容的类型: {0} compiler.misc.prob.found.req=不兼容的类型: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\n需要: {2}\n找到: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0}无法转换为{1} compiler.misc.possible.loss.of.precision=从{0}转换到{1}可能会有损失 # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=在复合赋值中从 {0} 隐式转换为 {1} 可能会有损失 compiler.misc.unchecked.assign=未经检查的转换 @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=varargs 不匹配; {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file={1} 中的辅助类{0}不应从其自身的源文件以外访问 ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\n正在尝试分配更低的访问权限 compiler.err.override.incompatible.ret={0}\n返回类型{1}与{2}不兼容 # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\n返回类型需要从{1}到{2}的未经检查的转换 # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\n被覆盖的方法未抛出{1} # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=类{0}覆盖了 equals, 但该类或任何超类都未覆盖 hashCode 方法 ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0} 是预览功能,默认情况 compiler.err.preview.feature.disabled.classfile={0} 的类文件使用 Java SE {1} 的预览功能。\n(请使用 --enable-preview 以允许加载包含预览功能的类文件) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0} 是预览功能,可能会在未来发行版中删除。 # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0} 是预览功能,可能会在未来发行版中删除。 # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile={0} 的类文件使用 Java SE {1} 的预览功能。 compiler.misc.feature.modules=模块 @@ -2515,6 +2630,7 @@ compiler.err.expected.module=预期 ''module'' compiler.err.module.not.found=找不到模块: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=找不到模块: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=服务实现 compiler.err.package.empty.or.not.found=程序包为空或不存在: {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=程序包为空或不存在: {0} compiler.err.no.output.dir=未指定类输出目录 @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option={0} 选项的值中有错误的名称: ''{1}'' compiler.err.bad.name.for.option={0} 选项的值中有错误的名称: ''{1}'' # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found=找不到 {0} 选项中的模块名称: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH 只能在编译未命名模块或在自动模块的上下文中编译时使用 @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=不允许在使用 --release 时从系统 # 0: symbol compiler.err.add.reads.with.release=不允许在使用 --release 时为系统模块 {0} 添加读取维边: +# lint: options compiler.warn.addopens.ignored=--add-opens 在编译时没有任何效果 compiler.misc.locn.module_source_path=模块源路径 @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=不允许模块说明符: {0} compiler.warn.service.provided.but.not.exported.or.used=已提供服务接口, 但未导出或使用服务接口 # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible=模块 {2} 中的 {0} {1} 对需要该模块的客户机不可访问 # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported=未导出模块 {2} 中的 {0} {1} # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive=未使用 ''requires transitive'' 间接导出模块 {2} 中的 {0} {1} # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified=模块 {2} 中的 {0} {1} 可能对需要该模块的所有客户机都不可见 ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=不得包含类型变量:{0} compiler.misc.is.duplicated=不得包含重复项:{0} # 0: type -compiler.misc.doesnt.extend.sealed=子类 {0} 必须扩展密封类 +compiler.misc.doesnt.extend.sealed=类 {0} 必须扩展密封类 + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1} 必须扩展密封接口 compiler.misc.must.not.be.same.class=permits 子句中存在非法自引用 @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=解构模式只能应用于 compiler.err.incorrect.number.of.nested.patterns=嵌套模式数不正确\n需要:{0}\n已找到:{1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1} 是使用预览功能声明的,可能会在未来发行版中删除。 +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=尝试在基于值的类的实例上同步 +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=使用基于值的类,其操作需要可靠的身份 + # 0: type compiler.err.enclosing.class.type.non.denotable=封闭类类型:{0}\n是不可指示的类型,尝试转换为可指示的类型 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties index f7e271259af..ae61e8decfe 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties @@ -294,6 +294,7 @@ javac.opt.Xlint.desc.preview=\ javac.opt.Xlint.desc.restricted=\ Warn about use of restricted methods. +# L10N: do not localize: identity synchronization javac.opt.Xlint.desc.synchronization=\ Warn about synchronization attempts on instances of value-based classes.\n\ \ This key is a deprecated alias for ''identity'', which has the same uses and\n\ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties index 447695c9cf8..18a43abe14a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -32,7 +32,7 @@ javac.description=Java-Klasse und Schnittstellendefinitionen lesen und in Byteco javac.opt.g=Generiert alle Debugginginformationen javac.opt.g.none=Generiert keine Debugginginformationen javac.opt.g.lines.vars.source=Generiert nur einige Debugginginformationen -javac.opt.nowarn=Generiert keine Warnungen +javac.opt.nowarn=Nur obligatorische Warnungen generieren javac.opt.verbose=Gibt Nachrichten zu den Compilervorgängen aus javac.opt.deprecation=Gibt Quellspeicherorte aus, wo veraltete APIs verwendet werden javac.opt.classpath=Gibt an, wo sich die Benutzerklassendateien und Annotationsprozessoren befinden @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=Dem Bootstrap Classpath voranstellen javac.opt.Xbootclasspath.a=An Bootstrap Classpath anhängen -javac.opt.Xlint=Aktiviert die empfohlenen Warnungen -javac.opt.Xlint.all=Alle Warnungen aktivieren -javac.opt.Xlint.none=Alle Warnungen deaktivieren +javac.opt.Xlint=Empfohlene Warnungskategorien aktivieren +javac.opt.Xlint.all=Alle Warnungskategorien aktivieren +javac.opt.Xlint.none=Alle Warnungskategorien deaktivieren #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=Warnungen, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. +javac.opt.Xlint.custom=Durch Komma getrennte Warnungskategorien, die aktiviert oder deaktiviert werden sollen.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. javac.opt.Xlint.desc.auxiliaryclass=Warnt vor Auxiliary-Klassen, die in einer Quelldatei verborgen sind und aus anderen Dateien heraus verwendet werden. javac.opt.Xlint.desc.cast=Warnt vor unnötigen Umwandlungen mit Cast. @@ -159,7 +159,7 @@ javac.opt.Xlint.desc.serial=Warnt vor serialisierbaren Klassen, die kein serialV javac.opt.Xlint.desc.static=Warnt vor Zugriff auf ein statisches Mitglied mit einer Instanz. -javac.opt.Xlint.desc.strictfp=Warnt vor unnötiger Verwendung des strictfp-Modifizierers. +javac.opt.Xlint.desc.strictfp=Warnt vor unnötiger Verwendung des strictfp-Modifikators. javac.opt.Xlint.desc.text-blocks=Warnt vor inkonsistenten Leerzeichen in Textblockeinzug. @@ -175,7 +175,13 @@ javac.opt.Xlint.desc.preview=Warnt vor Verwendung von Vorschausprachfeatures. javac.opt.Xlint.desc.restricted=Warnt vor der Verwendung eingeschränkter Methoden. -javac.opt.Xlint.desc.synchronization=Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen. +javac.opt.Xlint.desc.synchronization=\ + Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen.\n\ +\ Dieser Schlüssel ist ein veralteter Alias für die Kategorie ''identity'', die dieselben Verwendungen und\n\ +\ Effekte hat. Benutzern wird empfohlen, die Kategorie ''identity'' für alle zukünftigen\n\ +\ und vorhandenen Verwendungen von ''synchronization'' zu verwenden. + +javac.opt.Xlint.desc.identity=Warnt vor Verwendungen wertbasierter Klassen, wenn eine Identitätsklasse erwartet wird. javac.opt.Xdoclint=Empfohlene Prüfungen für Probleme in javadoc-Kommentaren aktivieren # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index c215ad5eeba..66e2e3dce39 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -32,7 +32,7 @@ javac.description=Javaクラスおよびインタフェースの定義を読み javac.opt.g=すべてのデバッグ情報を生成する javac.opt.g.none=デバッグ情報を生成しない javac.opt.g.lines.vars.source=いくつかのデバッグ情報のみを生成する -javac.opt.nowarn=警告を発生させない +javac.opt.nowarn=必須の警告のみを生成します javac.opt.verbose=コンパイラの動作についてメッセージを出力する javac.opt.deprecation=推奨されないAPIが使用されているソースの位置を出力する javac.opt.classpath=ユーザー・クラス・ファイルおよび注釈プロセッサを検索する位置を指定する @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=ブートストラップ・クラス・パスの先頭に付加する javac.opt.Xbootclasspath.a=ブートストラップ・クラス・パスに追加する -javac.opt.Xlint=推奨の警告を有効にする -javac.opt.Xlint.all=すべての警告を有効にします -javac.opt.Xlint.none=すべての警告を無効にします +javac.opt.Xlint=推奨の警告カテゴリを有効にします +javac.opt.Xlint.all=すべての警告カテゴリを有効にします +javac.opt.Xlint.none=すべての警告カテゴリを無効にします #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=有効または無効にする警告(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 +javac.opt.Xlint.custom=有効または無効にする警告カテゴリ(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 javac.opt.Xlint.desc.auxiliaryclass=ソース・ファイルで非表示になっているが他のファイルから使用されている補助クラスについて警告します。 javac.opt.Xlint.desc.cast=不要なキャストの使用について警告します。 @@ -175,7 +175,9 @@ javac.opt.Xlint.desc.preview=プレビュー言語機能の使用について警 javac.opt.Xlint.desc.restricted=制限されたメソッドの使用について警告します。 -javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。 +javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。\n このキーは、''identity''の非推奨のエイリアスであり、同じ使用方法と効果を\n 持ちます。ユーザーには、今後および既存の''synchronization''の使用に対して''identity''カテゴリを\n 使用することをお薦めします。 + +javac.opt.Xlint.desc.identity=アイデンティティ・クラスが必要な場所での値ベース・クラスの使用について警告します。 javac.opt.Xdoclint=javadocコメントの問題に関する推奨チェックを有効にします # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index 1593280fd4d..efc6e73494e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -32,7 +32,7 @@ javac.description=读取 Java 类和接口定义,并将其编译为字节码 javac.opt.g=生成所有调试信息 javac.opt.g.none=不生成任何调试信息 javac.opt.g.lines.vars.source=只生成某些调试信息 -javac.opt.nowarn=不生成任何警告 +javac.opt.nowarn=仅生成必需警告 javac.opt.verbose=输出有关编译器正在执行的操作的消息 javac.opt.deprecation=输出使用已过时的 API 的源位置 javac.opt.classpath=指定查找用户类文件和批注处理程序的位置 @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=置于引导类路径之前 javac.opt.Xbootclasspath.a=置于引导类路径之后 -javac.opt.Xlint=启用建议的警告 -javac.opt.Xlint.all=启用所有警告 -javac.opt.Xlint.none=禁用所有警告 +javac.opt.Xlint=启用建议的警告类别 +javac.opt.Xlint.all=启用所有警告类别 +javac.opt.Xlint.none=禁用所有警告类别 #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=要启用或禁用的警告(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 +javac.opt.Xlint.custom=要启用或禁用的警告类别(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 javac.opt.Xlint.desc.auxiliaryclass=有关辅助类在源文件中隐藏, 但在其他文件中使用的警告。 javac.opt.Xlint.desc.cast=有关使用了不必要转换的警告。 @@ -175,7 +175,9 @@ javac.opt.Xlint.desc.preview=有关使用预览语言功能的警告。 javac.opt.Xlint.desc.restricted=有关使用受限制方法的警告。 -javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。 +javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。\n 此密钥是 ''identity'' 的已过时别名,具有相同的用法和\n 效果。建议用户在 ''synchronization'' 的所有未来和现有\n 用法中使用 ''identity'' 类别。 + +javac.opt.Xlint.desc.identity=有关在需要身份类的情况下使用基于值的类的警告。 javac.opt.Xdoclint=为 javadoc 注释中的问题启用建议的检查 # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties index 0c67a60aa0a..7f12decb225 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -100,7 +100,10 @@ launcher.err.main.not.void=Methode "main" ist nicht mit Rückgabetyp "void" dekl launcher.err.cant.find.class=Klasse nicht gefunden: {0} # 0: string -launcher.err.cant.find.main.method=Methode "main(String[])" nicht gefunden in Klasse: {0} +launcher.err.cant.find.main.method=Konnte keine main(String[])- oder main()-Methode in der Klasse: {0} finden. + +# 0: string +launcher.err.cant.instantiate=Abstrakte Klasse: {0} kann nicht instanziiert werden # 0: string launcher.err.cant.access.main.method=kein Zugriff auf Methode "main" in Klasse: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties index ef4d0f1f9e0..be1feb4a8a9 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -100,7 +100,10 @@ launcher.err.main.not.void=''main'メソッドが戻り型''void''で宣言さ launcher.err.cant.find.class=クラスが見つかりません: {0} # 0: string -launcher.err.cant.find.main.method=クラスにmain(String[])メソッドが見つかりません: {0} +launcher.err.cant.find.main.method=クラスにmain(String[])またはmain()メソッドが見つかりません: {0} + +# 0: string +launcher.err.cant.instantiate=抽象クラス: {0}はインスタンス化できません # 0: string launcher.err.cant.access.main.method=クラスのメイン・メソッドにアクセスできません: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties index a442cfe1e68..5367036d82f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -100,7 +100,10 @@ launcher.err.main.not.void=未使用返回类型 ''void'' 声明 ''main'' 方法 launcher.err.cant.find.class=找不到类:{0} # 0: string -launcher.err.cant.find.main.method=在类 {0} 中找不到 main(String[]) 方法 +launcher.err.cant.find.main.method=在类 {0} 中找不到 main(String[]) 或 main() 方法 + +# 0: string +launcher.err.cant.instantiate=无法实例化抽象类 {0} # 0: string launcher.err.cant.access.main.method=无法访问类 {0} 中的 main 方法 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java index 220ec856d62..b5fc6fd4a77 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java @@ -25,6 +25,7 @@ package com.sun.tools.javac.util; +import java.util.Arrays; import java.util.EnumSet; import java.util.function.UnaryOperator; import java.util.Locale; @@ -237,7 +238,7 @@ public JCDiagnostic fragment(Fragment fragmentKey) { */ public JCDiagnostic create( DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args)); + return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, null, prefix, key, args)); } /** @@ -252,7 +253,7 @@ public JCDiagnostic create( */ public JCDiagnostic create( DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, UnaryOperator rewriter, Object... args) { - return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, prefix, key, args), rewriter); + return create(EnumSet.noneOf(DiagnosticFlag.class), source, pos, DiagnosticInfo.of(kind, null, prefix, key, args), rewriter); } /** @@ -279,7 +280,7 @@ public JCDiagnostic create( */ public JCDiagnostic create(DiagnosticType kind, LintCategory lc, Set flags, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) { - return create(flags, source, pos, DiagnosticInfo.of(kind, lc, prefix, key, args)); + return create(flags, source, pos, DiagnosticInfo.of(kind, null, lc, prefix, key, args)); } /** @@ -303,7 +304,8 @@ DiagnosticInfo normalize(DiagnosticInfo diagnosticInfo) { //replace all nested FragmentKey with full-blown JCDiagnostic objects LintCategory category = diagnosticInfo instanceof LintWarning lintWarning ? lintWarning.category : null; - return DiagnosticInfo.of(diagnosticInfo.type, category, diagnosticInfo.prefix, diagnosticInfo.code, + return DiagnosticInfo.of(diagnosticInfo.type, diagnosticInfo.flags, + category, diagnosticInfo.prefix, diagnosticInfo.code, Stream.of(diagnosticInfo.args).map(o -> { return (o instanceof Fragment frag) ? fragment(frag) : o; @@ -314,28 +316,28 @@ DiagnosticInfo normalize(DiagnosticInfo diagnosticInfo) { * Create a new error key. */ public Error errorKey(String code, Object... args) { - return (Error)DiagnosticInfo.of(ERROR, prefix, code, args); + return (Error)DiagnosticInfo.of(ERROR, null, prefix, code, args); } /** * Create a new warning key. */ Warning warningKey(LintCategory lintCategory, String code, Object... args) { - return (Warning)DiagnosticInfo.of(WARNING, lintCategory, prefix, code, args); + return (Warning)DiagnosticInfo.of(WARNING, null, lintCategory, prefix, code, args); } /** * Create a new note key. */ public Note noteKey(String code, Object... args) { - return (Note)DiagnosticInfo.of(NOTE, prefix, code, args); + return (Note)DiagnosticInfo.of(NOTE, null, prefix, code, args); } /** * Create a new fragment key. */ Fragment fragmentKey(String code, Object... args) { - return (Fragment)DiagnosticInfo.of(FRAGMENT, prefix, code, args); + return (Fragment)DiagnosticInfo.of(FRAGMENT, null, prefix, code, args); } } @@ -351,6 +353,7 @@ Fragment fragmentKey(String code, Object... args) { public static JCDiagnostic fragment(String key, Object... args) { return new JCDiagnostic(getFragmentFormatter(), DiagnosticInfo.of(FRAGMENT, + null, null, "compiler", key, @@ -447,12 +450,17 @@ public enum DiagnosticFlag { RECOVERABLE, NON_DEFERRABLE, COMPRESSED, + /** Flags mandatory warnings that should pass through a mandatory warning aggregator. + */ + AGGREGATE, /** Flag for diagnostics that were reported through API methods. */ API, /** Flag for not-supported-in-source-X errors. */ - SOURCE_LEVEL; + SOURCE_LEVEL, + /** Flag for warnings that cannot be disabled */ + STRICT; } private final DiagnosticSource source; @@ -503,6 +511,9 @@ public abstract static class DiagnosticInfo { /** The diagnostic kind (i.e. error). */ DiagnosticType type; + /** A set of diagnostic flags to be automatically added to newly created JCDiagnostics. */ + Set flags; + /** The diagnostic prefix (i.e. 'javac'); used to compute full resource key. */ String prefix; @@ -513,8 +524,9 @@ public abstract static class DiagnosticInfo { /** The diagnostic arguments. */ Object[] args; - private DiagnosticInfo(DiagnosticType type, String prefix, String code, Object... args) { + private DiagnosticInfo(DiagnosticType type, Set flags, String prefix, String code, Object... args) { this.type = type; + this.flags = flags != null ? flags : EnumSet.noneOf(DiagnosticFlag.class); this.prefix = prefix; this.code = code; this.args = args; @@ -530,22 +542,24 @@ public String key() { /** * Static factory method; build a custom diagnostic key using given kind, prefix, code and args. */ - public static DiagnosticInfo of(DiagnosticType type, String prefix, String code, Object... args) { - return of(type, null, prefix, code, args); + public static DiagnosticInfo of(DiagnosticType type, Set flags, + String prefix, String code, Object... args) { + return of(type, flags, null, prefix, code, args); } - public static DiagnosticInfo of(DiagnosticType type, LintCategory lc, String prefix, String code, Object... args) { + public static DiagnosticInfo of(DiagnosticType type, Set flags, + LintCategory lc, String prefix, String code, Object... args) { switch (type) { case ERROR: - return new Error(prefix, code, args); + return new Error(flags, prefix, code, args); case WARNING: return lc == null ? - new Warning(prefix, code, args) : - new LintWarning(lc, prefix, code, args); + new Warning(flags, prefix, code, args) : + new LintWarning(flags, lc, prefix, code, args); case NOTE: - return new Note(prefix, code, args); + return new Note(flags, prefix, code, args); case FRAGMENT: - return new Fragment(prefix, code, args); + return new Fragment(flags, prefix, code, args); default: Assert.error("Wrong diagnostic type: " + type); return null; @@ -569,14 +583,18 @@ public Object[] getArgs() { public void setArgs(Object[] args) { this.args = args; } + + public boolean hasFlag(DiagnosticFlag flag) { + return flags.contains(flag); + } } /** * Class representing error diagnostic keys. */ public static final class Error extends DiagnosticInfo { - public Error(String prefix, String key, Object... args) { - super(DiagnosticType.ERROR, prefix, key, args); + public Error(Set flags, String prefix, String key, Object... args) { + super(DiagnosticType.ERROR, flags, prefix, key, args); } } @@ -584,8 +602,8 @@ public Error(String prefix, String key, Object... args) { * Class representing warning diagnostic keys. */ public static sealed class Warning extends DiagnosticInfo { - public Warning(String prefix, String key, Object... args) { - super(DiagnosticType.WARNING, prefix, key, args); + public Warning(Set flags, String prefix, String key, Object... args) { + super(DiagnosticType.WARNING, flags, prefix, key, args); } } @@ -595,8 +613,8 @@ public Warning(String prefix, String key, Object... args) { public static final class LintWarning extends Warning { final LintCategory category; - public LintWarning(LintCategory category, String prefix, String key, Object... args) { - super(prefix, key, args); + public LintWarning(Set flags, LintCategory category, String prefix, String key, Object... args) { + super(flags, prefix, key, args); this.category = category; } @@ -609,8 +627,8 @@ public LintCategory getLintCategory() { * Class representing note diagnostic keys. */ public static final class Note extends DiagnosticInfo { - public Note(String prefix, String key, Object... args) { - super(DiagnosticType.NOTE, prefix, key, args); + public Note(Set flags, String prefix, String key, Object... args) { + super(DiagnosticType.NOTE, flags, prefix, key, args); } } @@ -618,8 +636,8 @@ public Note(String prefix, String key, Object... args) { * Class representing fragment diagnostic keys. */ public static final class Fragment extends DiagnosticInfo { - public Fragment(String prefix, String key, Object... args) { - super(DiagnosticType.FRAGMENT, prefix, key, args); + public Fragment(Set flags, String prefix, String key, Object... args) { + super(DiagnosticType.FRAGMENT, flags, prefix, key, args); } } @@ -664,6 +682,8 @@ protected JCDiagnostic(DiagnosticFormatter formatter, this.source = source; this.position = pos; this.rewriter = rewriter; + + this.flags.addAll(diagnosticInfo.flags); } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java index fd51729bf21..576344a3d2a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java @@ -30,6 +30,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -41,6 +42,9 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.api.DiagnosticFormatter; +import com.sun.tools.javac.code.Lint; +import com.sun.tools.javac.code.Lint.LintCategory; +import com.sun.tools.javac.code.Source; import com.sun.tools.javac.main.Main; import com.sun.tools.javac.main.Option; import com.sun.tools.javac.tree.EndPosTable; @@ -50,6 +54,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; import static com.sun.tools.javac.main.Option.*; +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; /** A class for error logs. Reports errors and warnings, and * keeps track of error numbers and positions. @@ -148,7 +153,7 @@ public DeferredDiagnosticHandler(Predicate filter, boolean passOnN } private boolean deferrable(JCDiagnostic diag) { - return !(diag.isFlagSet(DiagnosticFlag.NON_DEFERRABLE) && passOnNonDeferrable) && filter.test(diag); + return !(diag.isFlagSet(NON_DEFERRABLE) && passOnNonDeferrable) && filter.test(diag); } @Override @@ -237,6 +242,16 @@ public enum WriterKind { NOTICE, WARNING, ERROR, STDOUT, STDERR } */ private JavacMessages messages; + /** + * The compilation context. + */ + private final Context context; + + /** + * The root {@link Lint} singleton. + */ + private Lint rootLint; + /** * Handler for initial dispatch of diagnostics. */ @@ -334,6 +349,7 @@ private static Map initWriters(PrintWriter out, PrintWr private Log(Context context, Map writers) { super(JCDiagnostic.Factory.instance(context)); context.put(logKey, this); + this.context = context; this.writers = writers; @SuppressWarnings("unchecked") // FIXME @@ -517,7 +533,7 @@ private boolean shouldReport(JCDiagnostic d) { if (!shouldReport(file, d.getIntPosition())) return false; - if (!d.isFlagSet(DiagnosticFlag.SOURCE_LEVEL)) + if (!d.isFlagSet(SOURCE_LEVEL)) return true; Pair> coords = new Pair<>(file, getCode(d)); @@ -664,16 +680,6 @@ protected void directError(String key, Object... args) { errWriter.flush(); } - /** Report a warning that cannot be suppressed. - * @param pos The source position at which to report the warning. - * @param key The key for the localized warning message. - * @param args Fields of the warning message. - */ - public void strictWarning(DiagnosticPosition pos, String key, Object ... args) { - writeDiagnostic(diags.warning(null, source, pos, key, args)); - nwarnings++; - } - /** * Primary method to report a diagnostic. * @param diagnostic @@ -681,7 +687,48 @@ public void strictWarning(DiagnosticPosition pos, String key, Object ... args) { @Override public void report(JCDiagnostic diagnostic) { diagnosticHandler.report(diagnostic); - } + } + + // Obtain root Lint singleton lazily to avoid init loops + private Lint rootLint() { + if (rootLint == null) + rootLint = Lint.instance(context); + return rootLint; + } + +// Mandatory Warnings + + private final EnumMap aggregators = new EnumMap<>(LintCategory.class); + + private final EnumSet suppressedDeferredMandatory = EnumSet.noneOf(LintCategory.class); + + /** + * Suppress aggregated mandatory warning notes for the specified category. + */ + public void suppressAggregatedWarningNotes(LintCategory category) { + suppressedDeferredMandatory.add(category); + } + + /** + * Report any remaining unreported aggregated mandatory warning notes. + */ + public void reportOutstandingNotes() { + aggregators.entrySet().stream() + .filter(entry -> !suppressedDeferredMandatory.contains(entry.getKey())) + .map(Map.Entry::getValue) + .map(WarningAggregator::aggregationNotes) + .flatMap(List::stream) + .forEach(this::report); + aggregators.clear(); + } + + private WarningAggregator aggregatorFor(LintCategory lc) { + return switch (lc) { + case PREVIEW -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, Source.instance(context), c)); + case DEPRECATION -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, null, c, "deprecated")); + default -> aggregators.computeIfAbsent(lc, c -> new WarningAggregator(this, null, c)); + }; + } /** * Reset the state of this instance. @@ -695,14 +742,19 @@ public void clear() { nsuppressedwarns = 0; while (diagnosticHandler.prev != null) popDiagnosticHandler(diagnosticHandler); + aggregators.clear(); + suppressedDeferredMandatory.clear(); } +// DefaultDiagnosticHandler + /** * Common diagnostic handling. * The diagnostic is counted, and depending on the options and how many diagnostics have been * reported so far, the diagnostic may be handed off to writeDiagnostic. */ private class DefaultDiagnosticHandler extends DiagnosticHandler { + @Override public void report(JCDiagnostic diagnostic) { if (expectDiagKeys != null) @@ -727,6 +779,23 @@ public void report(JCDiagnostic diagnostic) { break; case WARNING: + + // Apply the appropriate mandatory warning aggregator, if needed + if (diagnostic.isFlagSet(AGGREGATE)) { + LintCategory category = diagnostic.getLintCategory(); + boolean verbose = rootLint().isEnabled(category); + if (!aggregatorFor(category).aggregate(diagnostic, verbose)) + return; + } + + // Strict warnings are always emitted + if (diagnostic.isFlagSet(DiagnosticFlag.STRICT)) { + writeDiagnostic(diagnostic); + nwarnings++; + return; + } + + // Emit other warning unless not mandatory and warnings are disabled if (emitWarnings || diagnostic.isMandatory()) { if (nwarnings < MaxWarnings) { writeDiagnostic(diagnostic); @@ -738,8 +807,7 @@ public void report(JCDiagnostic diagnostic) { break; case ERROR: - if (diagnostic.isFlagSet(DiagnosticFlag.API) || - shouldReport(diagnostic)) { + if (diagnostic.isFlagSet(API) || shouldReport(diagnostic)) { if (nerrors < MaxErrors) { writeDiagnostic(diagnostic); nerrors++; @@ -749,7 +817,7 @@ public void report(JCDiagnostic diagnostic) { } break; } - if (diagnostic.isFlagSet(JCDiagnostic.DiagnosticFlag.COMPRESSED)) { + if (diagnostic.isFlagSet(COMPRESSED)) { compressedOutput = true; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java index 63f5b0ca75a..32a31028b68 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java @@ -172,55 +172,67 @@ public boolean isUnset(Option option, String value) { } /** - * Check whether the given lint category is explicitly enabled or disabled. + * Determine if a specific {@link LintCategory} is enabled via a custom + * option flag of the form {@code -Xlint}, {@code -Xlint:all}, or {@code -Xlint:key}. * *

          - * If the category is neither enabled nor disabled, return the given default value. + * Note: It's possible the category was also disabled; this method does not check that. * - * @param option the plain (non-custom) option * @param lc the {@link LintCategory} in question - * @param defaultValue presumed default value - * @return true if {@code lc} would be included + * @return true if {@code lc} has been enabled */ - public boolean isSet(Option option, LintCategory lc, boolean defaultValue) { - Option customOption = option.getCustom(); - if (lc.optionList.stream().anyMatch(alias -> isSet(customOption, alias))) { - return true; - } - if (lc.optionList.stream().anyMatch(alias -> isSet(customOption, "-" + alias))) { - return false; - } - if (isSet(option) || isSet(customOption, Option.LINT_CUSTOM_ALL)) { - return true; - } - if (isSet(customOption, Option.LINT_CUSTOM_NONE)) { - return false; - } - return defaultValue; + public boolean isLintEnabled(LintCategory lc) { + return isLintExplicitlyEnabled(lc) || + isSet(Option.XLINT_CUSTOM) || + isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_ALL); } /** - * Determine if a specific {@link LintCategory} was explicitly enabled via a custom option flag - * of the form {@code -Flag:all} or {@code -Flag:key}. + * Determine if a specific {@link LintCategory} is disabled via a custom + * option flag of the form {@code -Xlint:none} or {@code -Xlint:-key}. + * + *

          + * Note: It's possible the category was also enabled; this method does not check that. + * + * @param lc the {@link LintCategory} in question + * @return true if {@code lc} has been disabled + */ + public boolean isLintDisabled(LintCategory lc) { + return isLintExplicitlyDisabled(lc) || isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_NONE); + } + + /** + * Determine if a specific {@link LintCategory} is explicitly enabled via a custom + * option flag of the form {@code -Xlint:key}. + * + *

          + * Note: This does not check for option flags of the form {@code -Xlint} or {@code -Xlint:all}. + * + *

          + * Note: It's possible the category was also disabled; this method does not check that. * - * @param option the option * @param lc the {@link LintCategory} in question * @return true if {@code lc} has been explicitly enabled */ - public boolean isExplicitlyEnabled(Option option, LintCategory lc) { - return isSet(option, lc, false); + public boolean isLintExplicitlyEnabled(LintCategory lc) { + return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, alias)); } /** - * Determine if a specific {@link LintCategory} was explicitly disabled via a custom option flag - * of the form {@code -Flag:none} or {@code -Flag:-key}. + * Determine if a specific {@link LintCategory} is explicitly disabled via a custom + * option flag of the form {@code -Xlint:-key}. + * + *

          + * Note: This does not check for an option flag of the form {@code -Xlint:none}. + * + *

          + * Note: It's possible the category was also enabled; this method does not check that. * - * @param option the option * @param lc the {@link LintCategory} in question * @return true if {@code lc} has been explicitly disabled */ - public boolean isExplicitlyDisabled(Option option, LintCategory lc) { - return !isSet(option, lc, true); + public boolean isLintExplicitlyDisabled(LintCategory lc) { + return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, "-" + alias)); } public void put(String name, String value) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/WarningAggregator.java similarity index 68% rename from src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java rename to src/jdk.compiler/share/classes/com/sun/tools/javac/util/WarningAggregator.java index 046740ddc30..2bb8d2e2754 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/WarningAggregator.java @@ -25,11 +25,14 @@ package com.sun.tools.javac.util; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -39,16 +42,10 @@ /** - * A handler to process mandatory warnings, setting up a deferred diagnostic + * An aggregator for warnings, setting up a deferred diagnostic * to be printed at the end of the compilation if some warnings get suppressed - * because too many warnings have already been generated. - * - *

          - * Note that the SuppressWarnings annotation can be used to suppress warnings - * about conditions that would otherwise merit a warning. Such processing - * is done when the condition is detected, and in those cases, no call is - * made on any API to generate a warning at all. In consequence, this handler only - * Returns to handle those warnings that JLS says must be generated. + * because the lint category is not enabled or too many warnings have already + * been generated. * *

          * All warnings must be in the same {@link LintCategory} provided to the constructor. @@ -58,12 +55,11 @@ * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class MandatoryWarningHandler { +class WarningAggregator { /** * The kinds of different deferred diagnostics that might be generated - * if a mandatory warning is suppressed because too many warnings have - * already been output. + * if a warning is suppressed because too many warnings have already been output. * * The parameter is a fragment used to build an I18N message key for Log. */ @@ -105,64 +101,50 @@ private enum DeferredDiagnosticKind { /** - * Create a handler for mandatory warnings. + * Create an aggregator for warnings. * * @param log The log on which to generate any diagnostics * @param source Associated source file, or null for none - * @param verbose Specify whether or not detailed messages about - * individual instances should be given, or whether an aggregate - * message should be generated at the end of the compilation. - * Typically set via -Xlint:option. - * @param enforceMandatory - * True if mandatory warnings and notes are being enforced. * @param lc The lint category for all warnings */ - public MandatoryWarningHandler(Log log, Source source, boolean verbose, boolean enforceMandatory, LintCategory lc) { - this(log, source, verbose, enforceMandatory, lc, null); + public WarningAggregator(Log log, Source source, LintCategory lc) { + this(log, source, lc, null); } /** - * Create a handler for mandatory warnings. + * Create an aggregator for warnings. * * @param log The log on which to generate any diagnostics * @param source Associated source file, or null for none - * @param verbose Specify whether or not detailed messages about - * individual instances should be given, or whether an aggregate - * message should be generated at the end of the compilation. - * Typically set via -Xlint:option. - * @param enforceMandatory - * True if mandatory warnings and notes are being enforced. * @param lc The lint category for all warnings * @param prefix A common prefix for the set of message keys for the messages * that may be generated, or null to infer from the lint category. */ - public MandatoryWarningHandler(Log log, Source source, boolean verbose, boolean enforceMandatory, LintCategory lc, String prefix) { + public WarningAggregator(Log log, Source source, LintCategory lc, String prefix) { this.log = log; this.source = source; - this.verbose = verbose; this.prefix = prefix != null ? prefix : lc.option; - this.enforceMandatory = enforceMandatory; this.lintCategory = lc; } /** - * Report a mandatory warning. + * Aggregate a warning and determine whether to emit it. * - * @param pos source code position - * @param warnKey lint warning + * @param diagnostic the warning + * @param verbose whether the warning's lint category is enabled + * @return true if diagnostic should be emitted, otherwise false */ - public void report(DiagnosticPosition pos, LintWarning warnKey) { + public boolean aggregate(JCDiagnostic diagnostic, boolean verbose) { + Assert.check(diagnostic.getLintCategory() == lintCategory); JavaFileObject currentSource = log.currentSourceFile(); - Assert.check(warnKey.getLintCategory() == lintCategory); - if (verbose) { if (sourcesWithReportedWarnings == null) sourcesWithReportedWarnings = new HashSet<>(); - if (log.nwarnings < log.MaxWarnings) { // generate message and remember the source file - logMandatoryWarning(pos, warnKey); sourcesWithReportedWarnings.add(currentSource); + anyWarningEmitted = true; + return true; } else if (deferredDiagnosticKind == null) { // set up deferred message if (sourcesWithReportedWarnings.contains(currentSource)) { @@ -194,30 +176,36 @@ public void report(DiagnosticPosition pos, LintWarning warnKey) { deferredDiagnosticArg = null; } } + return false; } /** - * Report any diagnostic that might have been deferred by previous calls of report(). + * Build and return any accumulated aggregation notes. */ - public void reportDeferredDiagnostic() { + public List aggregationNotes() { + List list = new ArrayList<>(2); if (deferredDiagnosticKind != null) { if (deferredDiagnosticArg == null) { if (source != null) { - logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), source); + addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), source); } else { - logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix)); + addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix)); } } else { if (source != null) { - logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg, source); + addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg, source); } else { - logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg); + addNote(list, deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg); } } - - if (!verbose) - logMandatoryNote(deferredDiagnosticSource, prefix + ".recompile"); + if (!anyWarningEmitted) + addNote(list, deferredDiagnosticSource, prefix + ".recompile"); } + return list; + } + + private void addNote(List list, JavaFileObject file, String msg, Object... args) { + list.add(log.diags.mandatoryNote(log.getSource(file), new Note(null, "compiler", msg, args))); } /** @@ -226,12 +214,6 @@ public void reportDeferredDiagnostic() { private final Log log; private final Source source; - /** - * Whether or not to report individual warnings, or simply to report a - * single aggregate warning at the end of the compilation. - */ - private final boolean verbose; - /** * The common prefix for all I18N message keys generated by this handler. */ @@ -268,9 +250,10 @@ public void reportDeferredDiagnostic() { private Object deferredDiagnosticArg; /** - * True if mandatory warnings and notes are being enforced. + * Whether we have actually emitted a warning or just deferred everything. + * In the latter case, the "recompile" notice is included in the summary. */ - private final boolean enforceMandatory; + private boolean anyWarningEmitted; /** * A LintCategory to be included in point-of-use diagnostics to indicate @@ -278,28 +261,6 @@ public void reportDeferredDiagnostic() { */ private final LintCategory lintCategory; - /** - * Reports a mandatory warning to the log. If mandatory warnings - * are not being enforced, treat this as an ordinary warning. - */ - private void logMandatoryWarning(DiagnosticPosition pos, LintWarning warnKey) { - if (enforceMandatory) - log.mandatoryWarning(pos, warnKey); - else - log.warning(pos, warnKey); - } - - /** - * Reports a mandatory note to the log. If mandatory notes are - * not being enforced, treat this as an ordinary note. - */ - private void logMandatoryNote(JavaFileObject file, String msg, Object... args) { - if (enforceMandatory) - log.mandatoryNote(file, new Note("compiler", msg, args)); - else - log.note(file, new Note("compiler", msg, args)); - } - public void clear() { sourcesWithReportedWarnings = null; deferredDiagnosticKind = null; diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties index 11c8b51dc53..f9eea0b9030 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2024, 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 diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties index a92c8324681..765d60199cb 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2024, 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 diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties index 994efca2408..246381ed212 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2024, 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 diff --git a/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt index 36f9e40e526..b83866d609e 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt @@ -484,19 +484,17 @@ method name withEncryption descriptor ([C)Ljava/security/PEMEncoder; flags 1 class name java/security/PEMRecord header extends java/lang/Record implements java/security/DEREncodable record true flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) recordcomponent name type descriptor Ljava/lang/String; -recordcomponent name pem descriptor Ljava/lang/String; +recordcomponent name content descriptor Ljava/lang/String; recordcomponent name leadingData descriptor [B -innerclass innerClass java/util/Base64$Decoder outerClass java/util/Base64 innerClassName Decoder flags 9 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name descriptor (Ljava/lang/String;Ljava/lang/String;[B)V flags 1 methodParameters 0:type,0:pem,0:leadingData method name descriptor (Ljava/lang/String;Ljava/lang/String;)V flags 1 -method name getEncoded descriptor ()[B flags 1 method name toString descriptor ()Ljava/lang/String; flags 1 method name hashCode descriptor ()I flags 11 method name equals descriptor (Ljava/lang/Object;)Z flags 11 method name type descriptor ()Ljava/lang/String; flags 1 -method name pem descriptor ()Ljava/lang/String; flags 1 method name leadingData descriptor ()[B flags 1 +method name content descriptor ()Ljava/lang/String; flags 1 class name java/security/SecurityPermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") diff --git a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index 747db000158..3808e6e1e48 100644 --- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @@ -1313,6 +1313,7 @@ void showProperty(NCRYPT_HANDLE hKey) { EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB); //EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB); //EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB); + /* BCryptBuffer bb; bb.BufferType = NCRYPTBUFFER_PKCS_SECRET; bb.cbBuffer = 18; @@ -1321,6 +1322,7 @@ void showProperty(NCRYPT_HANDLE hKey) { bbd.ulVersion = 0; bbd.cBuffers = 1; bbd.pBuffers = &bb; + */ if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { snprintf(header, sizeof(header), "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java index dfc49d1a81f..6acacc28722 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java @@ -158,6 +158,7 @@ private static synchronized void initialize(TypeDataBase db) { virtualConstructor.addMapping("JvmtiAgentThread", JavaThread.class); virtualConstructor.addMapping("NotificationThread", JavaThread.class); virtualConstructor.addMapping("AttachListenerThread", JavaThread.class); + virtualConstructor.addMapping("JfrRecorderThread", JavaThread.class); // These are all the hidden JavaThread subclasses that don't execute java code. virtualConstructor.addMapping("StringDedupThread", HiddenJavaThread.class); @@ -195,7 +196,8 @@ public JavaThread createJavaThreadWrapper(Address threadAddr) { } catch (Exception e) { throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr + " (expected type JavaThread, CompilerThread, MonitorDeflationThread, AttachListenerThread," + - " DeoptimizeObjectsALotThread, StringDedupThread, NotificationThread, ServiceThread or JvmtiAgentThread)", e); + " DeoptimizeObjectsALotThread, StringDedupThread, NotificationThread, ServiceThread," + + " JfrRecorderThread, or JvmtiAgentThread)", e); } } @@ -222,29 +224,18 @@ private JavaThread owningThreadFromMonitor(Address o) { public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) { if (monitor.isOwnedAnonymous()) { - if (VM.getVM().getCommandLineFlag("LockingMode").getInt() == LockingMode.getLightweight()) { - OopHandle object = monitor.object(); - for (int i = 0; i < getNumberOfThreads(); i++) { - JavaThread thread = getJavaThreadAt(i); - if (thread.isLockOwned(object)) { - return thread; - } - } - // We should have found the owner, however, as the VM could be in any state, including the middle - // of performing GC, it is not always possible to do so. Just return null if we can't locate it. - System.out.println("Warning: We failed to find a thread that owns an anonymous lock. This is likely"); - System.out.println("due to the JVM currently running a GC. Locking information may not be accurate."); - return null; - } else { - assert(VM.getVM().getCommandLineFlag("LockingMode").getInt() == LockingMode.getLegacy()); - Address o = (Address)monitor.stackLocker(); - for (int i = 0; i < getNumberOfThreads(); i++) { - JavaThread thread = getJavaThreadAt(i); - if (thread.isLockOwned(o)) - return thread; - } - return null; + OopHandle object = monitor.object(); + for (int i = 0; i < getNumberOfThreads(); i++) { + JavaThread thread = getJavaThreadAt(i); + if (thread.isLockOwned(object)) { + return thread; + } } + // We should have found the owner, however, as the VM could be in any state, including the middle + // of performing GC, it is not always possible to do so. Just return null if we can't locate it. + System.out.println("Warning: We failed to find a thread that owns an anonymous lock. This is likely"); + System.out.println("due to the JVM currently running a GC. Locking information may not be accurate."); + return null; } else { return owningThreadFromMonitor(monitor.owner()); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index 2b1cc879e66..c788b4e1617 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -3120,17 +3120,30 @@ ByteVector fromArray(VectorSpecies species, } // Check indices are within array bounds. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + + IntVector vix2 = null; + IntVector vix3 = null; + if (vlen == idx_vlen * 4) { + vix2 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 2).add(offset); + VectorIntrinsics.checkIndex(vix2, a.length); + vix3 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 3).add(offset); + VectorIntrinsics.checkIndex(vix3, a.length); } return VectorSupport.loadWithMap( vectorType, null, byte.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, null, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, vix2, vix3, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3882,17 +3895,30 @@ ByteVector fromArray0Template(Class maskClass, byte[] a, int offset, // Check indices are within array bounds. // FIXME: Check index under mask controlling. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + + IntVector vix2 = null; + IntVector vix3 = null; + if (vlen == idx_vlen * 4) { + vix2 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 2).add(offset); + VectorIntrinsics.checkIndex(vix2, a.length); + vix3 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 3).add(offset); + VectorIntrinsics.checkIndex(vix3, a.length); } return VectorSupport.loadWithMap( vectorType, maskClass, byte.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, m, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, vix2, vix3, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 48446c6fa01..786cd089ebe 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -2937,8 +2937,8 @@ DoubleVector fromArray(VectorSpecies species, return VectorSupport.loadWithMap( vectorType, null, double.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, null, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3228,7 +3228,7 @@ void intoArray(double[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, null, a, offset, indexMap, mapOffset, @@ -3423,8 +3423,8 @@ DoubleVector fromArray0Template(Class maskClass, double[] a, int offset, return VectorSupport.loadWithMap( vectorType, maskClass, double.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, m, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); @@ -3539,7 +3539,7 @@ void intoArray0Template(Class maskClass, double[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, m, a, offset, indexMap, mapOffset, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 1e0829a3b1c..b481d5a51d7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -2943,8 +2943,8 @@ FloatVector fromArray(VectorSpecies species, return VectorSupport.loadWithMap( vectorType, null, float.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, null, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3215,7 +3215,7 @@ void intoArray(float[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, null, a, offset, indexMap, mapOffset, @@ -3392,8 +3392,8 @@ FloatVector fromArray0Template(Class maskClass, float[] a, int offset, return VectorSupport.loadWithMap( vectorType, maskClass, float.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, m, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); @@ -3489,7 +3489,7 @@ void intoArray0Template(Class maskClass, float[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, m, a, offset, indexMap, mapOffset, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index b691527bec6..85aac460f8b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -3097,8 +3097,8 @@ IntVector fromArray(VectorSpecies species, return VectorSupport.loadWithMap( vectorType, null, int.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, null, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3369,7 +3369,7 @@ void intoArray(int[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, null, a, offset, indexMap, mapOffset, @@ -3546,8 +3546,8 @@ IntVector fromArray0Template(Class maskClass, int[] a, int offset, return VectorSupport.loadWithMap( vectorType, maskClass, int.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, m, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); @@ -3643,7 +3643,7 @@ void intoArray0Template(Class maskClass, int[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, m, a, offset, indexMap, mapOffset, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 9e4dcd23d67..abd86863165 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -2976,8 +2976,8 @@ LongVector fromArray(VectorSpecies species, return VectorSupport.loadWithMap( vectorType, null, long.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, null, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3267,7 +3267,7 @@ void intoArray(long[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, null, a, offset, indexMap, mapOffset, @@ -3462,8 +3462,8 @@ LongVector fromArray0Template(Class maskClass, long[] a, int offset, return VectorSupport.loadWithMap( vectorType, maskClass, long.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, m, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); @@ -3578,7 +3578,7 @@ void intoArray0Template(Class maskClass, long[] a, int offset, VectorSupport.storeWithMap( vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, m, a, offset, indexMap, mapOffset, diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index 46df27309ae..464b792e0f7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -3121,17 +3121,21 @@ ShortVector fromArray(VectorSpecies species, } // Check indices are within array bounds. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); } return VectorSupport.loadWithMap( vectorType, null, short.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, null, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -3868,17 +3872,21 @@ ShortVector fromArray0Template(Class maskClass, short[] a, int offset, // Check indices are within array bounds. // FIXME: Check index under mask controlling. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); } return VectorSupport.loadWithMap( vectorType, maskClass, short.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, m, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java index 0e231bd5174..f4da4f42934 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java @@ -577,7 +577,7 @@ static boolean opKind(Operator op, int bit) { /** Produce saturating unsigned {@code a+b}. Integral only. * @see VectorMath#addSaturatingUnsigned(int, int) */ - public static final Binary SUADD = binary("SUADD", "+", VectorSupport.VECTOR_OP_SUADD, VO_NOFP); + public static final Associative SUADD = assoc("SUADD", "+", VectorSupport.VECTOR_OP_SUADD, VO_NOFP+VO_ASSOC); /** Produce saturating {@code a-b}. Integral only. * @see VectorMath#subSaturating(int, int) */ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 6d9db65a1ba..3fa7d1dab6c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -3763,20 +3763,43 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { } // Check indices are within array bounds. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + +#if[byte] + IntVector vix2 = null; + IntVector vix3 = null; + if (vlen == idx_vlen * 4) { + vix2 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 2).add(offset); + VectorIntrinsics.checkIndex(vix2, a.length); + vix3 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 3).add(offset); + VectorIntrinsics.checkIndex(vix3, a.length); } return VectorSupport.loadWithMap( vectorType, null, $type$.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, null, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, vix2, vix3, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); +#else[byte] + return VectorSupport.loadWithMap( + vectorType, null, $type$.class, vsp.laneCount(), + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, null, + a, offset, indexMap, mapOffset, vsp, + (c, idx, iMap, idy, s, vm) -> + s.vOp(n -> c[idx + iMap[idy+n]])); +#end[byte] } #else[byteOrShort] @ForceInline @@ -3824,8 +3847,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return VectorSupport.loadWithMap( vectorType, null, $type$.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, null, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, null, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(n -> c[idx + iMap[idy+n]])); @@ -4450,7 +4473,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { VectorSupport.storeWithMap( vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, null, a, offset, indexMap, mapOffset, @@ -4971,20 +4994,43 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { // Check indices are within array bounds. // FIXME: Check index under mask controlling. - for (int i = 0; i < vsp.length(); i += lsp.length()) { - IntVector vix = IntVector - .fromArray(lsp, indexMap, mapOffset + i) - .add(offset); - VectorIntrinsics.checkIndex(vix, a.length); + IntVector vix0 = IntVector.fromArray(lsp, indexMap, mapOffset).add(offset); + VectorIntrinsics.checkIndex(vix0, a.length); + + int vlen = vsp.length(); + int idx_vlen = lsp.length(); + IntVector vix1 = null; + if (vlen >= idx_vlen * 2) { + vix1 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen).add(offset); + VectorIntrinsics.checkIndex(vix1, a.length); + } + +#if[byte] + IntVector vix2 = null; + IntVector vix3 = null; + if (vlen == idx_vlen * 4) { + vix2 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 2).add(offset); + VectorIntrinsics.checkIndex(vix2, a.length); + vix3 = IntVector.fromArray(lsp, indexMap, mapOffset + idx_vlen * 3).add(offset); + VectorIntrinsics.checkIndex(vix3, a.length); } return VectorSupport.loadWithMap( vectorType, maskClass, $type$.class, vsp.laneCount(), - lsp.vectorType(), - a, ARRAY_BASE, null, m, + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, vix2, vix3, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); +#else[byte] + return VectorSupport.loadWithMap( + vectorType, maskClass, $type$.class, vsp.laneCount(), + lsp.vectorType(), lsp.length(), + a, ARRAY_BASE, vix0, vix1, null, null, m, + a, offset, indexMap, mapOffset, vsp, + (c, idx, iMap, idy, s, vm) -> + s.vOp(vm, n -> c[idx + iMap[idy+n]])); +#end[byte] } #else[byteOrShort] @ForceInline @@ -5034,8 +5080,8 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return VectorSupport.loadWithMap( vectorType, maskClass, $type$.class, vsp.laneCount(), - isp.vectorType(), - a, ARRAY_BASE, vix, m, + isp.vectorType(), isp.length(), + a, ARRAY_BASE, vix, null, null, null, m, a, offset, indexMap, mapOffset, vsp, (c, idx, iMap, idy, s, vm) -> s.vOp(vm, n -> c[idx + iMap[idy+n]])); @@ -5225,7 +5271,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { VectorSupport.storeWithMap( vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(), - isp.vectorType(), + isp.vectorType(), isp.length(), a, arrayAddress(a, 0), vix, this, m, a, offset, indexMap, mapOffset, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java index 66aed480bbb..391ac224609 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java @@ -179,6 +179,7 @@ public enum CPUFeature implements CPUFeatureName { SHA3, SHA512, SVE, + SB, PACA, SVEBITPERM, SVE2, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/BytecodeFrame.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/BytecodeFrame.java index c4d090a74c4..8c698b4ee3d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/BytecodeFrame.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/BytecodeFrame.java @@ -387,4 +387,11 @@ public boolean equals(Object obj) { public String toString() { return CodeUtil.append(new StringBuilder(100), this).toString(); } + + /** + * Returns a copy of the array describing the Java kinds in {@link #values}. + */ + public JavaKind[] getSlotKinds() { + return (slotKinds == null) ? null : slotKinds.clone(); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeCacheProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeCacheProvider.java index 6b1042e35ca..e52ffdc227c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeCacheProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -42,13 +42,15 @@ public interface CodeCacheProvider { * @param installedCode a predefined {@link InstalledCode} object to use as a reference to the * installed code. If {@code null}, a new {@link InstalledCode} object will be * created. + * @param profileDeopt specifies if HotSpot should profile deoptimizations for the + * {@code nmethod} associated with this object. * @return a reference to the ready-to-run code * @throws BailoutException if the code installation failed * @throws IllegalArgumentException if {@code installedCode != null} and this object does not * support a predefined {@link InstalledCode} object */ - default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCode, SpeculationLog log, InstalledCode installedCode) { - return installCode(method, compiledCode, installedCode, log, false); + default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCode, SpeculationLog log, InstalledCode installedCode, boolean profileDeopt) { + return installCode(method, compiledCode, installedCode, log, false, profileDeopt); } /** @@ -64,7 +66,7 @@ default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCo * support a predefined {@link InstalledCode} object */ default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompiledCode compiledCode) { - return installCode(method, compiledCode, null, null, true); + return installCode(method, compiledCode, null, null, true, true); } /** @@ -81,10 +83,12 @@ default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompiledCode com * {@code compRequest.getMethod()}. The default implementation for a method is the * code executed for standard calls to the method. This argument is ignored if * {@code compRequest == null}. + * @param profileDeopt specifies if HotSpot should profile deoptimizations for the + * {@code nmethod} associated with this object. * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ - InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault); + InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt); /** * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java index d26b135a405..1033fa559f8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java @@ -289,17 +289,18 @@ public boolean equals(Object o) { if (o == this) { return true; } - if (o instanceof VirtualObject) { - VirtualObject l = (VirtualObject) o; - if (!l.type.equals(type) || l.values.length != values.length) { + if (o instanceof VirtualObject that) { + int thatValuesLength = (that.values == null) ? 0 : that.values.length; + int valuesLength = (values == null) ? 0 : values.length; + if (!that.type.equals(type) || thatValuesLength != valuesLength) { return false; } - for (int i = 0; i < values.length; i++) { + for (int i = 0; i < valuesLength; i++) { /* * Virtual objects can form cycles. Calling equals() could therefore lead to * infinite recursion. */ - if (!same(values[i], l.values[i])) { + if (!same(values[i], that.values[i])) { return false; } } @@ -311,4 +312,11 @@ public boolean equals(Object o) { private static boolean same(Object o1, Object o2) { return o1 == o2; } + + /** + * Returns a copy of the array containing the Java kinds of the values stored in this virtual object. + */ + public JavaKind[] getSlotKinds() { + return (slotKinds == null) ? null : slotKinds.clone(); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/package-info.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/package-info.java index 753e40c90a3..b6474e28dbe 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/package-info.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -23,8 +23,6 @@ /** * Package that defines the interface between a Java application that wants to install code and the * runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider} - * interface. The method - * {@link jdk.vm.ci.code.CodeCacheProvider#addCode(jdk.vm.ci.meta.ResolvedJavaMethod, CompiledCode, jdk.vm.ci.meta.SpeculationLog, InstalledCode)} - * can be used to install code. + * interface. The method {@link jdk.vm.ci.code.CodeCacheProvider#addCode} can be used to install code. */ package jdk.vm.ci.code; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/site/Site.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/site/Site.java index dbf76c58be0..7d1239fea0e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/site/Site.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/site/Site.java @@ -39,8 +39,8 @@ public Site(int pos) { } @Override - public final int hashCode() { - throw new UnsupportedOperationException("hashCode"); + public int hashCode() { + return 41 * pcOffset; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java index 9545c9aa9ec..271b27721d3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -101,7 +101,7 @@ private InstalledCode logOrDump(InstalledCode installedCode, CompiledCode compil } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { InstalledCode resultInstalledCode; if (installedCode != null) { throw new IllegalArgumentException("InstalledCode argument must be null"); @@ -131,7 +131,7 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile } else { hsCompiledNmethod = (HotSpotCompiledNmethod) hsCompiledCode; HotSpotResolvedJavaMethodImpl hsMethod = (HotSpotResolvedJavaMethodImpl) method; - HotSpotNmethod nmethod = new HotSpotNmethod(hsMethod, name, isDefault, hsCompiledNmethod.id); + HotSpotNmethod nmethod = new HotSpotNmethod(hsMethod, name, isDefault, profileDeopt, hsCompiledNmethod.id); nmethod.setSpeculationLog(speculationLog); resultInstalledCode = nmethod; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCode.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCode.java index 6004db48423..6d1f16d5bd2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCode.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCode.java @@ -188,4 +188,88 @@ public int getOffset(ResolvedJavaField field) { } }); } + + /** + * Returns a copy of the compiled machine code. + */ + public byte[] getTargetCode() { + return (targetCode == null) ? null : targetCode.clone(); + } + + /** + * Gets the size of the compiled machine code in bytes. + */ + public int getTargetCodeSize() { + return targetCodeSize; + } + + /** + * Returns a copy of the code annotations describing special sites in {@link #targetCode}. + */ + public Site[] getSites() { + return (sites == null) ? null : sites.clone(); + } + + /** + * Returns an array copy of the assumptions this code relies on. + */ + public Assumption[] getAssumptions() { + return (assumptions == null) ? null : assumptions.clone(); + } + + /** + * Returns an array copy of the methods whose bytecodes were used as input to the compilation. + */ + public ResolvedJavaMethod[] getMethods() { + return (methods == null) ? null : methods.clone(); + } + + /** + * Returns an array copy of the comments that are included in code dumps. + */ + public Comment[] getComments() { + return (comments == null) ? null : comments.clone(); + } + + /** + * Returns a copy of the data section containing serialized constants for the emitted machine code. + */ + public byte[] getDataSection() { + return (dataSection == null) ? null : dataSection.clone(); + } + + /** + * Gets the minimum alignment of the data section. + */ + public int getDataSectionAlignment() { + return dataSectionAlignment; + } + + /** + * Returns a copy of the {@link #dataSection} relocations. + */ + public DataPatch[] getDataSectionPatches() { + return (dataSectionPatches == null) ? null : dataSectionPatches.clone(); + } + + /** + * Checks if this compiled code is immutable and position independent. + */ + public boolean isImmutablePIC() { + return isImmutablePIC; + } + + /** + * Gets the total size of the stack frame of this compiled method. + */ + public int getTotalFrameSize() { + return totalFrameSize; + } + + /** + * Gets the deoptimization rescue slot associated with this compiled code. + */ + public StackSlot getDeoptRescueSlot() { + return deoptRescueSlot; + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java index b1be3dee25c..e0e93b0f8bc 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java @@ -118,4 +118,44 @@ public boolean hasScopedAccess() { return false; } + /** + * Returns the method to which this compiled nmethod belongs. + */ + public HotSpotResolvedJavaMethod getMethod() { + return method; + } + + /** + * Returns the bytecode index (BCI) in the {@link #getMethod() method} that is the beginning of this compiled + * nmethod. -1 denotes the beginning of the method. + * + * @return the entry BCI of this nmethod or -1 if the entry is the method's beginning + */ + public int getEntryBCI() { + return entryBCI; + } + + /** + * Returns the identifier of the compilation request. + */ + public int getId() { + return id; + } + + /** + * Returns the address of a native {@code JVMCICompileState} object associated with this compiled nmethod. + * If no such object exists, it returns 0L. + * + * @return the address of the native {@code JVMCICompileState} object or 0L if it does not exist + */ + public long getCompileState() { + return compileState; + } + + /** + * Checks if this compiled nmethod has a memory access via the {@code Unsafe} class. + */ + public boolean hasUnsafeAccess() { + return hasUnsafeAccess; + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJavaType.java index ef8253596d8..792c7bc00a2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJavaType.java @@ -36,7 +36,7 @@ public HotSpotJavaType(String name) { } @Override - public final String getName() { + public String getName() { return name; } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java index 5c7089da6cb..f5cd5013f65 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -54,6 +54,13 @@ public class HotSpotNmethod extends HotSpotInstalledCode { */ private final boolean isDefault; + /** + * Specifies whether HotSpot should profile deoptimizations for the {@code nmethod} associated + * with this object. This is particularly useful for whitebox testing scenarios that involve + * deoptimization. + */ + private final boolean profileDeopt; + /** * Determines whether this object is in the oops table of the nmethod. *

          @@ -83,10 +90,11 @@ boolean inOopsTable() { */ private int invalidationReason; - HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) { + HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, boolean profileDeopt, long compileId) { super(name); this.method = method; this.isDefault = isDefault; + this.profileDeopt = profileDeopt; boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault; this.compileIdSnapshot = inOopsTable ? 0L : compileId; this.invalidationReason = -1; @@ -103,12 +111,13 @@ public void setSpeculationLog(HotSpotSpeculationLog log) { /** * The speculation log containing speculations embedded in the nmethod. - * + *

          * If {@code speculationLog.managesFailedSpeculations() == true}, this field ensures the failed * speculation list lives at least as long as this object. This prevents deoptimization from * appending to an already freed list. */ - @SuppressWarnings("unused") private HotSpotSpeculationLog speculationLog; + @SuppressWarnings("unused") + private HotSpotSpeculationLog speculationLog; /** * Determines if the nmethod associated with this object is the compiled entry point for @@ -118,6 +127,14 @@ public boolean isDefault() { return isDefault; } + /** + * Determines if HotSpot should profile deoptimization for the {@code nmethod} associated + * with this object. + */ + public boolean profileDeopt() { + return profileDeopt; + } + @Override public boolean isValid() { if (compileIdSnapshot != 0L) { @@ -133,7 +150,8 @@ public ResolvedJavaMethod getMethod() { /** * Invalidate this nmethod using the reason specified in {@code invalidationReason} and * optionally deoptimize the method if {@code deoptimize} is set. - * @param deoptimize whether or not to deoptimize the method. + * + * @param deoptimize whether or not to deoptimize the method. * @param invalidationReason invalidation reason code. */ public void invalidate(boolean deoptimize, int invalidationReason) { @@ -164,7 +182,7 @@ public long getEntryPoint() { @Override public String toString() { return String.format("HotSpotNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s, inOopsTable=%s]", - method, getAddress(), isDefault, name, inOopsTable()); + method, getAddress(), isDefault, name, inOopsTable()); } private boolean checkArgs(Object... args) { @@ -183,7 +201,7 @@ private boolean checkArgs(Object... args) { /** * {@inheritDoc} - * + *

          * It's possible for the HotSpot runtime to sweep nmethods at any point in time. As a result, * there is no guarantee that calling this method will execute the wrapped nmethod. Instead, it * may end up executing the bytecode of the associated {@link #getMethod() Java method}. Only if diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java index 227fcb731a9..bed38f91988 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java @@ -22,14 +22,15 @@ */ package jdk.vm.ci.hotspot; -import java.lang.invoke.CallSite; -import java.util.Objects; - import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.VMConstant; +import java.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.util.Objects; + /** * Represents a constant non-{@code null} object reference, within the compiler and across the * compiler/runtime interface. @@ -61,7 +62,26 @@ public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VM * change * @return {@code null} if this constant does not represent a {@link CallSite} object */ - JavaConstant getCallSiteTarget(Assumptions assumptions); + default JavaConstant getCallSiteTarget(Assumptions assumptions) { + Assumptions.AssumptionResult result = getCallSiteTarget(); + if (!result.canRecordTo(assumptions)) { + return null; + } + result.recordTo(assumptions); + return result.getResult(); + } + + /** + * Gets the result of {@link CallSite#getTarget()} for the {@link CallSite} object represented + * by this constant. The target is bound to an assumption if this is not a fully initialized + * {@link ConstantCallSite}. + * + * @return a call-site target (possibly bound to an assumption) or {@code null} if this constant + * does not represent a {@link CallSite} object + */ + default Assumptions.AssumptionResult getCallSiteTarget() { + throw new UnsupportedOperationException("getCallSiteTarget"); + } /** * Determines if this constant represents an {@linkplain String#intern() interned} string. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index cf3ac0f994a..1dcc969b3e6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -89,19 +89,15 @@ private HotSpotObjectConstantImpl readTarget() { } @Override - public JavaConstant getCallSiteTarget(Assumptions assumptions) { + public Assumptions.AssumptionResult getCallSiteTarget() { if (runtime().getCallSite().isInstance(this)) { // For ConstantCallSites, we need to read "isFrozen" before reading "target" // isFullyInitializedConstantCallSite() reads "isFrozen" if (isFullyInitializedConstantCallSite()) { - return readTarget(); - } - if (assumptions == null) { - return null; + return new Assumptions.AssumptionResult<>(readTarget()); } HotSpotObjectConstantImpl result = readTarget(); - assumptions.record(new Assumptions.CallSiteTargetValue(this, result)); - return result; + return new Assumptions.AssumptionResult<>(result, new Assumptions.CallSiteTargetValue(this, result)); } return null; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 6eb4dfb9b02..b75edb9df08 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -25,6 +25,9 @@ import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkAreAnnotations; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkIsAnnotation; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.getFirstAnnotationOrNull; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; @@ -234,15 +237,19 @@ public JavaConstant getConstantValue() { @Override public AnnotationData getAnnotationData(ResolvedJavaType annotationType) { if (!hasAnnotations()) { + checkIsAnnotation(annotationType); return null; } - return getAnnotationData0(annotationType).get(0); + return getFirstAnnotationOrNull(getAnnotationData0(annotationType)); } @Override public List getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) { + checkIsAnnotation(type1); + checkIsAnnotation(type2); + checkAreAnnotations(types); if (!hasAnnotations()) { - return Collections.emptyList(); + return List.of(); } return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types)); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 9440a719dd4..224e8b1a070 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -28,6 +28,9 @@ import static jdk.vm.ci.hotspot.HotSpotModifiers.SYNTHETIC; import static jdk.vm.ci.hotspot.HotSpotModifiers.VARARGS; import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmMethodModifiers; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkAreAnnotations; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkIsAnnotation; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.getFirstAnnotationOrNull; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; @@ -775,15 +778,19 @@ public int methodIdnum() { @Override public AnnotationData getAnnotationData(ResolvedJavaType type) { if (!hasAnnotations()) { + checkIsAnnotation(type); return null; } - return getAnnotationData0(type).get(0); + return getFirstAnnotationOrNull(getAnnotationData0(type)); } @Override public List getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) { + checkIsAnnotation(type1); + checkIsAnnotation(type2); + checkAreAnnotations(types); if (!hasAnnotations()) { - return Collections.emptyList(); + return List.of(); } return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types)); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java index fbb5a3fc9b5..ab634568a84 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java @@ -22,14 +22,17 @@ */ package jdk.vm.ci.hotspot; +import java.util.List; + +import jdk.vm.ci.meta.AnnotationData; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaType; public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { - HotSpotResolvedObjectTypeImpl arrayOfType; + HotSpotResolvedObjectType arrayOfType; - HotSpotResolvedJavaType(String name) { + protected HotSpotResolvedJavaType(String name) { super(name); } @@ -37,16 +40,22 @@ public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements public abstract boolean equals(Object obj); @Override - public final int hashCode() { + public int hashCode() { return getName().hashCode(); } - abstract JavaConstant getJavaMirror(); + /** + * Gets the runtime representation of the {@link Class} object of this type. + */ + public abstract JavaConstant getJavaMirror(); - abstract HotSpotResolvedObjectTypeImpl getArrayType(); + /** + * Gets the array type of this type without caching the result. + */ + protected abstract HotSpotResolvedObjectType getArrayType(); @Override - public final HotSpotResolvedObjectType getArrayClass() { + public HotSpotResolvedObjectType getArrayClass() { if (arrayOfType == null) { arrayOfType = getArrayType(); } @@ -60,5 +69,21 @@ public final HotSpotResolvedObjectType getArrayClass() { * * @return {@code true} if this type is being initialized */ - abstract boolean isBeingInitialized(); + protected abstract boolean isBeingInitialized(); + + static void checkIsAnnotation(ResolvedJavaType type) { + if (!type.isAnnotation()) { + throw new IllegalArgumentException(type.toJavaName() + " is not an annotation interface"); + } + } + + static void checkAreAnnotations(ResolvedJavaType... types) { + for (ResolvedJavaType type : types) { + checkIsAnnotation(type); + } + } + + static AnnotationData getFirstAnnotationOrNull(List list) { + return list.isEmpty() ? null : list.get(0); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 0417a761fc4..1fc5f1bfd6a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -80,6 +80,13 @@ default JavaKind getJavaKind() { @Override AssumptionResult findUniqueConcreteMethod(ResolvedJavaMethod method); + /** + * Gets the runtime representation of the {@link Class} object of this type. + */ + default JavaConstant getJavaMirror() { + throw new UnsupportedOperationException("getJavaMirror"); + } + /** * Performs a fast-path check that this type is resolved in the context of a given accessing * class. A negative result does not mean this type is not resolved with respect to diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 17eede6f490..46e53411dee 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -672,12 +672,12 @@ public boolean equals(Object obj) { } @Override - JavaConstant getJavaMirror() { + public JavaConstant getJavaMirror() { return mirror; } @Override - HotSpotResolvedObjectTypeImpl getArrayType() { + protected HotSpotResolvedObjectTypeImpl getArrayType() { return runtime().compilerToVm.getArrayType((char) 0, this); } @@ -1120,15 +1120,19 @@ public boolean isCloneableWithAllocation() { @Override public AnnotationData getAnnotationData(ResolvedJavaType annotationType) { if (!mayHaveAnnotations(true)) { + checkIsAnnotation(annotationType); return null; } - return getAnnotationData0(annotationType).get(0); + return getFirstAnnotationOrNull(getAnnotationData0(annotationType)); } @Override public List getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) { if (!mayHaveAnnotations(true)) { - return Collections.emptyList(); + checkIsAnnotation(type1); + checkIsAnnotation(type2); + checkAreAnnotations(types); + return List.of(); } return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types)); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index b707906af08..e83c5c54532 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -61,7 +61,13 @@ private HotSpotResolvedPrimitiveType(JavaKind kind, HotSpotObjectConstantImpl mi this.kind = kind; } - static HotSpotResolvedPrimitiveType forKind(JavaKind kind) { + /** + * Returns a primitive type instance corresponding to the given {@link JavaKind}. + * + * @param kind the Java kind of the primitive type + * @return the primitive type instance for the given Java kind + */ + public static HotSpotResolvedPrimitiveType forKind(JavaKind kind) { HotSpotResolvedPrimitiveType primitive = primitives[kind.getBasicType()]; assert primitive != null : kind; return primitive; @@ -84,7 +90,7 @@ public int getModifiers() { } @Override - HotSpotResolvedObjectTypeImpl getArrayType() { + protected HotSpotResolvedObjectType getArrayType() { if (kind == JavaKind.Void) { return null; } @@ -321,18 +327,21 @@ public boolean equals(Object obj) { } @Override - JavaConstant getJavaMirror() { + public JavaConstant getJavaMirror() { return mirror; } @Override public AnnotationData getAnnotationData(ResolvedJavaType type) { + checkIsAnnotation(type); return null; } @Override public List getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) { - return Collections.emptyList(); + checkIsAnnotation(type1); + checkIsAnnotation(type2); + checkAreAnnotations(types); + return List.of(); } - } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java index e3d812c2e83..4849750337c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Formatter; import java.util.List; +import java.util.Objects; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.common.JVMCIError; @@ -130,7 +131,7 @@ public static final class HotSpotSpeculation extends Speculation { private final byte[] encoding; - HotSpotSpeculation(SpeculationReason reason, JavaConstant id, byte[] encoding) { + public HotSpotSpeculation(SpeculationReason reason, JavaConstant id, byte[] encoding) { super(reason); this.id = id; this.encoding = encoding; @@ -140,6 +141,13 @@ public JavaConstant getEncoding() { return id; } + /** + * Returns a copy of the speculation reason encoding. + */ + public byte[] getReasonEncoding() { + return (encoding == null) ? null : encoding.clone(); + } + @Override public String toString() { long indexAndLength = id.asLong(); @@ -147,6 +155,20 @@ public String toString() { int length = decodeLength(indexAndLength); return String.format("{0x%016x[index: %d, len: %d, hash: 0x%x]: %s}", indexAndLength, index, length, Arrays.hashCode(encoding), getReason()); } + + @Override + public boolean equals(Object object) { + if (object instanceof HotSpotSpeculation that) { + return getReason().equals(that.getReason()) && id.equals(that.id) && Arrays.equals(encoding, that.encoding); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(getReason(), id, Arrays.hashCode(encoding)); + } } /** diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java index 9954c700ca7..15bd58a5a5d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java @@ -305,7 +305,7 @@ private T getFieldValue0(String name, Class type, T notPresent, String in * @return the field * @throws JVMCIError if the field is not present and {@code required == true} */ - private VMField getField(String name, String cppType, boolean required) { + public VMField getField(String name, String cppType, boolean required) { VMField entry = store.vmFields.get(name); if (entry == null) { if (!required) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMField.java index 3a294f5d9fe..21755445ca0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMField.java @@ -66,7 +66,7 @@ public boolean isStatic() { * Creates a description of a non-static field. */ @VMEntryPoint - VMField(String name, String type, long offset, long address, Object value) { + public VMField(String name, String type, long offset, long address, Object value) { this.name = name; this.type = type; this.offset = offset; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/EncodedSpeculationReason.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/EncodedSpeculationReason.java index 4df14bc672b..2e72896b31d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/EncodedSpeculationReason.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/EncodedSpeculationReason.java @@ -113,4 +113,25 @@ public int hashCode() { public String toString() { return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context)); } + + /** + * Returns the group ID of this speculation reason. + */ + public int getGroupId() { + return groupId; + } + + /** + * Returns the group name of this speculation reason. + */ + public String getGroupName() { + return groupName; + } + + /** + * Returns a copy of the array of context objects. + */ + public Object[] getContext() { + return (context == null) ? null : context.clone(); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 929a4713330..cdb24c5f1ad 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -50,6 +50,15 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated */ AssumptionResult hasFinalizableSubclass(); + /** + * Returns true if this type represents an annotation interface. + * + * @return {@code true} if this type represents an annotation interface + */ + default boolean isAnnotation() { + return (getModifiers() & java.lang.reflect.AccessFlag.ANNOTATION.mask()) != 0; + } + /** * Checks whether this type is an interface. * diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties index fe4ff9b50c4..c5d9f41ee85 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%s kein Provider provider.name.not.found=Provider namens "%s" nicht gefunden @@ -37,8 +37,8 @@ Illegal.option.=Unzulässige Option:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=Wenn -protected angegeben ist, dürfen -storepass und -keypass nicht angegeben werden If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=Wenn der Keystore nicht kennwortgeschützt ist, dürfen -storepass und -keypass nicht angegeben werden Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file alias -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [options] jar-file [alias...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [options] jar-file [alias...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] Keystore-Speicherort .storepass.password.password.for.keystore.integrity=[-storepass ] Kennwort für Keystore-Integrität .storetype.type.keystore.type=[-storetype ] Keystore-Typ @@ -51,7 +51,7 @@ Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file .verify.verify.a.signed.JAR.file=[-verify] Verifiziert eine signierte JAR-Datei .version.print.the.program.version=[-version] Gibt die Programmversion aus .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] Verbose-Ausgabe beim Signieren/Verifizieren. -.suboptions.can.be.all.grouped.or.summary=\u0020 Als Unteroptionen sind "all", "grouped" und "summary" möglich +.suboptions.can.be.all.grouped.or.summary=\ Als Unteroptionen sind "all", "grouped" und "summary" möglich .certs.display.certificates.when.verbose.and.verifying=[-certs] Zeigt Zertifikate bei Verbose und Verifizierung an .certs.revocation.check=[-revCheck] Aktiviert die Zertifikatswiderrufprüfung .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] Ort der Zeitstempelautorität @@ -63,9 +63,9 @@ Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file .protected.keystore.has.protected.authentication.path=[-protected] Keystore hat geschützten Authentifizierungspfad .providerName.name.provider.name=[-providerName ] Providername .add.provider.option=[-addprovider Fügt einen Sicherheitsprovider nach Name hinzu (z.B. SunPKCS11) -.providerArg.option.1=\u0020 [-providerArg ]] ... Konfiguriert Argument für -addprovider +.providerArg.option.1=\ [-providerArg ]] ... Konfiguriert Argument für -addprovider .providerClass.option=[-providerClass Fügt einen Sicherheitsprovider nach vollqualifiziertem Klassennamen hinzu -.providerArg.option.2=\u0020 [-providerArg ]] ... Konfiguriert Argument für -providerClass +.providerArg.option.2=\ [-providerArg ]] ... Konfiguriert Argument für -providerClass .providerPath.option=[-providerPath ] Provider-Classpath .strict.treat.warnings.as.errors=[-strict] Behandelt Warnungen als Fehler .conf.url.specify.a.pre.configured.options.file=[-conf ] Vorkonfigurierte Optionsdatei angeben @@ -83,11 +83,11 @@ k=k X=X q=? .and.d.more.=(und %d mehr) -.s.signature.was.verified.=\u0020 s = Signatur wurde verifiziert\u0020 -.m.entry.is.listed.in.manifest=\u0020 m = Eintrag ist in Manifest aufgeführt -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k = Mindestens ein Zertifikat im Keystore gefunden -.X.not.signed.by.specified.alias.es.=\u0020 X = Nicht von den angegebenen Aliasnamen signiert -.q.unsigned.entry=\u0020 ? = Nicht signierter Eintrag +.s.signature.was.verified.=\ s = Signatur wurde verifiziert\u0020 +.m.entry.is.listed.in.manifest=\ m = Eintrag ist in Manifest aufgeführt +.k.at.least.one.certificate.was.found.in.keystore=\ k = Mindestens ein Zertifikat im Keystore gefunden +.X.not.signed.by.specified.alias.es.=\ X = Nicht von den angegebenen Aliasnamen signiert +.q.unsigned.entry=\ ? = Nicht signierter Eintrag no.manifest.=Kein Manifest. .Signature.related.entries.=(Signaturbezogene Einträge) .Unsigned.entries.=(Nicht signierte Einträge) @@ -96,14 +96,15 @@ jar.is.unsigned=JAR-Datei ist nicht signiert. jar.treated.unsigned=Warnung: Signatur kann entweder nicht geparst oder nicht verifiziert werden. Die JAR-Datei wird als nicht signiert behandelt. Weitere Informationen erhalten Sie, indem Sie "jarsigner" mit aktiviertem Debugging erneut ausführen (-J-Djava.security.debug=jar). jar.treated.unsigned.see.weak=Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der jetzt deaktiviert ist.\n\nFühren Sie "jarsigner" mit der Option "-verbose" erneut aus, um weitere Einzelheiten zu erhalten. jar.treated.unsigned.see.weak.verbose=Warnung: Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der mittlerweile von der folgenden Sicherheitseigenschaft deaktiviert wurde: -jar.signed.=JAR-Datei signiert. +multiple.manifest.warning.=Doppelte Manifesteinträge in der JAR-Datei erkannt. JarSigner hat nur einen Eintrag bearbeitet. Die anderen wurden verworfen. +jar.signed.=JAR signiert. jar.signed.with.signer.errors.=JAR-Datei signiert, mit Signaturgeberfehlern. -jar.verified.=JAR-Datei verifiziert. +jar.verified.=JAR verifiziert. jar.verified.with.signer.errors.=JAR-Datei verifiziert, mit Signaturgeberfehlern. history.with.ts=- Von "%1$s" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s\n Zeitstempel von "%6$s" am %5$tc\n Digestalgorithmus für Zeitstempel: %7$s\n Signaturalgorithmus für Zeitstempel: %8$s, %9$s history.without.ts=- Von "%1$s" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s -history.nonexistent.entries=\u0020 Warnung: Nicht vorhandene signierte Einträge:\u0020 +history.nonexistent.entries=\ Warnung: Nicht vorhandene signierte Einträge:\u0020 history.unparsable=- Signaturbezogene Datei %s kann nicht geparst werden history.nosf=- Signaturbezogene Datei META-INF/%s.SF fehlt history.nobk=- Blockdatei für signaturbezogene Datei META-INF/%s.SF fehlt @@ -113,8 +114,8 @@ with.algparams.weak=%1$s mit %2$s (schwach) with.disabled=%s (deaktiviert) with.algparams.disabled=%1$s mit %2$s (deaktiviert) key.bit=%s-Schlüssel -key.bit.weak=%s Schlüssel (schwach) -key.bit.disabled=%s Schlüssel (deaktiviert) +key.bit.weak=%s-Schlüssel (schwach) +key.bit.disabled=%s-Schlüssel (deaktiviert) nonexistent.entries.found=Diese JAR-Datei enthält signierte Einträge für Dateien, die nicht vorhanden sind. Weitere Details finden Sie in der Verbose-Ausgabe (-verbose). external.file.attributes.detected=POSIX-Dateiberechtigung und/oder Symlink-Attribute erkannt. Diese Attribute werden bei der Signatur ignoriert und sind nicht durch die Signatur geschützt. @@ -122,9 +123,9 @@ jarsigner.=jarsigner:\u0020 signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=Signaturdateiname muss aus den folgenden Zeichen bestehen: A-Z, 0-9, _ oder - unable.to.open.jar.file.=JAR-Datei kann nicht geöffnet werden:\u0020 unable.to.create.=Erstellen nicht möglich:\u0020 -.adding.=\u0020 Wird hinzugefügt:\u0020 -.updating.=\u0020Wird aktualisiert:\u0020 -.signing.=\u0020 Wird signiert:\u0020 +.adding.=\ Wird hinzugefügt:\u0020 +.updating.=\ Wird aktualisiert:\u0020 +.signing.=\ Wird signiert:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed=Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich attempt.to.rename.jarFile.to.origJar.failed=Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich unable.to.sign.jar.=JAR-Datei kann nicht signiert werden:\u0020 @@ -149,7 +150,7 @@ certificate.will.expire.on=Zertifikat läuft am {0} ab .Invalid.certificate.chain.=[Ungültige Zertifikatskette:\u0020 .Invalid.TSA.certificate.chain.=[Ungültige TSA-Zertifikatskette:\u0020 requesting.a.signature.timestamp=Signaturzeitstempel wird angefordert -TSA.location.=TSA-Ort:\u0020 +TSA.location.=TSA-Speicherort:\u0020 TSA.certificate.=TSA-Zertifikat:\u0020 no.response.from.the.Timestamping.Authority.=Keine Antwort von der Zeitstempelautorität. Bei Verbindungen hinter einer Firewall muss möglicherweise ein HTTP- oder HTTPS-Proxy angegeben werden. Geben Sie die folgenden Optionen für "jarsigner" an: or=oder @@ -159,9 +160,9 @@ Warning.=Warnung:\u0020 Error.=Fehler:\u0020 ...Signer=>>> Signaturgeber ...TSA=>>> TSA -trusted.certificate=vertrauenswürdiges Zertifikat +trusted.certificate=Vertrauenswürdiges Zertifikat This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.=Diese JAR-Datei enthält nicht signierte Einträge, deren Integrität nicht geprüft wurde.\u0020 -This.jar.contains.entries.whose.signer.certificate.has.expired.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat abgelaufen ist. +This.jar.contains.entries.whose.signer.certificate.has.expired.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat abgelaufen ist.\u0020 This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat innerhalb der nächsten sechs Monate abläuft.\u0020 This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat noch nicht gültig ist.\u0020 This.jar.contains.entries.whose.signer.certificate.is.self.signed.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat selbstsigniert ist. @@ -188,9 +189,9 @@ The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is. The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Digestalgorithmus des Zeitstempels gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Digestalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Signaturalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. -size.bit.alg=%1$d-Bit %2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=Der %s Signaturschlüssel wird als Sicherheitsrisiko betrachtet. Wird in einem zukünftigen Update deaktiviert. -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=Der %s Signaturschlüssel wird als Sicherheitsrisiko betrachtet und ist deaktiviert. +size.bit.alg=%1$d-Bit-%2$s +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=Der %1$s-Signaturschlüssel gilt als Sicherheitsrisiko. Er wird in einem zukünftigen Update deaktiviert. +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=Der %s-Signaturschlüssel gilt als Sicherheitsrisiko und ist deaktiviert. This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=Diese JAR-Datei enthält Einträge, deren Zertifikatskette ungültig ist. Grund: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=Diese JAR-Datei enthält Einträge, deren TSA-Zertifikatskette ungültig ist. Grund: %s no.timestamp.signing=Weder -tsa noch -tsacert wurde angegeben, und diese JAR-Datei hat keinen Zeitstempel. Ohne Zeitstempel können Benutzer diese JAR-Datei nach dem Ablaufdatum des Signaturgeberzertifikats (%1$tY-%1$tm-%1$td) möglicherweise nicht mehr validieren. @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=Umgebungsvariable kann nicht gefunden werden:\ Cannot.find.file.=Datei kann nicht gefunden werden:\u0020 event.ocsp.check=Verbindung zu OCSP-Server bei %s wird hergestellt... event.crl.check=CRL wird von %s heruntergeladen... +manifest.missing.when.reading.jarfile=Manifest fehlt beim Lesen über JarFile +manifest.missing.when.reading.jarinputstream=Manifest fehlt beim Lesen über JarInputStream +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=Manifesthauptattribut %s ist beim Lesen über JarFile vorhanden, aber fehlt beim Lesen über JarInputStream +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=Manifesthauptattribut %s ist beim Lesen über JarInputStream vorhanden, aber fehlt beim Lesen über JarFile +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=Manifesthauptattribut %1$s unterschiedlich: JarFile-Wert = %2$s, JarInputStream-Wert = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=Eintrag %s ist beim Lesen über JarInputStream vorhanden, aber fehlt beim Lesen über JarFile +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=Eintrag %s ist beim Lesen über JarFile vorhanden, aber fehlt beim Lesen über JarInputStream +entry.1.present.in.jarfile.but.unreadable=Eintrag %s ist in JarFile vorhanden, aber nicht lesbar +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=Codesignaturgeber für Eintrag %s beim Lesen über JarFile anders als bei JarInputStream +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=Eintrag %s ist in JarFile, aber nicht in JarInputStream signiert +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=Eintrag %s ist in JarInputStream, aber nicht in JarFile signiert +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=Diese JAR-Datei enthält interne Inkonsistenzen, die zu anderem Inhalt beim Lesen über JarFile als beim Lesen über JarInputStream führen können: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=Signaturverifizierung war für Eintrag %s beim Lesen über JarInputStream nicht erfolgreich +signature.verification.failed.on.entry.1.when.reading.via.jarfile=Signaturverifizierung war für Eintrag %s beim Lesen über JarFile nicht erfolgreich diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties index e13d8b5a471..97ab6a918cb 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%sはプロバイダではありません provider.name.not.found=プロバイダ名"%s"が見つかりません @@ -37,8 +37,8 @@ Illegal.option.=不正なオプション:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=-protectedを指定する場合は、-storepassおよび-keypassを指定しないでください If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=キーストアがパスワードで保護されていない場合、-storepassおよび-keypassを指定しないでください Usage.jarsigner.options.jar.file.alias=使用方法: jarsigner [options] jar-file alias -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [options] jar-file [alias...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [options] jar-file [alias...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] キーストアの位置 .storepass.password.password.for.keystore.integrity=[-storepass ] キーストア整合性のためのパスワード .storetype.type.keystore.type=[-storetype ] キーストアの型 @@ -47,25 +47,25 @@ Usage.jarsigner.options.jar.file.alias=使用方法: jarsigner [options] jar-fil .sigfile.file.name.of.SF.DSA.file=[-sigfile ] .SF/.DSAファイルの名前 .signedjar.file.name.of.signed.JAR.file=[-signedjar ] 署名付きJARファイルの名前 .digestalg.algorithm.name.of.digest.algorithm=[-digestalg ] ダイジェスト・アルゴリズムの名前 -.sigalg.algorithm.name.of.signature.algorithm=[-sigalg ] シグネチャ・アルゴリズムの名前 +.sigalg.algorithm.name.of.signature.algorithm=[-sigalg ] 署名アルゴリズムの名前 .verify.verify.a.signed.JAR.file=[-verify] 署名付きJARファイルの検証 .version.print.the.program.version=[-version] プログラム・バージョンを出力します .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] 署名/検証時の詳細出力。 -.suboptions.can.be.all.grouped.or.summary=\u0020 サブオプションとして、all、groupedまたはsummaryを使用できます +.suboptions.can.be.all.grouped.or.summary=\ サブオプションとして、all、groupedまたはsummaryを使用できます .certs.display.certificates.when.verbose.and.verifying=[-certs] 詳細出力および検証時に証明書を表示 .certs.revocation.check=[-revCheck] 証明書失効チェックの有効化 .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] タイムスタンプ局の場所 .tsacert.alias.public.key.certificate.for.Timestamping.Authority=[-tsacert ] タイムスタンプ局の公開キー証明書 .tsapolicyid.tsapolicyid.for.Timestamping.Authority=[-tsapolicyid ] タイムスタンプ局のTSAPolicyID .tsadigestalg.algorithm.of.digest.data.in.timestamping.request=[-tsadigestalg ] タイムスタンプ・リクエストのダイジェスト・データのアルゴリズム -.internalsf.include.the.SF.file.inside.the.signature.block=[-internalsf] シグネチャ・ブロックに.SFファイルを含める +.internalsf.include.the.SF.file.inside.the.signature.block=[-internalsf] 署名ブロックに.SFファイルを含める .sectionsonly.don.t.compute.hash.of.entire.manifest=[-sectionsonly] マニフェスト全体のハッシュは計算しない .protected.keystore.has.protected.authentication.path=[-protected] キーストアには保護された認証パスがある .providerName.name.provider.name=[-providerName ] プロバイダ名 .add.provider.option=[-addprovider 名前でセキュリティ・プロバイダを追加する(SunPKCS11など) -.providerArg.option.1=\u0020 [-providerArg ]] ... -addproviderの引数を構成する +.providerArg.option.1=\ [-providerArg ]] ... -addproviderの引数を構成する .providerClass.option=[-providerClass 完全修飾クラス名でセキュリティ・プロバイダを追加する -.providerArg.option.2=\u0020 [-providerArg ]] ... -providerClassの引数を構成する +.providerArg.option.2=\ [-providerArg ]] ... -providerClassの引数を構成する .providerPath.option=[-providerPath ] プロバイダ・クラスパス .strict.treat.warnings.as.errors=[-strict] 警告をエラーとして処理 .conf.url.specify.a.pre.configured.options.file=[-conf ] 事前構成済のオプション・ファイルを指定する @@ -83,19 +83,20 @@ k=k X=X q=? .and.d.more.=(他にも%d個) -.s.signature.was.verified.=\u0020 s=シグネチャが検証されました\u0020 -.m.entry.is.listed.in.manifest=\u0020 m=エントリがマニフェスト内にリストされます -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k=1つ以上の証明書がキーストアで検出されました -.X.not.signed.by.specified.alias.es.=\u0020 X =指定した別名で署名されていません -.q.unsigned.entry=\u0020 ? = 署名なしのエントリ +.s.signature.was.verified.=\ s=署名が検証されました\u0020 +.m.entry.is.listed.in.manifest=\ m=エントリがマニフェスト内にリストされます +.k.at.least.one.certificate.was.found.in.keystore=\ k=1つ以上の証明書がキーストアで検出されました +.X.not.signed.by.specified.alias.es.=\ X =指定した別名で署名されていません +.q.unsigned.entry=\ ? = 署名なしのエントリ no.manifest.=マニフェストは存在しません。 -.Signature.related.entries.=(シグネチャ関連エントリ) +.Signature.related.entries.=(署名関連エントリ) .Unsigned.entries.=(署名なしのエントリ) .Directory.entries.=(ディレクトリ・エントリ) jar.is.unsigned=jarは署名されていません。 jar.treated.unsigned=警告: 署名が構文解析できないか検証できないため、このjarは署名なしとして扱われます。詳細は、デバッグを有効にして(-J-Djava.security.debug=jar) jarsignerを再実行してください。 jar.treated.unsigned.see.weak=このjarは、現在無効になっている弱いアルゴリズムで署名されているため、署名なしとして扱われます。\n\n詳細は、-verboseオプションを使用してjarsignerを再実行してください。 jar.treated.unsigned.see.weak.verbose=警告: このjarは、セキュリティ・プロパティによって現在無効になっている弱いアルゴリズムで署名されているため、署名なしとして扱われます: +multiple.manifest.warning.=jarファイルで重複したマニフェスト・エントリが検出されました。JarSignerは1つでのみ動作し、その他は破棄されました。 jar.signed.=jarは署名されました。 jar.signed.with.signer.errors.=jarは署名されました - 署名者エラーがあります。 jar.verified.=jarが検証されました。 @@ -103,7 +104,7 @@ jar.verified.with.signer.errors.=jarは検証されました - 署名者エラ history.with.ts=- 署名者: "%1$s"\n ダイジェスト・アルゴリズム: %2$s\n 署名アルゴリズム: %3$s、%4$s\n タイムスタンプ付加者: "%6$s" 日時: %5$tc\n タイムスタンプのダイジェスト・アルゴリズム: %7$s\n タイムスタンプの署名アルゴリズム: %8$s、%9$s history.without.ts=- 署名者: "%1$s"\n ダイジェスト・アルゴリズム: %2$s\n 署名アルゴリズム: %3$s、%4$s -history.nonexistent.entries=\u0020 警告: 存在しない署名済エントリ:\u0020 +history.nonexistent.entries=\ 警告: 存在しない署名済エントリ:\u0020 history.unparsable=- 署名関連ファイル%sを解析できません history.nosf=- 署名関連ファイルMETA-INF/%s.SFがありません history.nobk=- 署名関連ファイルMETA-INF/%s.SFのブロック・ファイルがありません @@ -113,18 +114,18 @@ with.algparams.weak=%2$sを使用した%1$s (弱) with.disabled=%s (無効) with.algparams.disabled=%2$sを使用した%1$s (無効) key.bit=%sキー -key.bit.weak=%sキー(弱い) +key.bit.weak=%sキー(弱) key.bit.disabled=%sキー(無効) nonexistent.entries.found=このjarには、存在しないファイルの署名済エントリが含まれます。詳細は、-verbose出力を参照してください。 external.file.attributes.detected=POSIXファイル権限またはsymlink(あるいはその両方)の属性が検出されました。署名中はこれらの属性は無視され、署名によって保護されません。 jarsigner.=jarsigner:\u0020 -signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=シグネチャのファイル名に使用できる文字は、A-Z、0-9、_、- のみです。 +signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=署名のファイル名に使用できる文字は、A-Z、0-9、_、- のみです unable.to.open.jar.file.=次のjarファイルを開くことができません:\u0020 unable.to.create.=作成できません:\u0020 -.adding.=\u0020 追加中:\u0020 -.updating.=\u0020更新中:\u0020 -.signing.=\u0020 署名中:\u0020 +.adding.=\ 追加中:\u0020 +.updating.=\ 更新中:\u0020 +.signing.=\ 署名中:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed={0}の名前を{1}に変更しようとしましたが失敗しました attempt.to.rename.jarFile.to.origJar.failed={0}の名前を{1}に変更しようとしましたが失敗しました unable.to.sign.jar.=jarに署名できません:\u0020 @@ -148,7 +149,7 @@ certificate.is.not.valid.until=証明書は{0}まで有効ではありません certificate.will.expire.on=証明書は{0}に失効します .Invalid.certificate.chain.=[無効な証明書チェーン:\u0020 .Invalid.TSA.certificate.chain.=[無効なTSA証明書チェーン:\u0020 -requesting.a.signature.timestamp=シグネチャ・タイムスタンプのリクエスト +requesting.a.signature.timestamp=署名タイムスタンプのリクエスト TSA.location.=TSAの場所:\u0020 TSA.certificate.=TSA証明書:\u0020 no.response.from.the.Timestamping.Authority.=タイムスタンプ局からのレスポンスがありません。ファイアウォールを介して接続するときは、必要に応じてHTTPまたはHTTPSプロキシを指定してください。jarsignerに次のオプションを指定してください: @@ -164,7 +165,7 @@ This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.=この This.jar.contains.entries.whose.signer.certificate.has.expired.=このjarには、署名者の証明書が期限切れのエントリが含まれています。\u0020 This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.=このjarには、署名者の証明書が6か月以内に期限切れとなるエントリが含まれています。\u0020 This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.=このjarには、署名者の証明書がまだ有効になっていないエントリが含まれています。\u0020 -This.jar.contains.entries.whose.signer.certificate.is.self.signed.=このjarには、署名者の証明書が自己署名されているエントリが含まれています。\u0020 +This.jar.contains.entries.whose.signer.certificate.is.self.signed.=このjarには、署名者の証明書が自己署名されているエントリが含まれています。 Re.run.with.the.verbose.and.certs.options.for.more.details.=詳細は、-verboseおよび-certsオプションを使用して再実行してください。 The.signer.certificate.has.expired.=署名者の証明書は期限切れです。 The.timestamp.expired.1.but.usable.2=タイムスタンプは%1$tY-%1$tm-%1$tdに期限切れになります。ただし、JARは署名者の証明書が%2$tY-%2$tm-%2$tdに期限切れになるまで有効です。 @@ -188,9 +189,9 @@ The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is. The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$sタイムスタンプ・ダイジェスト・アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$sダイジェスト・アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s署名アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 -size.bit.alg=%1$dビット%2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s署名キーはセキュリティ・リスクとみなされます。今後の更新では無効になります。 -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s署名キーはセキュリティ・リスクとみなされ、無効になっています。 +size.bit.alg=%1$d-ビット %2$s +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s署名キーはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s署名キーはセキュリティ・リスクとみなされ、無効化されています。 This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=このjarには、証明書チェーンが無効なエントリが含まれています。理由: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=このjarには、TSA証明書チェーンが無効なエントリが含まれています。理由: %s no.timestamp.signing=-tsaまたは-tsacertが指定されていないため、このjarにはタイムスタンプが付加されていません。タイムスタンプがないと、署名者証明書の有効期限(%1$tY-%1$tm-%1$td)後に、ユーザーはこのjarを検証できない可能性があります。 @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=環境変数が見つかりません:\u0020 Cannot.find.file.=ファイルが見つかりません:\u0020 event.ocsp.check=%sのOCSPサーバーに接続しています... event.crl.check=%sからCRLをダウンロードしています... +manifest.missing.when.reading.jarfile=JarFileを介して読み取るときにマニフェストがありません +manifest.missing.when.reading.jarinputstream=JarInputStreamを介して読み取るときにマニフェストがありません +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=マニフェストのメイン属性%sは、JarFileを介して読み取るときは存在しますが、JarInputStreamを介して読み取るときにはありません +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=マニフェストのメイン属性%sは、JarInputStreamを介して読み取るときは存在しますが、JarFileを介して読み取るときにはありません +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=マニフェストのメイン属性%1$sが異なります: JarFileの値 = %2$s、JarInputStreamの値 = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=エントリ%sは、JarInputStreamを介して読み取るときは存在しますが、JarFileを介して読み取るときにはありません +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=エントリ%sは、JarFileを介して読み取るときは存在しますが、JarInputStreamを介して読み取るときにはありません +entry.1.present.in.jarfile.but.unreadable=エントリ%sはJarFileに存在しますが読み取れません +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=JarFileとJarInputStreamから読み取る場合のエントリ%sのコード署名者が異なります +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=エントリ%sは、JarFileでは署名されていますが、JarInputStreamでは署名されていません +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=エントリ%sは、JarInputStreamでは署名されていますが、JarFileでは署名されていません +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=このJARファイルには内部的な不整合があるため、JarFileとJarInputStreamから読み取る場合にコンテンツが異なる可能性があります: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=JarInputStreamを介して読み取るときに署名検証がエントリ%sで失敗しました +signature.verification.failed.on.entry.1.when.reading.via.jarfile=JarFileを介して読み取るときに署名検証がエントリ%sで失敗しました diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties index 2558239039f..378cc3ba9fc 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%s不是提供方 provider.name.not.found=未找到名为 "%s" 的提供方 @@ -37,8 +37,8 @@ Illegal.option.=非法选项:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=如果指定了 -protected, 则不能指定 -storepass 和 -keypass If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=如果密钥库未受口令保护, 则不能指定 -storepass 和 -keypass Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别名 -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [选项] jar-file [别名...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [选项] jar-file [别名...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] 密钥库位置 .storepass.password.password.for.keystore.integrity=[-storepass <口令>] 用于密钥库完整性的口令 .storetype.type.keystore.type=[-storetype <类型>] 密钥库类型 @@ -51,7 +51,7 @@ Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别 .verify.verify.a.signed.JAR.file=[-verify] 验证已签名的 JAR 文件 .version.print.the.program.version=[-version] 输出程序版本 .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] 签名/验证时输出详细信息。 -.suboptions.can.be.all.grouped.or.summary=\u0020 子选项可以是 all, grouped 或 summary +.suboptions.can.be.all.grouped.or.summary=\ 子选项可以是 all, grouped 或 summary .certs.display.certificates.when.verbose.and.verifying=[-certs] 输出详细信息和验证时显示证书 .certs.revocation.check=[-revCheck] 启用证书撤消检查 .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] 时间戳颁发机构的位置 @@ -63,9 +63,9 @@ Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别 .protected.keystore.has.protected.authentication.path=[-protected] 密钥库具有受保护验证路径 .providerName.name.provider.name=[-providerName <名称>] 提供方名称 .add.provider.option=[-addprovider <名称> 按名称 (例如 SunPKCS11) 添加安全提供方 -.providerArg.option.1=\u0020 [-providerArg <参数>]] ... 配置 -addprovider 的参数 +.providerArg.option.1=\ [-providerArg <参数>]] ... 配置 -addprovider 的参数 .providerClass.option=[-providerClass <类> 按全限定类名添加安全提供方 -.providerArg.option.2=\u0020 [-providerArg <参数>]] ... 配置 -providerClass 的参数 +.providerArg.option.2=\ [-providerArg <参数>]] ... 配置 -providerClass 的参数 .providerPath.option=[-providerPath ] 提供方类路径 .strict.treat.warnings.as.errors=[-strict] 将警告视为错误 .conf.url.specify.a.pre.configured.options.file=[-conf ] 指定预配置的选项文件 @@ -83,11 +83,11 @@ k=k X=X q=? .and.d.more.=(%d 及以上) -.s.signature.was.verified.=\u0020 s = 已验证签名\u0020 -.m.entry.is.listed.in.manifest=\u0020 m = 在清单中列出条目 -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k = 在密钥库中至少找到了一个证书 -.X.not.signed.by.specified.alias.es.=\u0020 X = 未由指定别名签名 -.q.unsigned.entry=\u0020 ? = 未签名条目 +.s.signature.was.verified.=\ s = 已验证签名\u0020 +.m.entry.is.listed.in.manifest=\ m = 在清单中列出条目 +.k.at.least.one.certificate.was.found.in.keystore=\ k = 在密钥库中至少找到了一个证书 +.X.not.signed.by.specified.alias.es.=\ X = 未由指定别名签名 +.q.unsigned.entry=\ ? = 未签名条目 no.manifest.=没有清单。 .Signature.related.entries.=(与签名相关的条目) .Unsigned.entries.=(未签名条目) @@ -96,6 +96,7 @@ jar.is.unsigned=jar 未签名。 jar.treated.unsigned=警告: 签名无法解析或验证, 该 jar 将被视为未签名。有关详细信息, 请在启用调试的情况下重新运行 jarsigner (-J-Djava.security.debug=jar)。 jar.treated.unsigned.see.weak=由于该 jar 是使用目前已禁用的弱算法签名的, 因此该 jar 将被视为未签名。\n\n有关详细信息, 请使用 -verbose 选项重新运行 jarsigner。 jar.treated.unsigned.see.weak.verbose=警告: 该 jar 将被视为未签名, 因为它是由目前安全属性禁用的弱算法签名的: +multiple.manifest.warning.=在 jar 文件中检测到重复的清单条目。JarSigner 仅对其中一个条目进行了操作,其他条目都已放弃。 jar.signed.=jar 已签名。 jar.signed.with.signer.errors.=jar 已签名, 但出现签名者错误。 jar.verified.=jar 已验证。 @@ -103,28 +104,28 @@ jar.verified.with.signer.errors.=jar 已验证, 但出现签名者错误。 history.with.ts=- 由 "%1$s" 签名\n 摘要算法: %2$s\n 签名算法: %3$s, %4$s\n 由 "%6$s" 于 %5$tc 加时间戳\n 时间戳摘要算法: %7$s\n 时间戳签名算法: %8$s, %9$s history.without.ts=- 由 "%1$s" 签名\n 摘要算法: %2$s\n 签名算法: %3$s, %4$s -history.nonexistent.entries=警告:不存在的签名条目:\u0020 +history.nonexistent.entries=\ 警告:不存在的签名条目:\u0020 history.unparsable=- 无法解析的与签名相关的文件 %s history.nosf=- 缺少与签名相关的文件 META-INF/%s.SF history.nobk=- 与签名相关的文件 META-INF/%s.SF 缺少块文件 -with.weak=%s (弱) +with.weak=%s(弱) with.algparams.weak=%1$s 使用 %2$s(弱) with.disabled=%s(禁用) with.algparams.disabled=%1$s 使用 %2$s(禁用) key.bit=%s 密钥 key.bit.weak=%s 密钥(弱) -key.bit.disabled=%s 密钥(已禁用) +key.bit.disabled=%s 密钥(禁用) nonexistent.entries.found=此 jar 的文件包含不存在的签名条目。有关更多详细信息,请参见 -verbose 输出。 external.file.attributes.detected=检测到 POSIX 文件权限和/或 symlink 属性。这些属性在进行签名时会被忽略,不受该签名的保护。 -jarsigner.=jarsigner:\u0020 +jarsigner.=jarsigner:\u0020 signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=签名文件名必须包含以下字符: A-Z, 0-9, _ 或 - unable.to.open.jar.file.=无法打开 jar 文件:\u0020 unable.to.create.=无法创建:\u0020 -.adding.=\u0020 正在添加:\u0020 -.updating.=\u0020正在更新:\u0020 -.signing.=\u0020 正在签名:\u0020 +.adding.=\ 正在添加:\u0020 +.updating.=\ 正在更新:\u0020 +.signing.=\ 正在签名:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed=尝试将{0}重命名为{1}时失败 attempt.to.rename.jarFile.to.origJar.failed=尝试将{0}重命名为{1}时失败 unable.to.sign.jar.=无法对 jar 进行签名:\u0020 @@ -151,12 +152,12 @@ certificate.will.expire.on=证书将在{0}到期 requesting.a.signature.timestamp=正在请求签名时间戳 TSA.location.=TSA 位置:\u0020 TSA.certificate.=TSA 证书:\u0020 -no.response.from.the.Timestamping.Authority.=时间戳颁发机构没有响应。如果要从防火墙后面连接, 则可能需要指定 HTTP 或 HTTPS 代理。请为 jarsigner 提供以下选项:\u0020 +no.response.from.the.Timestamping.Authority.=时间戳颁发机构没有响应。如果要从防火墙后面连接, 则可能需要指定 HTTP 或 HTTPS 代理。请为 jarsigner 提供以下选项: or=或 Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the=找不到{0}的证书。{1}必须引用包含时间戳颁发机构的 X.509 公共密钥证书的有效密钥库条目。 entry.was.signed.on=条目的签名日期为 {0} -Warning.=警告:\u0020 -Error.=错误:\u0020 +Warning.=警告:\u0020 +Error.=错误:\u0020 ...Signer=>>> 签名者 ...TSA=>>> TSA trusted.certificate=可信证书 @@ -189,8 +190,8 @@ The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.w The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s 摘要算法被视为存在安全风险。此算法将在未来的更新中被禁用。 The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s 签名算法被视为存在安全风险。此算法将在未来的更新中被禁用。 size.bit.alg=%1$d 位 %2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s 签名密钥被视为安全风险。在将来的更新中将禁用它。 -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s 签名密钥被视为安全风险并被禁用。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s 签名密钥被视为存在安全风险。它将在未来的更新中被禁用。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s 签名密钥被视为存在安全风险而且被禁用。 This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=此 jar 包含其证书链无效的条目。原因: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=此 jar 包含其 TSA 证书链无效的条目。原因: %s no.timestamp.signing=未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期日期 (%1$tY-%1$tm-%1$td) 之后, 用户可能无法验证此 jar。 @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=找不到环境变量:\u0020 Cannot.find.file.=找不到文件:\u0020 event.ocsp.check=正在联系位于 %s 的 OCSP 服务器... event.crl.check=正在从 %s 下载 CRL... +manifest.missing.when.reading.jarfile=通过 JarFile 读取时缺少清单 +manifest.missing.when.reading.jarinputstream=通过 JarInputStream 读取时缺少清单 +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=通过 JarFile 读取时,清单主属性 %s 存在,但通过 JarInputStream 读取时缺失 +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=通过 JarInputStream 读取时,清单主属性 %s 存在,但通过 JarFile 读取时缺失 +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=清单主属性 %1$s 不同:JarFile 值 = %2$s,JarInputStream 值 = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=通过 JarInputStream 读取时,条目 %s 存在,但通过 JarFile 读取时缺失 +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=通过 JarFile 读取时,条目 %s 存在,但通过 JarInputStream 读取时缺失 +entry.1.present.in.jarfile.but.unreadable=条目 %s 存在于 JarFile 中,但无法读取 +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=从 JarFile 和 JarInputStream 读取时,条目 %s 的代码签名者不同 +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=条目 %s 已在 JarFile 中签名,但未在 JarInputStream 中签名 +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=条目 %s 已在 JarInputStream 中签名,但未在 JarFile 中签名 +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=此 JAR 文件包含内部不一致,通过 JarFile 和 JarInputStream 读取时可能会导致内容不同: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=通过 JarInputStream 读取时,条目 %s 的签名验证失败 +signature.verification.failed.on.entry.1.when.reading.via.jarfile=通过 JarFile 读取时,条目 %s 的签名验证失败 diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties index e81bda89ef3..2a5786e10b4 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -58,6 +58,7 @@ error.missing.provider=Serviceprovider nicht gefunden: {0} error.release.value.notnumber=Release {0} nicht gültig error.release.value.toosmall=Release {0} nicht gültig, muss >= 9 sein error.release.unexpected.versioned.entry=Unerwarteter versionierte Eintrag {0} für Release {1} +error.release.value.toohigh.versioned.entry={0} hat Klassendateiversion {1}, aber Klassendateiversion {2} oder niedriger ist für Release {3} der Java-Plattform erforderlich error.date.notvalid=Datum {0} ist keine gültige erweiterte Datums-/Uhrzeitangabe mit Zeitunterschied und optionaler Zeitzone nach ISO-8601 error.date.out.of.range=Datum {0} liegt nicht im gültigen Bereich 1980-01-01T00:00:02Z bis 2099-12-31T23:59:59Z error.validator.jarfile.exception={0} kann nicht validiert werden: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: module-info.class in einem versionie warn.validator.identical.entry=Warnung: Eintrag {0} enthält eine Klasse, die mit\neinem bereits in der JAR-Datei enthaltenen Eintrag identisch ist warn.validator.resources.with.same.name=Warnung: Eintrag {0}, mehrere Ressourcen mit demselben Namen warn.validator.concealed.public.class=Warnung: Eintrag {0} ist eine öffentliche Klasse\nin einem verdeckten Package. Wenn Sie diese JAR-Datei in den Classpath einfügen, kommt es\nzu nicht kompatiblen öffentlichen Schnittstellen +warn.validator.duplicate.cen.entry=Warnung: {0} zentrale Verzeichniseinträge für {1} gefunden +warn.validator.duplicate.loc.entry=Warnung: {0} lokale Dateiheader für {1} gefunden +warn.validator.invalid.entry.name=Warnung: Eintragsname {0} ist ungültig +warn.validator.cen.only.entry=Warnung: Kein Äquivalent für zentralen Verzeichniseintrag {0} in den lokalen Dateiheadern gefunden +warn.validator.loc.only.entry=Warnung: Kein äquivalenter Eintrag für den lokalen Dateiheader {0} im zentralen Verzeichnis gefunden +warn.validator.order.mismatch=Warnung: Zentrale Verzeichniseinträge und lokale Dateiheadereinträge sind nicht in derselben Reihenfolge warn.release.unexpected.versioned.entry=Unerwarteter versionierter Eintrag {0} warn.index.is.ignored=Der JAR-Index (META-INF/INDEX.LIST) wird seit JDK 18 zur Laufzeit ignoriert warn.flag.is.deprecated=Warnung: Die Option {0} ist veraltet und wird möglicherweise ignoriert oder in einem zukünftigen Release entfernt\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t, --list Das Inhaltsverzeichnis fü main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren main.help.opt.main.extract=\ -x, --extract Extrahiert benannte (oder alle) Dateien aus dem Archiv.\n Wenn eine Datei mit demselben Namen mehrmals im\n Archiv enthalten ist, wird jede Kopie extrahiert. Dabei überschreiben (ersetzen) neuere Kopien\n ältere Kopien, es sei denn, "-k" ist angegeben. main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus -main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option\n validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API über die verschiedenen Releaseversionen\n hinweg konsistent ist. +main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option:\n - Validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API über die verschiedenen Releaseversionen\n hinweg konsistent ist.\n - Gibt eine Warnung aus, wenn ungültige oder doppelte Dateinamen vorhanden sind + + main.help.opt.any=\ In jedem Modus gültige Vorgangsmodifikatoren:\n\n -C DIR Zum angegebenen Verzeichnis wechseln und die folgende\n Datei aufnehmen. Bei Verwendung im Extraktionsmodus wird\n die JAR-Datei in das angegebene Verzeichnis extrahiert main.help.opt.any.file=\ -f, --file=FILE Der Name der Archivdatei. Wenn Sie dies auslassen, wird entweder stdin oder\n stdout verwendet, je nach Vorgang\n --release VERSION Speichert alle der folgenden Dateien in einem versionierten Verzeichnis\n der JAR-Datei (d.h. META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose Verbose-Ausgabe bei Standardausgabe generieren @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?, -h, --help[:compat] Gibt diese Meldung oder o main.help.opt.other.help-extra=\ --help-extra Hilfe zu zusätzlichen Optionen main.help.opt.other.version=\ --version Programmversion ausgeben main.help.postopt=\ Ein Archiv ist ein modulares JAR-Archiv, wenn der Moduldeskriptor "module-info.class"\n in der Root der angegebenen Verzeichnisse oder in der Root des JAR-Archivs selbst\n vorhanden ist. Die folgenden Vorgänge sind nur gültig, wenn Sie ein modulares JAR-Archiv\n erstellen oder ein vorhandenes nicht modulares JAR-Archiv aktualisieren: "--module-version",\n "--hash-modules" und "--modulepath".\n\n Obligatorische oder optionale Argumente zu langen Optionen sind auch für die jeweils\n zugehörigen kurzen Optionen obligatorisch oder optional. -main.help.opt.extract=\ Vorgangsmodifikatoren, die nur im Extraktionsmodus gültig sind:\n main.help.opt.extract.dir=\ --dir Verzeichnis, in das die JAR-Datei extrahiert wird diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties index 5be71c2e424..c7d7c14613a 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -58,6 +58,7 @@ error.missing.provider=サービス・プロバイダが見つかりません: { error.release.value.notnumber=リリース{0}は有効ではありません error.release.value.toosmall=リリース{0}は有効ではありません。9以上である必要があります error.release.unexpected.versioned.entry=リリース{1}で予期しないバージョニング済エントリ{0} +error.release.value.toohigh.versioned.entry={0}にはクラス・ファイル・バージョン{1}がありますが、Javaプラットフォームのリリース{3}をターゲットとするにはクラス・ファイル・バージョン{2}以下が必要です error.date.notvalid=日付{0}が、オプションのタイムゾーンを指定した、有効なISO-8601の拡張オフセットの日時ではありません error.date.out.of.range=日付{0}が有効な範囲1980-01-01T00:00:02Z to 2099-12-31T23:59:59Zにありません error.validator.jarfile.exception={0}を検証できません: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: バージョニングされたディ warn.validator.identical.entry=警告 : エントリ{0}には、jarにすでに存在する\nエントリと同じクラスが含まれます warn.validator.resources.with.same.name=警告 : エントリ{0}、同じ名前を持つ複数のリソース warn.validator.concealed.public.class=警告 : エントリ{0}は、隠しパッケージ内のpublicクラスです。\nクラスパスにこのjarを配置すると、互換性のない\npublicインタフェースが生成されます +warn.validator.duplicate.cen.entry=警告: {1}に対して{0}の中央ディレクトリ・エントリがありました +warn.validator.duplicate.loc.entry=警告: {1}に対して{0}のローカル・ファイル・ヘッダーがありました +warn.validator.invalid.entry.name=警告: エントリ名{0}が無効です +warn.validator.cen.only.entry=警告: 中央ディレクトリ・エントリ{0}と同等のものがローカル・ファイル・ヘッダーに見つかりませんでした +warn.validator.loc.only.entry=警告: ローカル・ファイル・ヘッダー{0}と同等のエントリが中央ディレクトリに見つかりませんでした +warn.validator.order.mismatch=警告: 中央ディレクトリとローカル・ファイル・ヘッダーのエントリが同じ順序ではありません warn.release.unexpected.versioned.entry=予期しないバージョニング済エントリ{0} warn.index.is.ignored=JDK 18以降、JAR索引(META-INF/INDEX.LIST)は実行時に無視されます warn.flag.is.deprecated=警告: {0}オプションは非推奨であり、今後のリリースで無視または削除される可能性があります\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t、--list アーカイブの内容 main.help.opt.main.update=\ -u、--update 既存のjarアーカイブを更新します main.help.opt.main.extract=\ -x、--extract 指定の(またはすべての)ファイルをアーカイブから抽出します。\n 同じ名前のファイルがアーカイブに複数回出現する場合、\n 各コピーが抽出され、後のコピーにより、前のコピーが\n 上書き(置換)されます(-kが指定されている場合以外)。 main.help.opt.main.describe-module=\ -d, --describe-module モジュール・ディスクリプタまたは自動モジュール名を出力します -main.help.opt.main.validate=\ --validate jarアーカイブの内容を検証します。このオプションは\n 複数リリースのjarアーカイブでエクスポートされたAPIが\n すべての異なるリリース・バージョンで一貫していることを\n 検証します。 +main.help.opt.main.validate=\ --validate jarアーカイブの内容を検証します。このオプションは\n - 複数リリースのjarアーカイブでエクスポートされたAPIが\n すべての異なるリリース・バージョンで一貫していることを\n 検証します。\n - 無効または重複するファイル名がある場合は警告を発行します + + main.help.opt.any=\ どのモードでも有効な操作修飾子:\n\n -C DIR 指定のディレクトリに変更し、次のファイルを\n 取り込みます。抽出モードで使用されている場合、jarを\n 指定のディレクトリに抽出します main.help.opt.any.file=\ -f、--file=FILE アーカイブ・ファイル名。省略した場合、stdinまたは\n stdoutのいずれかが操作に基づいて使用されます\n --release VERSION 次のすべてのファイルをjarのバージョニングされたディレクトリ\n (つまり、META-INF/versions/VERSION/)に配置します main.help.opt.any.verbose=\ -v、--verbose 標準出力に詳細な出力を生成します @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?、-h、--help[:compat] これ(オプショ main.help.opt.other.help-extra=\ --help-extra 追加オプションのヘルプを提供します main.help.opt.other.version=\ --version プログラム・バージョンを出力します main.help.postopt=\ モジュール・ディスクリプタ'module-info.class'が指定のディレクトリのルートまたは\n jarアーカイブ自体のルートにある場合、アーカイブはモジュラjarです。\n 次の操作は、モジュラjarの作成時または既存の非モジュラjarの更新時に\n のみ有効です: '--module-version'、\n '--hash-modules'および'--module-path'。\n\n ロング・オプションへの必須またはオプションの引数は、対応するショート・オプション\n に対しても必須またはオプションになります。 -main.help.opt.extract=\ 抽出モードでのみ有効な操作修飾子:\n main.help.opt.extract.dir=\ --dir jarが抽出されるディレクトリ diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties index 1f652d87029..1979f3e2386 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -58,6 +58,7 @@ error.missing.provider=未找到服务提供方: {0} error.release.value.notnumber=发行版 {0} 无效 error.release.value.toosmall=发行版 {0} 无效, 必须 >= 9 error.release.unexpected.versioned.entry=发行版 {1} 存在意外的版本化条目 {0} +error.release.value.toohigh.versioned.entry={0} 具有类文件版本 {1},但是 Java 平台的目标发行版 {3} 需要类文件版本 {2} 或更低版本 error.date.notvalid=日期 {0} 不是具有可选时区的有效 ISO-8601 扩展偏移日期时间 error.date.out.of.range=日期 {0} 不在 1980-01-01T00:00:02Z 到 2099-12-31T23:59:59Z 这一有效范围内 error.validator.jarfile.exception=无法验证 {0}: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: 版本化目录中的 module-info.cl warn.validator.identical.entry=警告: 条目 {0} 包含与 jar 中的\n现有条目相同的类 warn.validator.resources.with.same.name=警告: 条目 {0}, 多个资源具有相同名称 warn.validator.concealed.public.class=警告: 条目 {0} 是已隐藏程序包中的\n公共类, 将此 jar 放置在类路径中\n将导致公共接口不兼容 +warn.validator.duplicate.cen.entry=警告:为 {1} 找到 {0} 个中央目录条目 +warn.validator.duplicate.loc.entry=警告:为 {1} 找到 {0} 个本地文件标头 +warn.validator.invalid.entry.name=警告:条目名称 {0} 无效 +warn.validator.cen.only.entry=警告:在本地文件标头中找不到中央目录条目 {0} 的等效条目 +warn.validator.loc.only.entry=警告:在中央目录中找不到本地文件标头 {0} 的等效条目 +warn.validator.order.mismatch=警告:中央目录和本地文件标头条目的顺序不同 warn.release.unexpected.versioned.entry=意外的版本化条目 {0} warn.index.is.ignored=自 JDK 18 起,在运行时忽略 JAR 索引 (META-INF/INDEX.LIST) warn.flag.is.deprecated=警告:{0} 选项已过时,可能会在未来发行版中忽略或删除。\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t, --list 列出档案的目录 main.help.opt.main.update=\ -u, --update 更新现有 jar 档案 main.help.opt.main.extract=\ -x, --extract 从档案中提取指定的(或所有)文件。\n 如果某个同名的文件在档案中出现多次,\n 则将提取每个副本,除非指定 -k,否则\n 后面的副本将覆盖(替换)前面的副本。 main.help.opt.main.describe-module=\ -d, --describe-module 输出模块描述符或自动模块名称 -main.help.opt.main.validate=\ --validate 验证 jar 档案的内容。此选项\n 将验证由多发行版 jar 档案导出\n 的 API 在所有不同的发行版本中\n 是否一致。 +main.help.opt.main.validate=\ --validate 验证 jar 档案的内容。此选项:\n - 验证由多发行版 jar 档案导出\n 的 API 在所有不同的发行版本中\n 是否一致。\n - 如果文件名无效或重复,则发出警告 + + main.help.opt.any=\ 在任意模式下有效的操作修饰符:\n\n -C DIR 更改为指定目录并包含\n 以下文件。在提取模式下使用时,\n 将 jar 提取到指定目录 main.help.opt.any.file=\ -f, --file=FILE 档案文件名。省略时, 基于操作\n 使用 stdin 或 stdout\n --release VERSION 将下面的所有文件都放在\n jar 的版本化目录中 (即 META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose 在标准输出中生成详细输出 @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?, -h, --help[:compat] 提供此帮助,也可 main.help.opt.other.help-extra=\ --help-extra 提供额外选项的帮助 main.help.opt.other.version=\ --version 输出程序版本 main.help.postopt=\ 如果模块描述符 'module-info.class' 位于指定目录的\n 根目录中, 或者位于 jar 档案本身的根目录中, 则\n 该档案是一个模块化 jar。以下操作只在创建模块化 jar,\n 或更新现有的非模块化 jar 时有效: '--module-version',\n '--hash-modules' 和 '--module-path'。\n\n 如果为长选项提供了必需参数或可选参数, 则它们对于\n 任何对应的短选项也是必需或可选的。 -main.help.opt.extract=\ 仅在提取模式下有效的操作修饰符:\n main.help.opt.extract.dir=\ --dir jar 将提取到其中的目录 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties index b4d3f94bad5..a725d415406 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 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 @@ -97,6 +97,9 @@ doclet.Record_component_in=Komponente von {0} erfassen doclet.Static_method_in=Statische Methode in {0} doclet.Search_tag_in=Tag suchen in {0} doclet.Method_in=Methode in {0} +doclet.System_property_in=Systemeigenschaft in {0} +doclet.External_specification_in=Externe Spezifikation in {0} +doclet.Section_in=Abschnitt in {0} doclet.module=Modul doclet.package=Package doclet.MalformedURL=Nicht wohlgeformte URL: {0} @@ -116,14 +119,14 @@ doclet.tag.invalid_input=Ungültige Eingabe: "{0}" doclet.tag.invalid=ungültiges @{0} doclet.Deprecated_API=Veraltete API doclet.Deprecated_API_Checkbox_Label=Veraltete API anzeigen in: -doclet.Deprecated_API_Checkbox_All_Releases=Alle +doclet.Deprecated_API_Checkbox_All_Releases=Alle umschalten doclet.Deprecated_API_Checkbox_Other_Releases=Sonstige doclet.Deprecated_Elements=Veraltete {0} doclet.Deprecated_Elements_Release_Column_Header=Veraltet in doclet.Deprecated_In_Release=Veraltet in {0} doclet.New_API=Neue API doclet.New_API_Checkbox_Label=Hinzugefügte API anzeigen in: -doclet.New_API_Checkbox_All_Releases=Alle +doclet.New_API_Checkbox_All_Releases=Alle umschalten doclet.New_Elements=Neue {0} doclet.New_Elements_Release_Column_Header=Hinzugefügt in doclet.New_Label=Neu @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=Alle umschalten doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0} doclet.Preview_Label=Vorschau doclet.Preview_Mark=PREVIEW +doclet.Preview_Notes=Hinweise zur Vorschau-API +doclet.Preview_Notes_Elements=Elemente mit Vorschauhinweisen doclet.Restricted_Methods=Eingeschränkte Methoden doclet.Restricted_Mark=RESTRICTED doclet.searchTag=Suchtag @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=Umschließende Schnittstelle: doclet.Inheritance_Tree=Vererbungsbaum doclet.DefinedIn=Definiert in doclet.ReferencedIn=Referenziert in -doclet.Section=Abschnitt -doclet.External_Specification=Externe Spezifikation doclet.External_Specifications=Externe Spezifikationen doclet.External_Specifications.All_Specifications=Alle Spezifikationen doclet.External_Specifications.no-host=Lokal doclet.Specification=Spezifikation -doclet.System_Property=Systemeigenschaft +doclet.Summary_Page=Zusammenfassung (Seite) doclet.systemProperties=Systemeigenschaften doclet.systemPropertiesSummary=Systemeigenschaften - Übersicht doclet.Window_Source_title=Quellcode @@ -195,8 +198,9 @@ doclet.search.show_more=Zusätzliche Ressourcen doclet.search.help_page_link=Hilfeseite # 0: a link to the help page with text above doclet.search.help_page_info= Die {0} enthält eine Einführung in den Umfang und die Syntax der JavaDoc-Suche. -doclet.search.keyboard_info= Sie können die - oder -Taste zusammen mit den Pfeiltasten nach links und rechts verwenden, um zwischen Ergebnisregisterkarten auf dieser Seite zu wechseln. -doclet.search.browser_info= Mit der URL-Vorlage unten können Sie diese Seite als Suchmaschine in Browsern konfigurieren, die dieses Feature unterstützen. Das Feature wurde erfolgreich mit Google Chrome und Mozilla Firefox getestet. Beachten Sie, dass andere Browser dieses Feature möglicherweise nicht unterstützen oder ein anderes URL-Format erfordern. +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys) +doclet.search.keyboard_info= Sie können mit den Tasten {0}/{1} zwischen Suchergebnissen und mit den Tasten {2} zwischen Ergebnisregisterkarten wechseln. +doclet.search.browser_info= Die unten stehende URL-Vorlage kann nützlich sein, um diese Seite als Suchmaschine oder Bookmarklet in Browsern zu konfigurieren, die dieses Feature unterstützen. doclet.search.redirect=Zum ersten Ergebnis umleiten # 0: a date @@ -286,7 +290,18 @@ doclet.help.search.refer=Eine vollständige Beschreibung der Suchfeatures finden doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html # The title for the Javadoc Search Specification doclet.help.search.spec.title=Javadoc-Suchspezifikation - +doclet.help.keyboard_navigation.title=Tastaturnavigation +doclet.help.keyboard_navigation.intro=Dokumentationsseiten enthalten Tastenkombinationen für den einfachen Zugriff auf häufige Navigationsaufgaben. +# Arguments in the messages below are elements representing various keyboard keys +doclet.help.keyboard_navigation.index=Verwenden Sie {0}, um auf einer beliebigen Seite auf das Sucheingabefeld zuzugreifen. +doclet.help.keyboard_navigation.filter=Verwenden Sie {0}, um in der Randleiste von Klassenseiten auf das Filtereingabefeld zuzugreifen. +doclet.help.keyboard_navigation.escape=Verwenden Sie {0}, um die Eingabe zu löschen und den Tastaturfokus von einem Eingabefeld zu entfernen. +doclet.help.keyboard_navigation.search=Verwenden Sie {0}/{1}/{2}, um Listenelemente auszuwählen, nachdem Sie einen Suchbegriff in ein Such- oder Filtereingabefeld eingegeben haben. +doclet.help.keyboard_navigation.tabs=Verwenden Sie {0}/{1}, um in Zusammenfassungstabellen mit Registerkarten zwischen Registerkarten zu wechseln. +doclet.help.releases.head=Releasedetails +doclet.help.releases.body.specify.top-level=Die Details für die einzelnen Module, Packages, Klassen oder Schnittstellen enthalten normalerweise das Release, in dem die Deklaration eingeführt wurde. +doclet.help.releases.body.specify.member=Wenn ein Member nach der anfänglichen Einführung der umschließenden Klasse oder Schnittstelle hinzugefügt wird, enthalten die Details des Members das Release, in dem es eingeführt wurde. +doclet.help.releases.body.refer=Auf einigen Übersichtsseiten ("Neue API", "Veraltet") können Sie den Inhalt der Seite nach dem Release filtern, in dem die Deklaration eingeführt oder eingestellt wurde. doclet.ClassUse_Packages.that.use.0=Packages, die {0} verwenden doclet.ClassUse_Uses.of.0.in.1=Verwendungen von {0} in {1} doclet.ClassUse_Classes.in.0.used.by.1=Von {1} verwendete Klassen in {0} @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=Außer Kraft gesetzte Methoden im Absc doclet.usage.allow-script-in-comments.description=JavaScript in Dokumentationskommentaren und Optionen\nzulassen, die HTML-Code enthalten +doclet.usage.syntax-highlight.description=Syntaxhervorhebung für Codefragmente in {@snippet}-Tags\nund

          -Elementen aktivieren.
          +
           doclet.usage.xdocrootparent.parameters=< URL>
           doclet.usage.xdocrootparent.description=Ersetzt alle Vorkommen von @docRoot gefolgt von /.. in doc-Kommentaren durch\n
           
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
          index 31e745301b6..749ef5856b8 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2010, 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
          @@ -97,6 +97,9 @@ doclet.Record_component_in={0}のレコード・コンポーネント
           doclet.Static_method_in={0}のstaticメソッド
           doclet.Search_tag_in={0}の検索タグ
           doclet.Method_in={0}のメソッド
          +doclet.System_property_in={0}のシステム・プロパティ
          +doclet.External_specification_in={0}の外部仕様
          +doclet.Section_in={0}のセクション
           doclet.module=モジュール
           doclet.package=パッケージ
           doclet.MalformedURL=不正なURL: {0}
          @@ -116,14 +119,14 @@ doclet.tag.invalid_input=入力が無効です: ''{0}''
           doclet.tag.invalid=@{0}が無効です
           doclet.Deprecated_API=推奨されていないAPI
           doclet.Deprecated_API_Checkbox_Label=次で非推奨のAPIを表示:
          -doclet.Deprecated_API_Checkbox_All_Releases=すべて
          +doclet.Deprecated_API_Checkbox_All_Releases=すべて設定
           doclet.Deprecated_API_Checkbox_Other_Releases=その他
           doclet.Deprecated_Elements=推奨されていない{0}
           doclet.Deprecated_Elements_Release_Column_Header=次で非推奨
           doclet.Deprecated_In_Release={0}で非推奨
           doclet.New_API=新規API
           doclet.New_API_Checkbox_Label=次で追加されたAPIを表示:
          -doclet.New_API_Checkbox_All_Releases=すべて
          +doclet.New_API_Checkbox_All_Releases=すべて設定
           doclet.New_Elements=新規{0}
           doclet.New_Elements_Release_Column_Header=次で追加
           doclet.New_Label=新規
          @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=すべて設定
           doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0}
           doclet.Preview_Label=プレビュー
           doclet.Preview_Mark=PREVIEW
          +doclet.Preview_Notes=プレビューAPIのノート
          +doclet.Preview_Notes_Elements=プレビュー・ノートを含む要素
           doclet.Restricted_Methods=制限されたメソッド
           doclet.Restricted_Mark=RESTRICTED
           doclet.searchTag=検索タグ
          @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=含まれているインタフェース:
           doclet.Inheritance_Tree=継承ツリー
           doclet.DefinedIn=定義先
           doclet.ReferencedIn=参照
          -doclet.Section=セクション
          -doclet.External_Specification=外部仕様
           doclet.External_Specifications=外部仕様
           doclet.External_Specifications.All_Specifications=すべての仕様
           doclet.External_Specifications.no-host=ローカル
           doclet.Specification=仕様
          -doclet.System_Property=システム・プロパティ
          +doclet.Summary_Page=サマリー・ページ
           doclet.systemProperties=システム・プロパティ
           doclet.systemPropertiesSummary=システム・プロパティ・サマリー
           doclet.Window_Source_title=ソース・コード
          @@ -195,8 +198,9 @@ doclet.search.show_more=その他のリソース
           doclet.search.help_page_link=ヘルプ・ページ
           # 0: a link to the help page with text above
           doclet.search.help_page_info= {0}では、JavaDoc検索の範囲および構文の概要について説明します。
          -doclet.search.keyboard_info= またはキーを左右の矢印キーと組み合せて使用すると、このページの結果タブを切り替えることができます。
          -doclet.search.browser_info= 次のURLテンプレートは、この機能をサポートするブラウザでこのページを検索エンジンとして構成するために使用できます。Google ChromeおよびMozilla Firefoxで動作することがテストされています。他のブラウザでは、この機能がサポートされていないか、別のURL形式が必要になる場合があります。
          +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys)
          +doclet.search.keyboard_info= {0}/{1}キーを使用して検索結果間を移動し、{2}キーを使用して結果タブ間を切り替えます。
          +doclet.search.browser_info= 下のURLテンプレートは、この機能をサポートするブラウザで検索エンジンまたはブックマークとして、このページを構成するのに役立つ可能性があります。
           doclet.search.redirect=最初の結果にリダイレクト
           
           # 0: a date
          @@ -286,7 +290,18 @@ doclet.help.search.refer=検索機能の詳細な説明は、{0}を参照して
           doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html
           # The title for the Javadoc Search Specification
           doclet.help.search.spec.title=Javadoc検索仕様
          -
          +doclet.help.keyboard_navigation.title=キーボード・ナビゲーション
          +doclet.help.keyboard_navigation.intro=ドキュメント・ページは、一般的なナビゲーション・タスクへのアクセスを容易にするキーボード・ショートカットを提供します。
          +# Arguments in the messages below are  elements representing various keyboard keys
          +doclet.help.keyboard_navigation.index=任意のページの検索入力フィールドにアクセスするには{0}と入力します。
          +doclet.help.keyboard_navigation.filter=クラス・ページのサイドバーのフィルタ入力フィールドにアクセスするには{0}と入力します。
          +doclet.help.keyboard_navigation.escape=任意の入力フィールドの入力をクリアし、キーボード・フォーカスを解放するには{0}と入力します。
          +doclet.help.keyboard_navigation.search=検索またはフィルタ入力フィールドに検索語を入力した後でリスト項目を選択するには{0}/{1}/{2}と入力します。
          +doclet.help.keyboard_navigation.tabs=タブ付きサマリー表のタブ間を切り替えるには{0}/{1}と入力します。
          +doclet.help.releases.head=リリース詳細
          +doclet.help.releases.body.specify.top-level=各モジュール、パッケージ、クラスまたはインタフェースの詳細には、通常、宣言が導入されたリリースが含まれます。
          +doclet.help.releases.body.specify.member=含まれているクラスまたはインタフェースの初期導入後にメンバーが追加された場合、メンバーの詳細にはそれが導入されたリリースが含まれます。
          +doclet.help.releases.body.refer=一部のサマリー・ページ(新規API、非推奨)では、宣言が導入または非推奨化されたリリースに従ってページのコンテンツをフィルタできます。
           doclet.ClassUse_Packages.that.use.0={0}を使用しているパッケージ
           doclet.ClassUse_Uses.of.0.in.1={1}での{0}の使用
           doclet.ClassUse_Classes.in.0.used.by.1={1}により使用される{0}のクラス
          @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=オーバーライドされたメソ
           
           doclet.usage.allow-script-in-comments.description=ドキュメント・コメント、および値がhtml-codeであるオプションで\nJavaScriptを許可します
           
          +doclet.usage.syntax-highlight.description={@snippet}タグおよび
          要素のコード・フラグメントの\n構文ハイライト表示を有効にします。
          +
           doclet.usage.xdocrootparent.parameters=
           doclet.usage.xdocrootparent.description=docコメント内の/..が後に続く@docRootのすべてをで置換します
           
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
          index 36e27355b63..4bb154065b6 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2010, 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
          @@ -97,6 +97,9 @@ doclet.Record_component_in={0} 的记录组件
           doclet.Static_method_in={0}中的静态方法
           doclet.Search_tag_in={0}中的搜索标记
           doclet.Method_in={0}中的方法
          +doclet.System_property_in={0} 中的系统属性
          +doclet.External_specification_in={0} 中的外部规范
          +doclet.Section_in={0} 中的节
           doclet.module=模块
           doclet.package=程序包
           doclet.MalformedURL=格式错误的 URL: {0}
          @@ -116,14 +119,14 @@ doclet.tag.invalid_input=无效输入:''{0}''
           doclet.tag.invalid=@{0} 无效
           doclet.Deprecated_API=已过时的 API
           doclet.Deprecated_API_Checkbox_Label=显示在以下发行版中已过时的 API:
          -doclet.Deprecated_API_Checkbox_All_Releases=全部
          +doclet.Deprecated_API_Checkbox_All_Releases=全部切换
           doclet.Deprecated_API_Checkbox_Other_Releases=其他
           doclet.Deprecated_Elements=已过时的 {0}
           doclet.Deprecated_Elements_Release_Column_Header=在以下发行版中已过时
           doclet.Deprecated_In_Release=在 {0} 中已过时
           doclet.New_API=新建 API
           doclet.New_API_Checkbox_Label=显示在以下发行版中添加的 API:
          -doclet.New_API_Checkbox_All_Releases=全部
          +doclet.New_API_Checkbox_All_Releases=全部切换
           doclet.New_Elements=新建 {0}
           doclet.New_Elements_Release_Column_Header=在以下发行版中已添加
           doclet.New_Label=新建
          @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=全部切换
           doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0}
           doclet.Preview_Label=预览
           doclet.Preview_Mark=PREVIEW
          +doclet.Preview_Notes=预览 API 注释
          +doclet.Preview_Notes_Elements=包含预览注释的元素
           doclet.Restricted_Methods=受限制的方法
           doclet.Restricted_Mark=RESTRICTED
           doclet.searchTag=搜索标记
          @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=封闭接口:
           doclet.Inheritance_Tree=继承树
           doclet.DefinedIn=定义位置
           doclet.ReferencedIn=参考位置
          -doclet.Section=节
          -doclet.External_Specification=外部规范
           doclet.External_Specifications=外部规范
           doclet.External_Specifications.All_Specifications=所有规范
           doclet.External_Specifications.no-host=本地
           doclet.Specification=规范
          -doclet.System_Property=系统属性
          +doclet.Summary_Page=概要页
           doclet.systemProperties=系统属性
           doclet.systemPropertiesSummary=系统属性概要
           doclet.Window_Source_title=源代码
          @@ -195,8 +198,9 @@ doclet.search.show_more=其他资源
           doclet.search.help_page_link=帮助页
           # 0: a link to the help page with text above
           doclet.search.help_page_info= {0} 介绍了 JavaDoc 搜索的范围和语法。
          -doclet.search.keyboard_info= 您可以使用  键与左箭头和右箭头键组合在此页面中的结果选项卡之间切换。
          -doclet.search.browser_info= 下面的 URL 模板可用于在支持此功能的浏览器中将此页面配置为搜索引擎。已经对其进行了测试以在 Google Chrome 和 Mozilla Firefox 中使用。请注意,其他浏览器可能不支持此功能或需要不同的 URL 格式。
          +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys)
          +doclet.search.keyboard_info= 使用 {0}/{1} 键在搜索结果之间移动,使用 {2} 键在结果选项卡之间切换。
          +doclet.search.browser_info= 下面的 URL 模板可能有助于在支持此功能的浏览器中将此页面配置为搜索引擎或 bookmarklet。
           doclet.search.redirect=重定向到第一个结果
           
           # 0: a date
          @@ -286,7 +290,18 @@ doclet.help.search.refer=有关搜索功能的完整说明,请参阅 {0}。
           doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html
           # The title for the Javadoc Search Specification
           doclet.help.search.spec.title=Javadoc 搜索规范
          -
          +doclet.help.keyboard_navigation.title=键盘导航
          +doclet.help.keyboard_navigation.intro=文档页面提供键盘快捷键,以方便访问常见的导航任务。
          +# Arguments in the messages below are  elements representing various keyboard keys
          +doclet.help.keyboard_navigation.index=键入 {0} 以访问任何页面中的搜索输入字段。
          +doclet.help.keyboard_navigation.filter=键入 {0} 以访问类页面子工具栏中的筛选器输入字段。
          +doclet.help.keyboard_navigation.escape=键入 {0} 以清除任何输入字段中的输入并释放键盘焦点。
          +doclet.help.keyboard_navigation.search=在搜索或筛选器输入字段中输入搜索词后,键入 {0}/{1}/{2} 以选择列表项。
          +doclet.help.keyboard_navigation.tabs=键入 {0}/{1} 以在选项卡式概要表中的选项卡之间切换。
          +doclet.help.releases.head=发行版详细信息
          +doclet.help.releases.body.specify.top-level=每个模块、程序包、类或接口的详细信息通常包括引入声明的发行版。
          +doclet.help.releases.body.specify.member=当在最初引入封闭类或接口后添加成员时,成员的详细信息包括引入它的发行版。
          +doclet.help.releases.body.refer=某些概要页(新建 API、已过时)允许您根据声明被引入或已过时的发行版筛选页面的内容。
           doclet.ClassUse_Packages.that.use.0=使用{0}的程序包
           doclet.ClassUse_Uses.of.0.in.1={1}中{0}的使用
           doclet.ClassUse_Classes.in.0.used.by.1={1}使用的{0}中的类
          @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=在详细信息部分或概要部分
           
           doclet.usage.allow-script-in-comments.description=允许在文档注释和选项中使用 JavaScript\n其值为 html-code
           
          +doclet.usage.syntax-highlight.description=为 {@snippet} 标记和 
           元素中的代码片段\n启用语法突出显示。
          +
           doclet.usage.xdocrootparent.parameters=
           doclet.usage.xdocrootparent.description=将文档注释中出现的所有后跟 /.. 的 @docRoot 替换为\n
           
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
          index 7ab2d3fc1dc..0ee34071c93 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2010, 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
          @@ -218,14 +218,15 @@ doclet.Annotation_Type_Optional_Members=Optionale Elemente
           doclet.Annotation_Type_Required_Members=Erforderliche Elemente
           doclet.Enum_Constants=Enum-Konstanten
           doclet.Nested_Classes=Verschachtelte Klassen
          -doclet.Modifier=Modifizierer
          +doclet.Modifier=Modifikator
           doclet.Type=Typ
          -doclet.Modifier_and_Type=Modifizierer und Typ
          +doclet.Modifier_and_Type=Modifikator und Typ
           doclet.Implementation=Implementierung(en):
           doclet.search=Suchen
          -doclet.search_placeholder=Suchen
          +doclet.search_placeholder=In Dokumentation suchen ("/" eingeben)
           doclet.search_in_documentation=In Dokumentation suchen
           doclet.search_reset=Zurücksetzen
          +doclet.Member=Mitglied
           doclet.Field=Feld
           doclet.Property=Eigenschaft
           doclet.Constructor=Konstruktor
          @@ -241,7 +242,7 @@ doclet.Value=Wert
           doclet.table_of_contents=Inhaltsverzeichnis
           doclet.hide_sidebar=Randleiste ausblenden
           doclet.show_sidebar=Randleiste einblenden
          -doclet.filter_label=Filter
          +doclet.filter_label=Inhalt filtern ("." eingeben)
           doclet.filter_table_of_contents=Inhaltsverzeichnis filtern
           doclet.filter_reset=Zurücksetzen
           doclet.linkMismatch_PackagedLinkedtoModule=Der Code, der dokumentiert wird, verwendet Packages im unbenannten Modul, aber die in {0} definierten Packages befinden sich in benannten Modulen.
          @@ -313,12 +314,16 @@ doclet.search.many_results={0} Ergebnisse gefunden
           doclet.search.loading=Suchindex wird geladen...
           doclet.search.searching=Suche wird ausgeführt...
           doclet.search.redirecting=Zum ersten Ergebnis wird umgeleitet...
          +# {0} is a select input containing all_modules message below and module names
          +doclet.search.in=in {0}
          +doclet.search.all_modules=allen Modulen
           doclet.search.modules=Module
           doclet.search.packages=Packages
           doclet.search.classes_and_interfaces=Klassen und Schnittstellen
           doclet.search.types=Typen
           doclet.search.members=Mitglieder
           doclet.search.search_tags=Tags suchen
          +doclet.search.linkSearchPageLabel=Gehe zur Suchseite
           
           doclet.snippet.contents.none=@snippet gibt keinen Inhalt an
           
          @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=Option --snippet-path kann mit dem gegebenen Date
           
           # 0: path; 1: exception
           doclet.error_setting_snippet_path=Fehler beim Festlegen von Snippet-Pfad {0}: {1}
          +
          +# 0: location
          +doclet.error.snippet.ambiguous.link=Snippet-Linktags: {0} und {1} überschneiden sich in {2}
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
          index 28126387ead..2b10f4e6e9a 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2010, 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
          @@ -223,9 +223,10 @@ doclet.Type=タイプ
           doclet.Modifier_and_Type=修飾子とタイプ
           doclet.Implementation=実装:
           doclet.search=検索
          -doclet.search_placeholder=検索
          +doclet.search_placeholder=ドキュメントの検索(/と入力)
           doclet.search_in_documentation=ドキュメントで検索
           doclet.search_reset=リセット
          +doclet.Member=メンバー
           doclet.Field=フィールド
           doclet.Property=プロパティ
           doclet.Constructor=コンストラクタ
          @@ -241,7 +242,7 @@ doclet.Value=値
           doclet.table_of_contents=目次
           doclet.hide_sidebar=サイドバーの非表示
           doclet.show_sidebar=サイドバーの表示
          -doclet.filter_label=フィルタ
          +doclet.filter_label=コンテンツのフィルタ(.と入力)
           doclet.filter_table_of_contents=目次のフィルタ
           doclet.filter_reset=リセット
           doclet.linkMismatch_PackagedLinkedtoModule=ドキュメント化しようとしているコードでは名前のないモジュールのパッケージが使用されていますが、{0}で定義されているパッケージは名前のあるモジュールのものです。
          @@ -313,12 +314,16 @@ doclet.search.many_results={0}の結果が見つかりました
           doclet.search.loading=検索索引をロード中...
           doclet.search.searching=検索中...
           doclet.search.redirecting=最初の結果にリダイレクト中...
          +# {0} is a select input containing all_modules message below and module names
          +doclet.search.in={0}内
          +doclet.search.all_modules=すべてのモジュール
           doclet.search.modules=モジュール
           doclet.search.packages=パッケージ
           doclet.search.classes_and_interfaces=クラスとインタフェース
           doclet.search.types=タイプ
           doclet.search.members=メンバー
           doclet.search.search_tags=タグの検索
          +doclet.search.linkSearchPageLabel=検索ページに移動します
           
           doclet.snippet.contents.none=@snippetにコンテンツが指定されていません
           
          @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=指定されたファイル・マネージャで'
           
           # 0: path; 1: exception
           doclet.error_setting_snippet_path=スニペットのパス{0}の設定中にエラーが発生しました: {1}
          +
          +# 0: location
          +doclet.error.snippet.ambiguous.link=スニペット・リンク・タグ: {2}の{0}と{1}の重複
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
          index e2722f1deab..f2c8762b283 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2010, 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
          @@ -223,9 +223,10 @@ doclet.Type=类型
           doclet.Modifier_and_Type=修饰符和类型
           doclet.Implementation=实现:
           doclet.search=搜索
          -doclet.search_placeholder=搜索
          +doclet.search_placeholder=搜索文档(键入 /)
           doclet.search_in_documentation=在文档中搜索
           doclet.search_reset=重置
          +doclet.Member=成员
           doclet.Field=字段
           doclet.Property=属性
           doclet.Constructor=构造器
          @@ -241,7 +242,7 @@ doclet.Value=值
           doclet.table_of_contents=目录
           doclet.hide_sidebar=隐藏子工具栏
           doclet.show_sidebar=显示子工具栏
          -doclet.filter_label=筛选器
          +doclet.filter_label=筛选内容(键入 .)
           doclet.filter_table_of_contents=筛选目录
           doclet.filter_reset=重置
           doclet.linkMismatch_PackagedLinkedtoModule=进行文档化的代码使用了未命名模块中的程序包,但在 {0} 中定义的程序包在命名模块中。
          @@ -313,12 +314,16 @@ doclet.search.many_results=找到 {0} 个结果
           doclet.search.loading=正在加载搜索索引...
           doclet.search.searching=正在搜索...
           doclet.search.redirecting=正在重定向到第一个结果...
          +# {0} is a select input containing all_modules message below and module names
          +doclet.search.in=在 {0} 中
          +doclet.search.all_modules=全部模块
           doclet.search.modules=模块
           doclet.search.packages=程序包
           doclet.search.classes_and_interfaces=类和接口
           doclet.search.types=类型
           doclet.search.members=成员
           doclet.search.search_tags=搜索标记
          +doclet.search.linkSearchPageLabel=转至搜索页
           
           doclet.snippet.contents.none=@snippet 未指定内容
           
          @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=不能将 ''--snippet-path'' 选项与给定的
           
           # 0: path; 1: exception
           doclet.error_setting_snippet_path=设置片段路径 {0} 时出错:{1}
          +
          +# 0: location
          +doclet.error.snippet.ambiguous.link=片段链接标记:{0} 和 {1} 在 {2} 中重叠
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
          index 93268943290..58f010fb967 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
          @@ -678,22 +678,16 @@ private boolean allowInheritedMethod(ExecutableElement inheritedMethod,
                       return false;
                   }
           
          -        // Multiple-Inheritance: remove the interface method that may have
          -        // been overridden by another interface method in the hierarchy
          -        //
          -        // Note: The following approach is very simplistic and is compatible
          -        // with old VMM. A future enhancement, may include a contention breaker,
          -        // to correctly eliminate those methods that are merely definitions
          -        // in favor of concrete overriding methods, for instance those that have
          -        // API documentation and are not abstract OR default methods.
          +        // Multiple-Inheritance: No Contention. In Java's method resolution,
          +        // any override of a signature (whether by a subclass or by a subinterface,
          +        // including when it is final from superclasses) always takes precedence
          +        // over the original interface definition. All interface methods have low resolution priority.
          +        // Therefore, when considering an interface inherited method, as soon as
          +        // at least one overrider exists in the inheritance chain,
          +        // we do not inherit the older interface definition.
                   if (inInterface) {
                       List list = overriddenByTable.get(inheritedMethod);
          -            if (list != null) {
          -                boolean found = list.stream()
          -                        .anyMatch(this::isDeclaredInInterface);
          -                if (found)
          -                    return false;
          -            }
          +            if (list != null && !list.isEmpty()) return false;
                   }
           
                   Elements elementUtils = config.docEnv.getElementUtils();
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
          index 4d0e7bae176..7829d2d7e27 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 1997, 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
          @@ -32,6 +32,8 @@ main.warning={0} Warnung
           
           main.usage=Verwendung:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\nmit folgenden Optionen:
           
          +main.usage.short=Verwendung:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
          +
           main.did-you-mean=Meinten Sie: {0}
           
           main.did-you-mean-one-of=Meinten Sie eine der folgenden Optionen: {0}
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
          index 42765ab4ded..da267939d3e 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 1997, 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
          @@ -32,6 +32,8 @@ main.warning=警告{0}個
           
           main.usage=使用方法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\nオプションは次のとおりです:
           
          +main.usage.short=使用方法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
          +
           main.did-you-mean=もしかして: {0}
           
           main.did-you-mean-one-of=もしかして次のいずれかですか: {0}
          diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
          index 27053b44753..0305eaf7743 100644
          --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
          +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 1997, 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
          @@ -32,6 +32,8 @@ main.warning={0} 个警告
           
           main.usage=用法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\n其中, 选项包括:
           
          +main.usage.short=用法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
          +
           main.did-you-mean=您要查找的是:{0}
           
           main.did-you-mean-one-of=您要查找的是以下项之一:{0}
          diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties b/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
          index 947fb1c8d66..e6859fd8d74 100644
          --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
          +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
          @@ -1,5 +1,5 @@
           #
          -# Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
          +# Copyright (c) 2012, 2021, 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
          diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
          index f3aadd3677c..04ec27a624d 100644
          --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
          +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
          @@ -1,5 +1,5 @@
           /*
          - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
          + * Copyright (c) 2001, 2023, 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
          diff --git a/src/jdk.jdi/windows/native/libdt_shmem/shmem_md.c b/src/jdk.jdi/windows/native/libdt_shmem/shmem_md.c
          index 4f7a520dd76..df07b753f0e 100644
          --- a/src/jdk.jdi/windows/native/libdt_shmem/shmem_md.c
          +++ b/src/jdk.jdi/windows/native/libdt_shmem/shmem_md.c
          @@ -37,8 +37,6 @@
            * yet.
            */
           
          -static HANDLE memHandle = NULL;
          -
           int
           sysSharedMemCreate(const char *name, int length,
                              sys_shmem_t *mem, void **buffer)
          diff --git a/src/jdk.jdwp.agent/windows/native/libjdwp/proc_md.h b/src/jdk.jdwp.agent/windows/native/libjdwp/proc_md.h
          index dc8caf18273..6c86473625f 100644
          --- a/src/jdk.jdwp.agent/windows/native/libjdwp/proc_md.h
          +++ b/src/jdk.jdwp.agent/windows/native/libjdwp/proc_md.h
          @@ -31,8 +31,8 @@
           
           #define MUTEX_T         int
           #define MUTEX_INIT      0
          -#define MUTEX_LOCK(x)           /* FIXUP? */
          -#define MUTEX_UNLOCK(x)         /* FIXUP? */
          +#define MUTEX_LOCK(x)   ((void) (x))        /* FIXUP? */
          +#define MUTEX_UNLOCK(x) ((void) (x))        /* FIXUP? */
           #define GET_THREAD_ID() GetCurrentThreadId()
           #define THREAD_T        unsigned long
           #define PID_T           int
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTimingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTimingEvent.java
          index 4998966939b..e927abf8024 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTimingEvent.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/MethodTimingEvent.java
          @@ -29,11 +29,13 @@
           import jdk.jfr.Name;
           import jdk.jfr.Timespan;
           import jdk.jfr.internal.RemoveFields;
          +import jdk.jfr.Description;
           
           @Name("jdk.MethodTiming")
           @Label("Method Timing")
           @Category({ "Java Virtual Machine", "Method Tracing" })
           @RemoveFields({ "duration", "eventThread", "stackTrace" })
          +@Description("Measures the approximate time it takes for a method to execute, including all delays, not just CPU processing time")
           public final class MethodTimingEvent extends AbstractJDKEvent {
           
               @Label("Method")
          @@ -43,14 +45,17 @@ public final class MethodTimingEvent extends AbstractJDKEvent {
               public long invocations;
           
               @Label("Minimum Time")
          +    @Description("The value may be missing (Long.MIN_VALUE) if the clock-resolution is too low to establish a minimum time")
               @Timespan(Timespan.TICKS)
               public long minimum;
           
               @Label("Average Time")
          +    @Description("The value may be missing (Long.MIN_VALUE) if the clock-resolution is too low to establish an average time")
               @Timespan(Timespan.TICKS)
               public long average;
           
               @Label("Maximum Time")
          +    @Description("The value may be missing (Long.MIN_VALUE) if the clock-resolution is too low to establish a maximum time")
               @Timespan(Timespan.TICKS)
               public long maximum;
           
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
          index 7f0ed76586a..032ccb5f4b5 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
          @@ -61,8 +61,8 @@
            *
            */
           public final class EventInstrumentation {
          -    public static final long MASK_THROTTLE               = 1 << 62;
          -    public static final long MASK_THROTTLE_CHECK         = 1 << 63;
          +    public static final long MASK_THROTTLE               = 1L << 62;
          +    public static final long MASK_THROTTLE_CHECK         = 1L << 63;
               public static final long MASK_THROTTLE_BITS          = MASK_THROTTLE | MASK_THROTTLE_CHECK;
               public static final long MASK_THROTTLE_CHECK_SUCCESS = MASK_THROTTLE_CHECK | MASK_THROTTLE;
               public static final long MASK_THROTTLE_CHECK_FAIL    = MASK_THROTTLE_CHECK | 0;
          @@ -482,6 +482,11 @@ private void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end,
                   blockCodeBuilder.ifne(durationEvent);
                   invokestatic(blockCodeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP);
                   blockCodeBuilder.lstore(1);
          +        if (throttled) {
          +            blockCodeBuilder.aload(0);
          +            blockCodeBuilder.lload(1);
          +            putfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME);
          +        }
                   Label commit = blockCodeBuilder.newLabel();
                   blockCodeBuilder.goto_(commit);
                   //   if (duration == 0) {
          @@ -491,7 +496,7 @@ private void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end,
                   blockCodeBuilder.labelBinding(durationEvent);
                   blockCodeBuilder.aload(0);
                   getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION);
          -        blockCodeBuilder.lconst_0();
          +        blockCodeBuilder.lconst_0(); // also blocks throttled event
                   blockCodeBuilder.lcmp();
                   blockCodeBuilder.ifne(commit);
                   blockCodeBuilder.aload(0);
          @@ -527,9 +532,7 @@ private void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end,
                       // write duration
                       blockCodeBuilder.dup();
                       // stack: [EW] [EW]
          -            blockCodeBuilder.aload(0);
          -            // stack: [EW] [EW] [this]
          -            getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION);
          +            getDuration(blockCodeBuilder);
                       // stack: [EW] [EW] [long]
                       invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method());
                       fieldIndex++;
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java
          index a28f1fdd41f..503a7955e00 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java
          @@ -45,6 +45,7 @@
           import jdk.jfr.events.MethodTimingEvent;
           import jdk.jfr.events.MethodTraceEvent;
           import jdk.jfr.internal.periodic.PeriodicEvents;
          +import jdk.jfr.internal.settings.MethodSetting;
           import jdk.jfr.internal.tracing.PlatformTracer;
           import jdk.jfr.tracing.MethodTracer;
           
          @@ -235,7 +236,7 @@ private static void emitInitialSecurityProperties() {
               }
           
               private static void emitMethodTiming() {
          -        if (MethodTimingEvent.enabled()) {
          +        if (MethodSetting.isInitialized() && MethodTimingEvent.enabled()) {
                       PlatformTracer.emitTiming();
                   }
               }
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
          index b91f0c337b2..841221c57d9 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
          @@ -273,12 +273,24 @@ public final class JVM {
               /**
                * Set the maximum event emission rate for the CPU time sampler
                *
          +     * Use {@link #setCPUPeriod(long)} if you want a fixed sampling period instead.
          +     *
                * Setting rate to 0 turns off the CPU time sampler.
                *
                * @param rate the new rate in events per second
          -     * @param autoAdapt true if the rate should be adapted automatically
                */
          -    public static native void setCPUThrottle(double rate, boolean autoAdapt);
          +    public static native void setCPURate(double rate);
          +
          +    /**
          +     * Set the fixed CPU time sampler period.
          +     *
          +     * Use {@link #setCPURate(double)} if you want a fixed rate with an auto-adjusted period instead.
          +     *
          +     * Setting period to 0 turns off the CPU time sampler.
          +     *
          +     * @param periodNanos the new fixed period in nanoseconds
          +     */
          +    public static native void setCPUPeriod(long periodNanos);
           
               /**
                * Sets the file where data should be written.
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
          index ff3e0238cf0..c820703b887 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
          @@ -204,7 +204,11 @@ public void setCPUThrottle(TimespanRate rate) {
                   if (isCPUTimeMethodSampling) {
                       this.cpuRate = rate;
                       if (isEnabled()) {
          -                JVM.setCPUThrottle(rate.rate(), rate.autoAdapt());
          +                if (rate.isRate()) {
          +                    JVM.setCPURate(rate.rate());
          +                } else {
          +                    JVM.setCPUPeriod(rate.periodNanos());
          +                }
                       }
                   }
               }
          @@ -270,8 +274,12 @@ public void setEnabled(boolean enabled) {
                           long p = enabled ? period : 0;
                           JVM.setMethodSamplingPeriod(getId(), p);
                       } else if (isCPUTimeMethodSampling) {
          -                TimespanRate r = enabled ? cpuRate : new TimespanRate(0, false);
          -                JVM.setCPUThrottle(r.rate(), r.autoAdapt());
          +                TimespanRate r = enabled ? cpuRate : TimespanRate.OFF;
          +                if (r.isRate()) {
          +                    JVM.setCPURate(r.rate());
          +                } else {
          +                    JVM.setCPUPeriod(r.periodNanos());
          +                }
                       } else {
                           JVM.setEnabled(getId(), enabled);
                       }
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
          index fd9636f17ab..495c5659949 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
          @@ -39,8 +39,7 @@ label = "Active Settings"
           table = "COLUMN 'Event Type', 'Enabled', 'Threshold',
                           'Stack Trace','Period','Cutoff', 'Throttle'
                    FORMAT none, missing:whitespace, missing:whitespace, missing:whitespace,
          -                missing:whitespace, missing:whitespace, missing:whitespace,
          -                missing:whitespace
          +                missing:whitespace, missing:whitespace, missing:whitespace
                    SELECT E.id, LAST_BATCH(E.value), LAST_BATCH(T.value),
                           LAST_BATCH(S.value), LAST_BATCH(P.value),
                           LAST_BATCH(C.value), LAST_BATCH(U.value)
          @@ -395,7 +394,7 @@ form = "SELECT LAST(initialSize), LAST(minSize), LAST(maxSize),
                          FROM GCHeapConfiguration"
           
           [application.hot-methods]
          -label = "Java Methods that Executes the Most"
          +label = "Java Methods that Execute the Most"
           table = "COLUMN 'Method', 'Samples', 'Percent'
                    FORMAT none, none, normalized
                    SELECT stackTrace.topFrame AS T, COUNT(*), COUNT(*)
          @@ -471,9 +470,9 @@ table = "COLUMN 'Alloc. Time', 'Application Method', 'Object Age', 'Heap Usage'
           
           [application.method-timing]
           label = "Method Timing"
          -table = "COLUMN 'Timed Method', 'Invocations', 'Min. Time', 'Max. Time', 'Average Time'
          +table = "COLUMN 'Timed Method', 'Invocations', 'Minimum Time', 'Average Time', 'Maximum Time'
                    FORMAT none, none, ms-precision:6, ms-precision:6, ms-precision:6
          -         SELECT LAST_BATCH(method) AS M, LAST_BATCH(invocations), LAST_BATCH(minimum), LAST_BATCH(maximum), LAST_BATCH(average)
          +         SELECT LAST_BATCH(method) AS M, LAST_BATCH(invocations), LAST_BATCH(minimum), LAST_BATCH(average), LAST_BATCH(maximum)
                    FROM jdk.MethodTiming GROUP BY method ORDER BY average"
           
           [application.method-calls]
          @@ -518,10 +517,10 @@ table = "COLUMN 'Memory Type', 'First Observed', 'Average', 'Last Observed', 'Ma
           
           [application.native-methods]
           label = "Waiting or Executing Native Methods"
          -table = "COLUMN 'Method', 'Samples', 'Percent'
          -         FORMAT none, none, normalized
          -         SELECT stackTrace.topFrame AS T, COUNT(*), COUNT(*)
          -         FROM NativeMethodSample GROUP BY T"
          +table = "COLUMN 'Method', 'Samples'
          +         FORMAT none, none
          +         SELECT stackTrace.topFrame AS T, COUNT(*) AS C
          +         FROM NativeMethodSample GROUP BY T ORDER BY C DESC"
           
           [environment.network-utilization]
           label = "Network Utilization"
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java
          index c18aeef2132..997f4a84949 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java
          @@ -58,18 +58,18 @@ public CPUThrottleSetting(PlatformEventType eventType) {
           
               @Override
               public String combine(Set values) {
          -        TimespanRate max = null;
          +        TimespanRate highestRate = null;
                   for (String value : values) {
                       TimespanRate rate = TimespanRate.of(value);
                       if (rate != null) {
          -                if (max == null || rate.isHigher(max)) {
          -                    max = rate;
          +                if (highestRate == null) {
          +                    highestRate = rate;
          +                } else {
          +                    highestRate = TimespanRate.selectHigherResolution(highestRate, rate);
                           }
          -                max = new TimespanRate(max.rate(), max.autoAdapt() || rate.autoAdapt());
                       }
                   }
          -        // "off" is not supported
          -        return Objects.requireNonNullElse(max.toString(), DEFAULT_VALUE);
          +        return Objects.requireNonNullElse(highestRate.toString(), DEFAULT_VALUE);
               }
           
               @Override
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java
          index f3e1069ca21..0f2751b6ac7 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java
          @@ -42,6 +42,7 @@
           @Name(Type.SETTINGS_PREFIX + "Filter")
           public final class MethodSetting extends FilterSetting {
               private final Modification modification;
          +    private volatile static boolean initialized;
           
               public MethodSetting(PlatformEventType eventType, Modification modification, String defaultValue) {
                   super(eventType, defaultValue);
          @@ -55,6 +56,20 @@ public boolean isValid(String text) {
           
               @Override
               protected void apply(PlatformEventType eventType, List filters) {
          +        ensureInitialized();
                   PlatformTracer.setFilters(modification, filters);
               }
          +
          +    // Expected to be called when holding external lock, so no extra
          +    // synchronization is required here.
          +    private static void ensureInitialized() {
          +        if (!initialized) {
          +            PlatformTracer.initialize();
          +            initialized = true;
          +        }
          +    }
          +
          +    public static boolean isInitialized() {
          +        return initialized;
          +    }
           }
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java
          index 5985b28b58e..2d40e496dc1 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java
          @@ -53,8 +53,6 @@ public final class PlatformTracer {
               private static List timingFilters = List.of();
               private static TimedMethod OBJECT;
           
          -    private static boolean initialized;
          -
               public static byte[] onMethodTrace(Module module, ClassLoader classLoader, String className,
                                                  byte[] oldBytecode, long[] ids, String[] names, String[] signatures,
                                                  int[] modifications) {
          @@ -159,7 +157,6 @@ public static void addTiming(long id, long duration) {
               }
           
               public static void setFilters(Modification modification, List filters) {
          -        ensureInitialized();
                   publishClasses(applyFilter(modification, filters));
               }
           
          @@ -252,14 +249,6 @@ private static void reset() {
                   timedClasses.clear();
               }
           
          -    // Expected to be called when holding external lock, so no extra
          -    // synchronization is required here.
          -    private static void ensureInitialized() {
          -        if (!initialized) {
          -            initialize();
          -            initialized = true;
          -        }
          -    }
           
               // This method has three purposes:
               //
          @@ -274,7 +263,7 @@ private static void ensureInitialized() {
               // This method takes 1-10 milliseconds to run and is only executed once,
               // provided a user has specified a non-empty filter for the MethodTrace or
               // MethodTiming event.
          -    private static void initialize() {
          +    public static void initialize() {
                   try {
                       Logger.log(LogTag.JFR_METHODTRACE, LogLevel.DEBUG, "Method tracer initialization started.");
                       Thread current = Thread.currentThread();
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedClass.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedClass.java
          index ed592fec645..2c3ee2cbb95 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedClass.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedClass.java
          @@ -33,6 +33,7 @@
            * Holds timed method for a class. Used when publishing method ids.
            */
           public final class TimedClass {
          +    private static final long MISSING = Long.MIN_VALUE;
               private final ConcurrentHashMap methods = new ConcurrentHashMap<>();
           
               public TimedMethod add(Method method) {
          @@ -60,13 +61,23 @@ public void emit(long timestamp) {
                           long methodId = tm.method().methodId();
                           long invocations = tm.invocations().get();
                           long time = tm.time().get();
          -                long average = invocations == 0 ? Long.MIN_VALUE : time / invocations;
                           long min = tm.minimum().get();
          -                if (min == Long.MAX_VALUE) {
          -                    min = Long.MIN_VALUE; // Signals that the value is missing
          -                }
                           long max = tm.maximum().get();
          -                MethodTimingEvent.commit(timestamp, methodId, invocations, min, average, max);
          +                if (time == 0 || invocations == 0) {
          +                    // If time is zero, it's a low resolution clock and more invocations are needed.
          +                    MethodTimingEvent.commit(timestamp, methodId, invocations, MISSING, MISSING, MISSING);
          +                } else {
          +                    long average = (time + invocations / 2) / invocations;
          +                    if (min == Long.MAX_VALUE) {
          +                        min = average;
          +                    }
          +                    if (max == Long.MIN_VALUE) {
          +                        max = average;
          +                    }
          +                    min = Math.min(min, average);
          +                    max = Math.max(max, average);
          +                    MethodTimingEvent.commit(timestamp, methodId, invocations, min, average, max);
          +                }
                           tm.method().log("Emitted event");
                       }
                   }
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedMethod.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedMethod.java
          index be7f0c8f084..bd4f2262444 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedMethod.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/TimedMethod.java
          @@ -39,6 +39,9 @@ record TimedMethod(AtomicLong invocations, AtomicLong time, AtomicLong minimum,
               }
           
               public void updateMinMax(long duration) {
          +        if (duration == 0) {
          +            return; // Ignore data due to low-resolution clock
          +        }
                   if (duration > maximum.getPlain()) {
                       while (true) {
                           long max = maximum.get();
          diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java
          index 5d671310e3c..c35432d5d6b 100644
          --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java
          +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java
          @@ -30,11 +30,22 @@
           /**
            * A rate or fixed period, see {@link jdk.jfr.internal.Rate}
            */
          -public record TimespanRate(double rate, boolean autoAdapt) {
          +public record TimespanRate(double rate, long periodNanos, boolean isRate) {
           
          +    public static final TimespanRate OFF = new TimespanRate(0, 0, false);
          +
          +    /**
          +     * Parses the rate string. Supports
          +     *
          +     * 
            + *
          • off
          • + *
          • time value like "1ms"
          • + *
          • rate value like "10/s"
          • + *
          + */ public static TimespanRate of(String text) { if (text.equals("off")) { - text = CPUThrottleSetting.DEFAULT_VALUE; + return OFF; } boolean isPeriod = !text.contains("/"); if (isPeriod) { @@ -43,26 +54,62 @@ public static TimespanRate of(String text) { return null; } if (period == 0) { - return new TimespanRate(0, false); + return OFF; } - return new TimespanRate(Runtime.getRuntime().availableProcessors() / (period / 1_000_000_000.0), false); + return new TimespanRate(0, period, false); } Rate r = Rate.of(text); if (r == null) { return null; } - return new TimespanRate(r.perSecond(), true); + return new TimespanRate(r.perSecond(), 0, true); } - public boolean isHigher(TimespanRate that) { - return rate() > that.rate(); + public static TimespanRate selectHigherResolution(TimespanRate a, TimespanRate b) { + if (a.isRate && b.isRate) { + return a.rate() > b.rate() ? a : b; + } + if (!a.isRate && !b.isRate) { + return a.periodNanos() < b.periodNanos() ? a : b; + } + if (a.isRate) { + double bRate = Runtime.getRuntime().availableProcessors() * (1_000_000_000.0 / b.periodNanos()); + return new TimespanRate(Math.max(a.rate(), bRate), 0, true); + } + double aRate = Runtime.getRuntime().availableProcessors() * (1_000_000_000.0 / a.periodNanos()); + return new TimespanRate(Math.max(aRate, b.rate()), 0, true); } @Override public String toString() { - if (autoAdapt) { - return String.format("%d/ns", (long)(rate * 1_000_000_000L)); + if (isRate) { + return toRateString(); + } + return toPeriodString(); + } + + private String toRateString() { + // idea: try to use the smallest unit possible where the rate is still an integer + // start with seconds, then try minutes, hours, etc. + assert isRate; + if (rate == 0) { + return "0/s"; + } + for (TimespanUnit unit : TimespanUnit.values()) { + double value = rate / unit.nanos * 1_000_000_000.0; + if (value % 1 == 0) { + return String.format("%d/%s", (long)value, unit.text); + } + } + // fallback to days if no smaller unit is found + return String.format("%d/%s", (long)(rate / TimespanUnit.DAYS.nanos * 1_000_000_000.0), TimespanUnit.DAYS.text); + } + + private String toPeriodString() { + assert !isRate; + if (periodNanos == 0) { + return "0ms"; } - return String.format("%dns", (long)(Runtime.getRuntime().availableProcessors() / rate * 1_000_000_000L)); + return String.format("%dns", periodNanos); } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties new file mode 100644 index 00000000000..fd30f5385e8 --- /dev/null +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties @@ -0,0 +1,68 @@ +# +# Copyright (c) 2015, 2018, 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. +# + +main.usage.summary=Verwendung: {0} jimage...\nMit -h oder --help können Sie eine Liste der möglichen Optionen aufrufen. + +main.usage=Verwendung: {0} jimage...\n\n extract - Extrahiert alle jimage-Einträge und platziert sie in einem mit der Option\n --dir= (Standardwert = ".") angegebenen Verzeichnis.\n\n info - Gibt detaillierte Informationen aus, die im jimage-Header enthalten sind.\n\n list - Gibt die Namen aller Einträge im jimage aus. Bei Verwendung mit\n --verbose gibt der Befehl "list" auch die Eintragsgröße und Offset-Attribute aus.\n\n verify - Meldet alle .class-Einträge, die nicht als Klassen verifiziert werden.\n\nMögliche Optionen: + +main.usage.extract=\ extract - Extrahiert alle jimage-Einträge und platziert sie in einem mit der Option\n --dir= (Standardwert = ".") angegebenen Verzeichnis. + +main.usage.info=\ info - Gibt detaillierte Informationen aus, die im jimage-Header enthalten sind. + +main.usage.list=\ list - Gibt die Namen aller Einträge im jimage aus. Bei Verwendung mit\n --verbose gibt der Befehl "list" auch die Eintragsgröße und Offset-Attribute aus. + +main.usage.verify=\ verify - Meldet alle .class-Einträge, die nicht als Klassen verifiziert werden. + +error.prefix=Fehler: +warn.prefix=Warnung: + +main.opt.dir=\ --dir Zielverzeichnis für extract-Direktive + +main.opt.include=\ --include Musterliste für das Filtern von Einträgen. + +main.opt.full-version=\ --full-version Gibt vollständige Versionsinformationen aus + +main.opt.help=\ -?, -h, --help Gibt diese Hilfemeldung aus + +main.opt.verbose=\ --verbose Gibt beim Auflisten die Eintragsgröße\n und Offset-Attribute aus + +main.opt.version=\ --version Gibt Versionsinformationen aus + +main.command.files=\ @ Liest Optionen aus der Datei + +main.opt.footer=\nBei Optionen, die eine erfordern, ist der Wert eine durch Komma getrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n \n glob:\n regex: + + + +err.not.a.task=Aufgabe muss einen der folgenden Werte aufweisen: : {0} +err.missing.arg=kein Wert angegeben für {0} +err.ambiguous.arg=Wert für Option {0} beginnt mit "--", aber muss das Format {0}= verwenden +err.not.a.dir=Kein Verzeichnis: {0} +err.not.a.jimage=Keine jimage-Datei: {0} +err.invalid.jimage={0} kann nicht geöffnet werden: {1} +err.no.jimage=Kein jimage angegeben +err.option.unsupported={0} nicht unterstützt: {1} +err.unknown.option=unbekannte Option: {0} +err.cannot.create.dir=Verzeichnis {0} kann nicht erstellt werden diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties new file mode 100644 index 00000000000..66471e23b38 --- /dev/null +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties @@ -0,0 +1,68 @@ +# +# Copyright (c) 2015, 2018, 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. +# + +main.usage.summary=使用方法: {0} jimage...\n使用可能なオプションのリストについては、-hまたは--helpを使用します。 + +main.usage=使用方法: {0} jimage...\n\n extract - すべてのjimageエントリを抽出し、--dir= (default=''.'')\n オプションで指定されたディレクトリに配置します。\n\n info - jimageヘッダーに含まれる詳細情報を出力します。\n\n list - jimage内のすべてのエントリの名前を出力します。--verboseと共に\n 使用すると、listはエントリ・サイズとオフセット属性も出力します。\n\n verify - クラスとして検証しない任意の.classエントリを報告します。\n\n使用可能なオプションには次のものがあります: + +main.usage.extract=\ extract - すべてのjimageエントリを抽出し、--dir= (default='.')\n オプションで指定されたディレクトリに配置します。 + +main.usage.info=\ info - jimageヘッダーに含まれる詳細情報を出力します。 + +main.usage.list=\ list - jimage内のすべてのエントリの名前を出力します。--verboseと共に\n 使用すると、listはエントリ・サイズとオフセット属性も出力します。 + +main.usage.verify=\ verify - クラスとして検証しない任意の.classエントリに関するエラーを報告します。 + +error.prefix=エラー: +warn.prefix=警告: + +main.opt.dir=\ --dir 抽出ディレクティブのターゲット・ディレクトリ + +main.opt.include=\ --include フィルタリング・エントリのパターン・リスト。 + +main.opt.full-version=\ --full-version 完全なバージョン情報を出力します + +main.opt.help=\ -?, -h, --help このヘルプ・メッセージを出力します + +main.opt.verbose=\ --verbose エントリ・サイズとオフセット属性の出力の\n リスティング + +main.opt.version=\ --version バージョン情報を出力します + +main.command.files=\ @ ファイルからオプションを読み取ります + +main.opt.footer=\nを必要とするオプションの場合、値は、次の形式のいずれかを使用する、\n要素のカンマ区切りリストになります:\n \n glob:\n regex: + + + +err.not.a.task=タスクはのいずれかである必要があります: {0} +err.missing.arg={0}に値が指定されていません +err.ambiguous.arg=オプション{0}の値が"--"で始まっています。{0}=形式を使用する必要があります +err.not.a.dir=ディレクトリではありません: {0} +err.not.a.jimage=jimageファイルではありません: {0} +err.invalid.jimage={0}を開けません: {1} +err.no.jimage=jimageが提供されていません +err.option.unsupported={0}はサポートされていません: {1} +err.unknown.option=不明なオプション: {0} +err.cannot.create.dir=ディレクトリ{0}を作成できません diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties new file mode 100644 index 00000000000..8355ed5595e --- /dev/null +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties @@ -0,0 +1,68 @@ +# +# Copyright (c) 2015, 2018, 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. +# + +main.usage.summary=用法:{0} jimage...\n使用 -h 或 --help 列出可能的选项。 + +main.usage=用法:{0} jimage...\n\n extract - 提取所有 jimage 条目,并将其放置在\n 由 --dir= (default=''.'') 选项指定的目录中。\n\n info - 输出 jimage 标头中包含的详细信息。\n\n list - 输出 jimage 中所有条目的名称。与\n --verbose 一起使用时,list 还将输出条目大小和偏移量属性。\n\n verify - 报告任何未验证为类的 .class 条目。\n\n可能的选项包括: + +main.usage.extract=\ extract - 提取所有 jimage 条目,并将其放置在\n 由 --dir= (default='.') 选项指定的目录中。 + +main.usage.info=\ info - 输出 jimage 标头中包含的详细信息。 + +main.usage.list=\ list - 输出 jimage 中所有条目的名称。与 \n --verbose 一起使用时,list 还将输出条目大小和偏移量属性。 + +main.usage.verify=\ verify - 报告任何未验证为类的 .class 条目的错误。 + +error.prefix=错误: +warn.prefix=警告: + +main.opt.dir=\ --dir 提取指令的目标目录 + +main.opt.include=\ --include 用于筛选条目的模式列表。 + +main.opt.full-version=\ --full-version 输出完整版本信息 + +main.opt.help=\ -?, -h, --help 输出此帮助消息 + +main.opt.verbose=\ --verbose 列表输出条目大小和偏移量\n 属性 + +main.opt.version=\ --version 输出版本信息 + +main.command.files=\ @<文件名> 从文件中读取选项 + +main.opt.footer=\n对于需要 的选项,值将为逗号分隔的元素列表,\n每个元素使用以下格式之一:\n \n glob:\n regex: + + + +err.not.a.task=任务必须是 之一:{0} +err.missing.arg=没有为{0}指定值 +err.ambiguous.arg=选项 {0} 的值以 "--" 开头,应使用 {0}= 格式 +err.not.a.dir=不是目录:{0} +err.not.a.jimage=不是 jimage 文件:{0} +err.invalid.jimage=无法打开 {0}: {1} +err.no.jimage=未提供 jimage +err.option.unsupported=不支持{0}: {1} +err.unknown.option=未知选项: {0} +err.cannot.create.dir=无法创建目录 {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java index ca576227692..ee00ea24d14 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -76,10 +76,10 @@ public String getString(int offset) { } public void addLocation(String fullname, long contentOffset, - long compressedSize, long uncompressedSize) { + long compressedSize, long uncompressedSize, int previewFlags) { ImageLocationWriter location = ImageLocationWriter.newLocation(fullname, strings, - contentOffset, compressedSize, uncompressedSize); + contentOffset, compressedSize, uncompressedSize, previewFlags); input.add(location); length++; } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java index 9e05fe31aa9..c8345d13358 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -49,6 +49,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.Archive.Entry; import jdk.tools.jlink.internal.Archive.Entry.EntryType; import jdk.tools.jlink.internal.JRTArchive.ResourceFileEntry; @@ -227,31 +228,8 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent, DataOutputStream out, boolean generateRuntimeImage ) throws IOException { - ResourcePool resultResources; - try { - resultResources = pluginSupport.visitResources(allContent); - if (generateRuntimeImage) { - // Keep track of non-modules resources for linking from a run-time image - resultResources = addNonClassResourcesTrackFiles(resultResources, - writer); - // Generate the diff between the input resources from packaged - // modules in 'allContent' to the plugin- or otherwise - // generated-content in 'resultResources' - resultResources = addResourceDiffFiles(allContent.resourcePool(), - resultResources, - writer); - } - } catch (PluginException pe) { - if (JlinkTask.DEBUG) { - pe.printStackTrace(); - } - throw pe; - } catch (Exception ex) { - if (JlinkTask.DEBUG) { - ex.printStackTrace(); - } - throw new IOException(ex); - } + ResourcePool resultResources = + getResourcePool(allContent, writer, pluginSupport, generateRuntimeImage); Set duplicates = new HashSet<>(); long[] offset = new long[1]; @@ -282,8 +260,10 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent, offset[0] += onFileSize; return; } + int locFlags = ImageLocation.getFlags( + res.path(), p -> resultResources.findEntry(p).isPresent()); duplicates.add(path); - writer.addLocation(path, offset[0], compressedSize, uncompressedSize); + writer.addLocation(path, offset[0], compressedSize, uncompressedSize, locFlags); paths.add(path); offset[0] += onFileSize; } @@ -307,6 +287,40 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent, return resultResources; } + private static ResourcePool getResourcePool( + ResourcePoolManager allContent, + BasicImageWriter writer, + ImagePluginStack pluginSupport, + boolean generateRuntimeImage) + throws IOException { + ResourcePool resultResources; + try { + resultResources = pluginSupport.visitResources(allContent); + if (generateRuntimeImage) { + // Keep track of non-modules resources for linking from a run-time image + resultResources = addNonClassResourcesTrackFiles(resultResources, + writer); + // Generate the diff between the input resources from packaged + // modules in 'allContent' to the plugin- or otherwise + // generated-content in 'resultResources' + resultResources = addResourceDiffFiles(allContent.resourcePool(), + resultResources, + writer); + } + } catch (PluginException pe) { + if (JlinkTask.DEBUG) { + pe.printStackTrace(); + } + throw pe; + } catch (Exception ex) { + if (JlinkTask.DEBUG) { + ex.printStackTrace(); + } + throw new IOException(ex); + } + return resultResources; + } + /** * Support for creating a runtime suitable for linking from the run-time * image. diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java index f2c7f102027..624e608ac21 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -54,8 +54,8 @@ private ImageLocationWriter addAttribute(int kind, String value) { } static ImageLocationWriter newLocation(String fullName, - ImageStringsWriter strings, - long contentOffset, long compressedSize, long uncompressedSize) { + ImageStringsWriter strings, + long contentOffset, long compressedSize, long uncompressedSize, int previewFlags) { String moduleName = ""; String parentName = ""; String baseName; @@ -90,13 +90,14 @@ static ImageLocationWriter newLocation(String fullName, } return new ImageLocationWriter(strings) - .addAttribute(ATTRIBUTE_MODULE, moduleName) - .addAttribute(ATTRIBUTE_PARENT, parentName) - .addAttribute(ATTRIBUTE_BASE, baseName) - .addAttribute(ATTRIBUTE_EXTENSION, extensionName) - .addAttribute(ATTRIBUTE_OFFSET, contentOffset) - .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize) - .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize); + .addAttribute(ATTRIBUTE_MODULE, moduleName) + .addAttribute(ATTRIBUTE_PARENT, parentName) + .addAttribute(ATTRIBUTE_BASE, baseName) + .addAttribute(ATTRIBUTE_EXTENSION, extensionName) + .addAttribute(ATTRIBUTE_OFFSET, contentOffset) + .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize) + .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize) + .addAttribute(ATTRIBUTE_PREVIEW_FLAGS, previewFlags); } @Override diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java index 8a4288f0cfd..48dbf2010bd 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java @@ -24,33 +24,40 @@ */ package jdk.tools.jlink.internal; +import jdk.internal.jimage.ImageLocation; +import jdk.internal.jimage.ModuleReference; + import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.TreeMap; -import java.util.TreeSet; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.joining; /** * A class to build a sorted tree of Resource paths as a tree of ImageLocation. - * */ // XXX Public only due to the JImageTask / JImageTask code duplication public final class ImageResourcesTree { public static boolean isTreeInfoResource(String path) { - return path.startsWith("/packages") || path.startsWith("/modules"); + return path.startsWith("/packages/") || path.startsWith("/modules/"); } /** * Path item tree node. */ - private static class Node { + // Visible for testing only. + static class Node { private final String name; private final Map children = new TreeMap<>(); @@ -66,6 +73,14 @@ private Node(String name, Node parent) { } } + private void setLocation(ImageLocationWriter loc) { + // This *can* be called more than once, but only with the same instance. + if (this.loc != null && loc != this.loc) { + throw new IllegalStateException("Cannot add different locations: " + name); + } + this.loc = Objects.requireNonNull(loc); + } + public String getPath() { if (parent == null) { return "/"; @@ -95,215 +110,240 @@ private static String buildPath(Node item) { } } - private static final class ResourceNode extends Node { + // Visible for testing only. + static final class ResourceNode extends Node { public ResourceNode(String name, Node parent) { super(name, parent); } } - private static class PackageNode extends Node { - /** - * A reference to a package. Empty packages can be located inside one or - * more modules. A package with classes exist in only one module. - */ - static final class PackageReference { - - private final String name; - private final boolean isEmpty; - - PackageReference(String name, boolean isEmpty) { - this.name = Objects.requireNonNull(name); - this.isEmpty = isEmpty; - } + /** + * A 2nd level package directory, {@code "/packages/"}. + * + *

          While package paths can exist within many modules, for each package + * there is at most one module in which that package has resources. + * + *

          For example, the package path {@code java/util} exists in both the + * {@code java.base} and {@code java.logging} modules. This means both + * {@code "/packages/java.util/java.base"} and + * {@code "/packages/java.util/java.logging"} will exist, but only + * {@code "java.base"} entry will be marked as non-empty. + * + *

          For preview mode however, a package that's empty in non-preview mode + * can be non-empty in preview mode. Furthermore, packages which only exist + * in preview mode (empty or not) need to be ignored in non-preview mode. + * + *

          To account for this, the following flags are used for each module + * reference in a package node: + *

            + *
          • {@code HAS_NORMAL_CONTENT}: Packages with resources in normal + * mode. At most one entry will have this flag set. + *
          • {@code HAS_PREVIEW_CONTENT}: Packages with resources in preview + * mode. At most one entry will have this flag set. + *
          • {@code IS_PREVIEW_ONLY}: This is set for packages, empty + * or not, which exist only in preview mode. + *
          + * + *

          While there are 8 combinations of these 3 flags, some will never + * occur (e.g. {@code HAS_NORMAL_CONTENT + IS_PREVIEW_ONLY}). + * + *

          Package node entries are sorted by name, with the exception that (if + * it exists) the unique entry marked as having content will be listed first. + * + *

          When processing entries in normal (non preview) mode, entries marked + * with {@code IS_PREVIEW_ONLY} must be ignored. If, after filtering, there + * are no entries left, then the entire package must be ignored. + * + *

          After this, in either mode, the content flag(s) of the first entry + * determine if that module contains resources for the package. + */ + // Visible for testing only. + static final class PackageNode extends Node { + private final List moduleReferences; + private final int packageFlags; - @Override - public String toString() { - return name + "[empty:" + isEmpty + "]"; - } + PackageNode(String name, List moduleReferences, Node parent) { + super(name, parent); + this.moduleReferences = Collections.unmodifiableList(moduleReferences); + this.packageFlags = validate(); } - private final Map references = new TreeMap<>(); - - PackageNode(String name, Node parent) { - super(name, parent); + List getModuleReferences() { + return moduleReferences; } - private void addReference(String name, boolean isEmpty) { - PackageReference ref = references.get(name); - if (ref == null || ref.isEmpty) { - references.put(name, new PackageReference(name, isEmpty)); + private int validate() { + if (moduleReferences.isEmpty()) { + throw new IllegalStateException("Package must be associated with modules: " + getName()); } + if (moduleReferences.stream().filter(ModuleReference::hasContent).count() > 1) { + throw new IllegalStateException("Multiple modules contain non-empty package: " + getName()); + } + // Calculate the package's ImageLocation flags. + boolean hasPreviewVersion = + moduleReferences.stream().anyMatch(ModuleReference::hasPreviewVersion); + boolean isPreviewOnly = + moduleReferences.stream().allMatch(ModuleReference::isPreviewOnly); + return (hasPreviewVersion ? ImageLocation.FLAGS_HAS_PREVIEW_VERSION : 0) + | (isPreviewOnly ? ImageLocation.FLAGS_IS_PREVIEW_ONLY : 0); } + } - private void validate() { - boolean exists = false; - for (PackageReference ref : references.values()) { - if (!ref.isEmpty) { - if (exists) { - throw new RuntimeException("Multiple modules to contain package " - + getName()); - } else { - exists = true; - } - } - } + // Not serialized, and never stored in any field of any class that is. + @SuppressWarnings("serial") + private static final class InvalidTreeException extends Exception { + public InvalidTreeException(Node badNode) { + super("Resources tree, invalid data structure, skipping: " + badNode.getPath()); } + // Exception only used for program flow, not debugging. + @Override + public Throwable fillInStackTrace() {return this;} } /** * Tree of nodes. */ - private static final class Tree { + // Visible for testing only. + static final class Tree { + private static final String PREVIEW_PREFIX = "META-INF/preview/"; private final Map directAccess = new HashMap<>(); private final List paths; private final Node root; - private Node modules; - private Node packages; + private Node packagesRoot; - private Tree(List paths) { - this.paths = paths; + // Visible for testing only. + Tree(List paths) { + this.paths = paths.stream().sorted(Comparator.reverseOrder()).toList(); + // Root node is not added to the directAccess map. root = new Node("", null); buildTree(); } private void buildTree() { - modules = new Node("modules", root); - directAccess.put(modules.getPath(), modules); - - Map> moduleToPackage = new TreeMap<>(); - Map> packageToModule = new TreeMap<>(); - - for (String p : paths) { - if (!p.startsWith("/")) { - continue; - } - String[] split = p.split("/"); - // minimum length is 3 items: // - if (split.length < 3) { - System.err.println("Resources tree, invalid data structure, " - + "skipping " + p); - continue; - } - Node current = modules; - String module = null; - for (int i = 0; i < split.length; i++) { - // When a non terminal node is marked as being a resource, something is wrong. + Node modulesRoot = new Node("modules", root); + directAccess.put(modulesRoot.getPath(), modulesRoot); + packagesRoot = new Node("packages", root); + directAccess.put(packagesRoot.getPath(), packagesRoot); + + // Map of dot-separated package names to module references (those + // in which the package appear). References are merged after to + // ensure each module name appears only once, but temporarily a + // module may have several entries per package (e.g. with-content, + // without-content, normal, preview-only etc..). + Map> packageToModules = new TreeMap<>(); + for (String fullPath : paths) { + try { + processPath(fullPath, modulesRoot, packageToModules); + } catch (InvalidTreeException err) { // It has been observed some badly created jar file to contain - // invalid directory entry marled as not directory (see 8131762) - if (current instanceof ResourceNode) { - System.err.println("Resources tree, invalid data structure, " - + "skipping " + p); - continue; - } - String s = split[i]; - if (!s.isEmpty()) { - // First item, this is the module, simply add a new node to the - // tree. - if (module == null) { - module = s; - } - Node n = current.children.get(s); - if (n == null) { - if (i == split.length - 1) { // Leaf - n = new ResourceNode(s, current); - String pkg = toPackageName(n.parent); - //System.err.println("Adding a resource node. pkg " + pkg + ", name " + s); - if (pkg != null && !pkg.startsWith("META-INF")) { - Set pkgs = moduleToPackage.get(module); - if (pkgs == null) { - pkgs = new TreeSet<>(); - moduleToPackage.put(module, pkgs); - } - pkgs.add(pkg); - } - } else { // put only sub trees, no leaf - n = new Node(s, current); - directAccess.put(n.getPath(), n); - String pkg = toPackageName(n); - if (pkg != null && !pkg.startsWith("META-INF")) { - Set mods = packageToModule.get(pkg); - if (mods == null) { - mods = new TreeSet<>(); - packageToModule.put(pkg, mods); - } - mods.add(module); - } - } - } - current = n; - } - } - } - packages = new Node("packages", root); - directAccess.put(packages.getPath(), packages); - // The subset of package nodes that have some content. - // These packages exist only in a single module. - for (Map.Entry> entry : moduleToPackage.entrySet()) { - for (String pkg : entry.getValue()) { - PackageNode pkgNode = new PackageNode(pkg, packages); - pkgNode.addReference(entry.getKey(), false); - directAccess.put(pkgNode.getPath(), pkgNode); + // invalid directory entry marked as not directory (see 8131762). + System.err.println(err.getMessage()); } } - // All packages - for (Map.Entry> entry : packageToModule.entrySet()) { - // Do we already have a package node? - PackageNode pkgNode = (PackageNode) packages.getChildren(entry.getKey()); - if (pkgNode == null) { - pkgNode = new PackageNode(entry.getKey(), packages); - } - for (String module : entry.getValue()) { - pkgNode.addReference(module, true); - } + // We've collected information for all "packages", including the root + // (empty) package and anything under "META-INF". However, these should + // not have entries in the "/packages" directory. + packageToModules.keySet().removeIf(p -> p.isEmpty() || p.equals("META-INF") || p.startsWith("META-INF.")); + packageToModules.forEach((pkgName, modRefs) -> { + // Merge multiple refs for the same module. + List pkgModules = modRefs.stream() + .collect(Collectors.groupingBy(ModuleReference::name)) + .values().stream() + .map(refs -> refs.stream().reduce(ModuleReference::merge).orElseThrow()) + .sorted() + .toList(); + PackageNode pkgNode = new PackageNode(pkgName, pkgModules, packagesRoot); directAccess.put(pkgNode.getPath(), pkgNode); + }); + } + + private void processPath( + String fullPath, + Node modulesRoot, + Map> packageToModules) + throws InvalidTreeException { + // Paths are untrusted, so be careful about checking expected format. + if (!fullPath.startsWith("/") || fullPath.endsWith("/") || fullPath.contains("//")) { + return; + } + int modEnd = fullPath.indexOf('/', 1); + // Ensure non-empty module name with non-empty suffix. + if (modEnd <= 1) { + return; } - // Validate that the packages are well formed. - for (Node n : packages.children.values()) { - ((PackageNode)n).validate(); + String modName = fullPath.substring(1, modEnd); + String pkgPath = fullPath.substring(modEnd + 1); + + Node parentNode = getDirectoryNode(modName, modulesRoot); + boolean isPreviewPath = false; + if (pkgPath.startsWith(PREVIEW_PREFIX)) { + // For preview paths, process nodes relative to the preview directory. + pkgPath = pkgPath.substring(PREVIEW_PREFIX.length()); + Node metaInf = getDirectoryNode("META-INF", parentNode); + parentNode = getDirectoryNode("preview", metaInf); + isPreviewPath = true; } + int pathEnd = pkgPath.lastIndexOf('/'); + // From invariants tested above, this must now be well-formed. + String fullPkgName = (pathEnd == -1) ? "" : pkgPath.substring(0, pathEnd).replace('/', '.'); + String resourceName = pkgPath.substring(pathEnd + 1); + // Intermediate packages are marked "empty" (no resources). This might + // later be merged with a non-empty reference for the same package. + ModuleReference emptyRef = ModuleReference.forEmptyPackage(modName, isPreviewPath); + + // Work down through empty packages to final resource. + for (int i = pkgEndIndex(fullPkgName, 0); i != -1; i = pkgEndIndex(fullPkgName, i)) { + // Due to invariants already checked, pkgName is non-empty. + String pkgName = fullPkgName.substring(0, i); + packageToModules.computeIfAbsent(pkgName, p -> new HashSet<>()).add(emptyRef); + String childNodeName = pkgName.substring(pkgName.lastIndexOf('.') + 1); + parentNode = getDirectoryNode(childNodeName, parentNode); + } + // Reached non-empty (leaf) package (could still be a duplicate). + Node resourceNode = parentNode.getChildren(resourceName); + if (resourceNode == null) { + ModuleReference resourceRef = ModuleReference.forResource(modName, isPreviewPath); + packageToModules.computeIfAbsent(fullPkgName, p -> new HashSet<>()).add(resourceRef); + // Init adds new node to parent (don't add resources to directAccess). + new ResourceNode(resourceName, parentNode); + } else if (!(resourceNode instanceof ResourceNode)) { + throw new InvalidTreeException(resourceNode); + } } - public String toResourceName(Node node) { - if (!node.children.isEmpty()) { - throw new RuntimeException("Node is not a resource"); + private Node getDirectoryNode(String name, Node parent) throws InvalidTreeException { + Node child = parent.getChildren(name); + if (child == null) { + // Adds child to parent during init. + child = new Node(name, parent); + directAccess.put(child.getPath(), child); + } else if (child instanceof ResourceNode) { + throw new InvalidTreeException(child); } - return removeRadical(node); + return child; } - public String getModule(Node node) { - if (node.parent == null || node.getName().equals("modules") - || node.getName().startsWith("packages")) { - return null; - } - String path = removeRadical(node); - // "/xxx/..."; - path = path.substring(1); - int i = path.indexOf("/"); - if (i == -1) { - return path; - } else { - return path.substring(0, i); + // Helper to iterate package names up to, and including, the complete name. + private int pkgEndIndex(String s, int i) { + if (i >= 0 && i < s.length()) { + i = s.indexOf('.', i + 1); + return i != -1 ? i : s.length(); } + return -1; } - public String toPackageName(Node node) { - if (node.parent == null) { - return null; - } - String path = removeRadical(node.getPath(), "/modules/"); - String module = getModule(node); - if (path.equals(module)) { - return null; + private String toResourceName(Node node) { + if (!node.children.isEmpty()) { + throw new RuntimeException("Node is not a resource"); } - String pkg = removeRadical(path, module + "/"); - return pkg.replace('/', '.'); + return removeRadical(node); } - public String removeRadical(Node node) { + private String removeRadical(Node node) { return removeRadical(node.getPath(), "/modules"); } @@ -339,9 +379,10 @@ private static final class LocationsAdder { private int addLocations(Node current) { if (current instanceof PackageNode) { + // "/packages/" entries have 8-byte entries (flags+offset). PackageNode pkgNode = (PackageNode) current; - int size = pkgNode.references.size() * 8; - writer.addLocation(current.getPath(), offset, 0, size); + int size = pkgNode.getModuleReferences().size() * 8; + writer.addLocation(current.getPath(), offset, 0, size, pkgNode.packageFlags); offset += size; } else { int[] ret = new int[current.children.size()]; @@ -351,8 +392,11 @@ private int addLocations(Node current) { i += 1; } if (current != tree.getRoot() && !(current instanceof ResourceNode)) { + int locFlags = ImageLocation.getFlags( + current.getPath(), tree.directAccess::containsKey); + // Normal directory entries have 4-byte entries (offset only). int size = ret.length * 4; - writer.addLocation(current.getPath(), offset, 0, size); + writer.addLocation(current.getPath(), offset, 0, size, locFlags); offset += size; } } @@ -369,7 +413,7 @@ private List computeContent() { for (Map.Entry entry : outLocations.entrySet()) { Node item = tree.getMap().get(entry.getKey()); if (item != null) { - item.loc = entry.getValue(); + item.setLocation(entry.getValue()); } } computeContent(tree.getRoot(), outLocations); @@ -378,18 +422,15 @@ private List computeContent() { private int computeContent(Node current, Map outLocations) { if (current instanceof PackageNode) { - // /packages/ + // "/packages/" entries have 8-byte entries (flags+offset). PackageNode pkgNode = (PackageNode) current; - int size = pkgNode.references.size() * 8; - ByteBuffer buff = ByteBuffer.allocate(size); - buff.order(writer.getByteOrder()); - for (PackageNode.PackageReference mod : pkgNode.references.values()) { - buff.putInt(mod.isEmpty ? 1 : 0); - buff.putInt(writer.addString(mod.name)); - } - byte[] arr = buff.array(); - content.add(arr); - current.loc = outLocations.get(current.getPath()); + + List refs = pkgNode.getModuleReferences(); + ByteBuffer byteBuffer = ByteBuffer.allocate(8 * refs.size()); + byteBuffer.order(writer.getByteOrder()); + ModuleReference.write(refs, byteBuffer.asIntBuffer(), writer::addString); + content.add(byteBuffer.array()); + current.setLocation(outLocations.get(current.getPath())); } else { int[] ret = new int[current.children.size()]; int i = 0; @@ -410,10 +451,10 @@ private int computeContent(Node current, Map outLoc if (current instanceof ResourceNode) { // A resource location, remove "/modules" String s = tree.toResourceName(current); - current.loc = outLocations.get(s); + current.setLocation(outLocations.get(s)); } else { // empty "/packages" or empty "/modules" paths - current.loc = outLocations.get(current.getPath()); + current.setLocation(outLocations.get(current.getPath())); } } if (current.loc == null && current != tree.getRoot()) { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java index 7ba9b7db72e..4dcbd955913 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,7 +33,6 @@ class ImageStringsWriter implements ImageStrings { private static final int NOT_FOUND = -1; - static final int EMPTY_OFFSET = 0; private final HashMap stringToOffsetMap; private final ImageStream stream; @@ -42,16 +41,17 @@ class ImageStringsWriter implements ImageStrings { this.stringToOffsetMap = new HashMap<>(); this.stream = new ImageStream(); - // Reserve 0 offset for empty string. - int offset = addString(""); - if (offset != 0) { - throw new InternalError("Empty string not offset zero"); - } + // Frequently used/special strings for which the offset is useful. + reserveString("", ImageStrings.EMPTY_STRING_OFFSET); + reserveString("class", ImageStrings.CLASS_STRING_OFFSET); + reserveString("modules", ImageStrings.MODULES_STRING_OFFSET); + reserveString("packages", ImageStrings.PACKAGES_STRING_OFFSET); + } - // Reserve 1 offset for frequently used ".class". - offset = addString("class"); - if (offset != 1) { - throw new InternalError("'class' string not offset one"); + private void reserveString(String value, int expectedOffset) { + int offset = addString(value); + if (offset != expectedOffset) { + throw new InternalError("Reserved string \"" + value + "\" not at expected offset " + expectedOffset + "[was " + offset + "]"); } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties index 6df60ada590..9b776745c66 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -61,7 +61,7 @@ main.msg.bug=Eine Ausnahme ist in jlink aufgetreten. Melden Sie in der Java-Bugd main.extended.help=Liste der verfügbaren Plug-ins: -main.extended.help.footer=Bei Optionen, die eine erfordern, ist der Wert eine kommagetrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n \n glob:\n regex:\n @, wobei der Dateiname der Name einer Datei mit zu verwendenden Mustern ist,\n ein Muster pro Zeile\n\n +main.extended.help.footer=Bei Optionen, die eine erfordern, ist der Wert eine kommagetrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n \n glob:\n regex:\n @, wobei der Dateiname der Name einer Datei mit zu verwendenden Mustern ist,\n ein Muster pro Zeile\n\n main.runtime.image.linking.cap.enabled=aktiviert main.runtime.image.linking.cap.disabled=deaktiviert main.runtime.image.linking.cap.sect.header=Funktionen: @@ -75,7 +75,7 @@ err.runtime.link.jdk.jlink.prohibited=Dieses JDK enthält keine verpackten Modul err.runtime.link.packaged.mods=Dieses JDK enthält keine verpackten Module. "--keep-packaged-modules" wird nicht unterstützt err.runtime.link.modified.file={0} wurde geändert err.runtime.link.patched.module=jlink unterstützt keine Verknüpfung vom Laufzeitimage unter einer gepatchten Laufzeit mit --patch-module -err.no.module.path=--module-path Option muss mit --add-modules ALL-MODULE-PATH angegeben werden +err.no.module.path=Option --module-path muss mit --add-modules ALL-MODULE-PATH angegeben werden err.empty.module.path=Kein Modul im Modulpfad "{0}" mit --add-modules ALL-MODULE-PATH gefunden err.limit.modules=--limit-modules nicht mit --add-modules ALL-MODULE-PATH zulässig err.jlink.version.mismatch=jlink-Version {0}.{1} stimmt nicht mit Ziel-java.base-Version {2}.{3} überein @@ -95,6 +95,7 @@ err.dir.exists={0} ist bereits vorhanden err.badpattern=ungültiges Muster {0} err.unknown.option=unbekannte Option: {0} err.missing.arg=kein Wert angegeben für {0} +err.ambiguous.arg=Wert für Option {0} beginnt mit "--", aber muss das Format {0}= verwenden err.internal.error=interner Fehler: {0} {1} {2} err.invalid.arg.for.option={0} akzeptiert nicht das Argument "{1}" err.option.after.class=Option muss angegeben werden vor den Klassen: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties index ef82d3bb461..c925f250c41 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -95,6 +95,7 @@ err.dir.exists={0}はすでに存在します err.badpattern=不正パターン{0} err.unknown.option=不明なオプション: {0} err.missing.arg={0}に値が指定されていません +err.ambiguous.arg=オプション{0}の値が"--"で始まっています。{0}=形式を使用する必要があります err.internal.error=内部エラー: {0} {1} {2} err.invalid.arg.for.option={0}は"{1}"引数を受け入れません err.option.after.class=オプションはクラスの前に指定する必要があります: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties index 12989131e65..b7526c9f57a 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -95,6 +95,7 @@ err.dir.exists={0} 已存在 err.badpattern=错误的模式 {0} err.unknown.option=未知选项: {0} err.missing.arg=没有为{0}指定值 +err.ambiguous.arg=选项 {0} 的值以 "--" 开头,应使用 {0}= 格式 err.internal.error=内部错误: {0} {1} {2} err.invalid.arg.for.option={0} 不接受 "{1}" 参数 err.option.after.class=必须在类之前指定选项: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties index a5896e94abb..126e04d0b58 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties @@ -47,7 +47,7 @@ main.opt.cmds=Speicherort der nativen Befehle main.opt.config=Speicherort der vom Benutzer editierbaren Konfigurationsdateien main.opt.extractDir=Zielverzeichnis für Extraktion main.opt.dry-run=Testlauf des Hashmodus -main.opt.exclude=Schließt Dateien aus, die der angegebenen kommagetrennten Musterliste entsprechen. Jedes Element verwendet eines der folgenden Formate: , glob: oder regex: +main.opt.exclude=Schließt Dateien aus, die der angegebenen kommagetrennten Musterliste entsprechen. Jedes Element verwendet eines der folgenden Formate: , glob: oder regex: main.opt.header-files=Speicherort der Headerdateien main.opt.legal-notices=Speicherort der rechtlichen Hinweise main.opt.module-version= Modulversion diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties index da983f76dd6..2f8fcddff73 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemd-Einheitsdatei error.tool-not-found.advice=Installieren Sie die erforderlichen Packages error.tool-old-version.advice=Installieren Sie die erforderlichen Packages -error.invalid-install-dir=Ungültiges Installationsverzeichnis "{0}" +error.deb-invalid-value-for-package-name=Ungültiger Wert "{0}" für den Packagenamen. +error.deb-invalid-value-for-package-name.advice=Setzen Sie die Option "--linux-package-name" auf einen gültigen Debian-Packagenamen. Die Packagenamen dürfen nur Kleinbuchstaben (a-z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-) und Punkte (.) umfassen. Sie müssen mindestens zwei Zeichen lang sein und mit einem Buchstaben beginnen. -error.invalid-value-for-package-name=Ungültiger Wert "{0}" für den Bundle-Namen. -error.invalid-value-for-package-name.advice=Setzen Sie die Option "linux-bundle-name" auf einen gültigen Debian-Packagenamen. Die Packagenamen dürfen nur Kleinbuchstaben (a-z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-) und Punkte (.) umfassen. Sie müssen mindestens zwei Zeichen lang sein und mit einem alphanumerischen Zeichen beginnen. +error.rpm-invalid-value-for-package-name=Ungültiger Wert "{0}" für den Packagenamen. +error.rpm-invalid-value-for-package-name.advice=Setzen Sie die Option "--linux-package-name" auf einen gültigen RPM-Packagenamen. Die Packagenamen dürfen nur Buchstaben (a-z, A-Z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-), Punkte (.) und Unterstriche (_) umfassen. Sie müssen mindestens ein Zeichen lang sein und mit einem Buchstaben beginnen. + +error.rpm-arch-not-detected="RPM-Architektur konnte nicht erkannt werden" message.icon-not-png=Das angegebene Symbol "{0}" ist keine PNG-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet. message.test-for-tool=Test für [{0}]. Ergebnis: {1} diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties index 002fc0baf48..be2cd00b42c 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemdユニット・ファイル error.tool-not-found.advice=必要なパッケージをインストールしてください error.tool-old-version.advice=必要なパッケージをインストールしてください -error.invalid-install-dir=無効なインストール・ディレクトリ"{0}" +error.deb-invalid-value-for-package-name=パッケージ名に対して値"{0}"は無効です。 +error.deb-invalid-value-for-package-name.advice="--linux-package-name"オプションを有効なDebianパッケージ名に設定してください。パッケージ名には、小文字(a-z)、数字(0-9)、プラス(+)とマイナス(-)の記号およびピリオド(.)のみを含めるようにしてください。長さは2文字以上とし、文字で始める必要があります。 -error.invalid-value-for-package-name=バンドル名の値"{0}"が無効です。 -error.invalid-value-for-package-name.advice="linux-bundle-name"オプションを有効なDebianパッケージ名に設定してください。パッケージ名には、小文字(a-z)、数字(0-9)、プラス(+)とマイナス(-)の記号およびピリオド(.)のみを含めるようにしてください。長さは2文字以上とし、英数字で始める必要があります。 +error.rpm-invalid-value-for-package-name=パッケージ名に対して値"{0}"は無効です。 +error.rpm-invalid-value-for-package-name.advice="--linux-package-name"オプションを有効なRPMパッケージ名に設定してください。パッケージ名には、文字(a-z、A-Z)、数字(0-9)、プラス(+)とマイナス(-)の記号、ピリオド(.)およびアダースコア(_)のみを含めるようにしてください。長さは1文字以上とし、文字で始める必要があります。 + +error.rpm-arch-not-detected="RPM archの検出に失敗しました" message.icon-not-png=指定したアイコン"{0}"はPNGファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。 message.test-for-tool=[{0}]のテスト。結果: {1} diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties index 034128f653a..5b583062ab6 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemd 单元文件 error.tool-not-found.advice=请安装所需的程序包 error.tool-old-version.advice=请安装所需的程序包 -error.invalid-install-dir=安装目录 "{0}" 无效 +error.deb-invalid-value-for-package-name=程序包名称的值 "{0}" 无效。 +error.deb-invalid-value-for-package-name.advice=将 "--linux-package-name" 选项设置为有效的 Debian 程序包名称。请注意,程序包名称只能包含小写字母 (a-z)、数字 (0-9)、加号 (+) 和减号 (-) 以及句点 (.)。名称长度必须至少为两个字符并且必须以字母字符开头。 -error.invalid-value-for-package-name=包名的值 "{0}" 无效。 -error.invalid-value-for-package-name.advice=将 "linux-bundle-name" 选项设置为有效的 Debian 程序包名称。请注意,程序包名称只能包含小写字母 (a-z)、数字 (0-9)、加号 (+) 和减号 (-) 以及句点 (.)。名称长度必须至少为两个字符并且必须以字母数字字符开头。 +error.rpm-invalid-value-for-package-name=程序包名称的值 "{0}" 无效。 +error.rpm-invalid-value-for-package-name.advice=将 "--linux-package-name" 选项设置为有效的 RPM 程序包名称。请注意,程序包名称只能包含字母 (a-z, A-Z)、数字 (0-9)、加号 (+) 和减号 (-)、句点 (.) 以及下划线 (_)。名称长度必须至少为一个字符并且必须以字母开头。 + +error.rpm-arch-not-detected="无法检测 RPM 体系结构" message.icon-not-png=指定的图标 "{0}" 不是 PNG 文件, 不会使用。将使用默认图标代替。 message.test-for-tool=[{0}] 的测试。结果: {1} diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties index f76d3a3743f..7e36a260c3f 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=Signatur wurde explizit angefordert, doch es wurde k error.explicit-sign-no-cert.advice=Geben Sie gültige Werte für mac-signing-key-user-name und mac-signing-keychain an error.must-sign-app-store=Mac App Store-Apps müssen signiert werden. Die Signierung wurde von der Bundler-Konfiguration deaktiviert error.must-sign-app-store.advice=Verwenden Sie die Option --mac-sign mit entsprechenden Werten für user-name und keychain -error.no-app-signing-key=Kein Signaturschlüssel für Mac App Store-App -error.no-app-signing-key.advice=Installieren Sie Ihre App-Signaturschlüssel mit XCode in Ihrem Mac-Schlüsselbund. -error.no-pkg-signing-key=Kein Signaturschlüssel für Mac App Store-Installationsprogramm -error.no-pkg-signing-key.advice=Installieren Sie Ihre App-Signaturschlüssel mit XCode in Ihrem Mac-Schlüsselbund. error.certificate.expired=Fehler: Zertifikat abgelaufen {0} error.cert.not.found=Kein Zertifikat gefunden, das [{0}] mit Schlüsselbund [{1}] entspricht error.multiple.certs.found=WARNUNG: Mehrere Zertifikate gefunden, die [{0}] mit Schlüsselbund [{1}] entsprechen. Es wird das erste Zertifikat verwendet @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG-Setupskript resource.license-setup=Lizenzsetup resource.dmg-background=DMG-Hintergrund resource.volume-icon=Symbol "Datenträger" -resource.post-install-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages resource.pkg-preinstall-script=PKG-Preinstall-Skript resource.pkg-postinstall-script=PKG-Postinstall-Skript resource.pkg-services-preinstall-script=PKG-Preinstall-Skript für Servicepackage @@ -72,12 +67,6 @@ message.ignoring.symlink=Warnung: codesign überspringt den Symlink {0}. message.already.signed=Datei ist bereits signiert: {0}. message.keychain.error=Fehler: Schlüsselbundliste kann nicht abgerufen werden. message.building-bundle=Mac App Store-Package für {0} wird erstellt. -message.app-image-dir-does-not-exist=Angegebenes Anwendungsimageverzeichnis {0}: {1} ist nicht vorhanden. -message.app-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist. -message.app-image-requires-app-name=Beim Verwenden eines internen Anwendungsimages müssen Sie den Anwendungsnamen angeben. -message.app-image-requires-app-name.advice=Legen Sie den Anwendungsnamen mit dem CLI-Kennzeichen -name, dem fx:application/@name ANT-Attribut oder dem Bundler-Argument "appName" fest. -message.app-image-requires-identifier=ID kann nicht aus Anwendungsimage extrahiert werden. -message.app-image-requires-identifier.advice=Verwenden Sie "--verbose" für eine erweiterte Fehlermeldung, oder geben Sie sie mit "--mac-package-identifier" an. message.invalid-identifier=Ungültige Mac-Bundle-ID [{0}]. message.invalid-identifier.advice=Geben Sie die ID mit "--mac-package-identifier" an. message.building-dmg=DMG-Package für {0} wird erstellt. @@ -91,7 +80,6 @@ message.preparing-scripts=Packageskripte werden vorbereitet. message.preparing-distribution-dist=distribution.dist wird vorbereitet: {0}. message.signing.pkg=Warnung: Zum Signieren von PKG müssen Sie möglicherweise mit dem Schlüsselbundverwaltungstool die Option "Immer vertrauen" für Ihr Zertifikat festlegen. message.setfile.dmg=Das Festlegen des benutzerdefinierten Symbols für die DMG-Datei wurde übersprungen, weil das Utility "SetFile" nicht gefunden wurde. Durch Installieren von Xcode mit Befehlszeilentools sollte dieses Problem behoben werden. -message.install-dir-ignored=Warnung: "--install-dir" wird von DMG nicht unterstützt. Stattdessen wird standardmäßig /Applications verwendet. message.codesign.failed.reason.app.content="codesign" war nicht erfolgreich, und zusätzlicher Anwendungsinhalt wurde über den Parameter "--app-content" angegeben. Wahrscheinlich hat der zusätzliche Inhalt die Integrität des Anwendungs-Bundles beeinträchtigt und den Fehler verursacht. Stellen Sie sicher, das der über den Parameter "--app-content" angegebene Inhalt nicht die Integrität des Anwendungs-Bundles beeinträchtigt, oder fügen Sie ihn im Nachverarbeitungsschritt hinzu. message.codesign.failed.reason.xcode.tools=Möglicher Grund für "codesign"-Fehler ist fehlender Xcode mit Befehlszeilen-Entwicklertools. Installieren Sie Xcode mit Befehlszeilen-Entwicklertools, und prüfen Sie, ob das Problem dadurch beseitigt wird. warning.unsigned.app.image=Warnung: Nicht signiertes app-image wird zum Erstellen von signiertem {0} verwendet. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index 5ea13254e93..4384d6507f9 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=署名が明示的に要求されましたが、署 error.explicit-sign-no-cert.advice=有効なmac-signing-key-user-nameおよびmac-signing-keychainを指定してください error.must-sign-app-store=Mac App Storeアプリケーションは署名されている必要がありますが、署名はバンドラ構成によって無効化されています error.must-sign-app-store.advice=--mac-signオプションを適切なuser-nameおよびkeychain付きで使用してください -error.no-app-signing-key=Mac App Storeアプリケーションの署名キーがありません -error.no-app-signing-key.advice=XCodeを使用してアプリケーションの署名キーをMacキーチェーンにインストールします。 -error.no-pkg-signing-key=Mac App Storeインストーラの署名キーがありません -error.no-pkg-signing-key.advice=XCodeを使用してアプリケーションの署名キーをMacキーチェーンにインストールします。 error.certificate.expired=エラー: 証明書は{0}に期限が切れました error.cert.not.found=キーチェーン[{1}]を使用する[{0}]と一致する証明書が見つかりません error.multiple.certs.found=警告: キーチェーン[{1}]を使用する[{0}]と一致する複数の証明書が見つかりました。最初のものを使用します @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG設定スクリプト resource.license-setup=ライセンスの設定 resource.dmg-background=dmg背景 resource.volume-icon=ボリューム・アイコン -resource.post-install-script=アプリケーション・イメージを移入した後に実行するスクリプト resource.pkg-preinstall-script=PKGインストール前スクリプト resource.pkg-postinstall-script=PKGインストール後スクリプト resource.pkg-services-preinstall-script=サービス・パッケージのPKGインストール前スクリプト @@ -72,12 +67,6 @@ message.ignoring.symlink=警告: codesignがsymlink {0}をスキップしてい message.already.signed=ファイルはすでに署名されています: {0}。 message.keychain.error=エラー: キーチェーン・リストを取得できません。 message.building-bundle={0}のMac App Storeパッケージを作成しています。 -message.app-image-dir-does-not-exist=指定されたアプリケーション・イメージ・ディレクトリ {0}: {1}は存在しません。 -message.app-image-dir-does-not-exist.advice={0}の値が存在することを確認してください -message.app-image-requires-app-name=外部アプリケーション・イメージを使用する場合、アプリケーション名を指定する必要があります。 -message.app-image-requires-app-name.advice=-name CLIフラグ、fx:application/@name ANT属性または'appName'バンドラ引数でアプリケーション名を設定します。 -message.app-image-requires-identifier=アプリケーション・イメージから識別子を抽出できません。 -message.app-image-requires-identifier.advice=拡張エラー・メッセージに"--verbose"を使用するか、"--mac-package-identifier"を使用して指定します。 message.invalid-identifier=macバンドル識別子[{0}]が無効です。 message.invalid-identifier.advice="--mac-package-identifier"で識別子を指定してください。 message.building-dmg={0}のDMGパッケージを作成しています @@ -91,7 +80,6 @@ message.preparing-scripts=パッケージ・スクリプトを準備していま message.preparing-distribution-dist=distribution.distを準備しています: {0} message.signing.pkg=警告: PKGへの署名の場合、「キーチェーン・アクセス」ツールを使用して証明書に「常に信頼する」を設定する必要があります。 message.setfile.dmg='SetFile'ユーティリティが見つからないため、DMGファイルでのカスタム・アイコンの設定がスキップされました。Xcodeとコマンド・ライン・ツールをインストールすると、この問題は解決されます。 -message.install-dir-ignored=警告: "--install-dir"はDMGでサポートされていません。/Applicationsにデフォルト設定されます。 message.codesign.failed.reason.app.content="codesign"が失敗したため、追加のアプリケーション・コンテンツが、"--app-content"パラメータを介して提供されました。追加のコンテンツにより、アプリケーション・バンドルの整合性が損われ、失敗の原因になった可能性があります。"--app-content"パラメータを介して提供されたコンテンツによって、アプリケーション・バンドルの整合性が損われていないことを確認するか、処理後のステップで追加してください。 message.codesign.failed.reason.xcode.tools="codesign"失敗の考えられる理由は、Xcodeとコマンドライン・デベロッパ・ツールの欠落です。Xcodeとコマンドライン・デベロッパ・ツールをインストールして、問題が解決されるかを確認してください。 warning.unsigned.app.image=警告: 署名されていないapp-imageを使用して署名された{0}を作成します。 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index 1a262f461ac..09c6d77694a 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=已明确请求签名,但找不到签名证书 error.explicit-sign-no-cert.advice=指定有效的 mac-signing-key-user-name 和 mac-signing-keychain error.must-sign-app-store=Mac App Store 应用程序必须签名, 而打包程序配置已禁用签名 error.must-sign-app-store.advice=将 --mac-sign 选项用于适当的用户名和密钥链 -error.no-app-signing-key=无 Mac App Store 应用程序签名密钥 -error.no-app-signing-key.advice=使用 XCode 将应用程序签名密钥安装到 Mac 密钥链中。 -error.no-pkg-signing-key=无 Mac App Store 安装程序签名密钥 -error.no-pkg-signing-key.advice=使用 XCode 将应用程序签名密钥安装到 Mac 密钥链中。 error.certificate.expired=错误: 证书已失效 {0} error.cert.not.found=使用密钥链 [{1}] 找不到与 [{0}] 匹配的证书 error.multiple.certs.found=警告:使用密钥链 [{1}] 找到多个与 [{0}] 匹配的证书,将使用第一个证书 @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG 设置脚本 resource.license-setup=许可证设置 resource.dmg-background=DMG 背景 resource.volume-icon=卷图标 -resource.post-install-script=要在填充应用程序映像之后运行的脚本 resource.pkg-preinstall-script=PKG 安装前脚本 resource.pkg-postinstall-script=PKG 安装后脚本 resource.pkg-services-preinstall-script=服务程序包的 PKG 安装前脚本 @@ -72,12 +67,6 @@ message.ignoring.symlink=警告: codesign 正在跳过符号链接 {0}。 message.already.signed=文件已签名:{0}。 message.keychain.error=错误:无法获取密钥链列表。 message.building-bundle=正在为 {0} 构建 Mac App Store 程序包。 -message.app-image-dir-does-not-exist=指定的应用程序映像目录 {0}:{1} 不存在。 -message.app-image-dir-does-not-exist.advice=确认 {0} 的值是否存在。 -message.app-image-requires-app-name=使用外部应用程序映像时, 必须指定应用程序名称。 -message.app-image-requires-app-name.advice=通过 -name CLI 标记, fx:application/@name ANT 属性或通过 'appName' 打包程序参数设置应用程序名称。 -message.app-image-requires-identifier=无法从应用程序映像提取标识符。 -message.app-image-requires-identifier.advice=请使用 "--verbose" 获取扩展错误消息,或者通过 "--mac-package-identifier" 指定它。 message.invalid-identifier=无效的 Mac 包标识符 [{0}]。 message.invalid-identifier.advice=请使用 "--mac-package-identifier" 指定标识符。 message.building-dmg=正在为 {0} 构建 DMG 程序包。 @@ -91,7 +80,6 @@ message.preparing-scripts=正在准备程序包脚本。 message.preparing-distribution-dist=正在准备 distribution.dist: {0}。 message.signing.pkg=警告:要对 PKG 进行签名,可能需要使用“密钥链访问”工具为证书设置“始终信任”。 message.setfile.dmg=由于未找到 'SetFile' 实用程序,跳过了针对 DMG 文件设置定制图标的操作。安装带命令行工具的 Xcode 应能解决此问题。 -message.install-dir-ignored=警告:"--install-dir" 不受 DMG 支持,将默认为 /Applications。 message.codesign.failed.reason.app.content="codesign" 失败,并通过 "--app-content" 参数提供了附加应用程序内容。可能是附加内容破坏了应用程序包的完整性,导致了故障。请确保通过 "--app-content" 参数提供的内容不会破坏应用程序包的完整性,或者在后处理步骤中添加该内容。 message.codesign.failed.reason.xcode.tools="codesign" 失败可能是因为缺少带命令行开发人员工具的 Xcode。请安装带命令行开发人员工具的 Xcode,看看是否可以解决问题。 warning.unsigned.app.image=警告:使用未签名的 app-image 生成已签名的 {0}。 diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties index 3c66e8bb151..c1cb5bf4283 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties @@ -33,7 +33,7 @@ MSG_Help_win_install=\ --win-dir-chooser\n Fügt ein Dialogfeld hinzu, MSG_Help_win_install_dir=Relativer Unterpfad unter dem Standardinstallationsverzeichnis\n MSG_Help_mac_install=\ --mac-dmg-content [,...]\n Nimmt den gesamten referenzierten Inhalt in die DMG-Datei auf.\n Diese Option kann mehrmals verwendet werden. \n MSG_Help_mac_launcher=\ --mac-package-identifier \n Eine ID, die die Anwendung für macOS eindeutig identifiziert\n Standardwert ist der Hauptklassenname.\n Es dürfen nur alphanumerische Zeichen (A-Z, a-z, 0-9), Bindestriche (-)\n und Punkte (.) verwendet werden.\n --mac-package-name \n Name der Anwendung, wie in der Menüleiste angezeigt\n Dieser kann vom Anwendungsnamen abweichen.\n Er darf maximal 15 Zeichen enthalten und muss für die Anzeige\n in der Menüleiste und im Infofenster der Anwendung geeignet sein.\n Standardwert: Anwendungsname.\n --mac-package-signing-prefix \n Beim Signieren des Anwendungspackages wird dieser Wert\n allen zu signierenden Komponenten ohne vorhandene\n Package-ID als Präfix vorangestellt.\n --mac-sign\n Anforderung zum Signieren des Packages oder des vordefinierten\nAnwendungsimages\n --mac-signing-keychain \n Name des Schlüsselbundes für die Suche nach der Signaturidentität\n Bei fehlender Angabe werden die Standardschlüsselbunde verwendet.\n --mac-signing-key-user-name \n Team- oder Benutzernamensteil der Apple-Signaturidentitäten. Um direkt zu steuern,\n welche Signaturidentität zum Signieren eines Anwendungsimages oder\n Installationsprogramms verwendet wird, verwenden Sie --mac-app-image-sign-identity und/oder\n --mac-installer-sign-identity. Diese Option kann nicht mit\n --mac-app-image-sign-identity oder --mac-installer-sign-identity kombiniert werden.\n --mac-app-image-sign-identity \n Zum Signieren des Anwendungsimages verwendete Identität. Dieser Wert wird\n direkt an die Option --sign des Tools "codesign" übergeben. Diese Option kann nicht\n mit --mac-signing-key-user-name kombiniert werden.\n --mac-installer-sign-identity \n Zum Signieren des Installationsprogramms "pkg" verwendete Identität. Dieser Wert wird\n direkt an die Option --sign des Tools "productbuild" übergeben. Diese Option\n kann nicht mit --mac-signing-key-user-name kombiniert werden.\n --mac-app-store\n Gibt an, dass die jpackage-Ausgabe für den\n Mac App Store bestimmt ist.\n --mac-entitlements \n Pfad zu einer Datei mit Berechtigungen, die beim Signieren\n von ausführbaren Dateien und Librarys im Bundle verwendet werden sollen.\n --mac-app-category \n Zeichenfolge für das Erstellen von LSApplicationCategoryType in\n Anwendungs-plist. Standardwert: "utilities".\n -MSG_Help_linux_install=\ --linux-package-name \n Name für das Linux-Package, Standardwert: Anwendungsname\n --linux-deb-maintainer \n Maintainer für .deb-Package\n --linux-menu-group \n Menügruppe, in der diese Anwendung abgelegt wird\n --linux-package-deps \n Erforderliche Packages oder Funktionen für die Anwendung\n --linux-rpm-license-type \n Typ der Lizenz ("License: " der RPM-SPEC-Datei)\n --linux-app-release \n Releasewert der RPM-SPEC-Datei oder \n Debian-Revisionswert der DEB-Kontrolldatei\n --linux-app-category \n Gruppenwert der RPM-SPEC-Datei oder \n Abschnittswert der DEB-Kontrolldatei\n --linux-shortcut\n Erstellt eine Verknüpfung für die Anwendung.\n +MSG_Help_linux_install=\ --linux-package-name \n Name für das Linux-Package, Standardwert: Anwendungsname\n --linux-deb-maintainer \n Maintainer für .deb-Package\n --linux-menu-group \n Menügruppe, in der diese Anwendung abgelegt wird\n --linux-package-deps \n Erforderliche Packages oder Funktionen für die Anwendung\n --linux-rpm-license-type \n Typ der Lizenz ("License: " der RPM-SPEC-Datei)\n --linux-app-release \n Releasewert der RPM-Datei .spec oder \n Debian-Revisionswert der DEB-Kontrolldatei\n --linux-app-category \n Gruppenwert der RPM-Datei .spec oder \n Abschnittswert der DEB-Kontrolldatei\n --linux-shortcut\n Erstellt einen Shortcut für die Anwendung.\n MSG_Help_mac_linux_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung\n MSG_Help_default_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung auf OS X\n oder Linux. Relativer Unterpfad des Installationsverzeichnisses der\n Anwendung wie "Programme" oder "AppData" unter Windows.\n MSG_Help_no_args=Verwendung: jpackage \nVerwenden Sie jpackage --help (oder -h), um eine Liste möglicher Optionen aufzurufen diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties index e50af2320ce..1221ae747de 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -30,24 +30,23 @@ param.copyright.default=Copyright (C) {0,date,YYYY} param.description.default=Kein Wert param.vendor.default=Unbekannt +resource.post-app-image-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages + message.using-default-resource=Standardpackageressource {0} {1} wird verwendet (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich). message.no-default-resource=Keine Standardpackageressource {0} {1} (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich). message.using-custom-resource-from-file=Benutzerdefinierte Packageressource {0} wird verwendet (aus Datei {1} geladen). message.using-custom-resource=Benutzerdefinierte Packageressource {0} wird verwendet (aus {1} geladen). message.creating-app-bundle=Anwendungspackage {0} wird in {1} erstellt -message.app-image-dir-does-not-exist=Angegebenes Anwendungsimageverzeichnis {0}: {1} ist nicht vorhanden -message.app-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist message.runtime-image-dir-does-not-exist=Angegebenes Laufzeitimageverzeichnis {0}: {1} ist nicht vorhanden -message.runtime-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist message.resource-dir-does-not-exist=Angegebenes Ressourcenverzeichnis {0}: {1} ist nicht vorhanden message.debug-working-directory=Arbeitsverzeichnis für Debug beibehalten: {0} message.bundle-created={0}-Package wurde erfolgreich erstellt message.module-version=Version "{0}" aus Modul "{1}" wird als Anwendungsversion verwendet message.module-class=Klasse "{0}" aus Modul "{1}" wird als Anwendungshauptklasse verwendet -error.version-string-empty="Version darf keine leere Zeichenfolge sein" -error.version-string-zero-length-component="Version [{0}] enthält eine Komponente mit einer Nulllänge" -error.version-string-invalid-component="Version [{0}] enthält ungültige Komponente [{1}]" +error.version-string-empty=Version darf keine leere Zeichenfolge sein +error.version-string-zero-length-component=Version [{0}] enthält eine Komponente mit Nulllänge +error.version-string-invalid-component=Version [{0}] enthält ungültige Komponente [{1}] error.cannot-create-output-dir=Zielverzeichnis {0} kann nicht erstellt werden error.cannot-write-to-output-dir=Zielverzeichnis {0} ist schreibgeschützt @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=Die Haupt-JAR-Datei muss relativ zum Eingab error.no-module-in-path="{0}-Modul im Modulpfad nicht gefunden" error.not-path-parameter="Ungültiger Wert für Parameter {0}: {1}" error.no-input-parameter="--input-Parameter für nicht modulare Anwendung fehlt" -error.no-main-jar-parameter="--main-jar-Parameter für nicht modulare Anwendung fehlt" error.no-content-types-for-file-association=Für Dateiverknüpfungsnummer {0} wurden keine MIME-Typen angegeben error.no-content-types-for-file-association.advice=Geben Sie einen MIME-Typ für Dateiverknüpfungsnummer {0} an @@ -75,11 +73,14 @@ error.tool-old-version.advice=Installieren Sie {0} {1} oder eine neuere Version error.jlink.failed=jlink nicht erfolgreich mit: {0} error.blocked.option=jlink-Option [{0}] ist in --jlink-options nicht zulässig error.no.name=Name nicht mit --name angegeben. Es kann auch kein Name aus app-image abgeleitet werden +error.no.name.advice=Geben Sie den Namen mit --name an warning.no.jdk.modules.found=Warnung: Keine JDK-Module gefunden error.foreign-app-image=Fehler : Fehlende .jpackage.xml-Datei in app-image-Verzeichnis "{0}" -error.invalid-app-image=Fehler: app-image-Verzeichnis "{0}" wurde von einer anderen jpackage-Version generiert, oder "{1}" ist nicht wohlgeformt +error.invalid-app-image=Fehler: app-image-Verzeichnis "{0}" wurde von einer anderen jpackage-Version generiert, oder Datei "{1}" ist nicht wohlgeformt + +error.invalid-install-dir=Ungültiges Installationsverzeichnis "{0}" MSG_BundlerFailed=Fehler: Bundler "{1}" ({0}) konnte kein Package generieren MSG_BundlerConfigException=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} \nEmpfehlung zur Behebung: {2} @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=Fehler: Option [{0}] ist nicht gültig beim ERR_MissingArgument=Fehler: Fehlendes Argument: {0} ERR_MissingRequiredArgument=Fehler: Für das Argument {0} ist mindestens eines der folgenden Argumente erforderlich: [{1}] -ERR_MissingAppResources=Fehler: Keine Anwendungs-JAR-Dateien gefunden ERR_AppImageNotExist=Fehler: Anwendungsimageverzeichnis "{0}" ist nicht vorhanden ERR_NoAddLauncherName=Fehler: Für Option --add-launcher müssen ein Name und ein Dateipfad angegeben werden (--add-launcher =) ERR_NoUniqueName=Fehler: Für --add-launcher = ist ein eindeutiger Name erforderlich -ERR_NoJreInstallerName=Fehler: Für JRE-Installationsprogramme ist ein Namensparameter erforderlich ERR_InvalidAppName=Fehler: Ungültiger Anwendungsname: {0} ERR_InvalidSLName=Fehler: Ungültiger Name für hinzuzufügenden Launcher: {0} ERR_IconFileNotExit=Fehler: Die angegebene Symboldatei [{0}] ist nicht vorhanden @@ -110,8 +109,6 @@ ERR_InvalidOption=Fehler: Ungültige Option: [{0}] ERR_InvalidInstallerType=Fehler: Ungültiger oder nicht unterstützter Typ: [{0}] ERR_BothMainJarAndModule=Fehler: Die Optionen --main-jar und --module dürfen nicht beide vorhanden sein ERR_NoEntryPoint=Fehler: Für das Erstellen des Anwendungsimages muss entweder die Option --main-jar oder die Option --module angegeben werden -ERR_InputNotDirectory=Fehler: Das angegebene Eingabeverzeichnis ist kein Verzeichnis: {0} -ERR_CannotReadInputDir=Fehler: Keine Berechtigung zum Lesen aus Eingabeverzeichnis vorhanden: {0} ERR_CannotParseOptions=Fehler: Option @filename wird verarbeitet: {0} ERR_MissingJLinkOptMacAppStore=Fehler: Argument "--mac-app-store" erfordert eine {0}-Option für Argument "--jlink-options" ERR_MacAppStoreRuntimeBinExists=Fehler: Laufzeitimage "{0}" darf nicht den Ordner "bin" enthalten. Verwenden Sie die jlink-Option "--strip-native-commands" beim Generieren des Laufzeitimages mit dem Argument "--mac-app-store". diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties index c5f0dc328d2..5a04af8a7bc 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -30,24 +30,23 @@ param.copyright.default=Copyright (C) {0,date,YYYY} param.description.default=なし param.vendor.default=不明 +resource.post-app-image-script=アプリケーション・イメージを移入した後に実行するスクリプト + message.using-default-resource=デフォルトのパッケージ・リソース{0} {1}の使用({2}をresource-dirに追加してカスタマイズ)。 message.no-default-resource=デフォルトのパッケージ・リソース{0} {1}なし({2}をresource-dirに追加してカスタマイズ)。 message.using-custom-resource-from-file=カスタム・パッケージ・リソース{0}の使用(ファイル{1}からロード済) message.using-custom-resource=カスタム・パッケージ・リソース{0}の使用({1}からロード済) message.creating-app-bundle=アプリケーション・パッケージを作成しています: {1}内の{0} -message.app-image-dir-does-not-exist=指定されたアプリケーション・イメージ・ディレクトリ{0}: {1}は存在しません -message.app-image-dir-does-not-exist.advice={0}の値が存在することを確認してください message.runtime-image-dir-does-not-exist=指定されたランタイム・イメージ・ディレクトリ{0}: {1}は存在しません -message.runtime-image-dir-does-not-exist.advice={0}の値が存在することを確認してください message.resource-dir-does-not-exist=指定されたリソース・ディレクトリ{0}: {1}は存在しません message.debug-working-directory=デバッグの作業ディレクトリが保持されました: {0} message.bundle-created={0}パッケージの作成に成功しました message.module-version=モジュール"{1}"のバージョン"{0}"をアプリケーション・バージョンとして使用 message.module-class=モジュール"{1}"のクラス"{0}"をアプリケーション・メイン・クラスとして使用 -error.version-string-empty="バージョンを空の文字列にすることはできません" -error.version-string-zero-length-component="バージョン[{0}]に長さゼロのコンポーネントが含まれます" -error.version-string-invalid-component="バージョン[{0}]に無効なコンポーネント[{1}]が含まれます" +error.version-string-empty=バージョンを空の文字列にすることはできません +error.version-string-zero-length-component=バージョン[{0}]に長さゼロのコンポーネントが含まれます +error.version-string-invalid-component=バージョン[{0}]に無効なコンポーネント[{1}]が含まれます error.cannot-create-output-dir=宛先ディレクトリ{0}を作成できません。 error.cannot-write-to-output-dir=宛先ディレクトリ{0}は書込み不可です @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=入力ディレクトリに対して相対 error.no-module-in-path="モジュール・パスに{0}モジュールが見つかりませんでした" error.not-path-parameter="{0}パラメータの無効な値: {1}" error.no-input-parameter="非モジュラ・アプリケーションに--inputパラメータがありません" -error.no-main-jar-parameter="非モジュラ・アプリケーションに--main-jarパラメータがありません" error.no-content-types-for-file-association=ファイル・アソシエーション番号{0}にMIMEタイプが指定されませんでした error.no-content-types-for-file-association.advice=ファイル・アソシエーション番号{0}にMIMEタイプを指定してください @@ -75,11 +73,14 @@ error.tool-old-version.advice={0} {1}以降をインストールしてくださ error.jlink.failed=jlinkが次で失敗しました: {0} error.blocked.option=jlinkオプション[{0}]は--jlink-optionsでは許可されません error.no.name=名前が--nameで指定されておらず、app-imageから推論できません +error.no.name.advice=--nameで名前を指定します warning.no.jdk.modules.found=警告: JDKモジュールが見つかりません error.foreign-app-image=エラー: app-imageディレクトリ"{0}"に.jpackage.xmlファイルがありません -error.invalid-app-image=エラー: app-imageディレクトリ"{0}"は、別のjpackageバージョンまたは不正な"{1}"で生成されました +error.invalid-app-image=エラー: app-imageディレクトリ"{0}"は、別のjpackageバージョンまたは不正な"{1}"ファイルで生成されました + +error.invalid-install-dir=無効なインストール・ディレクトリ"{0}" MSG_BundlerFailed=エラー: バンドラ"{1}" ({0})がパッケージの生成に失敗しました MSG_BundlerConfigException=構成の問題のため、バンドラ{0}がスキップされました: {1} \n次の修正を行ってください: {2} @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=エラー: アプリケーション・イ ERR_MissingArgument=エラー: 引数がありません: {0} ERR_MissingRequiredArgument=エラー: {0}引数には少なくとも1つの[{1}]引数が必要です -ERR_MissingAppResources=エラー: アプリケーションjarが見つかりませんでした ERR_AppImageNotExist=エラー: アプリケーション・イメージ・ディレクトリ"{0}"は存在しません ERR_NoAddLauncherName=エラー: --add-launcherオプションには名前およびファイル・パスが必要です(--add-launcher =) ERR_NoUniqueName=エラー: --add-launcher =には一意の名前が必要です -ERR_NoJreInstallerName=エラー: Jreインストーラには名前パラメータが必要です ERR_InvalidAppName=エラー: 無効なアプリケーション名: {0} ERR_InvalidSLName=エラー: 無効な追加ランチャ名: {0} ERR_IconFileNotExit=エラー: 指定されたアイコン・ファイル[{0}]は存在しません @@ -110,8 +109,6 @@ ERR_InvalidOption=エラー: 無効なオプション: [{0}] ERR_InvalidInstallerType=エラー: 無効またはサポートされていないタイプ: [{0}] ERR_BothMainJarAndModule=エラー: --main-jarオプションと--moduleオプションの両方を指定することはできません ERR_NoEntryPoint=エラー: アプリケーション・イメージの作成には--main-jarまたは--moduleオプションが必要です -ERR_InputNotDirectory=エラー: 指定された入力ディレクトリはディレクトリではありません: {0} -ERR_CannotReadInputDir=エラー: 入力ディレクトリから読み取る権限がありません: {0} ERR_CannotParseOptions=エラー: @filenameオプションの処理: {0} ERR_MissingJLinkOptMacAppStore=エラー: --mac-app-store引数では、--jlink-options引数に{0}オプションが必要です ERR_MacAppStoreRuntimeBinExists=エラー: ランタイム・イメージ"{0}"に"bin"フォルダを含めることはできません。--mac-app-store引数で使用されるランタイム・イメージを生成する際に、--strip-native-commands jlinkオプションを使用します。 diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties index 0d9c3b5a676..5546abef09f 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -30,24 +30,23 @@ param.copyright.default=版权所有 (C) {0,date,YYYY} param.description.default=无 param.vendor.default=未知 +resource.post-app-image-script=要在填充应用程序映像之后运行的脚本 + message.using-default-resource=使用默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。 message.no-default-resource=无默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。 message.using-custom-resource-from-file=使用定制程序包资源 {0} (从文件 {1} 加载)。 message.using-custom-resource=使用定制程序包资源 {0} (从 {1} 加载)。 message.creating-app-bundle=正在 {1} 中创建应用程序包 {0} -message.app-image-dir-does-not-exist=指定的应用程序映像目录 {0}:{1} 不存在 -message.app-image-dir-does-not-exist.advice=确认 {0} 的值是否存在 message.runtime-image-dir-does-not-exist=指定的运行时映像目录 {0}:{1} 不存在 -message.runtime-image-dir-does-not-exist.advice=确认 {0} 的值是否存在 message.resource-dir-does-not-exist=指定的资源目录 {0}:{1} 不存在 message.debug-working-directory=用于调试的已保留工作目录: {0} message.bundle-created=已成功地构建 {0} 程序包 message.module-version=正在将模块 "{1}" 中的版本 "{0}" 用作应用程序版本 message.module-class=正在将模块 "{1}" 中的类 "{0}" 用作应用程序主类 -error.version-string-empty="版本不能为空字符串" -error.version-string-zero-length-component="版本 [{0}] 包含长度为零的组件" -error.version-string-invalid-component="版本 [{0}] 包含无效组件 [{1}]" +error.version-string-empty=版本不能为空字符串 +error.version-string-zero-length-component=版本 [{0}] 包含长度为零的组件 +error.version-string-invalid-component=版本 [{0}] 包含无效组件 [{1}] error.cannot-create-output-dir=无法创建目标目录 {0} error.cannot-write-to-output-dir=目标目录 {0} 不可写 @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=必须使用相对于输入目录的路径 error.no-module-in-path="无法在模块路径中找到 {0} 模块" error.not-path-parameter="{0} 参数的值无效:{1}" error.no-input-parameter="非模块化应用程序缺少 --input 参数" -error.no-main-jar-parameter="非模块化应用程序缺少 --main-jar 参数" error.no-content-types-for-file-association=没有为文件关联号{0}指定 MIME 类型 error.no-content-types-for-file-association.advice=为文件关联号 {0} 指定 MIME 类型 @@ -75,11 +73,14 @@ error.tool-old-version.advice=请安装 {0} {1}或更新版本 error.jlink.failed=jlink 失败,出现 {0} error.blocked.option=不允许在 --jlink-options 中使用 jlink 选项 [{0}] error.no.name=未使用 --name 指定名称,无法从 app-image 推断名称 +error.no.name.advice=使用 --name 指定名称 warning.no.jdk.modules.found=警告: 未找到 JDK 模块 error.foreign-app-image=错误:app-image 目录 "{0}" 中缺少 .jpackage.xml 文件 -error.invalid-app-image=错误:另一个 jpackage 版本或格式错误的 "{1}" 生成了 app-image 目录 "{0}" +error.invalid-app-image=错误:另一个 jpackage 版本或格式错误的 "{1}" 文件生成了 app-image 目录 "{0}" + +error.invalid-install-dir=安装目录 "{0}" 无效 MSG_BundlerFailed=错误:打包程序 "{1}" ({0}) 无法生成程序包 MSG_BundlerConfigException=由于配置问题, 跳过了打包程序{0}: {1} \n修复建议: {2} @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=错误:对应用程序映像签名时, ERR_MissingArgument=错误: 缺少参数: {0} ERR_MissingRequiredArgument=错误:{0} 参数至少需要 [{1}] 参数之一 -ERR_MissingAppResources=错误: 找不到应用程序 jar ERR_AppImageNotExist=错误:应用程序映像目录 "{0}" 不存在 ERR_NoAddLauncherName=错误:--add-launcher 选项需要一个名称和一个文件路径 (--add-launcher =) ERR_NoUniqueName=错误:--add-launcher = 需要一个唯一的名称 -ERR_NoJreInstallerName=错误:Jre 安装程序需要一个名称参数 ERR_InvalidAppName=错误:应用程序名称 {0} 无效 ERR_InvalidSLName=错误:添加启动程序名称 {0} 无效 ERR_IconFileNotExit=错误:指定的图标文件 [{0}] 不存在 @@ -110,8 +109,6 @@ ERR_InvalidOption=错误:选项 [{0}] 无效 ERR_InvalidInstallerType=错误:类型 [{0}] 无效或不受支持 ERR_BothMainJarAndModule=错误:不能同时包含 --main-jar 和 --module 选项 ERR_NoEntryPoint=错误:创建应用程序映像需要 --main-jar 或 --module 选项 -ERR_InputNotDirectory=错误:指定的输入目录不是目录:{0} -ERR_CannotReadInputDir=错误:无权从输入目录读取:{0} ERR_CannotParseOptions=错误:正在处理 @filename 选项:{0} ERR_MissingJLinkOptMacAppStore=错误:对于 --jlink-options 参数,--mac-app-store 参数需要 {0} 选项 ERR_MacAppStoreRuntimeBinExists=错误:运行时映像 "{0}" 不应包含 "bin" 文件夹。生成与 --mac-app-store 参数一起使用的运行时映像时,使用 --strip-native-commands jlink 选项。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl index 5e30d3744ec..2d0d1d098f8 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl @@ -16,5 +16,5 @@ Mit [ProductName] öffnen - [ProductName][ProductVersion] is not supported on this version of Windows + [ProductName][ProductVersion] wird unter dieser Windows-Version nicht unterstützt diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl index 4639e2f8fed..88a662b4b1f 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl @@ -16,5 +16,5 @@ [ProductName]で開く - [ProductName][ProductVersion] is not supported on this version of Windows + [ProductName][ProductVersion]は、 このバージョンのWindowsでサポートされていません diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl index 06974dd84e5..48a342e58a3 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl @@ -16,5 +16,5 @@ 使用 [ProductName] 打开 - [ProductName][ProductVersion] is not supported on this version of Windows + 此版本的 Windows 不支持 [ProductName][ProductVersion] diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties index b6561747ce0..3e6f8e30d6a 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -32,7 +32,6 @@ param.menu-group.default=Unbekannt resource.executable-properties-template=Vorlage für das Erstellen der ausführbaren Eigenschaftendatei resource.setup-icon=Symbol für Dialogfeld "Setup" -resource.post-app-image-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages resource.post-msi-script=Auszuführendes Skript nach dem Erstellen der MSI-Datei für das EXE-Installationsprogramm resource.wxl-file=WiX-Lokalisierungsdatei resource.main-wix-file=Haupt-WiX-Projektdatei @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=Dialogfeld für Verknüpfungs-Prompt der WiX resource.installdirnotemptydlg-wix-file=Nicht leeres Installationsverzeichnis in Dialogfeld für WiX-Projektdatei resource.launcher-as-service-wix-file=WiX-Projektdatei für Serviceinstallationsprogramm resource.wix-src-conv=XSLT-Stylesheet zum Konvertieren von WiX-Quellen vom Format WiX v3 in WiX v4 +resource.installer-exe=Ausführbares Installationsprogramm error.no-wix-tools=WiX-Tools nicht gefunden. Gesucht wurden WiX v3 light.exe und candle.exe oder WiX v4/v5 wix.exe, aber keine der Dateien wurde gefunden error.no-wix-tools.advice=Laden Sie WiX 3.0 oder höher von https://wixtoolset.org herunter, und fügen Sie es zu PATH hinzu. @@ -67,7 +67,6 @@ message.output-location=Installationsprogramm (.exe) gespeichert in: {0} message.tool-version=[{0}]-Version [{1}] erkannt. message.creating-association-with-null-extension=Verknüpfung mit Nullerweiterung wird erstellt. message.wrong-tool-version=[{0}]-Version {1} wurde erkannt. Erforderlich ist jedoch Version {2}. -message.version-string-too-many-components=Versionszeichenfolge kann bis zu 3 Komponenten aufweisen: major.minor.build. message.use-wix36-features=WiX {0} erkannt. Erweiterte Bereinigungsaktion wird aktiviert. message.product-code=MSI-ProductCode: {0}. message.upgrade-code=MSI-UpgradeCode: {0}. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties index 5dbf0eaa058..07604dc9980 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -32,7 +32,6 @@ param.menu-group.default=不明 resource.executable-properties-template=実行可能なプロパティ・ファイル作成用のテンプレート resource.setup-icon=設定ダイアログ・アイコン -resource.post-app-image-script=アプリケーション・イメージを移入した後に実行するスクリプト resource.post-msi-script=exeインストーラのmsiファイルが作成された後に実行するスクリプト resource.wxl-file=WiXローカリゼーション・ファイル resource.main-wix-file=メインWiXプロジェクト・ファイル @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=ショートカット・プロンプト・ resource.installdirnotemptydlg-wix-file=インストール・ディレクトリ・ダイアログのWiXプロジェクト・ファイルが空ではありません resource.launcher-as-service-wix-file=サービス・インストーラWiXプロジェクト・ファイル resource.wix-src-conv=WiXソースをWiX v3からWiX v4フォーマットに変換するXSLTスタイルシート +resource.installer-exe=インストーラ実行可能ファイル error.no-wix-tools=WiXツールが見つかりません。WiX v3 light.exeとcandle.exeまたはWiX v4/v5 wix.exeを探しましたが、いずれも見つかりませんでした error.no-wix-tools.advice=WiX 3.0以降をhttps://wixtoolset.orgからダウンロードし、PATHに追加します。 @@ -67,7 +67,6 @@ message.output-location=インストーラ(.exe)は次に保存されました: message.tool-version=[{0}]バージョン[{1}]が検出されました。 message.creating-association-with-null-extension=null拡張子との関連付けを作成しています。 message.wrong-tool-version=[{0}]バージョン{1}が検出されましたが、バージョン{2}が必要です。 -message.version-string-too-many-components=バージョン文字列には、コンポーネントを3つ(メジャー.マイナー.ビルド)まで含めることができます。 message.use-wix36-features=WiX {0}が検出されました。拡張クリーンアップ・アクションを有効化しています。 message.product-code=MSI ProductCode: {0}。 message.upgrade-code=MSI UpgradeCode: {0}。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties index 2fb4e8e40e7..7eae69fba2f 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -32,7 +32,6 @@ param.menu-group.default=未知 resource.executable-properties-template=用于创建可执行属性文件的模板 resource.setup-icon=设置对话框图标 -resource.post-app-image-script=要在填充应用程序映像之后运行的脚本 resource.post-msi-script=在为 exe 安装程序创建 msi 文件之后要运行的脚本 resource.wxl-file=WiX 本地化文件 resource.main-wix-file=主 WiX 项目文件 @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=快捷方式提示对话框 WiX 项目文件 resource.installdirnotemptydlg-wix-file=安装目录对话框 WiX 项目文件非空 resource.launcher-as-service-wix-file=服务安装程序 WiX 项目文件 resource.wix-src-conv=将 WiX 源码从 WiX v3 格式转换为 WiX v4 格式的 XSLT 样式表 +resource.installer-exe=安装程序可执行文件 error.no-wix-tools=找不到 WiX 工具。已查找 WiX v3 light.exe 和 candle.exe 或 WiX v4/v5 wix.exe,但都未找到 error.no-wix-tools.advice=从 https://wixtoolset.org 下载 WiX 3.0 或更高版本,然后将其添加到 PATH。 @@ -67,7 +67,6 @@ message.output-location=安装程序 (.exe) 已保存到: {0} message.tool-version=检测到 [{0}] 版本 [{1}]。 message.creating-association-with-null-extension=正在使用空扩展名创建关联。 message.wrong-tool-version=检测到 [{0}] 版本 {1}, 但需要版本 {2}。 -message.version-string-too-many-components=版本字符串最多可以具有 3 个组成部分 - major.minor.build。 message.use-wix36-features=检测到 WiX {0}。正在启用高级清除操作。 message.product-code=MSI ProductCode:{0}。 message.upgrade-code=MSI UpgradeCode:{0}。 diff --git a/src/jdk.jpackage/windows/native/libjpackage/VersionInfo.cpp b/src/jdk.jpackage/windows/native/libjpackage/VersionInfo.cpp index 7b0b8fa5a74..122757b3ac3 100644 --- a/src/jdk.jpackage/windows/native/libjpackage/VersionInfo.cpp +++ b/src/jdk.jpackage/windows/native/libjpackage/VersionInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -180,7 +180,6 @@ void VersionInfo::fillBuffer(std::ostream& buf) const { write(buf, createFIXEDFILEINFO()); // Value add32bitPadding(buf); // Padding2 - const DWORD neutralLangId = (0x04b0 | MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) << 16); const DWORD engLangId = (0x04b0 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) << 16); do { diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index c5b3dae2d58..5cf301efac5 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -843,7 +843,7 @@ public void resume() { public void beforeUserCode() { synchronized (this) { pendingBytes = null; - pendingLine = null; + pendingLineCharacters = null; } input.setState(State.BUFFER); } @@ -977,26 +977,32 @@ public void perform(LineReaderImpl in) throws IOException { private static final Charset stdinCharset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); - private String pendingLine; - private int pendingLinePointer; + private char[] pendingLineCharacters; + private int pendingLineCharactersPointer; private byte[] pendingBytes; private int pendingBytesPointer; @Override public synchronized int readUserInput() throws IOException { if (pendingBytes == null || pendingBytes.length <= pendingBytesPointer) { - char userChar = readUserInputChar(); + int userCharInput = readUserInputChar(); + if (userCharInput == (-1)) { + return -1; + } + char userChar = (char) userCharInput; StringBuilder dataToConvert = new StringBuilder(); dataToConvert.append(userChar); if (Character.isHighSurrogate(userChar)) { //surrogates cannot be converted independently, //read the low surrogate and append it to dataToConvert: - char lowSurrogate = readUserInputChar(); - if (Character.isLowSurrogate(lowSurrogate)) { - dataToConvert.append(lowSurrogate); + int lowSurrogateInput = readUserInputChar(); + if (lowSurrogateInput == (-1)) { + //end of input, ignore at this stage + } else if (Character.isLowSurrogate((char) lowSurrogateInput)) { + dataToConvert.append((char) lowSurrogateInput); } else { //if not the low surrogate, rollback the reading of the character: - pendingLinePointer--; + pendingLineCharactersPointer--; } } pendingBytes = dataToConvert.toString().getBytes(stdinCharset); @@ -1006,19 +1012,32 @@ public synchronized int readUserInput() throws IOException { } @Override - public synchronized char readUserInputChar() throws IOException { - while (pendingLine == null || pendingLine.length() <= pendingLinePointer) { - pendingLine = doReadUserLine("", null) + System.getProperty("line.separator"); - pendingLinePointer = 0; + public synchronized int readUserInputChar() throws IOException { + if (pendingLineCharacters != null && pendingLineCharacters.length == 0) { + return -1; + } + while (pendingLineCharacters == null || pendingLineCharacters.length <= pendingLineCharactersPointer) { + String readLine = doReadUserLine("", null); + if (readLine == null) { + pendingLineCharacters = new char[0]; + return -1; + } else { + pendingLineCharacters = (readLine + System.getProperty("line.separator")).toCharArray(); + } + pendingLineCharactersPointer = 0; } - return pendingLine.charAt(pendingLinePointer++); + return pendingLineCharacters[pendingLineCharactersPointer++]; } @Override public synchronized String readUserLine(String prompt) throws IOException { //TODO: correct behavior w.r.t. pre-read stuff? - if (pendingLine != null && pendingLine.length() > pendingLinePointer) { - return pendingLine.substring(pendingLinePointer); + if (pendingLineCharacters != null && pendingLineCharacters.length > pendingLineCharactersPointer) { + String result = new String(pendingLineCharacters, + pendingLineCharactersPointer, + pendingLineCharacters.length - pendingLineCharactersPointer); + pendingLineCharacters = null; + return result; } return doReadUserLine(prompt, null); } @@ -1041,6 +1060,8 @@ private synchronized String doReadUserLine(String prompt, Character mask) throws return in.readLine(prompt.replace("%", "%%"), mask); } catch (UserInterruptException ex) { throw new InterruptedIOException(); + } catch (EndOfFileException ex) { + return null; // Signal that Ctrl+D or similar happened } finally { in.setParser(prevParser); in.setHistory(prevHistory); @@ -1051,7 +1072,11 @@ private synchronized String doReadUserLine(String prompt, Character mask) throws public char[] readPassword(String prompt) throws IOException { //TODO: correct behavior w.r.t. pre-read stuff? - return doReadUserLine(prompt, '\0').toCharArray(); + String line = doReadUserLine(prompt, '\0'); + if (line == null) { + return null; + } + return line.toCharArray(); } @Override @@ -1406,6 +1431,14 @@ public TestTerminal(InputStream input, OutputStream output) throws Exception { private TestTerminal(InputStream input, OutputStream output, Size size) throws Exception { super(input, output, "ansi", size, size); } + + @Override + public Attributes enterRawMode() { + Attributes res = super.enterRawMode(); + res.setControlChar(ControlChar.VEOF, 4); + return res; + } + } private static final class CompletionState { diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java index aa1f840c9c3..e6d43bb346e 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.io.Writer; import java.nio.charset.Charset; -import jdk.internal.org.jline.reader.UserInterruptException; /** * Interface for defining user interaction with the shell. @@ -59,18 +58,18 @@ abstract class IOContext implements AutoCloseable { public abstract int readUserInput() throws IOException; - public char readUserInputChar() throws IOException { - throw new UserInterruptException(""); + public int readUserInputChar() throws IOException { + return -1; } public String readUserLine(String prompt) throws IOException { userOutput().write(prompt); userOutput().flush(); - throw new UserInterruptException(""); + return null; } public String readUserLine() throws IOException { - throw new UserInterruptException(""); + return null; } public Writer userOutput() { @@ -80,7 +79,7 @@ public Writer userOutput() { public char[] readPassword(String prompt) throws IOException { userOutput().write(prompt); userOutput().flush(); - throw new UserInterruptException(""); + return null; } public void setIndent(int indent) {} diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 86a84953c80..795321253fd 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -4121,7 +4121,11 @@ public synchronized Reader reader() { public int read(char[] cbuf, int off, int len) throws IOException { if (len == 0) return 0; try { - cbuf[off] = input.readUserInputChar(); + int r = input.readUserInputChar(); + if (r == (-1)) { + return -1; + } + cbuf[off] = (char) r; return 1; } catch (UserInterruptException ex) { return -1; diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties index dbd4a5183c3..cb93ae4ed57 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties @@ -154,6 +154,7 @@ jshell.err.exception.thrown = Ausnahme {0} jshell.err.exception.thrown.message = Ausnahme {0}: {1} jshell.err.exception.cause = Verursacht von: {0} jshell.err.exception.cause.message = Verursacht von: {0}: {1} +jshell.err.incomplete.input = Unvollständige Eingabe: {0} jshell.console.see.synopsis = jshell.console.see.full.documentation = diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties index 14a88c56b70..fa84c3f38fb 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties @@ -154,6 +154,7 @@ jshell.err.exception.thrown = 例外{0} jshell.err.exception.thrown.message = 例外{0}: {1} jshell.err.exception.cause = 原因: {0} jshell.err.exception.cause.message = 原因: {0}: {1} +jshell.err.incomplete.input = 不完全な入力: {0} jshell.console.see.synopsis = <概要を表示するにはタブを再度押してください> jshell.console.see.full.documentation = <ドキュメント全体を表示するにはタブを再度押してください> diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties index 0bbc5d76404..879e9633e6a 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties @@ -154,6 +154,7 @@ jshell.err.exception.thrown = 异常错误 {0} jshell.err.exception.thrown.message = 异常错误 {0}:{1} jshell.err.exception.cause = 原因:{0} jshell.err.exception.cause.message = 原因: {0}: {1} +jshell.err.incomplete.input = 输入不完整:{0} jshell.console.see.synopsis = <再次按 Tab 可查看提要> jshell.console.see.full.documentation = <再次按 Tab 可查看完整文档> diff --git a/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 4ca8e3830c8..336746047dc 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -56,6 +56,7 @@ import jdk.jshell.spi.ExecutionControlProvider; import jdk.jshell.spi.ExecutionEnv; import static jdk.jshell.Util.expunge; +import jdk.jshell.execution.impl.RestartableInputStream; /** * The JShell evaluation state engine. This is the central class in the JShell @@ -115,7 +116,7 @@ public class JShell implements AutoCloseable { private static ResourceBundle outputRB = null; JShell(Builder b) throws IllegalStateException { - this.in = b.in; + this.in = new RestartableInputStream(b.in); this.out = b.out; this.err = b.err; this.console = Optional.ofNullable(b.console); diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java index 2475a959fdf..cbf68558f11 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -47,6 +47,7 @@ import jdk.jshell.spi.ExecutionControl.ExecutionControlException; import static java.nio.charset.StandardCharsets.UTF_8; +import jdk.jshell.execution.impl.RestartableInputStream; /** * Miscellaneous utility methods for setting-up implementations of @@ -62,6 +63,7 @@ public class Util { private static final int TAG_DATA = 0; private static final int TAG_CLOSED = 1; private static final int TAG_EXCEPTION = 2; + private static final int TAG_EOF = 3; // never instantiated private Util() {} @@ -122,6 +124,7 @@ public synchronized int read() throws IOException { switch (tag) { case TAG_DATA: return super.read(); case TAG_CLOSED: close(); return -1; + case TAG_EOF: return -1; case TAG_EXCEPTION: int len = (super.read() << 0) + (super.read() << 8) + (super.read() << 16) + (super.read() << 24); byte[] message = new byte[len]; @@ -183,7 +186,11 @@ public void write(int b) throws IOException { try { int r = in.read(); if (r == (-1)) { - inTarget.write(TAG_CLOSED); + if (in instanceof RestartableInputStream ris && !ris.isClosed()) { + inTarget.write(TAG_EOF); + } else { + inTarget.write(TAG_CLOSED); + } } else { inTarget.write(new byte[] {TAG_DATA, (byte) r}); } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java index 5f4defc8afd..03f578746af 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java @@ -182,9 +182,18 @@ public synchronized Reader reader() { reader = new Reader() { @Override public int read(char[] cbuf, int off, int len) throws IOException { + if (len == 0) { + return 0; + } return sendAndReceive(() -> { remoteInput.write(Task.READ_CHARS.ordinal()); - return readChars(cbuf, off, len); + int r = readInt(); + if (r == (-1)) { + return -1; + } else { + cbuf[off] = (char) r; + return 1; + } }); } @@ -374,13 +383,9 @@ public synchronized void write(int b) throws IOException { bp = 0; } case READ_CHARS -> { - if (bp >= 5) { - int len = readInt(1); - int c = console.reader().read(); - //XXX: EOF handling! - sendChars(sinkOutput, new char[] {(char) c}, 0, 1); - bp = 0; - } + int c = console.reader().read(); + sendInt(sinkOutput, c); + bp = 0; } case READ_LINE -> { char[] data = readCharsOrNull(1); diff --git a/test/micro/org/openjdk/bench/valhalla/types/R128long.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/RestartableInputStream.java similarity index 54% rename from test/micro/org/openjdk/bench/valhalla/types/R128long.java rename to src/jdk.jshell/share/classes/jdk/jshell/execution/impl/RestartableInputStream.java index 943b45fa7ce..3b634f693e1 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/R128long.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/RestartableInputStream.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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. + * 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 @@ -20,44 +22,28 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; +package jdk.jshell.execution.impl; -public class R128long implements Int128, ByLong { +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.atomic.AtomicBoolean; - public final long v0; - public final long v1; +public class RestartableInputStream extends FilterInputStream { - public R128long(long v) { - this(0, v); - } - - public R128long(long hi, long lo) { - this.v0 = hi; - this.v1 = lo; - } + private final AtomicBoolean closed = new AtomicBoolean(); - @Override - public int intValue() { - return (int)loValue(); + public RestartableInputStream(InputStream delegate) { + super(delegate); } @Override - public long longValue() { - return loValue(); + public void close() throws IOException { + closed.set(true); + super.close(); } - @Override - public long hiValue() { - return v0; - } - - @Override - public long loValue() { - return v1; - } - - @Override - public long longSum() { - return v0 + v1; + public boolean isClosed() { + return closed.get(); } } diff --git a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index 067cfffb158..8ce7c03f62d 100644 --- a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -158,7 +158,8 @@ public static enum ThreadDumpFormat { TEXT_PLAIN, /** * JSON (JavaScript Object Notation) format. - * @spec https://datatracker.ietf.org/doc/html/rfc8259 JavaScript Object Notation + * @spec https://datatracker.ietf.org/doc/html/rfc8259 RFC 8259: The JavaScript + * Object Notation (JSON) Data Interchange Format */ JSON, } diff --git a/src/utils/IdealGraphVisualizer/README.md b/src/utils/IdealGraphVisualizer/README.md index 195878a5b99..7f48702c769 100644 --- a/src/utils/IdealGraphVisualizer/README.md +++ b/src/utils/IdealGraphVisualizer/README.md @@ -33,7 +33,7 @@ Ideal graphs are dumped at the following points: * `N=2`: additionally, after every major phase * `N=3`: additionally, after every minor phase * `N=4`: additionally, after every loop optimization -* `N=5`: additionally, after every effective IGVN and every macro expansion step (slow) +* `N=5`: additionally, after every effective IGVN, macro elimination, and macro expansion step (slow) * `N=6`: additionally, after parsing every bytecode (very slow) By default the JVM expects that it will connect to a visualizer on the local diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index b0c8cdbc330..5b2c18b0a2b 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1605,7 +1605,7 @@ def generate(kind, names): generate (Op, ["nop", "yield", "wfe", "sev", "sevl", "autia1716", "autiasp", "autiaz", "autib1716", "autibsp", "autibz", "pacia1716", "paciasp", "paciaz", "pacib1716", "pacibsp", "pacibz", - "eret", "drps", "isb",]) + "eret", "drps", "isb", "sb",]) # Ensure the "i" is not stripped off the end of the instruction generate (PostfixExceptionOp, ["wfi", "xpaclri"]) diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 2b4ea356d70..d90c2479995 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -187,6 +187,7 @@ __ eret(); // eret __ drps(); // drps __ isb(); // isb + __ sb(); // sb // PostfixExceptionOp __ wfi(); // wfi @@ -1437,306 +1438,306 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x140004af, 0x94000000, - 0x97ffffd4, 0x940004ac, 0x3400000a, 0x34fffa2a, - 0x3400952a, 0x35000008, 0x35fff9c8, 0x350094c8, - 0xb400000b, 0xb4fff96b, 0xb400946b, 0xb500001d, - 0xb5fff91d, 0xb500941d, 0x10000013, 0x10fff8b3, - 0x100093b3, 0x90000013, 0x36300016, 0x3637f836, - 0x36309336, 0x3758000c, 0x375ff7cc, 0x375892cc, + 0x14000000, 0x17ffffd7, 0x140004b0, 0x94000000, + 0x97ffffd4, 0x940004ad, 0x3400000a, 0x34fffa2a, + 0x3400954a, 0x35000008, 0x35fff9c8, 0x350094e8, + 0xb400000b, 0xb4fff96b, 0xb400948b, 0xb500001d, + 0xb5fff91d, 0xb500943d, 0x10000013, 0x10fff8b3, + 0x100093d3, 0x90000013, 0x36300016, 0x3637f836, + 0x36309356, 0x3758000c, 0x375ff7cc, 0x375892ec, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540090a0, 0x54000001, 0x54fff541, 0x54009041, - 0x54000002, 0x54fff4e2, 0x54008fe2, 0x54000002, - 0x54fff482, 0x54008f82, 0x54000003, 0x54fff423, - 0x54008f23, 0x54000003, 0x54fff3c3, 0x54008ec3, - 0x54000004, 0x54fff364, 0x54008e64, 0x54000005, - 0x54fff305, 0x54008e05, 0x54000006, 0x54fff2a6, - 0x54008da6, 0x54000007, 0x54fff247, 0x54008d47, - 0x54000008, 0x54fff1e8, 0x54008ce8, 0x54000009, - 0x54fff189, 0x54008c89, 0x5400000a, 0x54fff12a, - 0x54008c2a, 0x5400000b, 0x54fff0cb, 0x54008bcb, - 0x5400000c, 0x54fff06c, 0x54008b6c, 0x5400000d, - 0x54fff00d, 0x54008b0d, 0x5400000e, 0x54ffefae, - 0x54008aae, 0x5400000f, 0x54ffef4f, 0x54008a4f, + 0x540090c0, 0x54000001, 0x54fff541, 0x54009061, + 0x54000002, 0x54fff4e2, 0x54009002, 0x54000002, + 0x54fff482, 0x54008fa2, 0x54000003, 0x54fff423, + 0x54008f43, 0x54000003, 0x54fff3c3, 0x54008ee3, + 0x54000004, 0x54fff364, 0x54008e84, 0x54000005, + 0x54fff305, 0x54008e25, 0x54000006, 0x54fff2a6, + 0x54008dc6, 0x54000007, 0x54fff247, 0x54008d67, + 0x54000008, 0x54fff1e8, 0x54008d08, 0x54000009, + 0x54fff189, 0x54008ca9, 0x5400000a, 0x54fff12a, + 0x54008c4a, 0x5400000b, 0x54fff0cb, 0x54008beb, + 0x5400000c, 0x54fff06c, 0x54008b8c, 0x5400000d, + 0x54fff00d, 0x54008b2d, 0x5400000e, 0x54ffefae, + 0x54008ace, 0x5400000f, 0x54ffef4f, 0x54008a6f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, 0xd503239f, 0xd50321df, 0xd50323ff, 0xd50323df, 0xd503211f, 0xd503233f, 0xd503231f, 0xd503215f, 0xd503237f, 0xd503235f, 0xd69f03e0, 0xd6bf03e0, - 0xd5033fdf, 0xd503207f, 0xd50320ff, 0xd5033e9f, - 0xd50332bf, 0xd61f0200, 0xd63f0280, 0xdac123ea, - 0xdac127fb, 0xdac12be8, 0xdac12fe0, 0xdac133e1, - 0xdac137f5, 0xdac13bf1, 0xdac13ffd, 0xdac147fd, - 0xd61f0b9f, 0xd61f0c3f, 0xd63f0aff, 0xd63f0ebf, - 0xd51b4434, 0xd51b4216, 0xd53b443b, 0xd53b4213, - 0xd53b00eb, 0xd53b0030, 0xdac143e6, 0xc8117c80, - 0xc80afed8, 0xc85f7e6a, 0xc85ffca1, 0xc89ffd1e, - 0xc8dffe2c, 0x88097cee, 0x8801fe05, 0x885f7d82, - 0x885ffd8a, 0x889fff83, 0x88dfff4e, 0x481e7dca, - 0x4815fd2d, 0x485f7f76, 0x485ffe7c, 0x489fffcb, - 0x48dffc53, 0x08027c37, 0x0800fe0c, 0x085f7ded, - 0x085ffeb1, 0x089ffd6d, 0x08dffd1e, 0xc87f3578, - 0xc87feaa1, 0xc83b506d, 0xc82c87a6, 0x887f1166, - 0x887f93d0, 0x883e32a4, 0x883bf12f, 0xf80011f9, - 0xb81b1022, 0x381ea354, 0x79002fd7, 0xf85cf39a, - 0xb8580309, 0x385e218c, 0x784051e1, 0x389e11d8, - 0x789fa1f8, 0x79c01865, 0xb881131b, 0xfc5dd3ad, - 0xbc5d1137, 0xfc00900b, 0xbc181015, 0xf818ec7d, - 0xb81b8c91, 0x381efc40, 0x78007c3d, 0xf857beb0, - 0xb8413dd4, 0x385fddd6, 0x78409e2f, 0x389eddea, - 0x789e7d94, 0x78de3d55, 0xb8805c13, 0xfc5cadc0, - 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, 0xf81475f6, - 0xb81f95d1, 0x381e757e, 0x78014561, 0xf8402436, - 0xb85896e2, 0x385f4763, 0x785db4f0, 0x3880374f, - 0x789e25e7, 0x78dd0563, 0xb88166f9, 0xfc529540, - 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, 0xf820ea7b, - 0xb82d68c8, 0x38367a04, 0x782f4b59, 0xf878c8a4, - 0xb8674a24, 0x386b78f1, 0x78776bc0, 0x38a15aca, - 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbe, - 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, 0xf91f1193, - 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, 0xf95d4b0a, - 0xb9581010, 0x395fc034, 0x795fb221, 0x399d8731, - 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, 0xfd583723, - 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, 0x58ffdaa2, - 0x1800001d, 0xf885d1c0, 0xd8ffda40, 0xf8a77820, - 0xf9980220, 0x1a030301, 0x3a140311, 0x5a0d000b, - 0x7a07015c, 0x9a1001e4, 0xba140182, 0xda0d01bd, - 0xfa0c00ce, 0x0b31f194, 0x2b206d7b, 0xcb29f027, - 0x6b210f63, 0x8b2cb34d, 0xab2a88b1, 0xcb2f511e, - 0xeb3332f3, 0x3a4533aa, 0x7a4d312b, 0xba442146, - 0xfa42818c, 0x3a466a02, 0x7a4b68ed, 0xba4a9b6b, - 0xfa4dd86d, 0x1a8a637a, 0x1a9cd6aa, 0x5a9bd137, - 0x5a8fd7aa, 0x9a95233e, 0x9a95c620, 0xda9422b0, - 0xda8397d3, 0x5ac00173, 0x5ac00418, 0x5ac00b3b, - 0x5ac0106e, 0x5ac0162e, 0xdac001e7, 0xdac00798, - 0xdac00b31, 0xdac00f42, 0xdac010bc, 0xdac01759, - 0xdac1021b, 0xdac104d1, 0xdac10995, 0xdac10c80, - 0xdac1136c, 0xdac11791, 0xdac1185c, 0xdac11d51, - 0xd71f09ee, 0xd71f0dc3, 0xd73f0b2f, 0xd73f0e6e, - 0x1ac40a05, 0x1ac40f3a, 0x1acc2042, 0x1ac8263d, - 0x1ac42867, 0x1ada2c99, 0x9ad10899, 0x9ad10f40, - 0x9ad521f7, 0x9adb263c, 0x9ac0286a, 0x9ac92f27, - 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, 0x1b1ddcf7, - 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, 0x9b2cdd6d, - 0x9bae275e, 0x9ba7954d, 0x7ec315fe, 0x1ef0098c, - 0x1ef21bff, 0x1ef02ab3, 0x1ef5394f, 0x1efc4942, - 0x1eff5bc7, 0x1ee28832, 0x7ea3d546, 0x1e270979, - 0x1e201981, 0x1e3d2a63, 0x1e263ae6, 0x1e3b4b80, - 0x1e2758a2, 0x1e39899d, 0x7ef8d58d, 0x1e720913, - 0x1e751b56, 0x1e622a74, 0x1e683ade, 0x1e754a76, - 0x1e755a4c, 0x1e638a06, 0x1fc373a3, 0x1f0a35cf, - 0x1f0aea4c, 0x1f2f74e7, 0x1f2032e0, 0x1f4d21d8, - 0x1f49d0ef, 0x1f7f43b3, 0x1f705522, 0x1e20409e, - 0x1e20c361, 0x1e214319, 0x1e21c2ae, 0x1e22c0cd, - 0x1e23c32c, 0x1ee243d9, 0x1e6042bc, 0x1e60c2f0, - 0x1e6143a5, 0x1e61c276, 0x1e62428d, 0x1ee1c393, - 0x1e3800d1, 0x9e3800ed, 0x1e78035c, 0x9e7800d1, - 0x1e220081, 0x9e22028e, 0x1e6202a7, 0x9e6202fb, - 0x1e24028d, 0x9e64039e, 0x1e3002aa, 0x9e700225, - 0x1e2601cb, 0x9e6602ad, 0x1e2701db, 0x9e6702e4, - 0x1e3e2300, 0x1e6e2180, 0x1e202228, 0x1e602388, - 0x29021b40, 0x297c78c0, 0x69660970, 0xa908018f, - 0xa9427ae7, 0x29a03cfa, 0x29fc3d4b, 0x69c84033, - 0xa988240e, 0xa9fa0d9b, 0x28a02d88, 0x28c8408a, - 0x68f87a6a, 0xa8ba09f8, 0xa8c52a18, 0x280257be, - 0x28727948, 0xa83868de, 0xa8440a98, 0x0c40733f, - 0x4cdfa1e5, 0x0ccd6cea, 0x4cdf260d, 0x0d40c227, - 0x4ddfcb30, 0x0dc7cc6b, 0x4c408ced, 0x0cdf8769, - 0x4d60c346, 0x0dffca17, 0x4de8cda6, 0x4cda4834, - 0x0c4049ef, 0x4d40e6dd, 0x4ddfe946, 0x0dcfeccf, - 0x4cdf0546, 0x0cc7006b, 0x0d60e32c, 0x0dffe5eb, - 0x0dfce8de, 0x0e31bb9b, 0x4e31bbbc, 0x0e71b841, - 0x4e71bbbc, 0x4eb1b841, 0x0e30aab4, 0x4e30abdd, - 0x0e70aa30, 0x4e70a9cd, 0x4eb0a96a, 0x6e30fbdd, - 0x0e31abdd, 0x2e31aa93, 0x4e31aaf6, 0x6e31a96a, - 0x0e71a8a4, 0x2e71a81f, 0x4e71aad5, 0x6e71a928, - 0x4eb1a81f, 0x6eb1aa93, 0x6eb0f96a, 0x7e30fbbc, - 0x7e70f862, 0x7eb0fb59, 0x7ef0f8c5, 0x0ea0c883, - 0x4ea0c928, 0x4ee0caf6, 0x2ea0ca93, 0x6ea0c9cd, - 0x6ee0c8c5, 0x0ea0dbdd, 0x4ea0db38, 0x4ee0dad5, - 0x0ea0eb7a, 0x4ea0eb38, 0x4ee0e883, 0x2ea0db38, - 0x6ea0db7a, 0x6ee0db17, 0x0e20ba0f, 0x4e20bad5, - 0x0e60b883, 0x4e60bb38, 0x0ea0b928, 0x4ea0bb59, - 0x4ee0bab4, 0x0ea0fa30, 0x4ea0fa51, 0x4ee0f862, - 0x0ef8f841, 0x4ef8f820, 0x2ea0fb38, 0x6ea0f8a4, - 0x6ee0f883, 0x2ef8f9ac, 0x6ef8f81f, 0x2ea1fbbc, - 0x6ea1f96a, 0x6ee1fb7a, 0x2ef9f862, 0x6ef9f9ac, - 0x2e205a72, 0x6e20581f, 0x0e231c41, 0x4e2f1dcd, - 0x0ebf1fdd, 0x4ea21c20, 0x2e351e93, 0x6e2e1dac, - 0x0e338651, 0x4e3886f6, 0x0e6f85cd, 0x4e7e87bc, - 0x0ea087fe, 0x4ea1841f, 0x4ee38441, 0x0e3c0f7a, - 0x4e3e0fbc, 0x0e660ca4, 0x4e600ffe, 0x0ea60ca4, - 0x4ea80ce6, 0x4ee00ffe, 0x2e3c0f7a, 0x6e340e72, - 0x2e6b0d49, 0x6e6a0d28, 0x2eae0dac, 0x6ea20c20, - 0x6ef60eb4, 0x0e23d441, 0x4e3ad738, 0x4e64d462, - 0x0e421420, 0x4e4b1549, 0x2e3a8738, 0x6e3c877a, - 0x2e728630, 0x6e6087fe, 0x2ea58483, 0x6eac856a, - 0x6ef98717, 0x0e2c2d6a, 0x4e262ca4, 0x0e742e72, - 0x4e642c62, 0x0ead2d8b, 0x4eaa2d28, 0x4eec2d6a, - 0x2e312e0f, 0x6e332e51, 0x2e642c62, 0x6e6c2d6a, - 0x2eae2dac, 0x6eae2dac, 0x6ef12e0f, 0x0eafd5cd, - 0x4ea4d462, 0x4ee9d507, 0x0ed616b4, 0x4edc177a, - 0x0e329e30, 0x4e269ca4, 0x0e649c62, 0x4e669ca4, - 0x0eae9dac, 0x4eb49e72, 0x2eb7d6d5, 0x6eb2d630, - 0x6ef4d672, 0x2ecd158b, 0x6ed716d5, 0x2e39d717, - 0x6e2ed5ac, 0x6e7cd77a, 0x2e591717, 0x6e5e17bc, - 0x2e30ddee, 0x6e2ddd8b, 0x6e7adf38, 0x2e431c41, - 0x6e4e1dac, 0x0e61941f, 0x4e6c956a, 0x0eb29630, - 0x4ea99507, 0x0e24cc62, 0x4e25cc83, 0x4e6fcdcd, - 0x0e550e93, 0x4e530e51, 0x2e729630, 0x6e659483, - 0x2ea39441, 0x6ead958b, 0x0ea0cffe, 0x4ea7ccc5, - 0x4eeacd28, 0x0ed10e0f, 0x4edf0fdd, 0x2e20fffe, - 0x6e22fc20, 0x6e76feb4, 0x2e493d07, 0x6e563eb4, - 0x0e396717, 0x4e3e67bc, 0x0e7766d5, 0x4e7d679b, - 0x0ebb6759, 0x4ea764c5, 0x2e236441, 0x6e396717, - 0x2e726630, 0x6e61641f, 0x2ea764c5, 0x6eae65ac, - 0x0e2ba549, 0x4e3ea7bc, 0x0e71a60f, 0x4e7fa7dd, - 0x0eb8a6f6, 0x4ea1a41f, 0x0e35f693, 0x4e21f41f, - 0x4e67f4c5, 0x0e5035ee, 0x4e543672, 0x0e216c1f, - 0x4e346e72, 0x0e7d6f9b, 0x4e766eb4, 0x0eb26e30, - 0x4eae6dac, 0x2e2d6d8b, 0x6e2b6d49, 0x2e686ce6, - 0x6e606ffe, 0x2eb36e51, 0x6ebd6f9b, 0x0e3eafbc, - 0x4e20affe, 0x0e69ad07, 0x4e6cad6a, 0x0eb6aeb4, - 0x4eacad6a, 0x0e66b4a4, 0x4e7ab738, 0x0eb3b651, - 0x4eb3b651, 0x0e3826f6, 0x4e252483, 0x0e7f27dd, - 0x4e71260f, 0x0eb826f6, 0x4eb52693, 0x0eb5f693, - 0x4eb8f6f6, 0x4ee4f462, 0x0ed1360f, 0x4ec834e6, - 0x2eaeedac, 0x6eb2ee30, 0x6eeded8b, 0x2ecf2dcd, - 0x6ed92f17, 0x0f81100f, 0x4f848862, 0x4fc31841, - 0x0fad518b, 0x4fa780c5, 0x4fd059ee, 0x2fa890e6, - 0x4fa38841, 0x6fc1900f, 0x0f7b8149, 0x4f4688a4, - 0x0faf81cd, 0x4fa58083, 0x0e3736d5, 0x4e393717, - 0x0e61341f, 0x4e7b3759, 0x0ea43462, 0x4ea1341f, - 0x4efd379b, 0x0e343e72, 0x4e2c3d6a, 0x0e793f17, - 0x4e753e93, 0x0ea53c83, 0x4eb43e72, 0x4ee23c20, - 0x2e3b8f59, 0x6e3c8f7a, 0x2e798f17, 0x6e648c62, - 0x2eb48e72, 0x6eae8dac, 0x6ee68ca4, 0x2e3e37bc, - 0x6e2037fe, 0x2e7f37dd, 0x6e723630, 0x2ebd379b, - 0x6ea834e6, 0x6eeb3549, 0x2e3f3fdd, 0x6e343e72, - 0x2e693d07, 0x6e663ca4, 0x2ea93d07, 0x6eb13e0f, - 0x6eeb3d49, 0x0e39e717, 0x4e2ae528, 0x4e64e462, - 0x2ebee7bc, 0x6eb7e6d5, 0x6ee1e41f, 0x2e27e4c5, - 0x6e3de79b, 0x6e62e420, 0x659239e8, 0x65d03b94, - 0x65d0232d, 0x65d120c2, 0x659129f2, 0x65933ca3, - 0x25969683, 0x25961d15, 0x254d1c48, 0x259e3f61, - 0x25953b96, 0x255b91d1, 0x247686ed, 0x24309098, - 0x2462edb9, 0x24a57468, 0xba5fd3e3, 0x3a5f03e5, - 0xfa411be4, 0x7a42cbe2, 0x93df03ff, 0xc820ffff, - 0x8822fc7f, 0xc8247cbf, 0x88267fff, 0x4e010fe0, - 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, 0x4e0a1fe1, - 0x4e071fe1, 0x4e042c20, 0x4e062c20, 0x4e052c20, - 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, 0x0e073c20, - 0x9eae0020, 0x0f03f409, 0x6f03f40e, 0x4cc0ac3f, - 0x0ea1b820, 0x0ef9b820, 0x4ef9b820, 0x4e21c862, - 0x0e79c862, 0x4e79c862, 0x4e61b8a4, 0x0e79b8a4, - 0x4e79b8a4, 0x05a08020, 0x05104fe0, 0x05505001, - 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, - 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, - 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, - 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, - 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, - 0x04018100, 0x04018621, 0x04418b22, 0x04418822, - 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, - 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, - 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, - 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, - 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, - 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, - 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, - 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, - 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, - 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, - 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, - 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, - 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, - 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, - 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, - 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, - 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, - 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, - 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, - 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, - 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, - 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, - 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, - 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, - 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, - 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, - 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, - 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, - 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, - 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, - 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, - 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, - 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, - 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, - 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, - 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, - 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, - 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8268267, 0xf82d023c, 0xf8301046, 0xf83d2083, - 0xf8263290, 0xf82d528c, 0xf8284299, 0xf8337160, - 0xf8386286, 0xf8bf820e, 0xf8a600e0, 0xf8af1353, - 0xf8a922ea, 0xf8b53396, 0xf8a251e3, 0xf8b340f4, - 0xf8a470fd, 0xf8a06209, 0xf8f48097, 0xf8f002ea, - 0xf8eb10d9, 0xf8ff21b0, 0xf8f7302c, 0xf8ee52a9, - 0xf8f041fa, 0xf8e471e4, 0xf8e863c6, 0xf864823d, - 0xf87d013a, 0xf86f1162, 0xf87d20e3, 0xf86132bb, - 0xf870510e, 0xf8704336, 0xf86572b4, 0xf8706217, - 0xb83e8294, 0xb8200264, 0xb8381284, 0xb8242358, - 0xb8333102, 0xb828530e, 0xb83042df, 0xb824703f, - 0xb82a6194, 0xb8a080e9, 0xb8b80090, 0xb8bb1146, - 0xb8bb21b8, 0xb8b032df, 0xb8b653f4, 0xb8bd41c9, - 0xb8b47287, 0xb8bc6169, 0xb8ee828c, 0xb8e10138, - 0xb8f3126d, 0xb8f020b0, 0xb8e03183, 0xb8e851ef, - 0xb8f041e4, 0xb8fe7005, 0xb8ea6376, 0xb8638120, - 0xb873015d, 0xb8781284, 0xb86723b8, 0xb86e3175, - 0xb87b51ed, 0xb87f41d1, 0xb863721e, 0xb87660f4, - 0xce216874, 0xce104533, 0xce648c15, 0xce8e3302, - 0xce6e82ab, 0xce6c87d1, 0xcec08063, 0xce638937, - 0x25e0c358, 0x25a1c7d3, 0x0580785a, 0x05426328, - 0x05009892, 0x25a0cc29, 0x2561cec8, 0x058044b3, - 0x05401c99, 0x05006b49, 0x25e0d6f7, 0x2561c528, - 0x0583c8bc, 0x0542522f, 0x05001ec0, 0x25e0de65, - 0x25a1c113, 0x05803cad, 0x0540f3c0, 0x0500ab15, - 0x2560c28c, 0x2561d7c0, 0x05801ed7, 0x0542633b, - 0x05003696, 0x2560d4b4, 0x25e1c918, 0x058021ff, - 0x05400e15, 0x0500f3de, 0x0473025a, 0x04bd05ab, - 0x658e0025, 0x658a08e2, 0x659a0493, 0x043e1062, - 0x04f418b4, 0x046d15bd, 0x04611fce, 0x04d6a07c, - 0x04001929, 0x041a09da, 0x04d098f4, 0x04db10d4, - 0x0459a3ad, 0x041aa029, 0x041919fb, 0x04d39e24, - 0x04118302, 0x04101dba, 0x04d7ae16, 0x04dea571, - 0x04180210, 0x05e786fc, 0x05e4915c, 0x04881cf1, - 0x044a0f04, 0x04090969, 0x048b16c4, 0x044101e4, - 0x04dcbf44, 0x65809745, 0x658d833f, 0x65c68468, - 0x65c79b07, 0x65829e38, 0x049dafca, 0x6582bba8, - 0x65c0b7ff, 0x65c1b4e0, 0x658dbadd, 0x65819a9d, - 0x65ed9246, 0x65b30815, 0x65e6263c, 0x65eebb94, - 0x65bad14e, 0x65efe178, 0x65fc5697, 0x65e07f14, - 0x040c55a6, 0x04977f4d, 0x043d3046, 0x04b733a0, - 0x046830a4, 0x04ed322d, 0x05686948, 0x05bd6c13, - 0x65c88ef0, 0x450db3d7, 0x4540b6d9, 0x043e3979, - 0x445896ce, 0x445a9005, 0x44d98069, 0x445b87ae, - 0x04da348e, 0x04982edb, 0x0499397f, 0x0408338c, - 0x04ca309c, 0x65c721e6, 0x65c63641, 0x65982882, - 0x04812b8b, 0x0e251083, 0x4e3712d5, 0x0e61101f, - 0x4e6d118b, 0x0eba1338, 0x4eb712d5, 0x2e31120f, - 0x6e2e11ac, 0x2e6810e6, 0x6e6f11cd, 0x2eaa1128, - 0x6eb1120f, + 0xd5033fdf, 0xd50330ff, 0xd503207f, 0xd50320ff, + 0xd5033e9f, 0xd50332bf, 0xd61f0200, 0xd63f0280, + 0xdac123ea, 0xdac127fb, 0xdac12be8, 0xdac12fe0, + 0xdac133e1, 0xdac137f5, 0xdac13bf1, 0xdac13ffd, + 0xdac147fd, 0xd61f0b9f, 0xd61f0c3f, 0xd63f0aff, + 0xd63f0ebf, 0xd51b4434, 0xd51b4216, 0xd53b443b, + 0xd53b4213, 0xd53b00eb, 0xd53b0030, 0xdac143e6, + 0xc8117c80, 0xc80afed8, 0xc85f7e6a, 0xc85ffca1, + 0xc89ffd1e, 0xc8dffe2c, 0x88097cee, 0x8801fe05, + 0x885f7d82, 0x885ffd8a, 0x889fff83, 0x88dfff4e, + 0x481e7dca, 0x4815fd2d, 0x485f7f76, 0x485ffe7c, + 0x489fffcb, 0x48dffc53, 0x08027c37, 0x0800fe0c, + 0x085f7ded, 0x085ffeb1, 0x089ffd6d, 0x08dffd1e, + 0xc87f3578, 0xc87feaa1, 0xc83b506d, 0xc82c87a6, + 0x887f1166, 0x887f93d0, 0x883e32a4, 0x883bf12f, + 0xf80011f9, 0xb81b1022, 0x381ea354, 0x79002fd7, + 0xf85cf39a, 0xb8580309, 0x385e218c, 0x784051e1, + 0x389e11d8, 0x789fa1f8, 0x79c01865, 0xb881131b, + 0xfc5dd3ad, 0xbc5d1137, 0xfc00900b, 0xbc181015, + 0xf818ec7d, 0xb81b8c91, 0x381efc40, 0x78007c3d, + 0xf857beb0, 0xb8413dd4, 0x385fddd6, 0x78409e2f, + 0x389eddea, 0x789e7d94, 0x78de3d55, 0xb8805c13, + 0xfc5cadc0, 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, + 0xf81475f6, 0xb81f95d1, 0x381e757e, 0x78014561, + 0xf8402436, 0xb85896e2, 0x385f4763, 0x785db4f0, + 0x3880374f, 0x789e25e7, 0x78dd0563, 0xb88166f9, + 0xfc529540, 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, + 0xf820ea7b, 0xb82d68c8, 0x38367a04, 0x782f4b59, + 0xf878c8a4, 0xb8674a24, 0x386b78f1, 0x78776bc0, + 0x38a15aca, 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, + 0xfc6ecbbe, 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, + 0xf91f1193, 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, + 0xf95d4b0a, 0xb9581010, 0x395fc034, 0x795fb221, + 0x399d8731, 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, + 0xfd583723, 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, + 0x58ffda82, 0x1800001d, 0xf885d1c0, 0xd8ffda20, + 0xf8a77820, 0xf9980220, 0x1a030301, 0x3a140311, + 0x5a0d000b, 0x7a07015c, 0x9a1001e4, 0xba140182, + 0xda0d01bd, 0xfa0c00ce, 0x0b31f194, 0x2b206d7b, + 0xcb29f027, 0x6b210f63, 0x8b2cb34d, 0xab2a88b1, + 0xcb2f511e, 0xeb3332f3, 0x3a4533aa, 0x7a4d312b, + 0xba442146, 0xfa42818c, 0x3a466a02, 0x7a4b68ed, + 0xba4a9b6b, 0xfa4dd86d, 0x1a8a637a, 0x1a9cd6aa, + 0x5a9bd137, 0x5a8fd7aa, 0x9a95233e, 0x9a95c620, + 0xda9422b0, 0xda8397d3, 0x5ac00173, 0x5ac00418, + 0x5ac00b3b, 0x5ac0106e, 0x5ac0162e, 0xdac001e7, + 0xdac00798, 0xdac00b31, 0xdac00f42, 0xdac010bc, + 0xdac01759, 0xdac1021b, 0xdac104d1, 0xdac10995, + 0xdac10c80, 0xdac1136c, 0xdac11791, 0xdac1185c, + 0xdac11d51, 0xd71f09ee, 0xd71f0dc3, 0xd73f0b2f, + 0xd73f0e6e, 0x1ac40a05, 0x1ac40f3a, 0x1acc2042, + 0x1ac8263d, 0x1ac42867, 0x1ada2c99, 0x9ad10899, + 0x9ad10f40, 0x9ad521f7, 0x9adb263c, 0x9ac0286a, + 0x9ac92f27, 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, + 0x1b1ddcf7, 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, + 0x9b2cdd6d, 0x9bae275e, 0x9ba7954d, 0x7ec315fe, + 0x1ef0098c, 0x1ef21bff, 0x1ef02ab3, 0x1ef5394f, + 0x1efc4942, 0x1eff5bc7, 0x1ee28832, 0x7ea3d546, + 0x1e270979, 0x1e201981, 0x1e3d2a63, 0x1e263ae6, + 0x1e3b4b80, 0x1e2758a2, 0x1e39899d, 0x7ef8d58d, + 0x1e720913, 0x1e751b56, 0x1e622a74, 0x1e683ade, + 0x1e754a76, 0x1e755a4c, 0x1e638a06, 0x1fc373a3, + 0x1f0a35cf, 0x1f0aea4c, 0x1f2f74e7, 0x1f2032e0, + 0x1f4d21d8, 0x1f49d0ef, 0x1f7f43b3, 0x1f705522, + 0x1e20409e, 0x1e20c361, 0x1e214319, 0x1e21c2ae, + 0x1e22c0cd, 0x1e23c32c, 0x1ee243d9, 0x1e6042bc, + 0x1e60c2f0, 0x1e6143a5, 0x1e61c276, 0x1e62428d, + 0x1ee1c393, 0x1e3800d1, 0x9e3800ed, 0x1e78035c, + 0x9e7800d1, 0x1e220081, 0x9e22028e, 0x1e6202a7, + 0x9e6202fb, 0x1e24028d, 0x9e64039e, 0x1e3002aa, + 0x9e700225, 0x1e2601cb, 0x9e6602ad, 0x1e2701db, + 0x9e6702e4, 0x1e3e2300, 0x1e6e2180, 0x1e202228, + 0x1e602388, 0x29021b40, 0x297c78c0, 0x69660970, + 0xa908018f, 0xa9427ae7, 0x29a03cfa, 0x29fc3d4b, + 0x69c84033, 0xa988240e, 0xa9fa0d9b, 0x28a02d88, + 0x28c8408a, 0x68f87a6a, 0xa8ba09f8, 0xa8c52a18, + 0x280257be, 0x28727948, 0xa83868de, 0xa8440a98, + 0x0c40733f, 0x4cdfa1e5, 0x0ccd6cea, 0x4cdf260d, + 0x0d40c227, 0x4ddfcb30, 0x0dc7cc6b, 0x4c408ced, + 0x0cdf8769, 0x4d60c346, 0x0dffca17, 0x4de8cda6, + 0x4cda4834, 0x0c4049ef, 0x4d40e6dd, 0x4ddfe946, + 0x0dcfeccf, 0x4cdf0546, 0x0cc7006b, 0x0d60e32c, + 0x0dffe5eb, 0x0dfce8de, 0x0e31bb9b, 0x4e31bbbc, + 0x0e71b841, 0x4e71bbbc, 0x4eb1b841, 0x0e30aab4, + 0x4e30abdd, 0x0e70aa30, 0x4e70a9cd, 0x4eb0a96a, + 0x6e30fbdd, 0x0e31abdd, 0x2e31aa93, 0x4e31aaf6, + 0x6e31a96a, 0x0e71a8a4, 0x2e71a81f, 0x4e71aad5, + 0x6e71a928, 0x4eb1a81f, 0x6eb1aa93, 0x6eb0f96a, + 0x7e30fbbc, 0x7e70f862, 0x7eb0fb59, 0x7ef0f8c5, + 0x0ea0c883, 0x4ea0c928, 0x4ee0caf6, 0x2ea0ca93, + 0x6ea0c9cd, 0x6ee0c8c5, 0x0ea0dbdd, 0x4ea0db38, + 0x4ee0dad5, 0x0ea0eb7a, 0x4ea0eb38, 0x4ee0e883, + 0x2ea0db38, 0x6ea0db7a, 0x6ee0db17, 0x0e20ba0f, + 0x4e20bad5, 0x0e60b883, 0x4e60bb38, 0x0ea0b928, + 0x4ea0bb59, 0x4ee0bab4, 0x0ea0fa30, 0x4ea0fa51, + 0x4ee0f862, 0x0ef8f841, 0x4ef8f820, 0x2ea0fb38, + 0x6ea0f8a4, 0x6ee0f883, 0x2ef8f9ac, 0x6ef8f81f, + 0x2ea1fbbc, 0x6ea1f96a, 0x6ee1fb7a, 0x2ef9f862, + 0x6ef9f9ac, 0x2e205a72, 0x6e20581f, 0x0e231c41, + 0x4e2f1dcd, 0x0ebf1fdd, 0x4ea21c20, 0x2e351e93, + 0x6e2e1dac, 0x0e338651, 0x4e3886f6, 0x0e6f85cd, + 0x4e7e87bc, 0x0ea087fe, 0x4ea1841f, 0x4ee38441, + 0x0e3c0f7a, 0x4e3e0fbc, 0x0e660ca4, 0x4e600ffe, + 0x0ea60ca4, 0x4ea80ce6, 0x4ee00ffe, 0x2e3c0f7a, + 0x6e340e72, 0x2e6b0d49, 0x6e6a0d28, 0x2eae0dac, + 0x6ea20c20, 0x6ef60eb4, 0x0e23d441, 0x4e3ad738, + 0x4e64d462, 0x0e421420, 0x4e4b1549, 0x2e3a8738, + 0x6e3c877a, 0x2e728630, 0x6e6087fe, 0x2ea58483, + 0x6eac856a, 0x6ef98717, 0x0e2c2d6a, 0x4e262ca4, + 0x0e742e72, 0x4e642c62, 0x0ead2d8b, 0x4eaa2d28, + 0x4eec2d6a, 0x2e312e0f, 0x6e332e51, 0x2e642c62, + 0x6e6c2d6a, 0x2eae2dac, 0x6eae2dac, 0x6ef12e0f, + 0x0eafd5cd, 0x4ea4d462, 0x4ee9d507, 0x0ed616b4, + 0x4edc177a, 0x0e329e30, 0x4e269ca4, 0x0e649c62, + 0x4e669ca4, 0x0eae9dac, 0x4eb49e72, 0x2eb7d6d5, + 0x6eb2d630, 0x6ef4d672, 0x2ecd158b, 0x6ed716d5, + 0x2e39d717, 0x6e2ed5ac, 0x6e7cd77a, 0x2e591717, + 0x6e5e17bc, 0x2e30ddee, 0x6e2ddd8b, 0x6e7adf38, + 0x2e431c41, 0x6e4e1dac, 0x0e61941f, 0x4e6c956a, + 0x0eb29630, 0x4ea99507, 0x0e24cc62, 0x4e25cc83, + 0x4e6fcdcd, 0x0e550e93, 0x4e530e51, 0x2e729630, + 0x6e659483, 0x2ea39441, 0x6ead958b, 0x0ea0cffe, + 0x4ea7ccc5, 0x4eeacd28, 0x0ed10e0f, 0x4edf0fdd, + 0x2e20fffe, 0x6e22fc20, 0x6e76feb4, 0x2e493d07, + 0x6e563eb4, 0x0e396717, 0x4e3e67bc, 0x0e7766d5, + 0x4e7d679b, 0x0ebb6759, 0x4ea764c5, 0x2e236441, + 0x6e396717, 0x2e726630, 0x6e61641f, 0x2ea764c5, + 0x6eae65ac, 0x0e2ba549, 0x4e3ea7bc, 0x0e71a60f, + 0x4e7fa7dd, 0x0eb8a6f6, 0x4ea1a41f, 0x0e35f693, + 0x4e21f41f, 0x4e67f4c5, 0x0e5035ee, 0x4e543672, + 0x0e216c1f, 0x4e346e72, 0x0e7d6f9b, 0x4e766eb4, + 0x0eb26e30, 0x4eae6dac, 0x2e2d6d8b, 0x6e2b6d49, + 0x2e686ce6, 0x6e606ffe, 0x2eb36e51, 0x6ebd6f9b, + 0x0e3eafbc, 0x4e20affe, 0x0e69ad07, 0x4e6cad6a, + 0x0eb6aeb4, 0x4eacad6a, 0x0e66b4a4, 0x4e7ab738, + 0x0eb3b651, 0x4eb3b651, 0x0e3826f6, 0x4e252483, + 0x0e7f27dd, 0x4e71260f, 0x0eb826f6, 0x4eb52693, + 0x0eb5f693, 0x4eb8f6f6, 0x4ee4f462, 0x0ed1360f, + 0x4ec834e6, 0x2eaeedac, 0x6eb2ee30, 0x6eeded8b, + 0x2ecf2dcd, 0x6ed92f17, 0x0f81100f, 0x4f848862, + 0x4fc31841, 0x0fad518b, 0x4fa780c5, 0x4fd059ee, + 0x2fa890e6, 0x4fa38841, 0x6fc1900f, 0x0f7b8149, + 0x4f4688a4, 0x0faf81cd, 0x4fa58083, 0x0e3736d5, + 0x4e393717, 0x0e61341f, 0x4e7b3759, 0x0ea43462, + 0x4ea1341f, 0x4efd379b, 0x0e343e72, 0x4e2c3d6a, + 0x0e793f17, 0x4e753e93, 0x0ea53c83, 0x4eb43e72, + 0x4ee23c20, 0x2e3b8f59, 0x6e3c8f7a, 0x2e798f17, + 0x6e648c62, 0x2eb48e72, 0x6eae8dac, 0x6ee68ca4, + 0x2e3e37bc, 0x6e2037fe, 0x2e7f37dd, 0x6e723630, + 0x2ebd379b, 0x6ea834e6, 0x6eeb3549, 0x2e3f3fdd, + 0x6e343e72, 0x2e693d07, 0x6e663ca4, 0x2ea93d07, + 0x6eb13e0f, 0x6eeb3d49, 0x0e39e717, 0x4e2ae528, + 0x4e64e462, 0x2ebee7bc, 0x6eb7e6d5, 0x6ee1e41f, + 0x2e27e4c5, 0x6e3de79b, 0x6e62e420, 0x659239e8, + 0x65d03b94, 0x65d0232d, 0x65d120c2, 0x659129f2, + 0x65933ca3, 0x25969683, 0x25961d15, 0x254d1c48, + 0x259e3f61, 0x25953b96, 0x255b91d1, 0x247686ed, + 0x24309098, 0x2462edb9, 0x24a57468, 0xba5fd3e3, + 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, 0x93df03ff, + 0xc820ffff, 0x8822fc7f, 0xc8247cbf, 0x88267fff, + 0x4e010fe0, 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, + 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, 0x4e062c20, + 0x4e052c20, 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, + 0x0e073c20, 0x9eae0020, 0x0f03f409, 0x6f03f40e, + 0x4cc0ac3f, 0x0ea1b820, 0x0ef9b820, 0x4ef9b820, + 0x4e21c862, 0x0e79c862, 0x4e79c862, 0x4e61b8a4, + 0x0e79b8a4, 0x4e79b8a4, 0x05a08020, 0x05104fe0, + 0x05505001, 0x05906fe2, 0x05d03005, 0x05101fea, + 0x05901feb, 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, + 0x043f9c35, 0x047f9c20, 0x04ff9c20, 0x04299420, + 0x04319160, 0x0461943e, 0x04a19020, 0x04038100, + 0x040381a0, 0x040387e1, 0x04438be2, 0x04c38fe3, + 0x040181e0, 0x04018100, 0x04018621, 0x04418b22, + 0x04418822, 0x04818c23, 0x040081e0, 0x04008120, + 0x04008761, 0x04008621, 0x04408822, 0x04808c23, + 0x042053ff, 0x047f5401, 0x25208028, 0x2538cfe0, + 0x2578d001, 0x25b8efe2, 0x25f8f007, 0x2538dfea, + 0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, 0xa4484be0, + 0xa467afe0, 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, + 0xa55c53e0, 0xa5e1540b, 0xe400fbf6, 0xe408ffff, + 0xe420e7e0, 0xe4484be0, 0xe460efe0, 0xe547e400, + 0xe4014be0, 0xe4a84fe0, 0xe5f15000, 0x858043e0, + 0x85a043ff, 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, + 0x04a0e3eb, 0x04e0e3ec, 0x25104042, 0x25104871, + 0x25904861, 0x25904c92, 0x05344020, 0x05744041, + 0x05b44062, 0x05f44083, 0x252c8840, 0x253c1420, + 0x25681572, 0x25a21ce3, 0x25ea1e34, 0x253c0421, + 0x25680572, 0x25a20ce3, 0x25ea0e34, 0x0522c020, + 0x05e6c0a4, 0x2401a001, 0x2443a051, 0x24858881, + 0x24c78cd1, 0x24850891, 0x24c70cc1, 0x250f9001, + 0x25508051, 0x25802491, 0x25df28c1, 0x25850c81, + 0x251e10d1, 0x65816001, 0x65c36051, 0x65854891, + 0x65c74cc1, 0x05733820, 0x05b238a4, 0x05f138e6, + 0x0570396a, 0x65d0a001, 0x65d6a443, 0x65d4a826, + 0x6594ac26, 0x6554ac26, 0x6556ac26, 0x6552ac26, + 0x65cbac85, 0x65caac01, 0x6589ac85, 0x6588ac01, + 0x65c9ac85, 0x65c8ac01, 0x65dea833, 0x659ca509, + 0x65d8a801, 0x65dcac01, 0x655cb241, 0x0520a1e0, + 0x0521a601, 0x052281e0, 0x05238601, 0x04a14026, + 0x042244a6, 0x046344a6, 0x04a444a6, 0x04e544a7, + 0x0568aca7, 0x05b23230, 0x853040af, 0xc5b040af, + 0xe57080af, 0xe5b080af, 0x25034440, 0x254054c4, + 0x25034640, 0x25415a05, 0x25834440, 0x25c54489, + 0x250b5d3a, 0x2550dc20, 0x2518e3e1, 0x2518e021, + 0x2518e0a1, 0x2518e121, 0x2518e1a1, 0x2558e3e2, + 0x2558e042, 0x2558e0c2, 0x2558e142, 0x2598e3e3, + 0x2598e063, 0x2598e0e3, 0x2598e163, 0x25d8e3e4, + 0x25d8e084, 0x25d8e104, 0x25d8e184, 0x2518e407, + 0x05214800, 0x05614800, 0x05a14800, 0x05e14800, + 0x05214c00, 0x05614c00, 0x05a14c00, 0x05e14c00, + 0x05304001, 0x05314001, 0x05a18610, 0x05e18610, + 0x05271e11, 0x6545e891, 0x6585e891, 0x65c5e891, + 0x6545c891, 0x6585c891, 0x65c5c891, 0x45b0c210, + 0x45f1c231, 0x1e601000, 0x1e603000, 0x1e621000, + 0x1e623000, 0x1e641000, 0x1e643000, 0x1e661000, + 0x1e663000, 0x1e681000, 0x1e683000, 0x1e6a1000, + 0x1e6a3000, 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, + 0x1e6e3000, 0x1e701000, 0x1e703000, 0x1e721000, + 0x1e723000, 0x1e741000, 0x1e743000, 0x1e761000, + 0x1e763000, 0x1e781000, 0x1e783000, 0x1e7a1000, + 0x1e7a3000, 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, + 0x1e7e3000, 0xf8268267, 0xf82d023c, 0xf8301046, + 0xf83d2083, 0xf8263290, 0xf82d528c, 0xf8284299, + 0xf8337160, 0xf8386286, 0xf8bf820e, 0xf8a600e0, + 0xf8af1353, 0xf8a922ea, 0xf8b53396, 0xf8a251e3, + 0xf8b340f4, 0xf8a470fd, 0xf8a06209, 0xf8f48097, + 0xf8f002ea, 0xf8eb10d9, 0xf8ff21b0, 0xf8f7302c, + 0xf8ee52a9, 0xf8f041fa, 0xf8e471e4, 0xf8e863c6, + 0xf864823d, 0xf87d013a, 0xf86f1162, 0xf87d20e3, + 0xf86132bb, 0xf870510e, 0xf8704336, 0xf86572b4, + 0xf8706217, 0xb83e8294, 0xb8200264, 0xb8381284, + 0xb8242358, 0xb8333102, 0xb828530e, 0xb83042df, + 0xb824703f, 0xb82a6194, 0xb8a080e9, 0xb8b80090, + 0xb8bb1146, 0xb8bb21b8, 0xb8b032df, 0xb8b653f4, + 0xb8bd41c9, 0xb8b47287, 0xb8bc6169, 0xb8ee828c, + 0xb8e10138, 0xb8f3126d, 0xb8f020b0, 0xb8e03183, + 0xb8e851ef, 0xb8f041e4, 0xb8fe7005, 0xb8ea6376, + 0xb8638120, 0xb873015d, 0xb8781284, 0xb86723b8, + 0xb86e3175, 0xb87b51ed, 0xb87f41d1, 0xb863721e, + 0xb87660f4, 0xce216874, 0xce104533, 0xce648c15, + 0xce8e3302, 0xce6e82ab, 0xce6c87d1, 0xcec08063, + 0xce638937, 0x25e0c358, 0x25a1c7d3, 0x0580785a, + 0x05426328, 0x05009892, 0x25a0cc29, 0x2561cec8, + 0x058044b3, 0x05401c99, 0x05006b49, 0x25e0d6f7, + 0x2561c528, 0x0583c8bc, 0x0542522f, 0x05001ec0, + 0x25e0de65, 0x25a1c113, 0x05803cad, 0x0540f3c0, + 0x0500ab15, 0x2560c28c, 0x2561d7c0, 0x05801ed7, + 0x0542633b, 0x05003696, 0x2560d4b4, 0x25e1c918, + 0x058021ff, 0x05400e15, 0x0500f3de, 0x0473025a, + 0x04bd05ab, 0x658e0025, 0x658a08e2, 0x659a0493, + 0x043e1062, 0x04f418b4, 0x046d15bd, 0x04611fce, + 0x04d6a07c, 0x04001929, 0x041a09da, 0x04d098f4, + 0x04db10d4, 0x0459a3ad, 0x041aa029, 0x041919fb, + 0x04d39e24, 0x04118302, 0x04101dba, 0x04d7ae16, + 0x04dea571, 0x04180210, 0x05e786fc, 0x05e4915c, + 0x04881cf1, 0x044a0f04, 0x04090969, 0x048b16c4, + 0x044101e4, 0x04dcbf44, 0x65809745, 0x658d833f, + 0x65c68468, 0x65c79b07, 0x65829e38, 0x049dafca, + 0x6582bba8, 0x65c0b7ff, 0x65c1b4e0, 0x658dbadd, + 0x65819a9d, 0x65ed9246, 0x65b30815, 0x65e6263c, + 0x65eebb94, 0x65bad14e, 0x65efe178, 0x65fc5697, + 0x65e07f14, 0x040c55a6, 0x04977f4d, 0x043d3046, + 0x04b733a0, 0x046830a4, 0x04ed322d, 0x05686948, + 0x05bd6c13, 0x65c88ef0, 0x450db3d7, 0x4540b6d9, + 0x043e3979, 0x445896ce, 0x445a9005, 0x44d98069, + 0x445b87ae, 0x04da348e, 0x04982edb, 0x0499397f, + 0x0408338c, 0x04ca309c, 0x65c721e6, 0x65c63641, + 0x65982882, 0x04812b8b, 0x0e251083, 0x4e3712d5, + 0x0e61101f, 0x4e6d118b, 0x0eba1338, 0x4eb712d5, + 0x2e31120f, 0x6e2e11ac, 0x2e6810e6, 0x6e6f11cd, + 0x2eaa1128, 0x6eb1120f, }; // END Generated code -- do not edit diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp index 3a5e0662b0c..2fd87b48dc2 100644 --- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp @@ -52,7 +52,7 @@ class ShenandoahOldGenerationTest : public ::testing::Test { ShenandoahHeap::heap()->lock()->lock(false); - old = new ShenandoahOldGeneration(8, 1024 * 1024, 1024); + old = new ShenandoahOldGeneration(8, 1024 * 1024); old->set_promoted_reserve(512 * HeapWordSize); old->expend_promoted(256 * HeapWordSize); old->set_evacuation_reserve(512 * HeapWordSize); diff --git a/test/hotspot/gtest/memory/test_guardedMemory.cpp b/test/hotspot/gtest/memory/test_guardedMemory.cpp index 0f6165b0afa..d8efe76f305 100644 --- a/test/hotspot/gtest/memory/test_guardedMemory.cpp +++ b/test/hotspot/gtest/memory/test_guardedMemory.cpp @@ -57,7 +57,7 @@ TEST(GuardedMemory, size) { } // Test the basic characteristics -TEST(GuardedMemory, basic) { +TEST_VM(GuardedMemory, basic) { u_char* basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal); GuardedMemory guarded(basep, 1, GEN_PURPOSE_TAG); @@ -78,7 +78,7 @@ TEST(GuardedMemory, basic) { } // Test a number of odd sizes -TEST(GuardedMemory, odd_sizes) { +TEST_VM(GuardedMemory, odd_sizes) { u_char* basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal); GuardedMemory guarded(basep, 1, GEN_PURPOSE_TAG); @@ -99,7 +99,7 @@ TEST(GuardedMemory, odd_sizes) { } // Test buffer overrun into head... -TEST(GuardedMemory, buffer_overrun_head) { +TEST_VM(GuardedMemory, buffer_overrun_head) { u_char* basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal); GuardedMemory guarded(basep, 1, GEN_PURPOSE_TAG); @@ -111,7 +111,7 @@ TEST(GuardedMemory, buffer_overrun_head) { } // Test buffer overrun into tail with a number of odd sizes -TEST(GuardedMemory, buffer_overrun_tail) { +TEST_VM(GuardedMemory, buffer_overrun_tail) { u_char* basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal); GuardedMemory guarded(basep, 1, GEN_PURPOSE_TAG); @@ -128,7 +128,7 @@ TEST(GuardedMemory, buffer_overrun_tail) { } // Test wrap_copy/wrap_free -TEST(GuardedMemory, wrap) { +TEST_VM(GuardedMemory, wrap) { EXPECT_TRUE(GuardedMemory::free_copy(nullptr)) << "Expected free nullptr to be OK"; const char* str = "Check my bounds out"; @@ -146,3 +146,10 @@ TEST(GuardedMemory, wrap) { EXPECT_TRUE(GuardedMemory::free_copy(no_data_copy)) << "Expected valid guards even for no data copy"; } + +// Test passing back a bogus GuardedMemory region +TEST_VM(GuardedMemory, unmapped) { + char* unmapped_base = (char*) (GuardedMemoryTest::get_guard_header_size() + 0x1000 + 1); // Avoids assert in constructor + GuardedMemory guarded(unmapped_base); + EXPECT_FALSE(guarded.verify_guards()) << "Guard was not broken as expected"; +} diff --git a/test/hotspot/gtest/oops/test_jmethodIDTable.cpp b/test/hotspot/gtest/oops/test_jmethodIDTable.cpp new file mode 100644 index 00000000000..12ee939a9b1 --- /dev/null +++ b/test/hotspot/gtest/oops/test_jmethodIDTable.cpp @@ -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. + * + * 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 "classfile/vmClasses.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/jmethodIDTable.hpp" +#include "oops/method.hpp" +#include "unittest.hpp" +#include "utilities/growableArray.hpp" + +// Tests for creating and deleting jmethodIDs +TEST_VM(jmethodIDTable, test_jmethod_ids) { + InstanceKlass* klass = vmClasses::ClassLoader_klass(); + Array* methods = klass->methods(); + int length = methods->length(); + // How many entries are in the jmethodID table? + uint64_t initial_entries = JmethodIDTable::get_entry_count(); + ResourceMark rm; + GrowableArray ints(10); + for (int i = 0; i < length; i++) { + Method* m = methods->at(i); + jmethodID mid = m->jmethod_id(); + ints.push((uint64_t)mid); + } + uint64_t entries_now = JmethodIDTable::get_entry_count(); + ASSERT_TRUE(entries_now == initial_entries + length) << "should have more entries " << entries_now << " " << initial_entries + length; + + // Test that new entries aren't created, and the values are the same. + for (int i = 0; i < length; i++) { + Method* m = methods->at(i); + jmethodID mid = m->jmethod_id(); + ASSERT_TRUE(ints.at(i) == (uint64_t)mid) << "should be the same"; + } + // should have the same number of entries + entries_now = JmethodIDTable::get_entry_count(); + ASSERT_TRUE(entries_now == initial_entries + length) << "should have more entries " << entries_now << " " << initial_entries + length; +} + diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index a6fee2c8fe1..9c0599fb513 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -90,10 +90,8 @@ static void check_inner(const ReservedMemoryRegion& rmr, R* regions, size_t regi class VirtualMemoryTrackerTest { public: static void test_add_committed_region_adjacent() { - size_t size = 0x01000000; ReservedSpace rs = MemoryReserver::reserve(size, mtTest); - MemTracker::NmtVirtualMemoryLocker nvml; address addr = (address)rs.base(); @@ -104,8 +102,10 @@ class VirtualMemoryTrackerTest { NativeCallStack stack2(&frame2, 1); // Fetch the added RMR for the space - ReservedMemoryRegion rmr = VirtualMemoryTracker::Instance::tree()->find_reserved_region(addr); RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); + MemTracker::NmtVirtualMemoryLocker nvml; + + ReservedMemoryRegion rmr = rtree->find_reserved_region(addr); ASSERT_EQ(rmr.size(), size); ASSERT_EQ(rmr.base(), addr); @@ -164,14 +164,15 @@ class VirtualMemoryTrackerTest { // Cleanup rtree->uncommit_region(addr, 3 * cs); ASSERT_EQ(rmr.committed_size(), 0u); - } - static void test_add_committed_region_adjacent_overlapping() { - RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); rtree->tree().remove_all(); + } + static void test_add_committed_region_adjacent_overlapping() { size_t size = 0x01000000; ReservedSpace rs = MemoryReserver::reserve(size, mtTest); + + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); MemTracker::NmtVirtualMemoryLocker nvml; address addr = (address)rs.base(); @@ -252,15 +253,15 @@ class VirtualMemoryTrackerTest { {addr + 3 * cs, 2 * cs} }; check(rmr, r); } - } - static void test_add_committed_region_overlapping() { - RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); rtree->tree().remove_all(); + } + static void test_add_committed_region_overlapping() { size_t size = 0x01000000; - ReservedSpace rs = MemoryReserver::reserve(size, mtTest); + + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); MemTracker::NmtVirtualMemoryLocker nvml; address addr = (address)rs.base(); @@ -418,6 +419,8 @@ class VirtualMemoryTrackerTest { {addr + 2 * cs, cs} }; check(rmr, r); } + + rtree->tree().remove_all(); } static void test_add_committed_region() { @@ -432,11 +435,10 @@ class VirtualMemoryTrackerTest { } static void test_remove_uncommitted_region() { - RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); - rtree->tree().remove_all(); - size_t size = 0x01000000; ReservedSpace rs = MemoryReserver::reserve(size, mtTest); + + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); MemTracker::NmtVirtualMemoryLocker nvml; address addr = (address)rs.base(); @@ -558,6 +560,8 @@ class VirtualMemoryTrackerTest { rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } + + rtree->tree().remove_all(); } }; @@ -575,4 +579,4 @@ TEST_VM(NMT_VirtualMemoryTracker, remove_uncommitted_region) { } else { tty->print_cr("skipped."); } -} \ No newline at end of file +} diff --git a/test/hotspot/gtest/utilities/test_deferredStatic.cpp b/test/hotspot/gtest/utilities/test_deferredStatic.cpp new file mode 100644 index 00000000000..b41b1e4ee60 --- /dev/null +++ b/test/hotspot/gtest/utilities/test_deferredStatic.cpp @@ -0,0 +1,120 @@ +/* + * 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. + * + * 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 "utilities/debug.hpp" +#include "utilities/deferredStatic.hpp" +#include "utilities/globalDefinitions.hpp" + +#include + +#include "unittest.hpp" + +class DeferredStaticTestClass { +public: + static unsigned _initialized_count; + int _value; + bool _allow_destruction; + + DeferredStaticTestClass() : DeferredStaticTestClass(0) {} + + DeferredStaticTestClass(int value, bool allow_destruction = false) + : _value(value), _allow_destruction(allow_destruction) + { + ++_initialized_count; + } + + ~DeferredStaticTestClass() { + if (!_allow_destruction) { + ShouldNotReachHere(); + } + } +}; + +unsigned DeferredStaticTestClass::_initialized_count = 0; + +using TC = DeferredStaticTestClass; + +DeferredStatic default_constructed; + +static_assert(std::is_same::value, + "expected"); + +TEST(DeferredStaticTest, default_constructed) { + unsigned init_count = TC::_initialized_count; + default_constructed.initialize(); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(0, default_constructed->_value); + ASSERT_EQ(0, default_constructed.get()->_value); + ASSERT_EQ(0, (*default_constructed)._value); + + int new_value = 5; + *default_constructed.get() = TC(new_value, true /* allow_destruction */); + ASSERT_EQ(init_count + 2, TC::_initialized_count); + ASSERT_EQ(new_value, default_constructed->_value); + ASSERT_EQ(new_value, default_constructed.get()->_value); + ASSERT_EQ(new_value, (*default_constructed)._value); + + int new_value2 = 8; + default_constructed->_value = new_value2; + ASSERT_EQ(init_count + 2, TC::_initialized_count); + ASSERT_EQ(new_value2, default_constructed->_value); + ASSERT_EQ(new_value2, default_constructed.get()->_value); + ASSERT_EQ(new_value2, (*default_constructed)._value); +} + +DeferredStatic arg_constructed; + +TEST(DeferredStaticTest, arg_constructed) { + unsigned init_count = TC::_initialized_count; + int arg = 10; + arg_constructed.initialize(arg); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(arg, arg_constructed->_value); + ASSERT_EQ(arg, arg_constructed.get()->_value); + ASSERT_EQ(arg, (*arg_constructed)._value); +} + +DeferredStatic const_test_object; + +static_assert(std::is_same::value, + "expected"); + +static_assert(std::is_same_value)>::value, + "expected"); + +TEST(DeferredStaticTest, const_test_object) { + unsigned init_count = TC::_initialized_count; + int arg = 20; + const_test_object.initialize(arg); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(arg, const_test_object->_value); + ASSERT_EQ(arg, const_test_object.get()->_value); + ASSERT_EQ(arg, (*const_test_object)._value); + + // Doesn't compile, as expected. + // *const_test_object.get() = TC(0, true /* allow_destruction */); + + // Doesn't compile, as expected. + // const_test_object->_value = 0; +} diff --git a/test/hotspot/jtreg/ProblemList-StaticJdk.txt b/test/hotspot/jtreg/ProblemList-StaticJdk.txt index cb727e470f3..1681fb74634 100644 --- a/test/hotspot/jtreg/ProblemList-StaticJdk.txt +++ b/test/hotspot/jtreg/ProblemList-StaticJdk.txt @@ -37,7 +37,6 @@ serviceability/sa/ClhsdbPstack.java#core 8346719 generic-all gtest/GTestWrapper.java 8356201 generic-all gtest/LargePageGtests.java#use-large-pages 8356201 generic-all gtest/LargePageGtests.java#use-large-pages-1G 8356201 generic-all -gtest/LockStackGtests.java 8356201 generic-all gtest/MetaspaceGtests.java#no-ccs 8356201 generic-all gtest/NMTGtests.java#nmt-detail 8356201 generic-all gtest/NMTGtests.java#nmt-off 8356201 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 3992647282b..3ceccb3b8fb 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -82,8 +82,7 @@ compiler/c2/TestVerifyConstraintCasts.java 8355574 generic-all compiler/c2/aarch64/TestStaticCallStub.java 8359963 linux-aarch64,macosx-aarch64 -compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java 8350208 generic-all -compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotResolvedJavaField.java 8350208 generic-all +compiler/debug/TestStressBailout.java 8361752 generic-all # Valhalla compiler/codegen/TestRedundantLea.java#StringInflate 8367518 generic-all @@ -135,8 +134,6 @@ containers/docker/TestJcmdWithSideCar.java 8341518 linux-x64 # Valhalla -runtime/AccModule/ConstModule.java 8294051 generic-all -runtime/valhalla/inlinetypes/CircularityTest.java 8349037 generic-all runtime/valhalla/inlinetypes/classloading/ConcurrentClassLoadingTest.java 8367412 linux-aarch64 runtime/valhalla/inlinetypes/verifier/StrictInstanceFieldsTest.java CODETOOLS-7904031 generic-all runtime/valhalla/inlinetypes/verifier/StrictStaticFieldsTest.java CODETOOLS-7904031 generic-all @@ -202,6 +199,8 @@ serviceability/sa/ClhsdbPstack.java#core 8318754 macosx-aarch64 serviceability/sa/TestJmapCore.java 8318754 macosx-aarch64 serviceability/sa/TestJmapCoreMetaspace.java 8318754 macosx-aarch64 +serviceability/sa/ClhsdbThreadContext.java 8356704 windows-x64 + serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 serviceability/sa/JhsdbThreadInfoTest.java 8344261 generic-all diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 32d0d05e675..f9990ce8c96 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -79,6 +79,7 @@ requires.properties= \ vm.rtm.cpu \ vm.rtm.compiler \ vm.cds \ + vm.cds.default.archive.available \ vm.cds.custom.loaders \ vm.cds.supports.aot.class.linking \ vm.cds.supports.aot.code.caching \ diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index f52274031ad..decd1ecf373 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -150,7 +150,6 @@ tier1_common = \ sources \ sanity/BasicVMTest.java \ gtest/GTestWrapper.java \ - gtest/LockStackGtests.java \ gtest/MetaspaceGtests.java \ gtest/LargePageGtests.java \ gtest/NMTGtests.java \ @@ -437,6 +436,7 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/aotClassLinking \ -runtime/cds/appcds/aotCode \ -runtime/cds/appcds/aotFlags \ + -runtime/cds/appcds/aotProfile \ -runtime/cds/appcds/applications \ -runtime/cds/appcds/cacheObject \ -runtime/cds/appcds/complexURI \ @@ -531,14 +531,17 @@ hotspot_cds_epsilongc = \ runtime/cds/appcds/jigsaw \ runtime/cds/appcds/loaderConstraints -# Run CDS tests with -XX:+AOTClassLinking. This should include most CDS tests, except for +# Run "old" CDS tests with -XX:+AOTClassLinking. This should include most CDS tests, except for # those that rely on redefining classes that are already archived. +# Note that appcds/aotXXX directories are excluded -- those tests already specifically +# test AOT class linking, so there's no need to run them again with -XX:+AOTClassLinking. hotspot_aot_classlinking = \ runtime/cds \ -runtime/cds/appcds/aotCache \ -runtime/cds/appcds/aotClassLinking \ -runtime/cds/appcds/aotCode \ -runtime/cds/appcds/aotFlags \ + -runtime/cds/appcds/aotProfile \ -runtime/cds/appcds/BadBSM.java \ -runtime/cds/appcds/cacheObject/ArchivedIntegerCacheTest.java \ -runtime/cds/appcds/cacheObject/ArchivedModuleCompareTest.java \ diff --git a/test/hotspot/jtreg/TEST.quick-groups b/test/hotspot/jtreg/TEST.quick-groups index fa1f7f5634e..32af8486b0f 100644 --- a/test/hotspot/jtreg/TEST.quick-groups +++ b/test/hotspot/jtreg/TEST.quick-groups @@ -1603,7 +1603,6 @@ vmTestbase_vm_compiler_quick = \ vmTestbase/jit/misctests/JitBug1/JitBug1.java \ vmTestbase/jit/misctests/Pi/Pi.java \ vmTestbase/jit/misctests/clss14702/clss14702.java \ - vmTestbase/jit/misctests/fpustack/GraphApplet.java \ vmTestbase/jit/misctests/putfield00802/putfield00802.java \ vmTestbase/jit/misctests/t5/t5.java \ vmTestbase/jit/overflow/overflow.java \ diff --git a/test/hotspot/jtreg/applications/scimark/Scimark.java b/test/hotspot/jtreg/applications/scimark/Scimark.java deleted file mode 100644 index 06700b74bf6..00000000000 --- a/test/hotspot/jtreg/applications/scimark/Scimark.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017, 2024, 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 - * @key external-dep - * @library /test/lib - * @run driver Scimark - */ - -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.artifacts.Artifact; -import jdk.test.lib.artifacts.ArtifactResolver; -import jdk.test.lib.artifacts.ArtifactResolverException; -import java.nio.file.Path; -import java.util.Map; - -@Artifact(organization = "gov.nist.math", name = "scimark", revision = "2.0", extension = "zip") -public class Scimark { - public static void main(String... args) throws Exception { - Map artifacts; - try { - artifacts = ArtifactResolver.resolve(Scimark.class); - } catch (ArtifactResolverException e) { - throw new Error("TESTBUG: Can not resolve artifacts for " - + Scimark.class.getName(), e); - } - - System.setProperty("test.noclasspath", "true"); - - OutputAnalyzer output = new OutputAnalyzer(ProcessTools.createTestJavaProcessBuilder( - "-cp", artifacts.get("gov.nist.math.scimark-2.0").toString(), - "jnt.scimark2.commandline", "-large") - .start()); - output.shouldHaveExitValue(0); - } -} diff --git a/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java b/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java index 420dc2b3414..870daa7f0a5 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java +++ b/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java @@ -1,5 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * 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 @@ -27,7 +28,18 @@ * @bug 8356000 * @requires vm.flagless * @requires vm.bits == "64" - * @run driver compiler.arguments.TestCompilerCounts + * @requires vm.debug + * @run driver compiler.arguments.TestCompilerCounts debug + */ + +/* + * @test + * @library /test/lib / + * @bug 8356000 + * @requires vm.flagless + * @requires vm.bits == "64" + * @requires !vm.debug + * @run driver compiler.arguments.TestCompilerCounts product */ package compiler.arguments; @@ -55,6 +67,8 @@ public class TestCompilerCounts { static final int MAX_LINEAR_CPUS = Math.min(16, MAX_CPUS); public static void main(String[] args) throws Throwable { + final boolean debug = args[0].startsWith("debug"); + // CICompilerCount=0 is incorrect in default modes. fail("-XX:CICompilerCount=0"); @@ -133,31 +147,51 @@ public static void main(String[] args) throws Throwable { pass(0, opt, "-XX:TieredStopAtLevel=0"); // Non-tiered modes - int nonTieredCount = heuristicCount(cpus, false); - pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=1"); - pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=2"); - pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=3"); - pass(nonTieredCount, opt, "-XX:-TieredCompilation"); + int c1OnlyCount = heuristicCount(cpus, Compilation.C1Only, debug); + pass(c1OnlyCount, opt, "-XX:TieredStopAtLevel=1", "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); + pass(c1OnlyCount, opt, "-XX:TieredStopAtLevel=2", "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); + pass(c1OnlyCount, opt, "-XX:TieredStopAtLevel=3", "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); + int c2OnlyCount = heuristicCount(cpus, Compilation.C2Only, debug); + pass(c2OnlyCount, opt, "-XX:-TieredCompilation", "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); // Tiered modes - int tieredCount = heuristicCount(cpus, true); - pass(tieredCount, opt); - pass(tieredCount, opt, "-XX:TieredStopAtLevel=4"); + int tieredCount = heuristicCount(cpus, Compilation.Tiered, debug); + pass(tieredCount, opt, "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); + pass(tieredCount, opt, "-XX:TieredStopAtLevel=4", "-XX:NonNMethodCodeHeapSize=" + NonNMethodCodeHeapSize); // Also check that heuristics did not set up more threads than CPUs available - Asserts.assertTrue(nonTieredCount <= cpus, - "Non-tiered count is larger than number of CPUs: " + nonTieredCount + " > " + cpus); + Asserts.assertTrue(c1OnlyCount <= cpus, + "Non-tiered count is larger than number of CPUs: " + c1OnlyCount + " > " + cpus); Asserts.assertTrue(tieredCount <= cpus, "Tiered count is larger than number of CPUs: " + tieredCount + " > " + cpus); } } + enum Compilation { + C1Only, + C2Only, + Tiered, + } + + // Buffer sizes for calculating the maximum number of compiler threads. + static final int NonNMethodCodeHeapSize = 5 * 1024 * 1024; + static final int CodeCacheMinimumUseSpace = 400 * 1024; + static final int C1BufSize = 64 * 1024 * 8 + (64 * 1024 * 8 / 10); + static final int C2BufSize = 6544; + static final int TieredBufSize = C1BufSize / 3 + 2 * C2BufSize / 3; + // Direct translation from CompilationPolicy::initialize: - public static int heuristicCount(int cpus, boolean tiered) { + public static int heuristicCount(int cpus, Compilation comp, boolean debug) { int log_cpu = log2(cpus); int loglog_cpu = log2(Math.max(log_cpu, 1)); - int min_count = tiered ? 2 : 1; - return Math.max(log_cpu * loglog_cpu * 3 / 2, min_count); + int min_count = comp == Compilation.C1Only || comp == Compilation.C2Only ? 1 : 2; + int count = Math.max(log_cpu * loglog_cpu * 3 / 2, min_count); + int max_count = (NonNMethodCodeHeapSize - (debug ? 3 : 1) * CodeCacheMinimumUseSpace) / switch (comp) { + case C1Only -> C1BufSize; + case C2Only -> C2BufSize; + case Tiered -> TieredBufSize; + }; + return Math.max(Math.min(count, max_count), min_count); } public static int log2(int v) { @@ -173,5 +207,4 @@ public static void fail(String... args) throws Throwable { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); } - } diff --git a/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java b/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java index ccf4822e676..534ec9d2d97 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java +++ b/test/hotspot/jtreg/compiler/arguments/TestStressOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -24,7 +24,7 @@ /* * @test * @key stress randomness - * @bug 8252219 8256535 8317349 8319879 8335334 + * @bug 8252219 8256535 8317349 8319879 8335334 8325478 * @requires vm.compiler2.enabled * @summary Tests that different combinations of stress options and * -XX:StressSeed=N are accepted. @@ -56,6 +56,10 @@ * compiler.arguments.TestStressOptions * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressUnstableIfTraps -XX:StressSeed=42 * compiler.arguments.TestStressOptions + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressMacroElimination + * compiler.arguments.TestStressOptions + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressMacroElimination -XX:StressSeed=42 + * compiler.arguments.TestStressOptions */ package compiler.arguments; diff --git a/test/hotspot/jtreg/compiler/arguments/TestUseSSE42IntrinsicsWithLowLevelSSE.java b/test/hotspot/jtreg/compiler/arguments/TestUseSSE42IntrinsicsWithLowLevelSSE.java new file mode 100644 index 00000000000..27886fb7694 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestUseSSE42IntrinsicsWithLowLevelSSE.java @@ -0,0 +1,39 @@ +/* + * 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. + * + * 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 + * @bug 8358592 + * @summary Regression test for -XX:+UseSSE42Intrinsics -XX:UseSSE=1 crash + * @requires os.arch=="amd64" | os.arch=="x86_64" + * @requires vm.debug + * @run main/othervm -XX:+UseSSE42Intrinsics -XX:UseSSE=1 compiler.arguments.TestUseSSE42IntrinsicsWithLowLevelSSE + */ +package compiler.arguments; + +public class TestUseSSE42IntrinsicsWithLowLevelSSE { + + public static void main(String[] args) { + System.out.println("passed"); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java index a3c9421a3f9..b1186a85cae 100644 --- a/test/hotspot/jtreg/compiler/c2/TestBit.java +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -33,7 +33,7 @@ * @library /test/lib / * * @requires vm.flagless - * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64le" | os.arch == "riscv64" + * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" * @requires vm.debug == true & vm.compiler2.enabled * * @run driver compiler.c2.TestBit diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 2e2b2b6661f..22920eda828 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -611,7 +611,7 @@ static Object[] test1R(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1a(byte[] a) { a[0] = (byte)0xbe; @@ -626,7 +626,7 @@ static Object[] test1a(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1b(byte[] a) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -636,7 +636,7 @@ static Object[] test1b(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1c(byte[] a) { storeLongLE(a, 0, 0xdeadbeefbaadbabeL); @@ -644,7 +644,7 @@ static Object[] test1c(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1d(byte[] a) { storeIntLE(a, 0, 0xbaadbabe); @@ -653,7 +653,7 @@ static Object[] test1d(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1e(byte[] a) { storeShortLE(a, 0, (short)0xbabe); @@ -664,7 +664,7 @@ static Object[] test1e(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1f(byte[] a) { UNSAFE.putByte(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -680,8 +680,8 @@ static Object[] test1f(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1g(byte[] a) { UNSAFE.putByteRelease(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -697,8 +697,8 @@ static Object[] test1g(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1h(byte[] a) { UNSAFE.putByteVolatile(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -714,8 +714,8 @@ static Object[] test1h(byte[] a) { @Test // Do not optimize these, just to be sure we do not mess with store ordering. - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test1i(byte[] a) { UNSAFE.putByteOpaque(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 0, (byte)0xbe); @@ -743,13 +743,13 @@ static Object[] test2R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -766,7 +766,7 @@ static Object[] test2a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test2b(byte[] a, int offset, long v) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -776,13 +776,13 @@ static Object[] test2b(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -823,14 +823,14 @@ static Object[] test2RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test2aBE(byte[] a, int offset, long v) { @@ -846,7 +846,7 @@ static Object[] test2aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test2bBE(byte[] a, int offset, long v) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store @@ -856,14 +856,14 @@ static Object[] test2bBE(byte[] a, int offset, long v) { } @Test - @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + @IR(counts = { IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test2cBE(byte[] a, int offset, long v) { @@ -903,16 +903,16 @@ static Object[] test3R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -942,14 +942,14 @@ static Object[] test3RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test3aBE(byte[] a, int offset, long v) { @@ -987,16 +987,16 @@ static Object[] test4R(byte[] a, int offset, long v1, int v2, short v3, byte v4) } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+ 1 for uncommon trap) - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+ 1 for uncommon trap) + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1", IRNode.REVERSE_BYTES_S, "2"}, applyIf = {"UseUnalignedAccesses", "true"}, @@ -1045,18 +1045,18 @@ static Object[] test4RBE(byte[] a, int offset, long v1, int v2, short v3, byte v } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // Unmerged stores: offset + (2,3,16) , and 1 for uncommon trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", // 1([+0,+1]) for platform order and 2([+4,+5], [+14,+15]) for reverse order + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", // 1([+6,+9]) for platform order and 1([+10,+13]) for reverse order + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1", IRNode.REVERSE_BYTES_S, "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+ 1 for uncommon trap) - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+ 1 for uncommon trap) + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test4aBE(byte[] a, int offset, long v1, int v2, short v3, byte v4) { @@ -1101,10 +1101,10 @@ static Object[] test5R(byte[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test5a(byte[] a, int offset) { a[offset + 0] = (byte)0x01; @@ -1139,10 +1139,10 @@ static Object[] test6R(byte[] a, byte[] b, int offset1, int offset2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test6a(byte[] a, byte[] b, int offset1, int offset2) { a[offset1 + 1] = (byte)0x02; a[offset1 + 3] = (byte)0x04; @@ -1164,10 +1164,10 @@ static Object[] test7R(byte[] a, int offset1, int v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test7a(byte[] a, int offset1, int v1) { a[offset1 + 1] = (byte)(v1 >> 8); a[offset1 + 2] = (byte)(v1 >> 16); @@ -1184,10 +1184,10 @@ static Object[] test7RBE(byte[] a, int offset1, int v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test7aBE(byte[] a, int offset1, int v1) { a[offset1 + 1] = (byte)(v1 >> 24); a[offset1 + 2] = (byte)(v1 >> 16); @@ -1211,10 +1211,10 @@ static Object[] test10R(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // no merge + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test10a(byte[] a) { // We have 11 summands: 10x zero variable + 1x array base. // Parsing only allows 10 summands -> does not merge the stores. @@ -1232,10 +1232,10 @@ static Object[] test10a(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // 1 left in uncommon trap path of RangeCheck + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10b(byte[] a) { int zero = zero0 + zero1 + zero2 + zero3 + zero4 @@ -1254,10 +1254,10 @@ static Object[] test10b(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // 1 left in uncommon trap path of RangeCheck - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // 1 left in uncommon trap path of RangeCheck + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10c(byte[] a) { int zero = 7 * zero0 + 7 * zero1 + 7 * zero2 + 7 * zero3 + 7 * zero4 @@ -1277,10 +1277,10 @@ static Object[] test10c(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10d(byte[] a) { // Summand is subtracted from itself -> scale = 0 -> should be removed from list. @@ -1296,10 +1296,10 @@ static Object[] test10d(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test10e(byte[] a) { // Summand is subtracted from itself -> scale = 0 -> should be removed from list. Thus equal to if not present at all. @@ -1315,10 +1315,10 @@ static Object[] test10e(byte[] a) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // no merge - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // no merge + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test10f(byte[] a) { int big = 1 << 29; // Adding up the scales overflows -> no merge. @@ -1355,10 +1355,10 @@ static Object[] test100R(short[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test100a(short[] a, int offset) { a[offset + 0] = (short)0x0100; // stays unchanged -> both used for RC and Return path @@ -1399,10 +1399,10 @@ static Object[] test101R(short[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // only for RC - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // only for RC + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test101a(short[] a, int offset) { a[offset + 0] = (short)0x0100; // I plus kept unchanged for RC @@ -1445,16 +1445,16 @@ static Object[] test102R(short[] a, int offset, long v1, int v2, short v3) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+1 that goes into RC) + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test102a(short[] a, int offset, long v1, int v2, short v3) { @@ -1501,16 +1501,16 @@ static Object[] test102RBE(short[] a, int offset, long v1, int v2, short v3) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) - IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", - IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4", // 3 (+1 that goes into RC) + IRNode.STORE_I_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "3", + IRNode.STORE_L_OF_CLASS, "short\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test102aBE(short[] a, int offset, long v1, int v2, short v3) { @@ -1555,10 +1555,10 @@ static Object[] test200R(int[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test200a(int[] a, int offset) { a[offset + 0] = 0x01001236; // stays unchanged -> both used for RC and Return path @@ -1599,10 +1599,10 @@ static Object[] test201R(int[] a, int offset) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // only for RC - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // only for RC + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test201a(int[] a, int offset) { a[offset + 0] = 0x01001236; // L and also kept unchanged for RC @@ -1645,16 +1645,16 @@ static Object[] test202R(int[] a, int offset, long v1, int v2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", // 5 (+1 that goes into RC) + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4"}, // Stores of constants can be merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test202a(int[] a, int offset, long v1, int v2) { @@ -1701,16 +1701,16 @@ static Object[] test202RBE(int[] a, int offset, long v1, int v2) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "4"}, // Stores of constants can be merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", // 5 (+1 that goes into RC) + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test202aBE(int[] a, int offset, long v1, int v2) { @@ -1745,7 +1745,7 @@ static Object[] test300R(int[] a) { } @Test - @IR(counts = {IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + @IR(counts = {IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2"}, applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test300a(int[] a) { a[2] = 42; @@ -1771,10 +1771,10 @@ static Object[] test400R(int[] a) { @Test // All constants are known, and AddI can be converted to AddL safely, hence the stores can be merged. - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test400a(int[] a) { UNSAFE.putByte(a, UNSAFE.ARRAY_INT_BASE_OFFSET + 0, (byte)0xbe); @@ -1818,16 +1818,16 @@ static Object[] test500R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // expect merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"little-endian", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // expect merged IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) @@ -1855,10 +1855,10 @@ static Object[] test500a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // No optimization because of too many RangeChecks - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // No optimization because of too many RangeChecks + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test501a(byte[] a, int offset, long v) { int idx = 0; try { @@ -1883,10 +1883,10 @@ static Object[] test501a(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // No optimization because of too many RangeChecks - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // No optimization because of too many RangeChecks + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test502a(byte[] a, int offset, long v) { int idx = 0; try { @@ -1940,17 +1940,17 @@ static Object[] test500RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // expect merged IRNode.REVERSE_BYTES_L, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // expect merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test500aBE(byte[] a, int offset, long v) { @@ -1977,17 +1977,17 @@ static Object[] test500aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_S, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test501aBE(byte[] a, int offset, long v) { @@ -2014,17 +2014,17 @@ static Object[] test501aBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_S, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test502aBE(byte[] a, int offset, long v) { @@ -2073,10 +2073,10 @@ static Object[] test600R(byte[] aB, int[] aI, int i) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}) static Object[] test600a(byte[] aB, int[] aI, int i) { Object a = null; @@ -2123,15 +2123,15 @@ static Object[] test601R(byte[] aB, int[] aI, int i, int offset1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", // nothing merged - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "8", // nothing merged + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIfPlatform = {"64-bit", "true"}) - @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "bottom\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // all merged + @IR(counts = {IRNode.STORE_B_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "bottom\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1"}, // all merged applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"32-bit", "true"}) static Object[] test601a(byte[] aB, int[] aI, int i, int offset1) { @@ -2165,10 +2165,10 @@ static Object[] test700R(int[] a, long v1) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_L_OF_CLASS, "int\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test700a(int[] a, long v1) { // Negative shift: cannot optimize a[0] = (int)(v1 >> -1); @@ -2188,10 +2188,10 @@ static Object[] test800R(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "6", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}) static Object[] test800a(byte[] a, int offset, long v) { // Merge attempts begin at the lowest store in the Memory chain. // Candidates are found following the chain. The list is trimmed to a @@ -2217,17 +2217,17 @@ static Object[] test800RBE(byte[] a, int offset, long v) { } @Test - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", IRNode.REVERSE_BYTES_I, "1"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatformAnd = {"little-endian", "true", "riscv64", "false"}) // Exclude riscv64 where ReverseBytes is only conditionally supported - @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", - IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", - IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", - IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "2", + IRNode.STORE_C_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\[int:>=0] \\(java/lang/Cloneable,java/io/Serializable\\)", "0"}, applyIf = {"UseUnalignedAccesses", "true"}, applyIfPlatform = {"big-endian", "true"}) static Object[] test800aBE(byte[] a, int offset, long v) { diff --git a/test/hotspot/jtreg/compiler/c2/TestModControlFoldedAfterCCP.java b/test/hotspot/jtreg/compiler/c2/TestModControlFoldedAfterCCP.java new file mode 100644 index 00000000000..1ac3281ca3f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestModControlFoldedAfterCCP.java @@ -0,0 +1,60 @@ +/* + * 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. + * + * 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 + * @bug 8359602 + * @summary The control input of a ModI node should be discarded if it is + * possible to prove that the divisor can never be 0. + * VerifyIterativeGVN checks that this optimization was applied + * @run main/othervm -XX:CompileCommand=quiet -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -Xcomp -XX:+IgnoreUnrecognizedVMOptions + * -XX:CompileCommand=compileonly,compiler.c2.TestModControlFoldedAfterCCP::test + * -XX:VerifyIterativeGVN=1110 compiler.c2.TestModControlFoldedAfterCCP + * @run main compiler.c2.TestModControlFoldedAfterCCP + * + */ + +package compiler.c2; + +public class TestModControlFoldedAfterCCP { + static void test() { + int i22, i24 = -1191, i28; + int iArr1[] = new int[1]; + for (int i = 1;i < 100; i++) { + for (int j = 4; j > i; j--) { + i22 = i24; + + // divisor is either -1191 or -13957 + iArr1[0] = 5 % i22; + } + for (i28 = i; i28 < 2; ++i28) { + i24 = -13957; + } + } + } + + public static void main(String[] args) { + test(); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/c2/TestReducePhiOnCmpWithNoOptPtrCompare.java b/test/hotspot/jtreg/compiler/c2/TestReducePhiOnCmpWithNoOptPtrCompare.java new file mode 100644 index 00000000000..1247effd46d --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestReducePhiOnCmpWithNoOptPtrCompare.java @@ -0,0 +1,90 @@ +/* + * 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. + * + * 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 + * @bug 8361140 + * @summary Test ConnectionGraph::reduce_phi_on_cmp when OptimizePtrCompare is disabled + * @library /test/lib / + * @run driver compiler.c2.TestReducePhiOnCmpWithNoOptPtrCompare + */ + +package compiler.c2; + +import java.util.Random; +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +public class TestReducePhiOnCmpWithNoOptPtrCompare { + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-OptimizePtrCompare","-XX:+VerifyReduceAllocationMerges","-XX:+IgnoreUnrecognizedVMOptions"); + } + + @Run(test = {"testReducePhiOnCmp_C2"}) + public void runner(RunInfo info) { + Random random = info.getRandom(); + boolean cond = random.nextBoolean(); + int x = random.nextInt(); + int y = random.nextInt(); + Asserts.assertEQ(testReducePhiOnCmp_Interp(cond, x, y),testReducePhiOnCmp_C2(cond, x, y)); + } + + @Test + int testReducePhiOnCmp_C2(boolean cond, int x, int y) { return testReducePhiOnCmp(cond, x, y); } + + @DontCompile + int testReducePhiOnCmp_Interp(boolean cond, int x, int y) { return testReducePhiOnCmp(cond, x, y); } + + int testReducePhiOnCmp(boolean cond,int x,int y) { + Point p = null; + + if (cond) { + p = new Point(x*x, y*y); + } else if (x > y) { + p = new Point(x+y, x*y); + } + + if (p != null) { + return p.x * p.y; + } else { + return 1984; + } + } + + static class Point { + int x, y; + Point(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Point)) return false; + Point p = (Point) o; + return (p.x == x) && (p.y == y); + } + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/types/R64int.java b/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsHelper.jasm similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/types/R64int.java rename to test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsHelper.jasm index 635f3b5f071..0ac3aa154ba 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/R64int.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsHelper.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -19,37 +19,26 @@ * 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. + * */ -package org.openjdk.bench.valhalla.types; - -public class R64int implements Int64, ByInt { - - public final int v0; - public final int v1; - - public R64int(long v) { - this((int) (v >>> 32), (int) v); - } - - public R64int(int hi, int lo) { - this.v0 = hi; - this.v1 = lo; - } - - private static final long MASK = 0xFFFFFFFFL; +package compiler/c2/gvn; - @Override - public long longValue() { - return (v0 & MASK) << 32 | (v1 & MASK); +public class ReverseBytesConstantsHelper { + public Method "":"()V" stack 1 locals 1 { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; } - @Override - public int intValue() { - return v1; + public static Method reverseBytesShort:"(I)S" stack 1 locals 1 { + iload_0; + invokestatic Method java/lang/Short."reverseBytes":"(S)S"; + ireturn; } - @Override - public int intSum() { - return v0 + v1 ; + public static Method reverseBytesChar:"(I)C" stack 1 locals 1 { + iload_0; + invokestatic Method java/lang/Character."reverseBytes":"(C)C"; + ireturn; } } diff --git a/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsTests.java b/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsTests.java index 13461771cc9..d9e06b47275 100644 --- a/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsTests.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/ReverseBytesConstantsTests.java @@ -34,9 +34,10 @@ /* * @test - * @bug 8353551 + * @bug 8353551 8359678 * @summary Test that ReverseBytes operations constant-fold. * @library /test/lib / + * @compile ReverseBytesConstantsHelper.jasm * @run driver compiler.c2.gvn.ReverseBytesConstantsTests */ public class ReverseBytesConstantsTests { @@ -51,14 +52,14 @@ public class ReverseBytesConstantsTests { private static final int C_INT = GEN_INT.next(); public static void main(String[] args) { - TestFramework.run(); + TestFramework.runWithFlags("-XX:CompileCommand=inline,compiler.c2.gvn.ReverseBytesConstantsHelper::*"); } @Run(test = { - "testI1", "testI2", "testI3", - "testL1", "testL2", "testL3", - "testS1", "testS2", "testS3", - "testUS1", "testUS2", "testUS3", + "testI1", "testI2", "testI3", "testI4", + "testL1", "testL2", "testL3", "testL4", + "testS1", "testS2", "testS3", "testS4", + "testUS1", "testUS2", "testUS3", "testUS4", }) public void runMethod() { assertResultI(); @@ -171,6 +172,18 @@ public short testS4() { return Short.reverseBytes(C_SHORT); } + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_S, IRNode.CALL}) + public short testS5() { + return ReverseBytesConstantsHelper.reverseBytesShort(C_INT); + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_S, IRNode.CALL}) + public short testS6() { + return ReverseBytesConstantsHelper.reverseBytesShort(C_CHAR); + } + @Test @IR(failOn = {IRNode.REVERSE_BYTES_US}) public char testUS1() { @@ -195,4 +208,16 @@ public char testUS4() { return Character.reverseBytes(C_CHAR); } + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_US, IRNode.CALL}) + public char testUS5() { + return ReverseBytesConstantsHelper.reverseBytesChar(C_INT); + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_US, IRNode.CALL}) + public char testUS6() { + return ReverseBytesConstantsHelper.reverseBytesChar(C_SHORT); + } + } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java index c96146b8e39..c8ee5e730fa 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java @@ -32,10 +32,14 @@ * @run driver TestFloat16ScalarOperations */ import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; import jdk.incubator.vector.Float16; import static jdk.incubator.vector.Float16.*; import java.util.Random; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; + public class TestFloat16ScalarOperations { private static final int count = 1024; @@ -55,19 +59,35 @@ public class TestFloat16ScalarOperations { private static final Float16 MAX_HALF_ULP = Float16.valueOf(16.0f); private static final Float16 SIGNALING_NAN = shortBitsToFloat16((short)31807); - private static Random r = jdk.test.lib.Utils.getRandomInstance(); + private static Generator genF = G.uniformFloats(); + private static Generator genHF = G.uniformFloat16s(); - private static final Float16 RANDOM1 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM2 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM3 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM4 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM5 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); + private static final Float16 RANDOM1 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM2 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM3 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM4 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM5 = Float16.valueOf(genF.next()); private static Float16 RANDOM1_VAR = RANDOM1; private static Float16 RANDOM2_VAR = RANDOM2; private static Float16 RANDOM3_VAR = RANDOM3; private static Float16 RANDOM4_VAR = RANDOM4; private static Float16 RANDOM5_VAR = RANDOM5; + private static Float16 POSITIVE_ZERO_VAR = POSITIVE_ZERO; + + private static final float INEXACT_FP16 = 2051.0f; + private static final float EXACT_FP16 = 2052.0f; + private static final float SNAN_FP16 = Float.intBitsToFloat(0x7F8000F0); + private static final float QNAN_FP16 = Float.intBitsToFloat(0x7FC00000); + + private Float16 GOLDEN_DIV_POT; + private Float16 GOLDEN_MUL2; + private short GOLDEN_INEXACT; + private short GOLDEN_EXACT; + private short GOLDEN_RANDOM_PAT1; + private short GOLDEN_RANDOM_PAT2; + private short GOLDEN_SNAN; + private short GOLDEN_QNAN; public static void main(String args[]) { Scenario s0 = new Scenario(0, "--add-modules=jdk.incubator.vector", "-Xint"); @@ -78,11 +98,19 @@ public static void main(String args[]) { public TestFloat16ScalarOperations() { src = new short[count]; dst = new short[count]; - fl = new float[count]; - for (int i = 0; i < count; i++) { - src[i] = Float.floatToFloat16(r.nextFloat() * MAX_VALUE.floatValue()); - fl[i] = r.nextFloat(); - } + fl = new float[count]; + + G.fill(genF, fl); + G.fill(genHF, src); + + GOLDEN_DIV_POT = testDivByPOT(); + GOLDEN_MUL2 = testMulByTWO(); + GOLDEN_INEXACT = testInexactFP16ConstantPatterns(); + GOLDEN_EXACT = testExactFP16ConstantPatterns(); + GOLDEN_RANDOM_PAT1 = testRandomFP16ConstantPatternSet1(); + GOLDEN_RANDOM_PAT2 = testRandomFP16ConstantPatternSet2(); + GOLDEN_SNAN = testSNaNFP16ConstantPatterns(); + GOLDEN_QNAN = testQNaNFP16ConstantPatterns(); } static void assertResult(float actual, float expected, String msg) { @@ -270,7 +298,7 @@ public void testFma() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " >0 ", IRNode.REINTERPRET_S2HF, " >0 ", IRNode.REINTERPRET_HF2S, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - public void testDivByPOT() { + public Float16 testDivByPOT() { Float16 res = valueOf(0.0f); for (int i = 0; i < 50; i++) { Float16 divisor = valueOf(8.0f); @@ -281,7 +309,12 @@ public void testDivByPOT() { divisor = valueOf(32.0f); res = add(res, divide(dividend, divisor)); } - dst[0] = float16ToRawShortBits(res); + return res; + } + + @Check(test="testDivByPOT") + public void checkDivByPOT(Float16 actual) { + Verify.checkEQ(Float16.float16ToRawShortBits(GOLDEN_DIV_POT), Float16.float16ToRawShortBits(actual)); } @Test @@ -289,16 +322,151 @@ public void testDivByPOT() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " 0 ", IRNode.ADD_HF, " >0 ", IRNode.REINTERPRET_S2HF, " >0 ", IRNode.REINTERPRET_HF2S, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - public void testMulByTWO() { + public Float16 testMulByTWO() { Float16 res = valueOf(0.0f); Float16 multiplier = valueOf(2.0f); for (int i = 0; i < 20; i++) { Float16 multiplicand = valueOf((float)i); res = add(res, multiply(multiplicand, multiplier)); } - assertResult(res.floatValue(), (float)((20 * (20 - 1))/2) * 2.0f, "testMulByTWO"); + return res; + } + + @Check(test="testMulByTWO") + public void checkMulByTWO(Float16 actual) { + Verify.checkEQ(Float16.float16ToRawShortBits(GOLDEN_MUL2), Float16.float16ToRawShortBits(actual)); } + @Test + @IR(counts = {IRNode.ADD_HF, " 0 ", IRNode.SUB_HF, " 0 ", IRNode.MUL_HF, " 0 ", IRNode.DIV_HF, " 0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " 0 ", IRNode.SUB_HF, " 0 ", IRNode.MUL_HF, " 0 ", IRNode.DIV_HF, " 0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + // Test point checks various floating point operations with exactly one floating + // point constant value passed as left or right argument, it then downcasts the + // result of computation to a float16 value. This pattern is used to infer a + // float16 IR during idealization. Floating point constant input is not-representable + // in float16 value range and is an inexact float16 value thereby preventing + // float16 IR inference. + public short testInexactFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + INEXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - INEXACT_FP16); + res += Float.floatToFloat16(INEXACT_FP16 * POSITIVE_ZERO_VAR.floatValue()); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / INEXACT_FP16); + return res; + } + + @Check(test="testInexactFP16ConstantPatterns") + public void checkInexactFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_INEXACT, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testSNaNFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / SNAN_FP16); + return res; + } + + @Check(test="testSNaNFP16ConstantPatterns") + public void checkSNaNFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_SNAN, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testQNaNFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / QNAN_FP16); + return res; + } + + @Check(test="testQNaNFP16ConstantPatterns") + public void checkQNaNFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_QNAN, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + // Test point checks various floating point operations with exactly one floating + // point constant value passed as left or right argument, it then downcasts the + // result of computation to a float16 value. This pattern is used to infer a + // Float16 IR during idealization. Floating point constant input is representable + // in Float16 value range thereby leading to a successful Float16 IR inference. + public short testExactFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(EXACT_FP16 + POSITIVE_ZERO_VAR.floatValue()); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - EXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * EXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / EXACT_FP16); + return res; + } + + @Check(test="testExactFP16ConstantPatterns") + public void checkExactFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_EXACT, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testRandomFP16ConstantPatternSet1() { + short res = 0; + res += Float.floatToFloat16(RANDOM1_VAR.floatValue() + RANDOM2.floatValue()); + res += Float.floatToFloat16(RANDOM2_VAR.floatValue() - RANDOM3.floatValue()); + res += Float.floatToFloat16(RANDOM3_VAR.floatValue() * RANDOM4.floatValue()); + res += Float.floatToFloat16(RANDOM4_VAR.floatValue() / RANDOM5.floatValue()); + return res; + } + + @Check(test="testRandomFP16ConstantPatternSet1") + public void checkRandomFP16ConstantPatternSet1(short actual) { + Verify.checkEQ(GOLDEN_RANDOM_PAT1, actual); + } + + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testRandomFP16ConstantPatternSet2() { + short res = 0; + res += Float.floatToFloat16(RANDOM2.floatValue() + RANDOM1_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM3.floatValue() - RANDOM2_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM4.floatValue() * RANDOM3_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM5.floatValue() / RANDOM4_VAR.floatValue()); + return res; + } + + @Check(test="testRandomFP16ConstantPatternSet2") + public void checkRandomFP16ConstantPatternSet2(short actual) { + Verify.checkEQ(GOLDEN_RANDOM_PAT2, actual); + } // // Tests points for various Float16 constant folding transforms. Following figure represents various @@ -373,41 +541,42 @@ public void testAddConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.SUB_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testSubConstantFolding() { // If either value is NaN, then the result is NaN. - assertResult(subtract(Float16.NaN, valueOf(2.0f)).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NaN, Float16.NaN).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NaN, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); + assertResult(subtract(Float16.NaN, valueOf(2.0f)).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NaN, Float16.NaN).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NaN, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); // The difference of two infinities of opposite sign is NaN. - assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.POSITIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.POSITIVE_INFINITY, "testSubConstantFolding"); // The difference of two infinities of the same sign is NaN. - assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NEGATIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NEGATIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); // The difference of an infinity and a finite value is equal to the infinite operand. - assertResult(subtract(Float16.POSITIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.POSITIVE_INFINITY, "testAddConstantFolding"); - assertResult(subtract(Float16.NEGATIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.NEGATIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.POSITIVE_INFINITY, "testSubConstantFolding"); + assertResult(subtract(Float16.NEGATIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.NEGATIVE_INFINITY, "testSubConstantFolding"); // The difference of two zeros of opposite sign is positive zero. - assertResult(subtract(NEGATIVE_ZERO, POSITIVE_ZERO).floatValue(), 0.0f, "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_ZERO, POSITIVE_ZERO).floatValue(), 0.0f, "testSubConstantFolding"); // Number equal to -MAX_VALUE when subtracted by half upl of MAX_VALUE results into -Inf. - assertResult(subtract(NEGATIVE_MAX_VALUE, MAX_HALF_ULP).floatValue(), Float.NEGATIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_MAX_VALUE, MAX_HALF_ULP).floatValue(), Float.NEGATIVE_INFINITY, "testSubConstantFolding"); // Number equal to -MAX_VALUE when subtracted by a number less than half upl for MAX_VALUE results into -MAX_VALUE. - assertResult(subtract(NEGATIVE_MAX_VALUE, LT_MAX_HALF_ULP).floatValue(), NEGATIVE_MAX_VALUE.floatValue(), "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_MAX_VALUE, LT_MAX_HALF_ULP).floatValue(), NEGATIVE_MAX_VALUE.floatValue(), "testSubConstantFolding"); - assertResult(subtract(valueOf(1.0f), valueOf(2.0f)).floatValue(), -1.0f, "testAddConstantFolding"); + assertResult(subtract(valueOf(1.0f), valueOf(2.0f)).floatValue(), -1.0f, "testSubConstantFolding"); } @Test - @Warmup(value = 10000) @IR(counts = {IRNode.MAX_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MAX_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMaxConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(max(valueOf(2.0f), Float16.NaN).floatValue(), Float.NaN, "testMaxConstantFolding"); @@ -428,6 +597,7 @@ public void testMaxConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MIN_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMinConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(min(valueOf(2.0f), Float16.NaN).floatValue(), Float.NaN, "testMinConstantFolding"); @@ -447,6 +617,7 @@ public void testMinConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.DIV_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testDivConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(divide(Float16.NaN, POSITIVE_ZERO).floatValue(), Float.NaN, "testDivConstantFolding"); @@ -489,6 +660,7 @@ public void testDivConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMulConstantFolding() { // If any operand is NaN, the result is NaN. assertResult(multiply(Float16.NaN, valueOf(4.0f)).floatValue(), Float.NaN, "testMulConstantFolding"); @@ -514,6 +686,7 @@ public void testMulConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.SQRT_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testSqrtConstantFolding() { // If the argument is NaN or less than zero, then the result is NaN. assertResult(sqrt(Float16.NaN).floatValue(), Float.NaN, "testSqrtConstantFolding"); @@ -535,6 +708,7 @@ public void testSqrtConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.FMA_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testFMAConstantFolding() { // If any argument is NaN, the result is NaN. assertResult(fma(Float16.NaN, valueOf(2.0f), valueOf(3.0f)).floatValue(), Float.NaN, "testFMAConstantFolding"); @@ -572,6 +746,7 @@ public void testFMAConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(failOn = {IRNode.ADD_HF, IRNode.SUB_HF, IRNode.MUL_HF, IRNode.DIV_HF, IRNode.SQRT_HF, IRNode.FMA_HF}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testRounding1() { dst[0] = float16ToRawShortBits(add(RANDOM1, RANDOM2)); dst[1] = float16ToRawShortBits(subtract(RANDOM2, RANDOM3)); @@ -608,13 +783,13 @@ public void checkRounding1() { } @Test - @Warmup(value = 10000) @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 ", IRNode.SQRT_HF, " >0 ", IRNode.FMA_HF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 ", IRNode.SQRT_HF, " >0 ", IRNode.FMA_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testRounding2() { dst[0] = float16ToRawShortBits(add(RANDOM1_VAR, RANDOM2_VAR)); dst[1] = float16ToRawShortBits(subtract(RANDOM2_VAR, RANDOM3_VAR)); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java index 69b3cb5274b..8d25706f521 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java @@ -76,7 +76,21 @@ public static void main(String[] args) { "-XX:CompileCommand=inline,*Nested::*", "-XX:CompileCommand=exclude,*::dummy*"); - framework.addScenarios(scenario0, scenario1, scenario2).start(); + Scenario scenario3 = new Scenario(3, "-XX:+UnlockDiagnosticVMOptions", + "-XX:+ReduceAllocationMerges", + "-XX:+TraceReduceAllocationMerges", + "-XX:+DeoptimizeALot", + "-XX:+UseCompressedOops", + "-XX:+UseCompressedClassPointers", + "-XX:-OptimizePtrCompare", + "-XX:+VerifyReduceAllocationMerges", + "-XX:CompileCommand=inline,*::charAt*", + "-XX:CompileCommand=inline,*PicturePositions::*", + "-XX:CompileCommand=inline,*Point::*", + "-XX:CompileCommand=inline,*Nested::*", + "-XX:CompileCommand=exclude,*::dummy*"); + + framework.addScenarios(scenario0, scenario1, scenario2, scenario3).start(); } // ------------------ No Scalar Replacement Should Happen in The Tests Below ------------------- // diff --git a/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java index e58f8660131..0108df40704 100644 --- a/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java +++ b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java @@ -224,23 +224,18 @@ private static Object[] setup() { } @Test + // TODO: Make tests more precise @IR(counts = {IRNode.LEA_P, "=2"}, phase = {CompilePhase.FINAL_CODE}, applyIfPlatform = {"mac", "false"}) // Negative - @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=5"}, + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=5"}, phase = {CompilePhase.FINAL_CODE}, - applyIfAnd = {"OptoPeephole", "false", "UseAVX", ">=2"}) - @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=13"}, - phase = {CompilePhase.FINAL_CODE}, - applyIfAnd = {"OptoPeephole", "false", "UseAVX", "<2"}) + applyIf = {"OptoPeephole", "false"}) // 2 decodes get removed - @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=3"}, + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=3"}, phase = {CompilePhase.FINAL_CODE}, - applyIfAnd = {"OptoPeephole", "true", "UseAVX", ">=2"}) - @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=11"}, - phase = {CompilePhase.FINAL_CODE}, - applyIfAnd = {"OptoPeephole", "true", "UseAVX", "<2"}) + applyIf = {"OptoPeephole", "true"}) @Arguments(setup = "setup") public static Name test(Name n1, Name n2) { return n1.append(n2); @@ -258,6 +253,7 @@ private static Object[] setup() { } @Test + // TODO: Make tests more precise @IR(counts = {IRNode.LEA_P, "=1"}, phase = {CompilePhase.FINAL_CODE}, applyIfPlatform = {"mac", "false"}) diff --git a/test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java b/test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java index bbcafb53460..9542e48e54e 100644 --- a/test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java +++ b/test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -30,7 +30,7 @@ /* * @test * @key stress randomness - * @bug 8252219 8256535 + * @bug 8252219 8256535 8325478 * @requires vm.compiler2.enabled * @summary Tests that using a stress option without -XX:StressSeed=N generates * and logs a random seed. @@ -40,6 +40,7 @@ * @run driver compiler.debug.TestGenerateStressSeed StressIGVN * @run driver compiler.debug.TestGenerateStressSeed StressCCP * @run driver compiler.debug.TestGenerateStressSeed StressMacroExpansion + * @run driver compiler.debug.TestGenerateStressSeed StressMacroElimination */ public class TestGenerateStressSeed { diff --git a/test/hotspot/jtreg/compiler/debug/TestStress.java b/test/hotspot/jtreg/compiler/debug/TestStress.java index 6678d09e649..2046488ac40 100644 --- a/test/hotspot/jtreg/compiler/debug/TestStress.java +++ b/test/hotspot/jtreg/compiler/debug/TestStress.java @@ -30,11 +30,11 @@ /* * @test * @key stress randomness - * @bug 8252219 8256535 8317349 + * @bug 8252219 8256535 8317349 8325478 * @requires vm.debug == true & vm.compiler2.enabled * @requires vm.flagless * @summary Tests that stress compilations with the same seed yield the same - * IGVN, CCP, and macro expansion traces. + * IGVN, CCP, macro elimination, and macro expansion traces. * @library /test/lib / * @run driver compiler.debug.TestStress */ @@ -69,6 +69,12 @@ static String macroExpansionTrace(int stressSeed) throws Exception { stressSeed); } + static String macroEliminationTrace(int stressSeed) throws Exception { + return phaseTrace("StressMacroElimination", + "CompileCommand=PrintIdealPhase,*::*,AFTER_MACRO_ELIMINATION_STEP", + stressSeed); + } + static void sum(int n) { int acc = 0; for (int i = 0; i < n; i++) acc += i; @@ -84,6 +90,8 @@ public static void main(String[] args) throws Exception { "got different CCP traces for the same seed"); Asserts.assertEQ(macroExpansionTrace(s), macroExpansionTrace(s), "got different macro expansion traces for the same seed"); + Asserts.assertEQ(macroEliminationTrace(s), macroEliminationTrace(s), + "got different macro elimination traces for the same seed"); } } else if (args.length > 0) { sum(Integer.parseInt(args[0])); diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java index 99a594ade69..6d09d7c042c 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java @@ -30,7 +30,8 @@ * @test * @key randomness * @bug 8283726 8287925 - * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" | os.arch=="ppc64" | os.arch=="ppc64le" + * @summary Test the intrinsics implementation of Integer/Long::compareUnsigned * @library /test/lib / * @run driver compiler.intrinsics.TestCompareUnsigned diff --git a/test/hotspot/jtreg/compiler/intrinsics/VectorIntoArrayInvalidControlFlow.java b/test/hotspot/jtreg/compiler/intrinsics/VectorIntoArrayInvalidControlFlow.java new file mode 100644 index 00000000000..e9c8edc4592 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/VectorIntoArrayInvalidControlFlow.java @@ -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. + * + * 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. + */ + +package compiler.intrinsics; + +/* + * @test + * @bug 8359344 + * @summary Intrinsic storeMasked can add some control flow before bailing out, leaving a malformed CFG. + * @modules jdk.incubator.vector + * @run main/othervm -XX:+UnlockDiagnosticVMOptions + * -XX:TypeProfileLevel=222 -Xbatch + * -XX:CompileCommand=compileonly,jdk.incubator.vector.Long*::intoArray0 + * -XX:+AbortVMOnCompilationFailure + * compiler.intrinsics.VectorIntoArrayInvalidControlFlow + * + * @run main compiler.intrinsics.VectorIntoArrayInvalidControlFlow + */ + +import jdk.incubator.vector.*; + +public class VectorIntoArrayInvalidControlFlow { + private static final VectorSpecies L_SPECIES = LongVector.SPECIES_128; + private static final LongVector longVector; + private static final long[] longArray = new long[L_SPECIES.length()]; + private static final boolean[] longMask = new boolean[L_SPECIES.length()]; + private static final VectorMask longVectorMask; + + static { + for (int i = 0; i < L_SPECIES.length(); i++) { + longArray[i] = i + 1; + longMask[i] = L_SPECIES.length() > 1 && i % 2 == 0; + } + longVector = LongVector.fromArray(L_SPECIES, longArray, 0); + longVectorMask = VectorMask.fromArray(L_SPECIES, longMask, 0); + } + + static long[] test() { + long[] res = new long[L_SPECIES.length()]; + for(int j = 0; j < 10_000; j++) { + longVector.intoArray(res, 0, longVectorMask); + } + return res; + } + + static public void main(String[] args) { + test(); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java index 9d2a731c6e5..506405078df 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java @@ -125,8 +125,7 @@ public static OutputAnalyzer runTest(Class expr, // Hide timestamps from warnings (e.g. due to potential AOT // saved/runtime state mismatch), to avoid false positives when // comparing output across runs. - vmOpts.add("-Xlog:all=warning:stdout:level,tags"); - vmOpts.add("-Xlog:aot=off"); + vmOpts.add("-Xlog:all=warning,aot=off:stdout:level,tags"); //setup mode-specific options switch (testVMMode) { diff --git a/test/hotspot/jtreg/compiler/jvmci/common/CodeInstallerTest.java b/test/hotspot/jtreg/compiler/jvmci/common/CodeInstallerTest.java index c4ce4173282..1fc49c93ac8 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/CodeInstallerTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/CodeInstallerTest.java @@ -112,7 +112,7 @@ protected InstalledCode installEmptyCode(Site[] sites, hasUnsafeAccess); SpeculationLog log = null; InstalledCode installedCode = null; - return codeCache.addCode(dummyMethod, code, log, installedCode); + return codeCache.addCode(dummyMethod, code, log, installedCode, true); } protected Register getRegister(PlatformKind kind, int index) { diff --git a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java index 4c8e63d0a42..d4c04ffb742 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -306,7 +306,7 @@ public static InstalledCode getInstalledCode(ResolvedJavaMethod method, String n } private static class InstalledCodeStub extends HotSpotNmethod { private InstalledCodeStub(HotSpotResolvedJavaMethodImpl method, String name, long address, long entryPoint) { - super(method, name, false, 0); + super(method, name, false, true, 0); this.address = address; this.entryPoint = entryPoint; } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java index dc68dd3d8d9..a38424e5572 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -106,7 +106,7 @@ protected HotSpotNmethod test(TestCompiler compiler, Method method, Object... ar asm.emitEpilogue(); HotSpotCompiledCode code = asm.finish(resolvedMethod); - InstalledCode installed = codeCache.addCode(resolvedMethod, code, null, null); + InstalledCode installed = codeCache.addCode(resolvedMethod, code, null, null, true); if (DEBUG) { String str = ((HotSpotCodeCacheProvider) codeCache).disassemble(installed); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MethodTagTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MethodTagTest.java index 9fcfb10cb65..58abb10c639 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MethodTagTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MethodTagTest.java @@ -138,7 +138,7 @@ protected HotSpotNmethod test(TestCompiler compiler, Method method, Object... ar asm.emitEpilogue(); HotSpotCompiledCode code = asm.finish(resolvedMethod); - InstalledCode installed = codeCache.addCode(resolvedMethod, code, null, null); + InstalledCode installed = codeCache.addCode(resolvedMethod, code, null, null, true); String str = ((HotSpotCodeCacheProvider) codeCache).disassemble(installed); Asserts.assertTrue(str.contains("# {method}"), "\"# {method}\" tag not found"); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java index dea523af166..3ca2c555d2e 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -76,7 +76,7 @@ public static void main(String args[]) { /* totalFrameSize */ 0, /* deoptRescueSlot */ null); try { - codeCache.installCode(null, stub, null, null, true); + codeCache.installCode(null, stub, null, null, true, true); throw new AssertionError("Didn't get expected " + BailoutException.class.getName()); } catch (BailoutException e) { Asserts.assertEQ(e.getMessage(), "Error installing " + stubToFail + ": code cache is full"); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 57b8f9ba99b..0cd8238d23b 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -158,6 +158,16 @@ public void findInstanceFieldWithOffsetTest() { } } + @Test + public void isAnnotationTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + boolean expected = c.isAnnotation(); + boolean actual = type.isAnnotation(); + assertEquals(expected, actual); + } + } + @Test public void isInterfaceTest() { for (Class c : classes) { @@ -1270,25 +1280,59 @@ private static boolean isSignaturePolymorphic(ResolvedJavaMethod method) { return method.getAnnotation(SIGNATURE_POLYMORPHIC_CLASS) != null; } + private static void getAnnotationDataExpectedToFail(Annotated annotated, ResolvedJavaType... annotationTypes) { + try { + if (annotationTypes.length == 1) { + annotated.getAnnotationData(annotationTypes[0]); + } else { + var tail = Arrays.copyOfRange(annotationTypes, 2, annotationTypes.length); + annotated.getAnnotationData(annotationTypes[0], annotationTypes[1], tail); + } + String s = Stream.of(annotationTypes).map(ResolvedJavaType::toJavaName).collect(Collectors.joining(", ")); + throw new AssertionError("Expected IllegalArgumentException for retrieving (" + s + " from " + annotated); + } catch (IllegalArgumentException iae) { + assertTrue(iae.getMessage(), iae.getMessage().contains("not an annotation interface")); + } + } + /** * Tests that {@link AnnotationData} obtained from a {@link Class}, {@link Method} or * {@link Field} matches {@link AnnotatedElement#getAnnotations()} for the corresponding JVMCI * object. * - * @param annotated a {@link Class}, {@link Method} or {@link Field} object + * @param annotatedElement a {@link Class}, {@link Method} or {@link Field} object */ - public static void getAnnotationDataTest(AnnotatedElement annotated) throws Exception { - testGetAnnotationData(annotated, List.of(annotated.getAnnotations())); - } - - private static void testGetAnnotationData(AnnotatedElement annotated, List annotations) throws AssertionError { + public static void getAnnotationDataTest(AnnotatedElement annotatedElement) throws Exception { + Annotated annotated = toAnnotated(annotatedElement); + ResolvedJavaType objectType = metaAccess.lookupJavaType(Object.class); + ResolvedJavaType suppressWarningsType = metaAccess.lookupJavaType(SuppressWarnings.class); + getAnnotationDataExpectedToFail(annotated, objectType); + getAnnotationDataExpectedToFail(annotated, suppressWarningsType, objectType); + getAnnotationDataExpectedToFail(annotated, suppressWarningsType, suppressWarningsType, objectType); + + // Check that querying a missing annotation returns null or an empty list + assertNull(annotated.getAnnotationData(suppressWarningsType)); + List data = annotated.getAnnotationData(suppressWarningsType, suppressWarningsType); + assertTrue(data.toString(), data.isEmpty()); + data = annotated.getAnnotationData(suppressWarningsType, suppressWarningsType, suppressWarningsType, suppressWarningsType); + assertTrue(data.toString(), data.isEmpty()); + + testGetAnnotationData(annotatedElement, annotated, List.of(annotatedElement.getAnnotations())); + } + + private static void testGetAnnotationData(AnnotatedElement annotatedElement, Annotated annotated, List annotations) throws AssertionError { + ResolvedJavaType suppressWarningsType = metaAccess.lookupJavaType(SuppressWarnings.class); for (Annotation a : annotations) { - AnnotationData ad = toAnnotated(annotated).getAnnotationData(metaAccess.lookupJavaType(a.annotationType())); + var annotationType = metaAccess.lookupJavaType(a.annotationType()); + AnnotationData ad = annotated.getAnnotationData(annotationType); assertAnnotationsEquals(a, ad); // Check that encoding/decoding produces a stable result - AnnotationData ad2 = toAnnotated(annotated).getAnnotationData(metaAccess.lookupJavaType(a.annotationType())); + AnnotationData ad2 = annotated.getAnnotationData(annotationType); assertEquals(ad, ad2); + + List annotationData = annotated.getAnnotationData(annotationType, suppressWarningsType, suppressWarningsType); + assertEquals(1, annotationData.size()); } if (annotations.size() < 2) { return; @@ -1301,7 +1345,7 @@ private static void testGetAnnotationData(AnnotatedElement annotated, List metaAccess.lookupJavaType(a.annotationType())).// toArray(ResolvedJavaType[]::new); - List annotationData = toAnnotated(annotated).getAnnotationData(type1, type2, types); + List annotationData = annotated.getAnnotationData(type1, type2, types); assertEquals(2 + types.length, annotationData.size()); for (int j = 0; j < annotationData.size(); j++) { diff --git a/test/hotspot/jtreg/compiler/lib/generators/Generators.java b/test/hotspot/jtreg/compiler/lib/generators/Generators.java index ac4062f19d5..c16b35cdae8 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/Generators.java +++ b/test/hotspot/jtreg/compiler/lib/generators/Generators.java @@ -605,6 +605,29 @@ public void fill(Generator generator, float[] a) { fillFloat(generator, MemorySegment.ofArray(a)); } + /** + * Fills the memory segments with shorts obtained by calling next on the generator. + * + * @param generator The generator from which to source the values. + * @param ms Memory segment to be filled with random values. + */ + public void fillShort(Generator generator, MemorySegment ms) { + var layout = ValueLayout.JAVA_SHORT_UNALIGNED; + for (long i = 0; i < ms.byteSize() / layout.byteSize(); i++) { + ms.setAtIndex(layout, i, generator.next()); + } + } + + /** + * Fill the array with shorts using the distribution of the generator. + * + * @param a Array to be filled with random values. + */ + public void fill(Generator generator, short[] a) { + fillShort(generator, MemorySegment.ofArray(a)); + } + + /** * Fills the memory segments with ints obtained by calling next on the generator. * diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java index b0e5f2fda5c..8b794e13e3f 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java @@ -86,6 +86,14 @@ public enum CompilePhase { ITER_GVN_AFTER_ELIMINATION( "Iter GVN after Eliminating Allocations and Locks"), BEFORE_PRE_MAIN_POST( "Before Pre/Main/Post Loops"), AFTER_PRE_MAIN_POST( "After Pre/Main/Post Loops"), + BEFORE_POST_LOOP( "Before Post Loop"), + AFTER_POST_LOOP( "After Post Loop"), + BEFORE_REMOVE_EMPTY_LOOP( "Before Remove Empty Loop"), + AFTER_REMOVE_EMPTY_LOOP( "After Remove Empty Loop"), + BEFORE_ONE_ITERATION_LOOP( "Before Replacing One-Iteration Loop"), + AFTER_ONE_ITERATION_LOOP( "After Replacing One-Iteration Loop"), + BEFORE_DUPLICATE_LOOP_BACKEDGE( "Before Duplicate Loop Backedge"), + AFTER_DUPLICATE_LOOP_BACKEDGE( "After Duplicate Loop Backedge"), PHASEIDEALLOOP1( "PhaseIdealLoop 1"), PHASEIDEALLOOP2( "PhaseIdealLoop 2"), PHASEIDEALLOOP3( "PhaseIdealLoop 3"), @@ -99,6 +107,8 @@ public enum CompilePhase { PHASEIDEALLOOP_ITERATIONS( "PhaseIdealLoop Iterations"), AFTER_LOOP_OPTS( "After Loop Optimizations"), AFTER_MERGE_STORES( "After Merge Stores"), + AFTER_MACRO_ELIMINATION_STEP( "After Macro Elimination Step"), + AFTER_MACRO_ELIMINATION( "After Macro Elimination"), BEFORE_MACRO_EXPANSION( "Before Macro Expansion"), AFTER_MACRO_EXPANSION_STEP( "After Macro Expansion Step"), AFTER_MACRO_EXPANSION( "After Macro Expansion"), diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index ec6fb7d8a23..cc105a52d45 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -100,11 +100,11 @@ public class IRNode { private static final String POSTFIX = "#_"; - private static final String START = "(\\d+(\\s){2}("; - private static final String MID = ".*)+(\\s){2}===.*"; - private static final String END = ")"; - private static final String STORE_OF_CLASS_POSTFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*" + END; - private static final String LOAD_OF_CLASS_POSTFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*" + END; + public static final String START = "(\\d+(\\s){2}("; + public static final String MID = ".*)+(\\s){2}===.*"; + public static final String END = ")"; + public static final String STORE_OF_CLASS_POSTFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*" + END; + public static final String LOAD_OF_CLASS_POSTFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*" + END; public static final String IS_REPLACED = "#IS_REPLACED#"; // Is replaced by an additional user-defined string. diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java index bf3021a6868..b86ae47e186 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/checkattribute/parsing/RawIRNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,6 +30,8 @@ import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo; import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException; +import java.util.regex.Matcher; + /** * This class represents a "raw IR node" as read from a check attribute. It has a node part that either represents an * {@link IRNode} placeholder string or a user defined regex. In the former case, we could additionally have a user @@ -62,7 +64,7 @@ public String regex(CompilePhase compilePhase, VMInfo vmInfo, Comparison.Bound b if (IRNode.isVectorIRNode(node)) { nodeRegex = regexForVectorIRNode(nodeRegex, vmInfo, bound); } else if (userPostfix.isValid()) { - nodeRegex = nodeRegex.replaceAll(IRNode.IS_REPLACED, userPostfix.value()); + nodeRegex = nodeRegex.replaceAll(IRNode.IS_REPLACED, Matcher.quoteReplacement(userPostfix.value())); } } return nodeRegex; diff --git a/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java b/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java index 4165e6285b6..1f861f301e3 100644 --- a/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java +++ b/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -26,9 +26,6 @@ * @bug 8337660 * @summary Test that C2 does not remove blocks with BoxLock nodes that are * otherwise empty. - * @run main/othervm -Xbatch -XX:LockingMode=1 - * -XX:CompileOnly=compiler.locks.TestSynchronizeWithEmptyBlock::* - * compiler.locks.TestSynchronizeWithEmptyBlock * @run main/othervm -Xbatch * -XX:CompileOnly=compiler.locks.TestSynchronizeWithEmptyBlock::* * compiler.locks.TestSynchronizeWithEmptyBlock diff --git a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java index 76953bfb124..3bcd60ed50c 100644 --- a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java +++ b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java @@ -29,17 +29,21 @@ * * @requires vm.flagless * @requires os.arch=="aarch64" + * @requires vm.debug * * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 nop 7 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 isb 3 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 yield 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 sb 1 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 nop 7 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 isb 3 - * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 yield + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 yield 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 sb 1 */ package compiler.onSpinWait; +import java.util.Arrays; import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; @@ -47,16 +51,16 @@ import jdk.test.lib.process.ProcessTools; public class TestOnSpinWaitAArch64 { + public static void main(String[] args) throws Exception { String compiler = args[0]; String spinWaitInst = args[1]; - String spinWaitInstCount = (args.length == 3) ? args[2] : "1"; + String spinWaitInstCount = args[2]; ArrayList command = new ArrayList(); command.add("-XX:+IgnoreUnrecognizedVMOptions"); command.add("-showversion"); command.add("-XX:-BackgroundCompilation"); command.add("-XX:+UnlockDiagnosticVMOptions"); - command.add("-XX:+PrintAssembly"); if (compiler.equals("c2")) { command.add("-XX:-TieredCompilation"); } else if (compiler.equals("c1")) { @@ -69,12 +73,18 @@ public static void main(String[] args) throws Exception { command.add("-XX:OnSpinWaitInst=" + spinWaitInst); command.add("-XX:OnSpinWaitInstCount=" + spinWaitInstCount); command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test"); + command.add("-XX:CompileCommand=print," + Launcher.class.getName() + "::" + "test"); command.add(Launcher.class.getName()); ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + if ("sb".equals(spinWaitInst) && analyzer.contains("CPU does not support SB")) { + System.out.println("Skipping the test. The current CPU does not support SB instruction."); + return; + } + analyzer.shouldHaveExitValue(0); System.out.println(analyzer.getOutput()); @@ -84,123 +94,85 @@ public static void main(String[] args) throws Exception { private static String getSpinWaitInstHex(String spinWaitInst) { if ("nop".equals(spinWaitInst)) { - return "1f20 03d5"; + return "1f2003d5"; } else if ("isb".equals(spinWaitInst)) { - return "df3f 03d5"; + return "df3f03d5"; } else if ("yield".equals(spinWaitInst)) { - return "3f20 03d5"; + return "3f2003d5"; + } else if ("sb".equals(spinWaitInst)) { + return "ff3003d5"; } else { throw new RuntimeException("Unknown spin wait instruction: " + spinWaitInst); } } - private static void addInstrs(String line, ArrayList instrs) { - for (String instr : line.split("\\|")) { - instrs.add(instr.trim()); - } - } - - // The expected output of PrintAssembly for example for a spin wait with three NOPs: - // - // # {method} {0x0000ffff6ac00370} 'test' '()V' in 'compiler/onSpinWait/TestOnSpinWaitAArch64$Launcher' - // # [sp+0x40] (sp of caller) - // 0x0000ffff9d557680: 1f20 03d5 | e953 40d1 | 3f01 00f9 | ff03 01d1 | fd7b 03a9 | 1f20 03d5 | 1f20 03d5 - // - // 0x0000ffff9d5576ac: ;*invokestatic onSpinWait {reexecute=0 rethrow=0 return_oop=0} - // ; - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0 (line 161) - // 0x0000ffff9d5576ac: 1f20 03d5 | fd7b 43a9 | ff03 0191 + // The expected output for a spin wait with three NOPs + // if the hsdis library is available: // - // The checkOutput method adds hex instructions before 'invokestatic onSpinWait' and from the line after - // it to a list. The list is traversed from the end to count spin wait instructions. + // ;; spin_wait { + // 0x0000000111dfa58c: nop + // 0x0000000111dfa590: nop + // 0x0000000111dfa594: nop + // ;; } // - // If JVM finds the hsdis library the output is like: - // - // # {method} {0x0000ffff63000370} 'test' '()V' in 'compiler/onSpinWait/TestOnSpinWaitAArch64$Launcher' - // # [sp+0x20] (sp of caller) - // 0x0000ffffa409da80: nop - // 0x0000ffffa409da84: sub sp, sp, #0x20 - // 0x0000ffffa409da88: stp x29, x30, [sp, #16] ;*synchronization entry - // ; - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@-1 (line 187) - // 0x0000ffffa409da8c: nop - // 0x0000ffffa409da90: nop - // 0x0000ffffa409da94: nop - // 0x0000ffffa409da98: nop - // 0x0000ffffa409da9c: nop - // 0x0000ffffa409daa0: nop - // 0x0000ffffa409daa4: nop ;*invokestatic onSpinWait {reexecute=0 rethrow=0 return_oop=0} - // ; - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0 (line 187) - private static void checkOutput(OutputAnalyzer output, String spinWaitInst, int spinWaitInstCount) { + private static void checkOutput(OutputAnalyzer output, final String spinWaitInst, final int expectedCount) { Iterator iter = output.asLines().listIterator(); - String match = skipTo(iter, "'test' '()V' in 'compiler/onSpinWait/TestOnSpinWaitAArch64$Launcher'"); - if (match == null) { - throw new RuntimeException("Missing compiler output for the method compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test"); - } - - ArrayList instrs = new ArrayList(); - String line = null; - boolean hasHexInstInOutput = false; + // 1. Check whether printed instructions are disassembled + boolean isDisassembled = false; while (iter.hasNext()) { - line = iter.next(); - if (line.contains("*invokestatic onSpinWait")) { + String line = iter.next(); + if (line.contains("[Disassembly]")) { + isDisassembled = true; break; } - if (!hasHexInstInOutput) { - hasHexInstInOutput = line.contains("|"); - } - if (line.contains("0x") && !line.contains(";")) { - addInstrs(line, instrs); - } - } - - if (!iter.hasNext() || !iter.next().contains("- compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0") || !iter.hasNext()) { - throw new RuntimeException("Missing compiler output for Thread.onSpinWait intrinsic"); - } - - String strToSearch = null; - if (!hasHexInstInOutput) { - instrs.add(line.split(";")[0].trim()); - strToSearch = spinWaitInst; - } else { - line = iter.next(); - if (!line.contains("0x") || line.contains(";")) { - throw new RuntimeException("Expected hex instructions"); - } - - addInstrs(line, instrs); - strToSearch = getSpinWaitInstHex(spinWaitInst); - } - - int foundInstCount = 0; - - ListIterator instrReverseIter = instrs.listIterator(instrs.size()); - while (instrReverseIter.hasPrevious()) { - if (instrReverseIter.previous().endsWith(strToSearch)) { - foundInstCount = 1; + if (line.contains("[MachCode]")) { break; } } - while (instrReverseIter.hasPrevious()) { - if (!instrReverseIter.previous().endsWith(strToSearch)) { + // 2. Look for the block comment + boolean foundHead = false; + while (iter.hasNext()) { + String line = iter.next().trim(); + if (line.contains(";; spin_wait {")) { + foundHead = true; break; } - ++foundInstCount; } - - if (foundInstCount != spinWaitInstCount) { - throw new RuntimeException("Wrong instruction " + strToSearch + " count " + foundInstCount + "!\n -- expecting " + spinWaitInstCount); + if (!foundHead) { + throw new RuntimeException("Block comment not found"); } - } - private static String skipTo(Iterator iter, String substring) { + // 3. Count spin wait instructions + final String expectedInst = isDisassembled ? spinWaitInst : getSpinWaitInstHex(spinWaitInst); + int foundCount = 0; while (iter.hasNext()) { - String nextLine = iter.next(); - if (nextLine.contains(substring)) { - return nextLine; + String line = iter.next().trim(); + if (line.startsWith(";; }")) { + break; + } + if (!line.startsWith("0x")) { + continue; } + int pos = line.indexOf(':'); + if (pos == -1 || pos == line.length() - 1) { + continue; + } + line = line.substring(pos + 1).replaceAll("\\s", ""); + if (line.startsWith(";")) { + continue; + } + // When code is disassembled, we have one instruction per line. + // Otherwise, there can be multiple hex instructions separated by '|'. + foundCount += (int)Arrays.stream(line.split("\\|")) + .takeWhile(i -> i.startsWith(expectedInst)) + .count(); + } + + if (foundCount != expectedCount) { + throw new RuntimeException("Expected " + expectedCount + " " + spinWaitInst + " instructions. Found: " + foundCount); } - return null; } static class Launcher { diff --git a/test/hotspot/jtreg/compiler/predicates/assertion/TestTemplateWithoutOpaqueLoopNodes.java b/test/hotspot/jtreg/compiler/predicates/assertion/TestTemplateWithoutOpaqueLoopNodes.java index 309da03e08c..9dcc6904270 100644 --- a/test/hotspot/jtreg/compiler/predicates/assertion/TestTemplateWithoutOpaqueLoopNodes.java +++ b/test/hotspot/jtreg/compiler/predicates/assertion/TestTemplateWithoutOpaqueLoopNodes.java @@ -24,7 +24,7 @@ /* * @test id=Xcomp * @bug 8333252 - * @summary Test that no Template Assertion Predicate is created in Loop Prediction for one iteration loop. + * @summary Test that no Template Assertion Predicate is created in Loop Prediction for one-iteration loop. * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,*TestTemplateWithoutOpaqueLoopNodes::test * compiler.predicates.assertion.TestTemplateWithoutOpaqueLoopNodes */ @@ -32,7 +32,7 @@ /* * @test id=Xbatch * @bug 8333252 - * @summary Test that no Template Assertion Predicate is created in Loop Prediction for one iteration loop. + * @summary Test that no Template Assertion Predicate is created in Loop Prediction for one-iteration loop. * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*TestTemplateWithoutOpaqueLoopNodes::test * compiler.predicates.assertion.TestTemplateWithoutOpaqueLoopNodes */ diff --git a/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java b/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java index adb5b5d44c7..e3ee65f454d 100644 --- a/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java +++ b/test/hotspot/jtreg/compiler/splitif/TestSplitDivisionThroughPhi.java @@ -140,7 +140,7 @@ static void testPushModLThruPhiForOuterLongLoop() { // the iv phi in one pass of Split If. static void testPushDivIThruPhiInChain() { for (int i = 10; i > 1; i -= 2) { - // Empty one iteration loop which is only removed after split if in first loop opts phase. This prevents + // Empty one-iteration loop which is only removed after split if in first loop opts phase. This prevents // that the Mul node is already split through the iv phi while the Div node cannot be split yet due to // the zero divisor check which can only be removed in the IGVN after the first loop opts pass. for (int j = 0; j < 1; j++) { diff --git a/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java b/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java index a646728b07a..485aed4c032 100644 --- a/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java +++ b/test/hotspot/jtreg/compiler/unsafe/OpaqueAccesses.java @@ -23,32 +23,15 @@ /* * @test - * @bug 8155781 + * @bug 8155781 8359344 * @modules java.base/jdk.internal.misc - * - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:-TieredCompilation -Xbatch - * -XX:+UseCompressedOops -XX:+UseCompressedClassPointers - * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* - * compiler.unsafe.OpaqueAccesses - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:-TieredCompilation -Xbatch - * -XX:+UseCompressedOops -XX:-UseCompressedClassPointers - * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* - * compiler.unsafe.OpaqueAccesses - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:-TieredCompilation -Xbatch - * -XX:-UseCompressedOops -XX:+UseCompressedClassPointers - * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* - * compiler.unsafe.OpaqueAccesses - * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:-TieredCompilation -Xbatch - * -XX:-UseCompressedOops -XX:-UseCompressedClassPointers - * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* - * compiler.unsafe.OpaqueAccesses + * @library /test/lib / + * @run driver compiler.unsafe.OpaqueAccesses */ package compiler.unsafe; +import compiler.lib.ir_framework.*; + import jdk.internal.misc.Unsafe; import java.lang.reflect.Field; @@ -77,74 +60,126 @@ public class OpaqueAccesses { private Object f = new Object(); private long l1, l2; + // To the end of a line, a new line character, repeated. + private static final String FULL_LINES = "(.*\\R)*"; + // Finish the line after the node type, skips full line, and eats until before the node types + private static final String SKIP = IRNode.MID + IRNode.END + "\\R" + FULL_LINES + "\\s*" + IRNode.START; + + private static final String CALL_STATIC_JAVA_AND_THEN_OPAQUE_NOT_NULL = IRNode.START + "CallStaticJava" + SKIP + "OpaqueNotNull" + IRNode.MID + IRNode.END; + private static final String OPAQUE_NOT_NULL_AND_THEN_CALL_STATIC_JAVA = IRNode.START + "OpaqueNotNull" + SKIP + "CallStaticJava" + IRNode.MID + IRNode.END; + /* Having both CallStaticJava and OpaqueNotNull, in any order. We use that in a failOn to make sure we have one + * or the other (or none), but not both. + * The CallStaticJava happens when the call is not intrinsified, and the OpaqueNotNull comes from the intrinsic. + * We don't want a unfinished intrinsic, with the call nevertheless. + */ + private static final String BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL = + "(" + CALL_STATIC_JAVA_AND_THEN_OPAQUE_NOT_NULL + ") | (" + OPAQUE_NOT_NULL_AND_THEN_CALL_STATIC_JAVA + ")"; + + + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testFixedOffsetField(Object o) { return UNSAFE.getReference(o, F_OFFSET); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader0(Object o) { return UNSAFE.getInt(o, 0); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader4(Object o) { return UNSAFE.getInt(o, 4); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader8(Object o) { return UNSAFE.getInt(o, 8); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader12(Object o) { return UNSAFE.getInt(o, 12); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader16(Object o) { return UNSAFE.getInt(o, 16); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeader17(Object o) { return UNSAFE.getIntUnaligned(o, 17); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testFixedBase(long off) { return UNSAFE.getReference(INSTANCE, off); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testOpaque(Object o, long off) { return UNSAFE.getReference(o, off); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray0(Object[] arr) { return UNSAFE.getInt(arr, 0); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray4(Object[] arr) { return UNSAFE.getInt(arr, 4); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray8(Object[] arr) { return UNSAFE.getInt(arr, 8); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray12(Object[] arr) { return UNSAFE.getInt(arr, 12); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray16(Object[] arr) { return UNSAFE.getInt(arr, 16); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static int testFixedOffsetHeaderArray17(Object[] arr) { return UNSAFE.getIntUnaligned(arr, 17); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testFixedOffsetArray(Object[] arr) { return UNSAFE.getReference(arr, E_OFFSET); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testFixedBaseArray(long off) { return UNSAFE.getReference(ARRAY, off); } + @Test + @IR(failOn = {BOTH_CALL_STATIC_JAVA_AND_OPAQUE_NOT_NULL}, phase = CompilePhase.BEFORE_MACRO_EXPANSION) static Object testOpaqueArray(Object[] o, long off) { return UNSAFE.getReference(o, off); } @@ -152,6 +187,7 @@ static Object testOpaqueArray(Object[] o, long off) { static final long ADDR = UNSAFE.allocateMemory(10); static boolean flag; + @Test static int testMixedAccess() { flag = !flag; Object o = (flag ? INSTANCE : null); @@ -159,31 +195,81 @@ static int testMixedAccess() { return UNSAFE.getInt(o, off); } - public static void main(String[] args) { - for (int i = 0; i < 20_000; i++) { - // Instance - testFixedOffsetField(INSTANCE); - testFixedOffsetHeader0(INSTANCE); - testFixedOffsetHeader4(INSTANCE); - testFixedOffsetHeader8(INSTANCE); - testFixedOffsetHeader12(INSTANCE); - testFixedOffsetHeader16(INSTANCE); - testFixedOffsetHeader17(INSTANCE); - testFixedBase(F_OFFSET); - testOpaque(INSTANCE, F_OFFSET); - testMixedAccess(); - - // Array - testFixedOffsetHeaderArray0(ARRAY); - testFixedOffsetHeaderArray4(ARRAY); - testFixedOffsetHeaderArray8(ARRAY); - testFixedOffsetHeaderArray12(ARRAY); - testFixedOffsetHeaderArray16(ARRAY); - testFixedOffsetHeaderArray17(ARRAY); - testFixedOffsetArray(ARRAY); - testFixedBaseArray(E_OFFSET); - testOpaqueArray(ARRAY, E_OFFSET); - } + @Run(test = { + "testFixedOffsetField", + "testFixedOffsetHeader0", + "testFixedOffsetHeader4", + "testFixedOffsetHeader8", + "testFixedOffsetHeader12", + "testFixedOffsetHeader16", + "testFixedOffsetHeader17", + "testFixedBase", + "testOpaque", + "testMixedAccess", + "testFixedOffsetHeaderArray0", + "testFixedOffsetHeaderArray4", + "testFixedOffsetHeaderArray8", + "testFixedOffsetHeaderArray12", + "testFixedOffsetHeaderArray16", + "testFixedOffsetHeaderArray17", + "testFixedOffsetArray", + "testFixedBaseArray", + "testOpaqueArray", + }) + public static void runMethod() { + // Instance + testFixedOffsetField(INSTANCE); + testFixedOffsetHeader0(INSTANCE); + testFixedOffsetHeader4(INSTANCE); + testFixedOffsetHeader8(INSTANCE); + testFixedOffsetHeader12(INSTANCE); + testFixedOffsetHeader16(INSTANCE); + testFixedOffsetHeader17(INSTANCE); + testFixedBase(F_OFFSET); + testOpaque(INSTANCE, F_OFFSET); + testMixedAccess(); + + // Array + testFixedOffsetHeaderArray0(ARRAY); + testFixedOffsetHeaderArray4(ARRAY); + testFixedOffsetHeaderArray8(ARRAY); + testFixedOffsetHeaderArray12(ARRAY); + testFixedOffsetHeaderArray16(ARRAY); + testFixedOffsetHeaderArray17(ARRAY); + testFixedOffsetArray(ARRAY); + testFixedBaseArray(E_OFFSET); + testOpaqueArray(ARRAY, E_OFFSET); System.out.println("TEST PASSED"); } + + public static void main(String[] args) { + TestFramework.runWithFlags( + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-TieredCompilation", "-Xbatch", + "-XX:+UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" + ); + TestFramework.runWithFlags( + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-TieredCompilation", "-Xbatch", + "-XX:+UseCompressedOops", "-XX:-UseCompressedClassPointers", + "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" + ); + TestFramework.runWithFlags( + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-TieredCompilation", "-Xbatch", + "-XX:-UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" + ); + TestFramework.runWithFlags( + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-TieredCompilation", "-Xbatch", + "-XX:-UseCompressedOops", "-XX:-UseCompressedClassPointers", + "-XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*" + ); + } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/RepairStackWithBigFrame.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/RepairStackWithBigFrame.java new file mode 100644 index 00000000000..831b619b82b --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/RepairStackWithBigFrame.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * 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. + */ + +package compiler.valhalla.inlinetypes; + +import static compiler.valhalla.inlinetypes.InlineTypes.*; + +/* + * @test + * @bug 8367156 + * @summary On Aarch64, when the frame is very big and we need to repair it after + * scalarization of the arguments, we cannot use ldp to get the stack + * increment and rfp at the same time, since it only has a 7 bit offset. + * We use two ldr with 9-bit offsets instead. + * @library /test/lib / + * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") + * @enablePreview + * @modules java.base/jdk.internal.vm.annotation + * @run main/othervm + * -Xcomp + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.RepairStackWithBigFrame::test + * compiler.valhalla.inlinetypes.RepairStackWithBigFrame + * @run main compiler.valhalla.inlinetypes.RepairStackWithBigFrame + */ + +public class RepairStackWithBigFrame { + static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL); + + public static void main(String[] args) { + new RepairStackWithBigFrame().test(testValue1); + } + + long test(MyValue1 arg) { + MyAbstract vt1 = MyValue1.createWithFieldsInline(rI, rL); + MyAbstract vt2 = MyValue1.createWithFieldsDontInline(rI, rL); + MyAbstract vt3 = MyValue1.createWithFieldsInline(rI, rL); + MyAbstract vt4 = arg; + return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() + + ((MyValue1)vt3).hash() + ((MyValue1)vt4).hash(); + } +} diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java index 22f5b4358b8..8ff49059dd8 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java @@ -27,7 +27,7 @@ * @summary Verify that TLAB allocated buffer initialization when returning a value object works properly with oops. * @library /test/lib * @enablePreview - * @run main/othervm -XX:CompileCommand=exclude,compiler.valhalla.inlinetypes.TestStressReturnBuffering::caller -Xmx4m + * @run main/othervm -XX:CompileCommand=exclude,compiler.valhalla.inlinetypes.TestStressReturnBuffering::caller -Xmx6m * compiler.valhalla.inlinetypes.TestStressReturnBuffering */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestVirtualThreads.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestVirtualThreads.java new file mode 100644 index 00000000000..06078f0c913 --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestVirtualThreads.java @@ -0,0 +1,686 @@ +/* + * 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. + * + * 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 + * @key randomness + * @summary Test that Virtual Threads work well with Value Objects. + * @library /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * TestVirtualThreads + * + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=compileonly,TestVirtualThreads*::* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=compileonly,TestVirtualThreads*::test* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=dontinline,*::test* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=dontinline,*::*Helper + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=exclude,*::*Helper + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=compileonly,TestVirtualThreads*::* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=compileonly,TestVirtualThreads*::test* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=dontinline,*::test* + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=dontinline,*::*Helper + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=dontinline,*::dontinline -XX:CompileCommand=compileonly,TestVirtualThreads*::test* -XX:CompileCommand=exclude,*::*Helper + * TestVirtualThreads + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:CompileCommand=dontinline,*::* -XX:CompileCommand=compileonly,TestVirtualThreads*::* + * TestVirtualThreads 250000 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xcomp -XX:CompileCommand=dontinline,*::* -XX:CompileCommand=compileonly,TestVirtualThreads*::* + * TestVirtualThreads 250000 + **/ + +import java.lang.reflect.Method; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.CountDownLatch; +import java.util.Random; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; +import jdk.test.whitebox.WhiteBox; + +public class TestVirtualThreads { + static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + static final int COMP_LEVEL_SIMPLE = 1; // C1 + static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; // C2 or JVMCI + static final Random RAND = Utils.getRandomInstance(); + static final int PARK_DURATION = 10; + + static value class SmallValue { + int x1; + int x2; + + public SmallValue(int i) { + this.x1 = i; + this.x2 = i; + } + + public String toString() { + return "x1 = " + x1 + ", x2 = " + x2; + } + + public void verify(String loc, int i) { + if (x1 != i || x2 != i) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this); + } + } + + public static void verify(SmallValue val, String loc, int i, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + val); + } + } else { + val.verify(loc, i); + } + } + } + + // Large value class + static value class LargeValue { + int x1; + int x2; + int x3; + int x4; + int x5; + int x6; + int x7; + + public LargeValue(int i) { + this.x1 = i; + this.x2 = i; + this.x3 = i; + this.x4 = i; + this.x5 = i; + this.x6 = i; + this.x7 = i; + } + + public String toString() { + return "x1 = " + x1 + ", x2 = " + x2 + ", x3 = " + x3 + ", x4 = " + x4 + ", x5 = " + x5 + + ", x6 = " + x6 + ", x7 = " + x7; + } + + public void verify(String loc, int i) { + if (x1 != i || x2 != i || x3 != i || x4 != i || x5 != i || + x6 != i || x7 != i) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this); + } + } + + public static void verify(LargeValue val, String loc, int i, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + val); + } + } else { + val.verify(loc, i); + } + } + } + + // Large value class with fields of different types + static value class LargeValue2 { + byte x1; + short x2; + int x3; + long x4; + double x5; + boolean x6; + + public LargeValue2(int i) { + this.x1 = (byte)i; + this.x2 = (short)i; + this.x3 = i; + this.x4 = i; + this.x5 = i; + this.x6 = (i % 2) == 0; + } + + public String toString() { + return "x1 = " + x1 + ", x2 = " + x2 + ", x3 = " + x3 + ", x4 = " + x4 + ", x5 = " + x5 + + ", x6 = " + x6; + } + + public void verify(String loc, int i) { + if (x1 != (byte)i || x2 != (short)i || x3 != i || x4 != i || x5 != i || + x6 != ((i % 2) == 0)) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this); + } + } + + public static void verify(LargeValue2 val, String loc, int i, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + val); + } + } else { + val.verify(loc, i); + } + } + } + + // Large value class with oops (and different number of fields) that requires stack extension/repair + static value class LargeValueWithOops { + Object x1; + Object x2; + Object x3; + Object x4; + Object x5; + + public LargeValueWithOops(Object obj) { + this.x1 = obj; + this.x2 = obj; + this.x3 = obj; + this.x4 = obj; + this.x5 = obj; + } + + public String toString() { + return "x1 = " + x1 + ", x2 = " + x2 + ", x3 = " + x3 + ", x4 = " + x4 + ", x5 = " + x5; + } + + public void verify(String loc, Object obj) { + if (x1 != obj || x2 != obj || x3 != obj || x4 != obj || x5 != obj) { + throw new RuntimeException("Incorrect result at " + loc + " for obj = " + obj + ": " + this); + } + } + + public static void verify(LargeValueWithOops val, String loc, Object obj, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for obj = " + obj + ": " + val); + } + } else { + val.verify(loc, obj); + } + } + } + + public static value class DoubleValue { + double d; + + public DoubleValue(double d) { + this.d = d; + } + + public String toString() { + return "d = " + d; + } + + public void verify(String loc, double d) { + if (this.d != d) { + throw new RuntimeException("Incorrect result at " + loc + " for d = " + d + ": " + this); + } + } + + public static void verify(DoubleValue val, String loc, double d, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for d = " + d+ ": " + val); + } + } else { + val.verify(loc, d); + } + } + } + + public static value class DoubleValue2 { + double d1; + double d2; + double d3; + double d4; + double d5; + + public DoubleValue2(double d) { + this.d1 = d; + this.d2 = d + 1; + this.d3 = d + 2; + this.d4 = d + 3; + this.d5 = d + 4; + } + + public String toString() { + return "d1 = " + d1 + ", d2 = " + d2 + ", d3 = " + d3 + ", d4= " + d4 + ", d5= " + d5; + } + + public void verify(String loc, double d) { + if (this.d1 != d || this.d2 != (d+1) || this.d3 != (d+2) || this.d4 != (d+3) || this.d5 != (d+4)) { + throw new RuntimeException("Incorrect result at " + loc + " for d = " + d + ": " + this); + } + } + + public static void verify(DoubleValue2 val, String loc, double d, boolean useNull) { + if (useNull) { + if (val != null) { + throw new RuntimeException("Incorrect result at " + loc + " for d = " + d + ": " + val); + } + } else { + val.verify(loc, d); + } + } + } + + static abstract value class BaseValue { + public abstract void verify(String loc, int i); + }; + + static value class ValueExtendsAbstract extends BaseValue { + int x1; + int x2; + int x3; + int x4; + int x5; + int x6; + int x7; + + public ValueExtendsAbstract(int i) { + this.x1 = i; + this.x2 = i; + this.x3 = i; + this.x4 = i; + this.x5 = i; + this.x6 = i; + this.x7 = i; + } + + public String toString() { + return "x1 = " + x1 + ", x2 = " + x2 + ", x3 = " + x3 + ", x4 = " + x4 + ", x5 = " + x5 + + ", x6 = " + x6 + ", x7 = " + x7; + } + + public void verify(String loc, int i) { + if (x1 != i || x2 != i || x3 != i || x4 != i || x5 != i || + x6 != i || x7 != i) { + throw new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this); + } + } + } + + public static void dontInline() { } + + public static SmallValue testSmall(SmallValue val, int i, boolean useNull, boolean park) { + SmallValue.verify(val, "entry", i, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + SmallValue.verify(val, "exit", i, useNull); + return val; + } + + public static SmallValue testSmallHelper(int i, boolean useNull, boolean park) { + SmallValue val = useNull ? null : new SmallValue(i); + val = testSmall(val, i, useNull, park); + SmallValue.verify(val, "helper", i, useNull); + return val; + } + + public static LargeValue testLarge(LargeValue val, int i, boolean useNull, boolean park) { + LargeValue.verify(val, "entry", i, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValue.verify(val, "exit", i, useNull); + return val; + } + + public static LargeValue testLargeHelper(int i, boolean useNull, boolean park) { + LargeValue val = useNull ? null : new LargeValue(i); + val = testLarge(val, i, useNull, park); + LargeValue.verify(val, "helper", i, useNull); + return val; + } + + // Version that already has values on the stack even before stack extensions + public static LargeValue testLargeManyArgs(LargeValue val1, LargeValue val2, LargeValue val3, LargeValue val4, int i, boolean useNull, boolean park) { + LargeValue.verify(val1, "entry", i, useNull); + LargeValue.verify(val2, "entry", i + 1, useNull); + LargeValue.verify(val3, "entry", i + 2, useNull); + LargeValue.verify(val4, "entry", i + 3, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValue.verify(val1, "exit", i, useNull); + LargeValue.verify(val2, "exit", i + 1, useNull); + LargeValue.verify(val3, "exit", i + 2, useNull); + LargeValue.verify(val4, "exit", i + 3, useNull); + return val4; + } + + public static LargeValue testLargeManyArgsHelper(int i, boolean useNull, boolean park) { + LargeValue val1 = useNull ? null : new LargeValue(i); + LargeValue val2 = useNull ? null : new LargeValue(i + 1); + LargeValue val3 = useNull ? null : new LargeValue(i + 2); + LargeValue val4 = useNull ? null : new LargeValue(i + 3); + LargeValue val = testLargeManyArgs(val1, val2, val3, val4, i, useNull, park); + LargeValue.verify(val, "helper", i + 3, useNull); + return val; + } + + public static LargeValue2 testLarge2(LargeValue2 val, int i, boolean useNull, boolean park) { + LargeValue2.verify(val, "entry", i, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValue2.verify(val, "exit", i, useNull); + return val; + } + + public static LargeValue2 testLarge2Helper(int i, boolean useNull, boolean park) { + LargeValue2 val = useNull ? null : new LargeValue2(i); + val = testLarge2(val, i, useNull, park); + LargeValue2.verify(val, "helper", i, useNull); + return val; + } + + // Version that already has values on the stack even before stack extensions + public static LargeValue2 testLarge2ManyArgs(LargeValue2 val1, LargeValue2 val2, LargeValue2 val3, LargeValue2 val4, int i, boolean useNull, boolean park) { + LargeValue2.verify(val1, "entry", i, useNull); + LargeValue2.verify(val2, "entry", i + 1, useNull); + LargeValue2.verify(val3, "entry", i + 2, useNull); + LargeValue2.verify(val4, "entry", i + 3, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValue2.verify(val1, "exit", i, useNull); + LargeValue2.verify(val2, "exit", i + 1, useNull); + LargeValue2.verify(val3, "exit", i + 2, useNull); + LargeValue2.verify(val4, "exit", i + 3, useNull); + return val4; + } + + public static LargeValue2 testLarge2ManyArgsHelper(int i, boolean useNull, boolean park) { + LargeValue2 val1 = useNull ? null : new LargeValue2(i); + LargeValue2 val2 = useNull ? null : new LargeValue2(i + 1); + LargeValue2 val3 = useNull ? null : new LargeValue2(i + 2); + LargeValue2 val4 = useNull ? null : new LargeValue2(i + 3); + LargeValue2 val = testLarge2ManyArgs(val1, val2, val3, val4, i, useNull, park); + return val; + } + + public static ValueExtendsAbstract testExtendsAbstractHelper(int i, boolean park) { + ValueExtendsAbstract val1 = new ValueExtendsAbstract(i); + ValueExtendsAbstract val2 = new ValueExtendsAbstract(i + 1); + ValueExtendsAbstract val3 = new ValueExtendsAbstract(i + 2); + ValueExtendsAbstract val4 = new ValueExtendsAbstract(i + 3); + + val1.verify("entry", i); + val2.verify("entry", i + 1); + val3.verify("entry", i + 2); + val4.verify("entry", i + 3); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + val1.verify("exit", i); + val2.verify("exit", i + 1); + val3.verify("exit", i + 2); + val4.verify("exit", i + 3); + return val4; + } + + public static LargeValueWithOops testLargeValueWithOops(LargeValueWithOops val, Object obj, boolean useNull, boolean park) { + LargeValueWithOops.verify(val, "entry", obj, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValueWithOops.verify(val, "exit", obj, useNull); + return val; + } + + public static LargeValueWithOops testLargeValueWithOopsHelper(Object obj, boolean useNull, boolean park) { + LargeValueWithOops val = useNull ? null : new LargeValueWithOops(obj); + val = testLargeValueWithOops(val, obj, useNull, park); + LargeValueWithOops.verify(val, "helper", obj, useNull); + return val; + } + + // Version that already has values on the stack even before stack extensions + public static LargeValueWithOops testLargeValueWithOops2(LargeValueWithOops val1, LargeValueWithOops val2, LargeValueWithOops val3, LargeValueWithOops val4, LargeValueWithOops val5, Object obj, boolean useNull, boolean park) { + LargeValueWithOops.verify(val1, "entry", obj, useNull); + LargeValueWithOops.verify(val2, "entry", obj, useNull); + LargeValueWithOops.verify(val3, "entry", obj, useNull); + LargeValueWithOops.verify(val4, "entry", obj, useNull); + LargeValueWithOops.verify(val5, "entry", obj, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + dontInline(); // Prevent C2 from optimizing out below checks + LargeValueWithOops.verify(val1, "exit", obj, useNull); + LargeValueWithOops.verify(val2, "exit", obj, useNull); + LargeValueWithOops.verify(val3, "exit", obj, useNull); + LargeValueWithOops.verify(val4, "exit", obj, useNull); + LargeValueWithOops.verify(val5, "exit", obj, useNull); + return val5; + } + + public static LargeValueWithOops testLargeValueWithOops2Helper(Object obj, boolean useNull, boolean park) { + LargeValueWithOops val1 = useNull ? null : new LargeValueWithOops(obj); + LargeValueWithOops val2 = useNull ? null : new LargeValueWithOops(obj); + LargeValueWithOops val3 = useNull ? null : new LargeValueWithOops(obj); + LargeValueWithOops val4 = useNull ? null : new LargeValueWithOops(obj); + LargeValueWithOops val5 = useNull ? null : new LargeValueWithOops(obj); + LargeValueWithOops val = testLargeValueWithOops2(val1, val2, val3, val4, val5, obj, useNull, park); + LargeValueWithOops.verify(val, "helper", obj, useNull); + return val; + } + + // Pass via fields to not affect number of arguments + static double testDoubleValueDP; + static boolean testDoubleValueUseNullP; + static boolean testDoubleValueParkP; + static double testDoubleValueDV; + static boolean testDoubleValueUseNullV; + static boolean testDoubleValueParkV; + + // This method needs less stack space when scalarized because (some of) the arguments can then be passed in floating point registers + public static DoubleValue testDoubleValue(DoubleValue val1, DoubleValue val2, DoubleValue val3, DoubleValue val4, DoubleValue val5, DoubleValue val6, DoubleValue val7) { + boolean isVirtual = Thread.currentThread().isVirtual(); + double d = isVirtual ? testDoubleValueDV : testDoubleValueDP; + boolean useNull = isVirtual ? testDoubleValueUseNullV : testDoubleValueUseNullP; + boolean park = isVirtual ? testDoubleValueParkV : testDoubleValueParkP; + + DoubleValue.verify(val1, "entry", d, useNull); + DoubleValue.verify(val2, "entry", d + 1, useNull); + DoubleValue.verify(val3, "entry", d + 2, useNull); + DoubleValue.verify(val4, "entry", d + 3, useNull); + DoubleValue.verify(val5, "entry", d + 4, useNull); + DoubleValue.verify(val6, "entry", d + 4, useNull); + DoubleValue.verify(val7, "entry", d + 4, useNull); + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + DoubleValue.verify(val1, "exit", d, useNull); + DoubleValue.verify(val2, "exit", d + 1, useNull); + DoubleValue.verify(val3, "exit", d + 2, useNull); + DoubleValue.verify(val4, "exit", d + 3, useNull); + DoubleValue.verify(val5, "exit", d + 4, useNull); + DoubleValue.verify(val6, "exit", d + 4, useNull); + DoubleValue.verify(val7, "exit", d + 4, useNull); + return val1; + } + + public static DoubleValue testDoubleValueHelper(double d, boolean useNull, boolean park) { + if (Thread.currentThread().isVirtual()) { + testDoubleValueDV = d; + testDoubleValueUseNullV = useNull; + testDoubleValueParkV = park; + } else { + testDoubleValueDP = d; + testDoubleValueUseNullP = useNull; + testDoubleValueParkP = park; + } + + DoubleValue val1 = useNull ? null : new DoubleValue(d); + DoubleValue val2 = useNull ? null : new DoubleValue(d + 1); + DoubleValue val3 = useNull ? null : new DoubleValue(d + 2); + DoubleValue val4 = useNull ? null : new DoubleValue(d + 3); + DoubleValue val5 = useNull ? null : new DoubleValue(d + 4); + DoubleValue val6 = useNull ? null : new DoubleValue(d + 4); + DoubleValue val7 = useNull ? null : new DoubleValue(d + 4); + val1 = testDoubleValue(val1, val2, val3, val4, val5, val6, val7); + DoubleValue.verify(val1, "helper", d, useNull); + return val1; + } + + public static DoubleValue2 recurseTestDoubleValue2(double d, boolean useNull, boolean park, int depth) { + if (depth > 0) { + DoubleValue2 val = recurseTestDoubleValue2(d, useNull, park, depth - 1); + DoubleValue2.verify(val, "entry", d, useNull); + dontInline(); // Prevent C2 from optimizing out below checks + DoubleValue2.verify(val, "exit", d, useNull); + return val; + } else { + if (park) { + LockSupport.parkNanos(PARK_DURATION); + } + return useNull ? null : new DoubleValue2(d); + } + } + + public static DoubleValue2 testDoubleValue2Helper(double d, boolean useNull, boolean park) { + DoubleValue2 val = recurseTestDoubleValue2(d, useNull, park, 4); + DoubleValue2.verify(val, "helper", d, useNull); + return val; + } + + static class GarbageProducerThread extends Thread { + public void run() { + for (;;) { + // Produce some garbage and then let the GC do its work + Object[] arrays = new Object[1024]; + for (int i = 0; i < arrays.length; i++) { + arrays[i] = new int[1024]; + } + System.gc(); + } + } + } + + public static void startTest(CountDownLatch cdl, Thread.Builder builder, int iterations) { + builder.start(() -> { + try { + // Trigger compilation + boolean isVirtual = Thread.currentThread().isVirtual(); + for (int i = 0; i < iterations; i++) { + boolean park = (i % 1000) == 0; + boolean useNull = RAND.nextBoolean(); + Object val = useNull ? null : new SmallValue(i); + SmallValue.verify(testSmallHelper(i, useNull, park), "return", i, useNull); + LargeValue.verify(testLargeHelper(i, useNull, park), "return", i, useNull); + LargeValue.verify(testLargeManyArgsHelper(i, useNull, park), "return", i + 3, useNull); + LargeValue2.verify(testLarge2Helper(i, useNull, park), "return", i, useNull); + LargeValue2.verify(testLarge2ManyArgsHelper(i, useNull, park), "return", i + 3, useNull); + testExtendsAbstractHelper(i, park).verify("return", i + 3); + LargeValueWithOops.verify(testLargeValueWithOopsHelper(val, useNull, park), "return", val, useNull); + LargeValueWithOops.verify(testLargeValueWithOops2Helper(val, useNull, park), "return", val, useNull); + DoubleValue.verify(testDoubleValueHelper(i, useNull, park), "return", i, useNull); + DoubleValue2.verify(testDoubleValue2Helper(i, useNull, park), "return", i, useNull); + if (i % 1000 == 0) { + System.out.format("%s => %s %d of %d%n", Instant.now(), isVirtual ? "Virtual: " : "Platform:", i, iterations); + } + } + cdl.countDown(); + } catch (Exception e) { + System.out.println("Exception thrown: " + e); + e.printStackTrace(System.out); + System.exit(1); + } + }); + } + + public static void main(String[] args) throws Exception { + // Sometimes, exclude some methods from compilation with C1 and/or C2 to stress test the calling convention + if (Utils.getRandomInstance().nextBoolean()) { + ArrayList methods = new ArrayList(); + Collections.addAll(methods, SmallValue.class.getDeclaredMethods()); + Collections.addAll(methods, LargeValue.class.getDeclaredMethods()); + Collections.addAll(methods, LargeValue2.class.getDeclaredMethods()); + Collections.addAll(methods, LargeValueWithOops.class.getDeclaredMethods()); + Collections.addAll(methods, DoubleValue.class.getDeclaredMethods()); + Collections.addAll(methods, TestVirtualThreads.class.getDeclaredMethods()); + System.out.println("Excluding methods from C1 compilation:"); + for (Method m : methods) { + if (Utils.getRandomInstance().nextBoolean()) { + System.out.println(m); + WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_SIMPLE, false); + } + } + System.out.println("Excluding methods from C2 compilation:"); + for (Method m : methods) { + if (Utils.getRandomInstance().nextBoolean()) { + System.out.println(m); + WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_FULL_OPTIMIZATION, false); + } + } + } + + // Start another thread that does some allocations and calls System.gc() + // to trigger GCs while virtual threads are parked. + Thread garbage_producer = new GarbageProducerThread(); + garbage_producer.setDaemon(true); + garbage_producer.start(); + + int iterations = args.length > 0 ? Integer.parseInt(args[0]) : 300_000; + if (Platform.isDebugBuild()) { + iterations /= 4; + } + CountDownLatch cdlPlatform = new CountDownLatch(1); + CountDownLatch cdlVirtual = new CountDownLatch(1); + startTest(cdlPlatform, Thread.ofPlatform(), iterations); + startTest(cdlVirtual, Thread.ofVirtual(), iterations); + cdlPlatform.await(); + cdlVirtual.await(); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java index 6cdd3754c09..fac829c82e4 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java @@ -127,11 +127,17 @@ public class TestCastMethods { // from S 64 // to X 64 makePair(SSPEC64, BSPEC64), + makePair(SSPEC64, ISPEC64), + makePair(SSPEC64, ISPEC64, true), + makePair(SSPEC64, FSPEC64), // to X 128 makePair(SSPEC64, BSPEC128), makePair(SSPEC64, ISPEC128), makePair(SSPEC64, ISPEC128, true), + makePair(SSPEC64, LSPEC128), + makePair(SSPEC64, LSPEC128, true), makePair(SSPEC64, FSPEC128), + makePair(SSPEC64, DSPEC128), // to X 256 makePair(SSPEC64, BSPEC256), makePair(SSPEC64, ISPEC256), @@ -156,7 +162,10 @@ public class TestCastMethods { makePair(SSPEC128, BSPEC128), makePair(SSPEC128, ISPEC128), makePair(SSPEC128, ISPEC128, true), + makePair(SSPEC128, LSPEC128), + makePair(SSPEC128, LSPEC128, true), makePair(SSPEC128, FSPEC128), + makePair(SSPEC128, DSPEC128), // to X 256 makePair(SSPEC128, BSPEC256), makePair(SSPEC128, ISPEC256), @@ -228,6 +237,7 @@ public class TestCastMethods { // ====== from I ====== // from I 64 // to X 64 + makePair(ISPEC64, SSPEC64), makePair(ISPEC64, FSPEC64), // to X 128 makePair(ISPEC64, LSPEC128), @@ -299,10 +309,12 @@ public class TestCastMethods { // ====== from L ====== // from L 128 // to X 64 + makePair(LSPEC128, SSPEC64), makePair(LSPEC128, ISPEC64), makePair(LSPEC128, FSPEC64), makePair(LSPEC128, DSPEC64), // to X 128 + makePair(LSPEC128, SSPEC128), makePair(LSPEC128, ISPEC128), makePair(LSPEC128, FSPEC128), makePair(LSPEC128, DSPEC128), @@ -369,6 +381,7 @@ public class TestCastMethods { // ====== from F ====== // from F 64 // to X 64 + makePair(FSPEC64, SSPEC64), makePair(FSPEC64, ISPEC64), // to X 128 makePair(FSPEC64, ISPEC128), @@ -433,10 +446,12 @@ public class TestCastMethods { // ====== from D ====== // from D 128 // to X 64 + makePair(DSPEC128, SSPEC64), makePair(DSPEC128, ISPEC64), makePair(DSPEC128, LSPEC64), makePair(DSPEC128, FSPEC64), // to X 128 + makePair(DSPEC128, SSPEC128), makePair(DSPEC128, ISPEC128), makePair(DSPEC128, LSPEC128), makePair(DSPEC128, FSPEC128), diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java index a0622d665b8..9c342574632 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java @@ -37,6 +37,7 @@ import jdk.incubator.vector.Float16; import static jdk.incubator.vector.Float16.*; import static java.lang.Float.*; +import java.util.Arrays; import jdk.test.lib.*; import compiler.lib.generators.Generator; import static compiler.lib.generators.Generators.G; @@ -46,9 +47,11 @@ public class TestFloat16VectorOperations { private short[] input2; private short[] input3; private short[] output; - private static short SCALAR_FP16 = (short)0x7777; + private static short FP16_SCALAR = (short)0x7777; private static final int LEN = 2048; + private static final Float16 FP16_CONST = Float16.valueOf(1023.0f); + public static void main(String args[]) { // Test with default MaxVectorSize TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); @@ -60,10 +63,14 @@ public static void main(String args[]) { TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=64"); } - public static boolean assertResults(short expected, short actual) { - Float16 expected_fp16 = shortBitsToFloat16(expected); - Float16 actual_fp16 = shortBitsToFloat16(actual); - return !expected_fp16.equals(actual_fp16); + public static void assertResults(int arity, short ... values) { + assert values.length == (arity + 2); + Float16 expected_fp16 = shortBitsToFloat16(values[arity]); + Float16 actual_fp16 = shortBitsToFloat16(values[arity + 1]); + if(!expected_fp16.equals(actual_fp16)) { + String inputs = Arrays.toString(Arrays.copyOfRange(values, 0, arity - 1)); + throw new AssertionError("Result Mismatch!, input = " + inputs + " actual = " + actual_fp16 + " expected = " + expected_fp16); + } } public TestFloat16VectorOperations() { @@ -84,9 +91,9 @@ public TestFloat16VectorOperations() { @Test @Warmup(50) - @IR(counts = {IRNode.ADD_VHF, ">= 1"}, + @IR(counts = {IRNode.ADD_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.ADD_VHF, ">= 1"}, + @IR(counts = {IRNode.ADD_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorAddFloat16() { for (int i = 0; i < LEN; ++i) { @@ -98,18 +105,16 @@ public void vectorAddFloat16() { public void checkResultAdd() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) + float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } + @Test @Warmup(50) - @IR(counts = {IRNode.SUB_VHF, ">= 1"}, + @IR(counts = {IRNode.SUB_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.SUB_VHF, ">= 1"}, + @IR(counts = {IRNode.SUB_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorSubFloat16() { for (int i = 0; i < LEN; ++i) { @@ -121,18 +126,16 @@ public void vectorSubFloat16() { public void checkResultSub() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) - float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } + @Test @Warmup(50) - @IR(counts = {IRNode.MUL_VHF, ">= 1"}, + @IR(counts = {IRNode.MUL_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MUL_VHF, ">= 1"}, + @IR(counts = {IRNode.MUL_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMulFloat16() { for (int i = 0; i < LEN; ++i) { @@ -144,18 +147,15 @@ public void vectorMulFloat16() { public void checkResultMul() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) * float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.DIV_VHF, ">= 1"}, + @IR(counts = {IRNode.DIV_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.DIV_VHF, ">= 1"}, + @IR(counts = {IRNode.DIV_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorDivFloat16() { for (int i = 0; i < LEN; ++i) { @@ -167,18 +167,15 @@ public void vectorDivFloat16() { public void checkResultDiv() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) / float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.MIN_VHF, ">= 1"}, + @IR(counts = {IRNode.MIN_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MIN_VHF, ">= 1"}, + @IR(counts = {IRNode.MIN_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMinFloat16() { for (int i = 0; i < LEN; ++i) { @@ -190,18 +187,15 @@ public void vectorMinFloat16() { public void checkResultMin() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(Math.min(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.MAX_VHF, ">= 1"}, + @IR(counts = {IRNode.MAX_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MAX_VHF, ">= 1"}, + @IR(counts = {IRNode.MAX_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMaxFloat16() { for (int i = 0; i < LEN; ++i) { @@ -213,18 +207,15 @@ public void vectorMaxFloat16() { public void checkResultMax() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(Math.max(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.SQRT_VHF, ">= 1"}, + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.SQRT_VHF, ">= 1"}, + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorSqrtFloat16() { for (int i = 0; i < LEN; ++i) { @@ -236,18 +227,15 @@ public void vectorSqrtFloat16() { public void checkResultSqrt() { for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(sqrt(shortBitsToFloat16(input1[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input = " + input1[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(1, input1[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16() { for (int i = 0; i < LEN; ++i) { @@ -261,22 +249,19 @@ public void checkResultFma() { for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - "input3 = " + input3[i] + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1[i], input2[i], input3[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16ScalarMixedConstants() { for (int i = 0; i < LEN; ++i) { - output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(FP16_SCALAR), shortBitsToFloat16(floatToFloat16(3.0f)))); } } @@ -284,21 +269,18 @@ public void vectorFmaFloat16ScalarMixedConstants() { @Check(test="vectorFmaFloat16ScalarMixedConstants") public void checkResultFmaScalarMixedConstants() { for (int i = 0; i < LEN; ++i) { - short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(FP16_SCALAR), shortBitsToFloat16(floatToFloat16(3.0f)))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + SCALAR_FP16 + - "input3 = 3.0 " + "output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], FP16_SCALAR, expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16MixedConstants() { short input3 = floatToFloat16(3.0f); @@ -307,15 +289,13 @@ public void vectorFmaFloat16MixedConstants() { } } + @Check(test="vectorFmaFloat16MixedConstants") public void checkResultFmaMixedConstants() { short input3 = floatToFloat16(3.0f); for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1[i], input2[i], input3, expected, output[i]); } } @@ -341,10 +321,118 @@ public void checkResultFmaAllConstants() { short input3 = floatToFloat16(3.0f); for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1), shortBitsToFloat16(input2), shortBitsToFloat16(input3))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1 + " input2 = " + input2 + - "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1, input2, input3, expected, output[i]); + } + } + + + @Test + @Warmup(50) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + public void vectorAddConstInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(add(shortBitsToFloat16(input1[i]), FP16_CONST)); + } + } + + @Check(test="vectorAddConstInputFloat16") + public void checkResultAddConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) + FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorSubConstInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(subtract(shortBitsToFloat16(input1[i]), FP16_CONST)); + } + } + + @Check(test="vectorSubConstInputFloat16") + public void checkResultSubConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) - FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMulConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(multiply(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMulConstantInputFloat16") + public void checkResultMulConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(FP16_CONST.floatValue() * float16ToFloat(input2[i])); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorDivConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(divide(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorDivConstantInputFloat16") + public void checkResultDivConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(FP16_CONST.floatValue() / float16ToFloat(input2[i])); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMaxConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(max(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMaxConstantInputFloat16") + public void checkResultMaxConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.max(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(min(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMinConstantInputFloat16") + public void checkResultMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); } } } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java new file mode 100644 index 00000000000..5985367b265 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java @@ -0,0 +1,396 @@ +/* + * 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. + * + * 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. + */ + +package compiler.vectorization; + +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; +import compiler.lib.generators.*; + +/* + * @test + * @bug 8350177 8362171 + * @summary Ensure that truncation of subword vectors produces correct results + * @library /test/lib / + * @run driver compiler.vectorization.TestSubwordTruncation + */ + +public class TestSubwordTruncation { + private static final RestrictableGenerator G = Generators.G.ints(); + private static final int SIZE = 10000; + + @Setup + static Object[] setupShortArray() { + short[] arr = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + arr[i] = G.next().shortValue(); + } + + return new Object[] { arr }; + } + + + @Setup + static Object[] setupByteArray() { + byte[] arr = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + arr[i] = G.next().byteValue(); + } + + return new Object[] { arr }; + } + + @Setup + static Object[] setupCharArray() { + char[] arr = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + arr[i] = (char) G.next().shortValue(); + } + + return new Object[] { arr }; + } + + // Shorts + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupShortArray") + public Object[] testShortLeadingZeros(short[] in) { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (short) Integer.numberOfLeadingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testShortLeadingZeros") + public void checkTestShortLeadingZeros(Object[] vals) { + short[] in = (short[]) vals[0]; + short[] res = (short[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + short val = (short) Integer.numberOfLeadingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupShortArray") + public Object[] testShortTrailingZeros(short[] in) { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (short) Integer.numberOfTrailingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testShortTrailingZeros") + public void checkTestShortTrailingZeros(Object[] vals) { + short[] in = (short[]) vals[0]; + short[] res = (short[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + short val = (short) Integer.numberOfTrailingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupShortArray") + public Object[] testShortReverse(short[] in) { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (short) Integer.reverse(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testShortReverse") + public void checkTestShortReverse(Object[] vals) { + short[] in = (short[]) vals[0]; + short[] res = (short[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + short val = (short) Integer.reverse(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupShortArray") + public Object[] testShortBitCount(short[] in) { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (short) Integer.bitCount(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testShortBitCount") + public void checkTestShortBitCount(Object[] vals) { + short[] in = (short[]) vals[0]; + short[] res = (short[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + short val = (short) Integer.bitCount(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + // Chars + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupCharArray") + public Object[] testCharLeadingZeros(char[] in) { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (char) Integer.numberOfLeadingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testCharLeadingZeros") + public void checkTestCharLeadingZeros(Object[] vals) { + char[] in = (char[]) vals[0]; + char[] res = (char[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + char val = (char) Integer.numberOfLeadingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupCharArray") + public Object[] testCharTrailingZeros(char[] in) { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (char) Integer.numberOfTrailingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testCharTrailingZeros") + public void checkTestCharTrailingZeros(Object[] vals) { + char[] in = (char[]) vals[0]; + char[] res = (char[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + char val = (char) Integer.numberOfTrailingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupCharArray") + public Object[] testCharReverse(char[] in) { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (char) Integer.reverse(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testCharReverse") + public void checkTestCharReverse(Object[] vals) { + char[] in = (char[]) vals[0]; + char[] res = (char[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + char val = (char) Integer.reverse(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupCharArray") + public Object[] testCharBitCount(char[] in) { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (char) Integer.bitCount(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testCharBitCount") + public void checkTestCharBitCount(Object[] vals) { + char[] in = (char[]) vals[0]; + char[] res = (char[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + char val = (char) Integer.bitCount(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + // Bytes + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupByteArray") + public Object[] testByteLeadingZeros(byte[] in) { + byte[] res = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (byte) Integer.numberOfLeadingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testByteLeadingZeros") + public void checkTestByteLeadingZeros(Object[] vals) { + byte[] in = (byte[]) vals[0]; + byte[] res = (byte[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + byte val = (byte) Integer.numberOfLeadingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupByteArray") + public Object[] testByteTrailingZeros(byte[] in) { + byte[] res = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (byte) Integer.numberOfTrailingZeros(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testByteTrailingZeros") + public void checkTestByteTrailingZeros(Object[] vals) { + byte[] in = (byte[]) vals[0]; + byte[] res = (byte[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + byte val = (byte) Integer.numberOfTrailingZeros(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupByteArray") + public Object[] testByteReverse(byte[] in) { + byte[] res = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (byte) Integer.reverse(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testByteReverse") + public void checkTestByteReverse(Object[] vals) { + byte[] in = (byte[]) vals[0]; + byte[] res = (byte[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + byte val = (byte) Integer.reverse(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + @Test + @IR(counts = { IRNode.STORE_VECTOR, "=0" }) + @Arguments(setup = "setupByteArray") + public Object[] testByteBitCount(byte[] in) { + byte[] res = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = (byte) Integer.bitCount(in[i]); + } + + return new Object[] { in, res }; + } + + @Check(test = "testByteBitCount") + public void checkTestByteBitCount(Object[] vals) { + byte[] in = (byte[]) vals[0]; + byte[] res = (byte[]) vals[1]; + + for (int i = 0; i < SIZE; i++) { + byte val = (byte) Integer.bitCount(in[i]); + if (res[i] != val) { + throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); + } + } + } + + int intField; + short shortField; + + @Test + @IR(counts = { IRNode.MOD_I, ">0" }) + public void testMod() { + for (int i = 1; i < SIZE; i++) { + for (int j = 1; j < 204; j++) { + shortField %= intField | 1; + } + } + } + + public static void main(String[] args) { + TestFramework.run(); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java index 9f1e5789056..8b85bfa6327 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java @@ -141,7 +141,7 @@ public int[] vectorMulSub() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, + @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "zvbb", "true"}, counts = {IRNode.POPCOUNT_VI, ">0"}) public int[] vectorPopCount() { int[] res = new int[SIZE]; diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index 9233b199532..8e2c0b6a85a 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -26,6 +26,7 @@ * @test * @summary Basic (sanity) test for JDK-under-test inside a docker image. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index 43cd6ec5152..9a4748563bd 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test for hsperfdata file name conflict when two containers share the same /tmp directory * @requires container.support + * @requires !vm.asan * @library /test/lib * @build WaitForFlagFile * @run driver ShareTmpDir diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index c51bfa1abbb..99220201f66 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's CPU resource awareness when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.base/jdk.internal.platform diff --git a/test/hotspot/jtreg/containers/docker/TestCPUSets.java b/test/hotspot/jtreg/containers/docker/TestCPUSets.java index aabe82e131f..7894172e401 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUSets.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUSets.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's awareness of cpu sets (cpus and mems) * @requires container.support + * @requires !vm.asan * @requires (os.arch != "s390x") * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java index 5db3c2af098..b9b6fb65b75 100644 --- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java +++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java @@ -28,6 +28,7 @@ * @summary Test container info for cgroup v2 * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 77c735cde00..c8905f4e49c 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -30,6 +30,7 @@ * Also make sure that PIDs are based on value provided by container, * not by the host system. * @requires (container.support & os.maxMemory >= 2g) + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java index 9f9497d9c63..c0dde368d1e 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -28,6 +28,7 @@ * the reported host ip and host name are correctly reported within * the container. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java index b7517254281..a9de46e00b0 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java @@ -26,6 +26,7 @@ * @test * @summary Test JFR recording controlled via JMX across container boundary. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 9feeda6f4ad..91a07012f00 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -31,6 +31,7 @@ * namespace such as PID namespace, specific sub-directories, IPC and more. * @requires container.support * @requires vm.flagless + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.management * jdk.jartool/sun.tools.jar diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index 14227a71068..7b05669085c 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @build jdk.test.whitebox.WhiteBox LimitUpdateChecker * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index f8c8b34135d..f80a83842c9 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -32,6 +32,7 @@ * @test * @key cgroups * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java index a75f314b53d..bd1713e578c 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java @@ -36,6 +36,7 @@ * @test * @bug 8343191 * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index 1ca3540683c..a1998cef344 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -26,6 +26,7 @@ * @test * @summary Test miscellanous functionality related to JVM running in docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java index 9b65a1b1ee8..2e9c97110b2 100644 --- a/test/hotspot/jtreg/containers/docker/TestPids.java +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test JVM's awareness of pids controller * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index e30cd3c5206..17ae437358d 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -38,8 +38,8 @@ * gc.g1.TestGCLogMessages */ -import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.whitebox.code.Compiler; @@ -194,7 +194,7 @@ public boolean isAvailable() { new LogMessageWithLevel("Serial Rebuild Free List:", Level.TRACE), new LogMessageWithLevel("Parallel Rebuild Free List \\(ms\\):", Level.TRACE), new LogMessageWithLevel("Prepare For Mutator:", Level.DEBUG), - new LogMessageWithLevel("Expand Heap After Collection:", Level.DEBUG), + new LogMessageWithLevel("Resize Heap After Collection:", Level.DEBUG), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { @@ -320,8 +320,7 @@ private void testExpandHeap() throws Exception { "-XX:+WhiteBoxAPI", GCTest.class.getName()); - output.shouldContain("Expand the heap. requested expansion amount: "); - output.shouldContain("B expansion amount: "); + output.shouldContain("Heap resize: "); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java index a3dded8d09a..7ca9c7f46d6 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java @@ -23,105 +23,175 @@ * */ -/* - * @test id=passive +/** + * @test id=satb-adaptive * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb * -XX:+ShenandoahDegeneratedGC - * -Dtarget=10000 + * -XX:ShenandoahGCHeuristics=adaptive * TestDynamicSoftMaxHeapSize * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive - * -XX:-ShenandoahDegeneratedGC - * -Dtarget=10000 - * TestDynamicSoftMaxHeapSize */ -/* - * @test id=aggressive +/** + * @test id=satb-aggressive * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive - * -Dtarget=1000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=aggressive * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=adaptive +/** + * @test id=satb-compact * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive - * -Dtarget=10000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=compact * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=generational +/** + * @test id=satb-static * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive -XX:ShenandoahGCMode=generational - * -Dtarget=10000 + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=static * TestDynamicSoftMaxHeapSize + * */ -/* - * @test id=static +/** + * @test id=passive * @requires vm.gc.Shenandoah * @library /test/lib * * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahDegeneratedGC + * -Dtarget=10000 + * TestDynamicSoftMaxHeapSize + * + * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:-ShenandoahDegeneratedGC * -Dtarget=10000 * TestDynamicSoftMaxHeapSize */ -/* - * @test id=compact +/** + * @test id=generational * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact - * -Dtarget=1000 - * TestDynamicSoftMaxHeapSize + * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 + * -XX:ShenandoahGCMode=generational + * -XX:ShenandoahGCHeuristics=adaptive + * TestDynamicSoftMaxHeapSize + * */ -import java.util.Random; +/** + * @test id=generational-softMaxHeapSizeValidation + * @requires vm.gc.Shenandoah + * @library /test/lib + * + * @run main/othervm -DvalidateSoftMaxHeap=true + * TestDynamicSoftMaxHeapSize + * -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 -DverifySoftMaxHeapValue=true + * -XX:ShenandoahGCMode=generational + * -XX:ShenandoahGCHeuristics=adaptive + */ import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.dcmd.PidJcmdExecutor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + public class TestDynamicSoftMaxHeapSize { + static final int K = 1024; + static final int XMS_MB = 100; + static final int XMX_MB = 512; + + public static void main(String[] args) throws Exception { + if ("true".equals(System.getProperty("validateSoftMaxHeap"))) { + List flagArgs = new ArrayList<>(Arrays.asList(args)); - static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation - static final long STRIDE = 10_000_000; + int softMaxInMb = Utils.getRandomInstance().nextInt(XMS_MB, XMX_MB); + flagArgs.add("-DsoftMaxCapacity=" + softMaxInMb * K * K); + flagArgs.add("-Dtest.jdk=" + System.getProperty("test.jdk")); + flagArgs.add("-Dcompile.jdk=" + System.getProperty("compile.jdk")); - static volatile Object sink; + flagArgs.add(SoftMaxWithExpectationTest.class.getName()); - public static void main(String[] args) throws Exception { - long count = TARGET_MB * 1024 * 1024 / 16; - Random r = Utils.getRandomInstance(); - PidJcmdExecutor jcmd = new PidJcmdExecutor(); - - for (long c = 0; c < count; c += STRIDE) { - // Sizes specifically include heaps below Xms and above Xmx to test saturation code. - jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true); - for (long s = 0; s < STRIDE; s++) { - sink = new Object(); + ProcessBuilder genShenPbValidateFlag = ProcessTools.createLimitedTestJavaProcessBuilder(flagArgs); + OutputAnalyzer output = new OutputAnalyzer(genShenPbValidateFlag.start()); + output.shouldHaveExitValue(0); + output.shouldContain(String.format("Soft Max Heap Size: %dM -> %dM", XMX_MB, softMaxInMb)); // By default, the soft max heap size is Xmx + } else { + SoftMaxSetFlagOnlyTest.test(); + } + } + + public static class SoftMaxSetFlagOnlyTest { + static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation + static final long STRIDE = 10_000_000; + + static volatile Object sink; + + public static void test() throws Exception { + long count = TARGET_MB * 1024 * 1024 / 16; + Random r = Utils.getRandomInstance(); + PidJcmdExecutor jcmd = new PidJcmdExecutor(); + + for (long c = 0; c < count; c += STRIDE) { + // Sizes specifically include heaps below Xms and above Xmx to test saturation code. + jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true); + for (long s = 0; s < STRIDE; s++) { + sink = new Object(); + } + Thread.sleep(1); } - Thread.sleep(1); } } + public static class SoftMaxWithExpectationTest { + static final long TOTAL = 100_000_000; + + static volatile Object sink; + + public static void main(String[] args) throws Exception { + int expectedSoftMaxHeapSize = Integer.getInteger("softMaxCapacity", 0); + PidJcmdExecutor jcmd = new PidJcmdExecutor(); + jcmd.execute("VM.set_flag SoftMaxHeapSize " + expectedSoftMaxHeapSize, false); + + for (long s = 0; s < TOTAL; s++) { + sink = new Object(); + } + } + } } diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index f799c0bac21..96440ba15ae 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved. + * Copyright (c) 2021, 2025, Red Hat, Inc. 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 @@ -27,7 +27,7 @@ * @summary guarantee(loc != NULL) failed: missing saved register with native invoke * * @requires vm.flavor == "server" - * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" | os.arch == "ppc64le" + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" * @requires vm.gc.Shenandoah * * @run main/othervm --enable-native-access=ALL-UNNAMED -XX:+UnlockDiagnosticVMOptions diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index 840ceffc4fe..b5d191e33ba 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -57,17 +57,17 @@ public static void makeOldAllocations() { for (int i = 0; i < ArraySize; i++) { int replaceIndex = r.nextInt(ArraySize); int deriveIndex = r.nextInt(ArraySize); - switch (i & 0x3) { - case 0: + switch (i & 0x7) { + case 0,1,2: // creates new old BigInteger, releases old BigInteger, // may create ephemeral data while computing gcd array[replaceIndex] = array[replaceIndex].gcd(array[deriveIndex]); break; - case 1: + case 3,4: // creates new old BigInteger, releases old BigInteger array[replaceIndex] = array[replaceIndex].multiply(array[deriveIndex]); break; - case 2,3: + case 5,6,7: // do nothing, let all objects in the array age to increase pressure on old generation break; } diff --git a/test/hotspot/jtreg/gtest/LockStackGtests.java b/test/hotspot/jtreg/gtest/LockStackGtests.java deleted file mode 100644 index e426b2c56f3..00000000000 --- a/test/hotspot/jtreg/gtest/LockStackGtests.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023, 2024, 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 - * @summary Run LockStack gtests with LockingMode=2 - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=LockStackTest* -XX:LockingMode=2 - */ diff --git a/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java b/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java index 9ceec3b9d8d..88dafed4a41 100644 --- a/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java +++ b/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -24,6 +24,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; @@ -34,10 +35,13 @@ * @bug 8318757 * @summary Test concurrent monitor deflation by MonitorDeflationThread and thread dumping * @library /test/lib - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedAsyncDeflationInterval=2000 -XX:LockingMode=0 ConcurrentDeflation + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedAsyncDeflationInterval=2000 -XX:+WhiteBoxAPI ConcurrentDeflation */ public class ConcurrentDeflation { + static final WhiteBox WB = WhiteBox.getWhiteBox(); public static final long TOTAL_RUN_TIME_NS = 10_000_000_000L; public static Object[] monitors = new Object[1000]; public static int monitorCount; @@ -73,6 +77,12 @@ static private void createMonitors() { index = index++ % 1000; monitors[index] = new Object(); synchronized (monitors[index]) { + try { + // Force inflation + monitors[index].wait(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } monitorCount++; } } diff --git a/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java b/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java index b12f0f007f8..0eeacabb82f 100644 --- a/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java +++ b/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java @@ -33,21 +33,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -63,21 +48,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 */ @@ -94,21 +64,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -125,21 +80,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 */ @@ -156,21 +96,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-EliminateNestedLocks - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -182,25 +107,10 @@ * @summary Tests recursive locking in C2 in alternate A and B mode. * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox - * * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=0 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=1 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 * * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=2 * -XX:-EliminateNestedLocks * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 diff --git a/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java b/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java index eae845c48b1..bea7a41ae2b 100644 --- a/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java +++ b/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java @@ -33,21 +33,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -63,21 +48,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 */ @@ -94,21 +64,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -125,21 +80,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 */ @@ -156,21 +96,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-EliminateNestedLocks - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -182,25 +107,10 @@ * @summary Tests recursive locking in C2 in alternate A and B mode. * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox - * * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=0 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=1 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 * * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=2 * -XX:-EliminateNestedLocks * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 @@ -212,11 +122,7 @@ public class TestRecursiveLocking { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int flagLockingMode = WB.getIntVMFlag("LockingMode").intValue(); static final int constLockStackCapacity = WB.getLockStackCapacity(); - static final int LM_MONITOR = 0; - static final int LM_LEGACY = 1; - static final int LM_LIGHTWEIGHT = 2; static final int def_mode = 2; static final int def_n_secs = 30; static final SyncThread syncThread = new SyncThread(); @@ -229,44 +135,32 @@ static class SynchronizedObject { synchronized void runInner(int depth, SynchronizedObject outer) { counter++; - // Legacy mode has no lock stack, i.e., there is no limit - // on recursion, so for legacy mode we can't say that - // "outer" must be inflated here, which we can say for all - // the other locking modes. - if (flagLockingMode != LM_LEGACY) { - outer.assertInflated(); - } + // There is limit on recursion, so "outer" must be + // inflated here. + outer.assertInflated(); // We haven't reached the stack lock capacity (recursion // level), so we shouldn't be inflated here. Except for // monitor mode, which is always inflated. - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); if (depth == 1) { return; } else { runInner(depth - 1, outer); } - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); } synchronized void runOuter(int depth, SynchronizedObject inner) { counter++; - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); if (depth == 1) { inner.runInner(constLockStackCapacity, this); } else { runOuter(depth - 1, inner); } - if (flagLockingMode != LM_LEGACY) { - assertInflated(); - } + assertInflated(); } // This test nests x recursive locks of INNER, in x recursive @@ -283,18 +177,11 @@ public void runOuterInnerTest() { synchronized (OUTER) { OUTER.counter++; - if (flagLockingMode != LM_MONITOR) { - OUTER.assertNotInflated(); - } + OUTER.assertNotInflated(); INNER.assertNotInflated(); OUTER.runOuter(constLockStackCapacity - 1, INNER); - - if (flagLockingMode != LM_LEGACY) { - OUTER.assertInflated(); - } - if (flagLockingMode != LM_MONITOR) { - INNER.assertNotInflated(); - } + OUTER.assertInflated(); + INNER.assertNotInflated(); } // Verify that the nested monitors have been properly released: @@ -308,25 +195,23 @@ public void runOuterInnerTest() { synchronized void runA(int depth, SynchronizedObject B) { counter++; - if (flagLockingMode == LM_LIGHTWEIGHT) { - // First time we lock A, A is the only one on the lock - // stack. - if (counter == 1) { - assertNotInflated(); - } else { - // Second time we want to lock A, the lock stack - // looks like this [A, B]. Lightweight locking - // doesn't allow interleaving ([A, B, A]), instead - // it inflates A and removes it from the lock - // stack. Which leaves us with only [B] on the - // lock stack. After more recursions it will grow - // to [B, B ... B]. - assertInflated(); - } - } else if (flagLockingMode == LM_MONITOR) { + + // First time we lock A, A is the only one on the lock + // stack. + if (counter == 1) { + assertNotInflated(); + } else { + // Second time we want to lock A, the lock stack + // looks like this [A, B]. Lightweight locking + // doesn't allow interleaving ([A, B, A]), instead + // it inflates A and removes it from the lock + // stack. Which leaves us with only [B] on the + // lock stack. After more recursions it will grow + // to [B, B ... B]. assertInflated(); } + // Call runB() at the same depth as runA's depth: B.runB(depth, this); } @@ -334,16 +219,13 @@ synchronized void runA(int depth, SynchronizedObject B) { synchronized void runB(int depth, SynchronizedObject A) { counter++; - if (flagLockingMode != LM_MONITOR) { - // Legacy tolerates endless recursions. While testing - // lightweight we don't go deeper than the size of the - // lock stack, which in this test case will be filled - // with a number of B-elements. See comment in runA() - // above for more info. - assertNotInflated(); - } else { - assertInflated(); - } + + // Legacy tolerates endless recursions. While testing + // lightweight we don't go deeper than the size of the + // lock stack, which in this test case will be filled + // with a number of B-elements. See comment in runA() + // above for more info. + assertNotInflated(); if (depth == 1) { // Reached LockStackCapacity in depth so we're done. @@ -370,16 +252,12 @@ public void runAlternateABTest() { Asserts.assertEquals(A.counter, constLockStackCapacity); Asserts.assertEquals(B.counter, constLockStackCapacity); - if (flagLockingMode == LM_LEGACY) { - A.assertNotInflated(); - } - // Implied else: for LM_MONITOR or LM_LIGHTWEIGHT it can be - // either inflated or not because A is not locked anymore - // and subject to deflation. - if (flagLockingMode != LM_MONITOR) { - B.assertNotInflated(); - } + // Here A can be either inflated or not because A is not + // locked anymore and subject to deflation. + + B.assertNotInflated(); + } void assertNotInflated() { @@ -443,7 +321,6 @@ public static void main(String... argv) throws Exception { } } - System.out.println("INFO: LockingMode=" + flagLockingMode); System.out.println("INFO: LockStackCapacity=" + constLockStackCapacity); System.out.println("INFO: n_secs=" + n_secs); System.out.println("INFO: mode=" + mode); diff --git a/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java index e832fa600b7..f0c99b24885 100644 --- a/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java @@ -49,9 +49,10 @@ public static void main(String[] args) throws Exception { CDSTestUtils.createArchiveAndCheck(opts); // Some mach5 tiers run with -vmoptions:-Xlog:cds=debug. This would cause the outputs to mismatch. - // Force the log level to warning for all tags to supressed the CDS logs. Also disable the timestamp. + // Force the log level to warning for all tags to suppress the CDS logs. Also disable the timestamp. + // Disable CDS error by turing off CDS logging. opts.setUseVersion(false); - opts.addSuffix("-showversion", "-Xlog:all=warning::level,tags", "ServiceLoaderApp"); + opts.addSuffix("-showversion", "-Xlog:all=warning::level,tags", "-Xlog:cds=off", "ServiceLoaderApp"); OutputAnalyzer out1 = CDSTestUtils.runWithArchive(opts); opts.setXShareMode("off"); diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java index d90618b51f2..4dd3b63c84a 100644 --- a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java +++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java @@ -26,6 +26,7 @@ * @test id=nocoops_nocoh * @summary Test Loading of default archives in all configurations * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -38,6 +39,7 @@ * @test id=nocoops_coh * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -50,6 +52,7 @@ * @test id=coops_nocoh * @summary Test Loading of default archives in all configurations * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib @@ -62,6 +65,7 @@ * @test id=coops_coh * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap * @requires vm.bits == 64 * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java index be0f6695545..baa519a42ae 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java @@ -67,6 +67,8 @@ static void test(boolean run_reloc) throws Exception { String logArg = "-Xlog:cds=debug,cds+reloc=debug,aot+heap"; String unlockArg = "-XX:+UnlockDiagnosticVMOptions"; String nmtArg = "-XX:NativeMemoryTracking=detail"; + String relocMsg1 = "ArchiveRelocationMode == 1: always map archive(s) at an alternative address"; + String relocMsg2 = "Try to map archive(s) at an alternative address"; OutputAnalyzer out = TestCommon.dump(appJar, TestCommon.list(mainClass), @@ -76,8 +78,10 @@ static void test(boolean run_reloc) throws Exception { TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg, mainClass) .assertNormalExit(output -> { if (run_reloc) { - output.shouldContain("ArchiveRelocationMode == 1: always map archive(s) at an alternative address") - .shouldContain("Try to map archive(s) at an alternative address"); + if (!output.contains(relocMsg1) && !output.contains(relocMsg2)) { + throw new RuntimeException("Relocation messages \"" + relocMsg1 + + "\" and \"" + relocMsg2 + "\" are missing from the output"); + } } else { output.shouldContain("ArchiveRelocationMode: 0"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java index 28e92ac3700..1650cddee3f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestDumpClassListSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -28,6 +28,7 @@ * @summary test dynamic dump meanwhile output loaded class list * @bug 8279009 8275084 * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.cds.custom.loaders * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java index 4ed2ce4446d..be7e69b076c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java @@ -121,34 +121,23 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use out.shouldNotContain(errMsg); out.shouldHaveExitValue(0); - int n = 2; if (!dumpWithParallel && execWithParallel) { // We dumped with G1, so we have an archived heap. At exec time, try to load them into // a small ParallelGC heap that may be too small. - String[] sizes = { - "4m", // usually this will success load the archived heap - "2m", // usually this will fail to load the archived heap, but app can launch - // or fail with "GC triggered before VM initialization completed" - "1m" // usually this will cause VM launch to fail with "Too small maximum heap" - }; - for (String sz : sizes) { - String xmx = "-Xmx" + sz; - System.out.println("=======\n" + n + ". Exec with " + execGC + " " + xmx); - out = TestCommon.exec(helloJar, - execGC, - small1, - small2, - xmx, - coops, - "-Xlog:cds", - "Hello"); - if (out.getExitValue() == 0) { - out.shouldContain(HELLO); - out.shouldNotContain(errMsg); - } else { - out.shouldNotHaveFatalError(); - } - n++; + System.out.println("2. Exec with " + execGC); + out = TestCommon.exec(helloJar, + execGC, + small1, + small2, + "-Xmx4m", + coops, + "-Xlog:cds", + "Hello"); + if (out.getExitValue() == 0) { + out.shouldContain(HELLO); + out.shouldNotContain(errMsg); + } else { + out.shouldNotHaveFatalError(); } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java b/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java index 8bbc713fa6f..88620fc039f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -28,6 +28,7 @@ * @summary Transforming an interface of an archived lambda proxy class should not * crash the VM. The lambda proxy class should be regenerated during runtime. * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.jvmti * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCompileEagerly.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCompileEagerly.java new file mode 100644 index 00000000000..c740ecd96f5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCompileEagerly.java @@ -0,0 +1,102 @@ +/* + * 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. + * + * 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 + * @bug 8359436 + * @summary Sanity-check that eager compilation flags are accepted + * @requires vm.cds + * @requires vm.flagless + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build Hello + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello + * @run driver AOTCompileEagerly + */ + +import java.io.File; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class AOTCompileEagerly { + static final String appJar = ClassFileInstaller.getJarPath("hello.jar"); + static final String aotConfigFile = "hello.aotconfig"; + static final String aotCacheFile = "hello.aot"; + static final String helloClass = "Hello"; + + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + OutputAnalyzer out; + + //---------------------------------------------------------------------- + System.out.println("Training Run"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "train"); + out.shouldHaveExitValue(0); + + //---------------------------------------------------------------------- + System.out.println("Assembly Phase"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar); + out = CDSTestUtils.executeAndLog(pb, "asm"); + out.shouldHaveExitValue(0); + + //---------------------------------------------------------------------- + System.out.println("Production Run with AOTCache defaults"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod-default"); + out.shouldHaveExitValue(0); + + //---------------------------------------------------------------------- + System.out.println("Production Run with AOTCache and eager compilation explicitly ON"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "-XX:+UnlockExperimentalVMOptions", + "-XX:+AOTCompileEagerly", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod-eager-on"); + out.shouldHaveExitValue(0); + + //---------------------------------------------------------------------- + System.out.println("Production Run with AOTCache and eager compilation explicitly OFF"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "-XX:+UnlockExperimentalVMOptions", + "-XX:-AOTCompileEagerly", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod-eager-off"); + out.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java index c808cd95bc7..f50a2d1f905 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java @@ -34,6 +34,8 @@ * TestApp$Foo * TestApp$Foo$Bar * TestApp$Foo$ShouldBeExcluded + * TestApp$Foo$ShouldBeExcludedChild + * TestApp$Foo$Taz * TestApp$MyInvocationHandler * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar * CustyWithLoop @@ -61,7 +63,7 @@ public class ExcludedClasses { public static void main(String[] args) throws Exception { Tester tester = new Tester(); - tester.runAOTWorkflow(); + tester.runAOTWorkflow("AOT", "--two-step-training"); } static class Tester extends CDSAppTester { @@ -77,7 +79,11 @@ public String classpath(RunMode runMode) { @Override public String[] vmArgs(RunMode runMode) { return new String[] { - "-Xlog:cds+resolve=trace", + "-Xlog:aot=debug", + "-Xlog:aot+class=debug", + "-Xlog:aot+resolve=trace", + "-Xlog:aot+verification=trace", + "-Xlog:class+load", }; } @@ -90,8 +96,13 @@ public String[] appCommandLine(RunMode runMode) { @Override public void checkExecution(OutputAnalyzer out, RunMode runMode) { - if (isDumping(runMode)) { - out.shouldNotMatch("cds,resolve.*archived field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I"); + if (runMode == RunMode.ASSEMBLY) { + out.shouldNotMatch("aot,resolve.*archived field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I"); + } else if (runMode == RunMode.PRODUCTION) { + out.shouldContain("check_verification_constraint: TestApp$Foo$Taz: TestApp$Foo$ShouldBeExcludedChild must be subclass of TestApp$Foo$ShouldBeExcluded"); + out.shouldContain("jdk.jfr.Event source: jrt:/jdk.jfr"); + out.shouldMatch("TestApp[$]Foo[$]ShouldBeExcluded source: .*/app.jar"); + out.shouldMatch("TestApp[$]Foo[$]ShouldBeExcludedChild source: .*/app.jar"); } } } @@ -102,8 +113,8 @@ class TestApp { static volatile Object custArrayInstance; public static void main(String args[]) throws Exception { - // In new workflow, classes from custom loaders are passed from the preimage - // to the final image. See ClassPrelinker::record_unregistered_klasses(). + // In AOT workflow, classes from custom loaders are passed from the preimage + // to the final image. See FinalImageRecipes::record_all_classes(). custInstance = initFromCustomLoader(); custArrayInstance = Array.newInstance(custInstance.getClass(), 0); System.out.println(custArrayInstance); @@ -157,6 +168,7 @@ static int hotSpot() { lambdaHotSpot(); s.hotSpot2(); b.hotSpot3(); + Taz.hotSpot4(); // In JDK mainline, generated proxy classes are excluded from the AOT cache. // In Leyden/premain, generated proxy classes included. The following code should @@ -165,7 +177,7 @@ static int hotSpot() { counter += i.intValue(); if (custInstance != null) { - // Classes loaded by custom loaders are included included in the AOT cache + // Classes loaded by custom loaders are included in the AOT cache // but their array classes are excluded. counter += custInstance.equals(null) ? 1 : 2; } @@ -216,6 +228,16 @@ void hotSpot2() { f(); } } + int func() { + return 1; + } + } + + static class ShouldBeExcludedChild extends ShouldBeExcluded { + @Override + int func() { + return 2; + } } static class Bar { @@ -234,6 +256,29 @@ void hotSpot3() { } } } + + static class Taz { + static ShouldBeExcluded m() { + // When verifying this method, we need to check the constraint that + // ShouldBeExcluded must be a supertype of ShouldBeExcludedChild. This information + // is checked by SystemDictionaryShared::check_verification_constraints() when the Taz + // class is linked during the production run. + // + // Because ShouldBeExcluded is excluded from the AOT archive, it must be loaded + // dynamically from app.jar inside SystemDictionaryShared::check_verification_constraints(). + // This must happen after the app class loader has been fully restored from the AOT cache. + return new ShouldBeExcludedChild(); + } + static void hotSpot4() { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < 20) { + for (int i = 0; i < 50000; i++) { + counter += i; + } + f(); + } + } + } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java index 410e60f2fe9..b09c2c944fb 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java @@ -133,6 +133,7 @@ private static void testArchivedModuleUsingImage(Path image) customJava.toString(), "-XX:SharedArchiveFile=./ArchivedModuleWithCustomImageTest.jsa", "-Xshare:on", + "-Xlog:cds=off", "--show-module-resolution", "-version"}; printCommand(showModuleCmd2); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LotsUnloadTest.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LotsUnloadTest.java index b98f1deaa9f..335a8694b33 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LotsUnloadTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LotsUnloadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -65,7 +65,7 @@ static void test() throws Exception { dump(topArchiveName, logging, - "-Xmx64m", "-Xms32m", + "-Xmx256m", "-Xms32m", "-cp", appJar, mainClass) .assertNormalExit(output -> { output.shouldHaveExitValue(0); @@ -73,7 +73,7 @@ static void test() throws Exception { run(topArchiveName, logging, - "-Xmx64m", "-Xms32m", + "-Xmx256m", "-Xms32m", "-cp", appJar, mainClass) .assertNormalExit(output -> { output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestHostOldInf.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestHostOldInf.java index 428e9c83df1..99ab68bda49 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestHostOldInf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestHostOldInf.java @@ -82,7 +82,7 @@ private static void doTest() throws Exception { output.shouldHaveExitValue(0) .shouldMatch(".class.load. OldInf source:.*oldclassapp.jar") .shouldMatch(".class.load. ChildOldInf source:.*oldclassapp.jar") - .shouldContain("ChildOldInf$InnerChild source: shared objects file (top)") + .shouldMatch(".class.load. ChildOldInf[$]InnerChild source:.*oldclassapp.jar") .shouldMatch(".class.load. ChildOldInf[$]InnerChild[$][$]Lambda.*/0x.*source:.ChildOldInf"); }); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java index 3bc1e395b17..fed06c4afee 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java @@ -556,10 +556,10 @@ private static void testAutoCreateSharedArchive() throws Exception { .shouldContain(HELLO_WORLD) .shouldContain("Dumping shared data to file:"); }); - ft2 = Files.getLastModifiedTime(Paths.get(versionB)); + ft2 = Files.getLastModifiedTime(Paths.get(versionF)); fileModified = !ft1.equals(ft2); if (!fileModified) { - throw new RuntimeException("Shared archive " + versionB + " should be created at exit"); + throw new RuntimeException("Shared archive " + versionF + " should be created at exit"); } // 22 create an archive with dynamic magic number only diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java index 4806f571dc6..6c46fd07550 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -27,6 +27,7 @@ * @summary Test -XX:+AutoCreateSharedArchive on a copied JDK without default shared archive * @bug 8261455 * @requires vm.cds + * @requires vm.cds.default.archive.available * @requires vm.flagless * @comment This test doesn't work on Windows because it depends on symlinks * @requires os.family != "windows" diff --git a/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java b/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java index b599f6c61ff..417e3a32b4b 100644 --- a/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java +++ b/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -26,13 +26,42 @@ * @bug 8309811 * @requires vm.debug * @summary Test the output of -XX:+TraceBytecodes, -XX:TraceBytecodesAt, and -XX:TraceBytecodesStopAt - * @run main/othervm -XX:+TraceBytecodes -XX:TraceBytecodesAt=2000 -XX:TraceBytecodesStopAt=3000 TraceBytecodes + * @run main/othervm -XX:+TraceBytecodes -XX:TraceBytecodesAt=1000000 -XX:TraceBytecodesStopAt=1001000 TraceBytecodes */ -// This is just a very simple sanity test. Trace about 1000 bytecodes. See the .jtr file for the output. +// CountBytecodes returns 1826384 bytecodes, so trace starting at a million to trace parallel threads. +// This is just a very simple sanity test. See the .jtr file for the output. // Consider it OK if the VM doesn't crash. It should test a fair amount of the code in bytecodeTracer.cpp -public class TraceBytecodes { - public static void main(String args[]) { +public class TraceBytecodes extends Thread { + public void run() { System.out.println("Hello TraceBytecodes"); } + + private static TraceBytecodes[] threads = new TraceBytecodes[2]; + private static boolean success = true; + + private static boolean report_success() { + for (int i = 0; i < 2; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) {} + } + return success; + } + + public static void main(String args[]) { + threads[0] = new TraceBytecodes(); + threads[1] = new TraceBytecodes(); + for (int i = 0; i < 2; i++) { + threads[i].setName("Loading Thread #" + (i + 1)); + threads[i].start(); + System.out.println("Thread " + (i + 1) + " was started..."); + } + + if (report_success()) { + System.out.println("PASSED"); + } else { + throw new RuntimeException("FAILED"); + } + } } diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java b/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java new file mode 100644 index 00000000000..7cb427cebbb --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/checked/TestCharArrayReleasing.java @@ -0,0 +1,129 @@ +/* + * 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. + * + * 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 + * @bug 8357601 + * @requires vm.flagless + * @library /test/lib + * @run main/othervm/native TestCharArrayReleasing 0 0 + * @run main/othervm/native TestCharArrayReleasing 1 0 + * @run main/othervm/native TestCharArrayReleasing 2 0 + * @run main/othervm/native TestCharArrayReleasing 3 0 + * @run main/othervm/native TestCharArrayReleasing 4 0 + * @run main/othervm/native TestCharArrayReleasing 0 1 + * @run main/othervm/native TestCharArrayReleasing 1 1 + * @run main/othervm/native TestCharArrayReleasing 2 1 + * @run main/othervm/native TestCharArrayReleasing 3 1 + * @run main/othervm/native TestCharArrayReleasing 4 1 + * @run main/othervm/native TestCharArrayReleasing 0 2 + * @run main/othervm/native TestCharArrayReleasing 1 2 + * @run main/othervm/native TestCharArrayReleasing 2 2 + * @run main/othervm/native TestCharArrayReleasing 3 2 + * @run main/othervm/native TestCharArrayReleasing 4 2 + * @run main/othervm/native TestCharArrayReleasing 0 3 + * @run main/othervm/native TestCharArrayReleasing 1 3 + * @run main/othervm/native TestCharArrayReleasing 2 3 + * @run main/othervm/native TestCharArrayReleasing 3 3 + * @run main/othervm/native TestCharArrayReleasing 4 3 + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +// Test the behaviour of the JNI "char" releasing functions, under Xcheck:jni, +// when they are passed "char" arrays obtained from different sources: +// - source_mode indicates which array to use +// - 0: use a raw malloc'd array +// - 1: use an array from GetCharArrayElements +// - 2: use an array from GetStringChars +// - 3: use an array from GetStringUTFChars +// - 4: use an array from GetPrimitiveArrayCritical +// - release_mode indicates which releasing function to use +// - 0: ReleaseCharArrayElements +// - 1: ReleaseStringChars +// - 2: ReleaseStringUTFChars +// - 3: ReleasePrimitiveArrayCritical + +public class TestCharArrayReleasing { + + static native void testIt(int srcMode, int releaseMode); + + static class Driver { + + static { + System.loadLibrary("CharArrayReleasing"); + } + + public static void main(String[] args) { + int srcMode = Integer.parseInt(args[0]); + int relMode = Integer.parseInt(args[1]); + testIt(srcMode, relMode); + } + } + + public static void main(String[] args) throws Throwable { + int ABRT = 1; + int[][] errorCodes = new int[][] { + { ABRT, 0, ABRT, ABRT, ABRT }, + { ABRT, ABRT, 0, ABRT, ABRT }, + { ABRT, ABRT, ABRT, 0, ABRT }, + { ABRT, ABRT, ABRT, ABRT, 0 }, + }; + + String rcae = "ReleaseCharArrayElements called on something allocated by GetStringChars"; + String rcaeUTF = "ReleaseCharArrayElements called on something allocated by GetStringUTFChars"; + String rcaeCrit = "ReleaseCharArrayElements called on something allocated by GetPrimitiveArrayCritical"; + String rcaeBounds = "ReleaseCharArrayElements: release array failed bounds check"; + String rsc = "ReleaseStringChars called on something not allocated by GetStringChars"; + String rscBounds = "ReleaseStringChars: release chars failed bounds check"; + String rsuc = "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars"; + String rsucBounds = "ReleaseStringUTFChars: release chars failed bounds check"; + String rpac = "ReleasePrimitiveArrayCritical called on something not allocated by GetPrimitiveArrayCritical"; + String rpacBounds = "ReleasePrimitiveArrayCritical: release array failed bounds check"; + String rpacStr = "ReleasePrimitiveArrayCritical called on something allocated by GetStringChars"; + String rpacStrUTF = "ReleasePrimitiveArrayCritical called on something allocated by GetStringUTFChars"; + + String[][] errorMsgs = new String[][] { + { rcaeBounds, "", rcae, rcaeUTF, rcaeCrit }, + { rscBounds, rsc, "", rsc, rsc }, + { rsucBounds, rsuc, rsuc, "", rsuc }, + { rpacBounds, rpac, rpacStr, rpacStrUTF, "" }, + }; + + int srcMode = Integer.parseInt(args[0]); + int relMode = Integer.parseInt(args[1]); + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Djava.library.path=" + System.getProperty("test.nativepath"), + "--enable-native-access=ALL-UNNAMED", + "-XX:-CreateCoredumpOnCrash", + "-Xcheck:jni", + "TestCharArrayReleasing$Driver", + args[0], args[1]); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(errorCodes[relMode][srcMode]); + output.shouldContain(errorMsgs[relMode][srcMode]); + } +} diff --git a/test/hotspot/jtreg/runtime/jni/checked/libCharArrayReleasing.c b/test/hotspot/jtreg/runtime/jni/checked/libCharArrayReleasing.c new file mode 100644 index 00000000000..459202e3054 --- /dev/null +++ b/test/hotspot/jtreg/runtime/jni/checked/libCharArrayReleasing.c @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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 +#include +#include + +#include "jni.h" +#include "jni_util.h" + +// Test the behaviour of the JNI "char" releasing functions, under Xcheck:jni, +// when they are passed "char" arrays obtained from different sources: +// - source_mode indicates which array to use +// - 0: use a raw malloc'd array +// - 1: use an array from GetCharArrayElements +// - 2: use an array from GetStringChars +// - 3: use an array from GetStringUTFChars +// - 4: use an array from GetPrimitiveArrayCritical +// - release_mode indicates which releasing function to use +// - 0: ReleaseCharArrayElements +// - 1: ReleaseStringChars +// - 2: ReleaseStringUTFChars +// - 3: ReleasePrimitiveArrayCritical +// + +static char* source[] = { + "malloc", + "GetCharArrayElements", + "GetStringChars", + "GetStringUTFChars", + "GetPrimitiveArrayCritical" +}; + +static char* release_func[] = { + "ReleaseCharArrayElements", + "ReleaseStringChars", + "ReleaseStringUTFChars", + "ReleasePrimitiveArrayCritical" +}; + +JNIEXPORT void JNICALL +Java_TestCharArrayReleasing_testIt(JNIEnv *env, jclass cls, jint source_mode, + jint release_mode) { + + // First create some Java objects to be used as the sources for jchar[] + // extraction. + const int len = 10; + jcharArray ca = (*env)->NewCharArray(env, len); + jstring str = (*env)->NewStringUTF(env, "A_String"); + + jthrowable exc = (*env)->ExceptionOccurred(env); + if (exc != NULL) { + fprintf(stderr, "ERROR: Unexpected exception during test set up:\n"); + (*env)->ExceptionDescribe(env); + exit(2); + } + + fprintf(stdout, "Testing release function %s with array from %s\n", + release_func[release_mode], source[source_mode]); + fflush(stdout); + + jboolean is_copy = JNI_FALSE; + jchar* to_release; + switch(source_mode) { + case 0: { + to_release = malloc(10 * sizeof(jchar)); + break; + } + case 1: { + to_release = (*env)->GetCharArrayElements(env, ca, &is_copy); + break; + } + case 2: { + to_release = (jchar*) (*env)->GetStringChars(env, str, &is_copy); + break; + } + case 3: { + to_release = (jchar*) (*env)->GetStringUTFChars(env, str, &is_copy); + break; + } + case 4: { + to_release = (jchar*) (*env)->GetPrimitiveArrayCritical(env, ca, &is_copy); + break; + } + default: fprintf(stderr, "Unexpected source_mode %d\n", source_mode); + exit(1); + } + + switch (release_mode) { + case 0: + (*env)->ReleaseCharArrayElements(env, ca, to_release, 0); + break; + case 1: + (*env)->ReleaseStringChars(env, str, to_release); + break; + case 2: + (*env)->ReleaseStringUTFChars(env, str, (const char*)to_release); + break; + case 3: + (*env)->ReleasePrimitiveArrayCritical(env, ca, to_release, 0); + break; + default: fprintf(stderr, "Unexpected release_mode %d\n", source_mode); + exit(1); + } + +} diff --git a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java index 01ba1f4f12c..f3f1f9c91a6 100644 --- a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java +++ b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -30,7 +30,7 @@ * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint -XX:LockingMode=2 TestLockStackCapacity + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint TestLockStackCapacity */ import jdk.test.lib.Asserts; @@ -39,8 +39,6 @@ public class TestLockStackCapacity { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int LockingMode = WB.getIntVMFlag("LockingMode").intValue(); - static final int LM_LIGHTWEIGHT = 2; static class SynchronizedObject { static final SynchronizedObject OUTER = new SynchronizedObject(); @@ -95,12 +93,8 @@ void assertInflated() { } public static void main(String... args) throws Exception { - if (LockingMode != LM_LIGHTWEIGHT) { - throw new SkippedException("Test only valid for LM_LIGHTWEIGHT"); - } - if (!WB.supportsRecursiveLightweightLocking()) { - throw new SkippedException("Test only valid if LM_LIGHTWEIGHT supports recursion"); + throw new SkippedException("Test only valid if lightweight locking supports recursion"); } SynchronizedObject.runTest(); diff --git a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java index 806f32aad88..e92e947ecfa 100644 --- a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java +++ b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java @@ -49,13 +49,12 @@ synchronized void doSomethingElse() { } static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int LM_MONITOR = 0; static final int COUNT = 100000; public static volatile Monitor monitor; public static void main(String[] args) { - if (WB.getIntVMFlag("LockingMode") == LM_MONITOR) { - throw new SkippedException("LM_MONITOR always inflates. Invalid test."); + if (WB.getBooleanVMFlag("VerifyHeavyMonitors")) { + throw new SkippedException("VerifyHeavyMonitors always inflates. Invalid test."); } final long pre_monitor_count = WB.getInUseMonitorCount(); System.out.println(" Precount = " + pre_monitor_count); diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java index 327b1cc0f24..c2c966cb047 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java +++ b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8141211 8147477 + * @bug 8141211 8147477 8358080 * @summary exceptions=info output should have an exception message for interpreter methods * @requires vm.flagless * @library /test/lib @@ -34,6 +34,8 @@ import java.io.File; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -44,10 +46,24 @@ static void updateEnvironment(ProcessBuilder pb, String environmentVariable, Str } static void analyzeOutputOn(ProcessBuilder pb) throws Exception { - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeProcess(pb); output.shouldContain(""); output.shouldContain(" thrown in interpreter method "); - output.shouldHaveExitValue(0); + output.shouldMatch("info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.bar[(]ExceptionsTest.java:[0-9]+" + + ".*\n.*" + + "info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.foo[(]ExceptionsTest.java:[0-9]+" + + ".*\n.*" + + "info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.main[(]ExceptionsTest.java:[0-9]+"); + + // Note: "(?s)" means that the "." in the regexp can match the newline character. + // To avoid verbosity, stack trace for bar2()->baz2() should be printed only once: + // - It should be printed when the exception is thrown inside bzz2() + // - It should not be printed when the interpreter is looking for an exception handler inside bar2() + output.shouldMatch("(?s)baz2.*bar2"); + output.shouldNotMatch("(?s)baz2.*bar2,*baz2.*bar2"); + + // Two stack traces should include main()->foo2(), as an exception is thrown at two different BCIs in bar2(). + output.shouldMatch("(?s)foo2.*main.*foo2.*main"); } static void analyzeOutputOff(ProcessBuilder pb) throws Exception { @@ -57,7 +73,7 @@ static void analyzeOutputOff(ProcessBuilder pb) throws Exception { } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:exceptions=info", + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:exceptions,exceptions+stacktrace", InternalClass.class.getName()); analyzeOutputOn(pb); @@ -66,7 +82,7 @@ public static void main(String[] args) throws Exception { analyzeOutputOff(pb); pb = ProcessTools.createLimitedTestJavaProcessBuilder(InternalClass.class.getName()); - updateEnvironment(pb, "_JAVA_OPTIONS", "-Xlog:exceptions=info"); + updateEnvironment(pb, "_JAVA_OPTIONS", "-Xlog:exceptions,exceptions+stacktrace"); analyzeOutputOn(pb); pb = ProcessTools.createLimitedTestJavaProcessBuilder(InternalClass.class.getName()); @@ -80,12 +96,45 @@ public static void main(String[] args) throws Exception { } public static class InternalClass { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { + foo(); + foo2(); + } + + static void foo() { + bar(); + } + + static void bar() { try { throw new RuntimeException("Test exception 1 for logging"); } catch (Exception e) { System.out.println("Exception 1 caught."); } } + + static void foo2() { + try { + bar2(); + } catch (Exception e) { + System.out.println("Exception 2 caught."); + } + } + + static void bar2() { + try { + baz2(); + } catch (RuntimeException e) { + throw e; // Rethrow -- should print a new callstack. + } + } + + static void baz2() { + bzz2(); + } + + static void bzz2() { + throw new RuntimeException("Test exception 2 for logging"); + } } } diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file b/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file index d3e8be7f857..1b566aaa456 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file +++ b/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file @@ -1 +1 @@ --Xlog:exceptions=info +-Xlog:exceptions,exceptions+stacktrace diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java deleted file mode 100644 index 0099679097a..00000000000 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2019, 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. - * - * 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. - */ - -package runtime.valhalla.inlinetypes; - -import jdk.test.lib.Asserts; -import jdk.internal.vm.annotation.LooselyConsistentValue; -import jdk.internal.vm.annotation.NullRestricted; -import jdk.internal.vm.annotation.Strict; - -/* - * @test - * @summary Test initialization of static inline fields with circularity - * @library /test/lib - * @modules java.base/jdk.internal.vm.annotation - * @enablePreview - * @run main/othervm runtime.valhalla.inlinetypes.CircularityTest - */ - - -public class CircularityTest { - static boolean b = true; - static int counter = 0; - @LooselyConsistentValue - static value class A { - @Strict - @NullRestricted - static B b; - @Strict - @NullRestricted - static C c; - int i = 0; - } - - @LooselyConsistentValue - static value class B { - static { - Asserts.assertNotNull(A.c, "Should have returned C's default value"); - } - int i = 0; - } - - @LooselyConsistentValue - static value class C { - int i; - public C(int i) { - this.i = i; - } - } - - @LooselyConsistentValue - static value class D { - @Strict - @NullRestricted - static C c; - int i = 0; - static { - if (CircularityTest.b) { - // throw an exception to cause D's initialization to fail - throw new RuntimeException(); - } - } - } - - @LooselyConsistentValue - static value class E { - @Strict - @NullRestricted - static F f; - @Strict - @NullRestricted - static C c; - int i = 0; - } - - @LooselyConsistentValue - static value class F { - int i = 0; - static { - E.c = new C(5); - } - } - - @LooselyConsistentValue - static value class G { - @Strict - @NullRestricted - static H h; - int i = 0; - } - - @LooselyConsistentValue - static value class H { - int i = 0; - static { - if (CircularityTest.b) { - // throw an exception to cause H's initialization to fail - throw new RuntimeException(); - } - } - } - - @LooselyConsistentValue - static value class I { - @Strict - @NullRestricted - static J j; - @Strict - @NullRestricted - static H h; - int i = 0; - } - - @LooselyConsistentValue - static value class J { - int i = 0; - static { - CircularityTest.counter = 1; - H h = I.h; - CircularityTest.counter = 2; - } - } - - static public void main(String[] args) { - Throwable exception = null; - // Test 1: - // Initialization of A will trigger initialization of B which, in its static - // initializer will access a static inline field c of A that has not been initialized - // yet. The access must succeed (no exception) because the field is being - // accessed during the initialization of D, by the thread initializing D, - // and the value must be the default value of C (not null). - try { - A a = new A(); - } catch (Throwable t) { - exception = t; - } - Asserts.assertNull(exception, "Circularity should not have caused exceptions"); - - // Test 2: - // Class D will fail to initialized (exception thrown in its static initializer). - // Attempt to access a static inline field of D *after* its failed initialization - // should trigger an exception. - exception = null; - try { - D d = new D(); - } catch (Throwable t) { - // ignoring the exception thrown to cause initialization failure - } - try { - C c = D.c; - } catch (Throwable t) { - exception = t; - } - Asserts.assertNotNull(exception, "Accessing static fields of a class which failed to initialized should throw an exception"); - Asserts.assertEquals(exception.getClass(), java.lang.NoClassDefFoundError.class, "Wrong exception class"); - // Test 3: - // Initialization of E will trigger the initialization of F which, in its static initalizer, - // will initialized a static inline field of F before the JVM does. The JVM must not - // overwrite the value set by user code. - E e = new E(); - Asserts.assertEquals(E.c.i, 5, "JVM must not overwrite fields initialized by user code"); - - // Test 4: - // Initialization of G should fail because its static inline field h - exception = null; - try { - G g = new G(); - } catch(Throwable t) { - exception = t; - } - Asserts.assertNotNull(exception, "G's initialization should have failed"); - Asserts.assertEquals(exception.getClass(), java.lang.ExceptionInInitializerError.class, "Wrong exception"); - - // Test 5: - // Initialization of of I should fail when J tries to access I.h - exception = null; - try { - I i = new I(); - } catch(Throwable t) { - exception = t; - } - Asserts.assertNotNull(exception, "I's initialization should have failed"); - Asserts.assertEquals(exception.getClass(), java.lang.NoClassDefFoundError.class, "Wrong exception"); - Asserts.assertEquals(CircularityTest.counter, 1, "Didn't failed at the right place"); - } -} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/PreloadCircularityTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/PreloadCircularityTest.java index 8dc3fdccc4d..bf0f7d72fc2 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/PreloadCircularityTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/PreloadCircularityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -296,159 +296,6 @@ void test_9() throws Exception { out.shouldContain("java.lang.IncompatibleClassChangeError: Class PreloadCircularityTest$Class9a expects class PreloadCircularityTest$Class9b to be a value class, but it is an identity class"); } - static value class Class10a { - @Strict - @NullRestricted - Class10b vb = new Class10b(); - } - - static value class Class10b { } - - // void test_10() throws Exception { - // OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class10a"); - // out.shouldHaveExitValue(1); - // out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class10b during loading of class PreloadCircularityTest$Class10a. Cause: a null-free non-static field is declared with this type"); - // out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class10b is not implicitly constructible and it is used in a null restricted non-static field (not supported)"); - // } - - // Testing preloading due to static fields - - static value class Class50a { - @Strict - @NullRestricted - static Class50a sa = new Class50a(); - } - - void test_50() throws Exception { - OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class50a"); - out.shouldHaveExitValue(0); - out.shouldNotContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class50a"); - } - - static value class Class51a { - @Strict - @NullRestricted - static Class51b sb = new Class51b(); - - @Strict - @NullRestricted - static Class51c sc = new Class51c(); - } - - static value class Class51b { - @Strict - @NullRestricted - static Class51a sa = new Class51a(); - } - - static value class Class51c { - @Strict - @NullRestricted - Class51a sa = new Class51a(); - } - - void test_51() throws Exception { - OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class51a"); - out.shouldHaveExitValue(0); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51b during linking of class PreloadCircularityTest$Class51a. Cause: a null-free static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51b during linking of class PreloadCircularityTest$Class51a (cause: null-free static field) succeeded"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51c during linking of class PreloadCircularityTest$Class51a. Cause: a null-free static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during loading of class PreloadCircularityTest$Class51c. Cause: a null-free non-static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during loading of class PreloadCircularityTest$Class51c (cause: null-free non-static field) succeeded"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51c during linking of class PreloadCircularityTest$Class51a (cause: null-free static field) succeeded"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during linking of class PreloadCircularityTest$Class51b. Cause: a null-free static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during linking of class PreloadCircularityTest$Class51b (cause: null-free static field) succeeded"); - } - - static value class Class52a { - @Strict - @NullRestricted - static Class52b vb = new Class52b(); - } - - static value class Class52b { - @Strict - @NullRestricted - Class52c vc = new Class52c(); - } - - static value class Class52c { - @Strict - @NullRestricted - Class52b vb = new Class52b(); - } - - void test_52() throws Exception { - OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class52a"); - out.shouldHaveExitValue(1); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class52b during linking of class PreloadCircularityTest$Class52a. Cause: a null-free static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class52c during loading of class PreloadCircularityTest$Class52b. Cause: a null-free non-static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class52b during loading of class PreloadCircularityTest$Class52c. Cause: a null-free non-static field is declared with this type"); - out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class52b during loading of class PreloadCircularityTest$Class52c (cause: null-free non-static field) failed: java/lang/ClassCircularityError"); - out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class52c during loading of class PreloadCircularityTest$Class52b (cause: null-free non-static field) failed: java/lang/ClassCircularityError"); - } - - static value class Class53a { - Class53b vb = new Class53b(); - - @Strict - @NullRestricted - static Class53b sb = new Class53b(); - } - - static value class Class53b { - @Strict - @NullRestricted - Class53a va = new Class53a(); - } - - // In the following test, Class53a fails to optimistically load Class53b at load time, but successfully loads it at link time - - // void test_53() throws Exception { - // OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class53a"); - // out.shouldHaveExitValue(0); - // out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class53b during loading of class PreloadCircularityTest$Class53a. Cause: field type in LoadableDescriptors attribute"); - // out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b. Cause: a null-free non-static field is declared with this type"); - // out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b (cause: null-free non-static field) failed: java/lang/ClassCircularityError"); - // out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class53b during loading of class PreloadCircularityTest$Class53a (cause: field type in LoadableDescriptors attribute) failed : java/lang/ClassCircularityError"); - // out.shouldContain("[info ][class,preload] Preloading of class PreloadCircularityTest$Class53b during linking of class PreloadCircularityTest$Class53a. Cause: a null-free static field is declared with this type"); - // out.shouldContain("[info ][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b. Cause: a null-free non-static field is declared with this type"); - // out.shouldContain("[info ][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b (cause: null-free non-static field) succeeded"); - // out.shouldContain("[info ][class,preload] Preloading of class PreloadCircularityTest$Class53b during linking of class PreloadCircularityTest$Class53a (cause: null-free static field) succeeded"); - // } - - static value class Class54a { - @Strict - @NullRestricted - static Class54b sb = new Class54b(); - } - - static class Class54b { } - - void test_54() throws Exception { - OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class54a"); - out.shouldHaveExitValue(1); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class54b during linking of class PreloadCircularityTest$Class54a. Cause: a null-free static field is declared with this type"); - out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class54b during linking of class PreloadCircularityTest$Class54a (cause: null-free static field) succeeded"); - out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class54a expects class PreloadCircularityTest$Class54b to be a value class but it is an identity class"); - } - - static class Class55a { - @Strict - @NullRestricted - static Class55b sb = new Class55b(); - } - - static value class Class55b { } - - // void test_55() throws Exception { - // OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class55a"); - // out.shouldHaveExitValue(1); - // out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class55b during linking of class PreloadCircularityTest$Class55a. Cause: a null-free static field is declared with this type"); - // out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class55b during linking of class PreloadCircularityTest$Class55a (cause: null-free static field) succeeded"); - // out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class55b is not implicitly constructible and it is used in a null restricted static field (not supported)"); - // } - public static class TestHelper { public static void main(String[] args) { try { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/LDTest.jcod b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/LDTest.jcod new file mode 100644 index 00000000000..8d65113774d --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/LDTest.jcod @@ -0,0 +1,208 @@ +/* + * 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. + * + * 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. + * + */ + +// This file contains a class file with an invalid entry in its +// LoadableDescriptors attribute. The class file has been generated +// from the source below with editing to the constant pool and +// the LoadableDescriptors attribute. +// +// +// import jdk.internal.vm.annotation.NullRestricted; +// import jdk.internal.vm.annotation.Strict; +// +// +// public class LDTest { +// static value class Point { +// short s0, s1; +// Point(short sa, short sb) { +// s0 = sa; +// s1 = sb; +// } +// } +// +// @Strict +// @NullRestricted +// Point p = new Point((short)0, (short)0); +// +// public static void main(String[] args) { +// LDTest test = new LDTest(); +// } +// } + + +class LDTest { + 0xCAFEBABE; + 65535; // minor version + 70; // version + [] { // Constant Pool + ; // first element is empty + class #2; // #1 + Utf8 "LDTest$Point"; // #2 + Method #1 #4; // #3 + NameAndType #5 #6; // #4 + Utf8 ""; // #5 + Utf8 "(SS)V"; // #6 + Field #8 #9; // #7 + class #10; // #8 + NameAndType #11 #12; // #9 + Utf8 "LDTest"; // #10 + Utf8 "p"; // #11 + Utf8 "LLDTest$Point;"; // #12 + Method #14 #15; // #13 + class #16; // #14 + NameAndType #5 #17; // #15 + Utf8 "java/lang/Object"; // #16 + Utf8 "()V"; // #17 + Method #8 #15; // #18 + Utf8 "RuntimeVisibleAnnotations"; // #19 + Utf8 "Ljdk/internal/vm/annotation/NullRestricted;"; // #20 + Utf8 "RuntimeInvisibleAnnotations"; // #21 + Utf8 "Ljdk/internal/vm/annotation/Strict;"; // #22 + Utf8 "Code"; // #23 + Utf8 "LineNumberTable"; // #24 + Utf8 "main"; // #25 + Utf8 "([Ljava/lang/String;)V"; // #26 + Utf8 "SourceFile"; // #27 + Utf8 "LDTest.java"; // #28 + Utf8 "NestMembers"; // #29 + Utf8 "InnerClasses"; // #30 + Utf8 "Point"; // #31 + Utf8 "LoadableDescriptors"; // #32 + Utf8 "[V"; // #33 // <== new invalid descriptor + } // Constant Pool + + 0x0021; // access + #8;// this_cpx + #14;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // Fields + { // field + 0x0800; // access + #11; // name_index + #12; // descriptor_index + [] { // Attributes + Attr(#19) { // RuntimeVisibleAnnotations + [] { // annotations + { // annotation + #20; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end RuntimeVisibleAnnotations + ; + Attr(#21) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #22; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end RuntimeInvisibleAnnotations + } // Attributes + } + } // Fields + + [] { // Methods + { // method + 0x0001; // access + #5; // name_index + #17; // descriptor_index + [] { // Attributes + Attr(#23) { // Code + 5; // max_stack + 1; // max_locals + Bytes[]{ + 0x2ABB0001590303B7; + 0x0003B500072AB700; + 0x0DB1; + } + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#24) { // LineNumberTable + [] { // line_number_table + 0 14; + 13 5; + 17 14; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } + ; + { // method + 0x0009; // access + #25; // name_index + #26; // descriptor_index + [] { // Attributes + Attr(#23) { // Code + 2; // max_stack + 2; // max_locals + Bytes[]{ + 0xBB000859B700124C; + 0xB1; + } + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#24) { // LineNumberTable + [] { // line_number_table + 0 19; + 8 20; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } + } // Methods + + [] { // Attributes + Attr(#27) { // SourceFile + #28; + } // end SourceFile + ; + Attr(#29) { // NestMembers + [] { // classes + #1; + } + } // end NestMembers + ; + Attr(#30) { // InnerClasses + [] { // classes + #1 #8 #31 24; + } + } // end InnerClasses + ; + Attr(#32) { // LoadableDescriptors + 0x00010021; // <== modified index to contant pool + } // end LoadableDescriptors + } // Attributes +} // end class LDTest diff --git a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/layout.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/TestIllegalLoadableDescriptors.java similarity index 53% rename from test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/layout.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/TestIllegalLoadableDescriptors.java index feb6e46e375..9c0e323b953 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/layout.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classfileparser/TestIllegalLoadableDescriptors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -19,28 +19,32 @@ * 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 + * @summary test a LoadableDescriptors attribute with an invalid entry + * @enablePreview + * @compile LDTest.jcod TestIllegalLoadableDescriptors.java + * @run main/othervm TestIllegalLoadableDescriptors */ -package jit.misctests.fpustack; - -import java.util.*; -import java.awt.*; -import java.applet.Applet; -import nsk.share.TestFailure; - -public class layout implements ilayout { - public void formatNodes( Node[] nodes, Dimension d, FontMetrics fm ) { - int h = d.height/2 - 10 ; - double alpha = -Math.PI/2; - for ( int j = 0; j < nodes.length; j++) { - Node n = nodes[j]; - int w = d.width/2 - fm.stringWidth( n.lbl )/2; - n.x = d.width/2 + (int)(w*Math.cos( alpha )); +public class TestIllegalLoadableDescriptors { - n.y = d.height/2 + (int)(h*Math.sin( alpha )); - alpha += 2*Math.PI/nodes.length; - } - } + public static void main(String[] args) throws ClassNotFoundException { + boolean gotException = false; + try { + Class newClass = Class.forName("LDTest"); + } catch (java.lang.ClassFormatError e) { + gotException = true; + if (!e.getMessage().contains("Descriptor from LoadableDescriptors attribute at index \"33\" in class LDTest has illegal signature \"[V")) { + throw new RuntimeException( "Wrong ClassFormatError: " + e.getMessage()); + } + } + if (!gotException) { + throw new RuntimeException("Missing ClassFormatError"); + } + } } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classloading/ConcurrentClassLoadingTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classloading/ConcurrentClassLoadingTest.java index e734f575668..a32495e3785 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classloading/ConcurrentClassLoadingTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/classloading/ConcurrentClassLoadingTest.java @@ -30,7 +30,7 @@ * @library /test/lib * @enablePreview * @compile BigClassTreeClassLoader.java - * @run junit/othervm -XX:NonNMethodCodeHeapSize=256M -XX:ProfiledCodeHeapSize=512M -XX:NonProfiledCodeHeapSize=512M ConcurrentClassLoadingTest + * @run junit/othervm -XX:ReservedCodeCacheSize=2G ConcurrentClassLoadingTest */ import java.util.Optional; diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive128int.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmp.jasm similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/array/sum/Primitive128int.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmp.jasm index cac7f1825e2..d56a9c5a1bd 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive128int.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmp.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,23 +20,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.sum; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive128int extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int sum(Primitive128int st) { - int s = 0; - int[] values = st.arr; - for (int i = 0; i < values.length; i++) { - s += values[i]; - } - return s; - } - -} +class UninitThisAcmp version 69:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + aload_1; + if_acmpne L14; + nop; + L14: stack_frame_type append; + locals_map class java/lang/Object; + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisAcmp diff --git a/test/jdk/java/lang/Thread/virtual/LockingMode.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmpOld.jasm similarity index 65% rename from test/jdk/java/lang/Thread/virtual/LockingMode.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmpOld.jasm index 59fde4a5f49..582ed5285bc 100644 --- a/test/jdk/java/lang/Thread/virtual/LockingMode.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisAcmpOld.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,19 +21,20 @@ * questions. */ -import java.lang.management.ManagementFactory; -import com.sun.management.HotSpotDiagnosticMXBean; - -class LockingMode { - private LockingMode() { } - - /** - * Returns true if using legacy locking mode. - */ - static boolean isLegacy() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode") - .getValue() - .equals("1"); - } -} \ No newline at end of file +class UninitThisAcmpOld version 49:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + aload_1; + if_acmpne L14; + nop; + L14: invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisAcmpOld diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNull.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNull.jasm new file mode 100644 index 00000000000..9b31e357d86 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNull.jasm @@ -0,0 +1,42 @@ +/* + * 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. + * + * 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. + */ + +class UninitThisIfNull version 69:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + ifnonnull L14; + nop; + L14: stack_frame_type append; + locals_map class java/lang/Object; + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisIfNull diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNullOld.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNullOld.jasm new file mode 100644 index 00000000000..9391f0c23d0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitThisIfNullOld.jasm @@ -0,0 +1,40 @@ +/* + * 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. + * + * 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. + */ + +class UninitThisIfNullOld version 49:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + ifnonnull L14; + nop; + L14: aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisIfNullOld diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmp.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmp.jasm new file mode 100644 index 00000000000..c4e070afcfb --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmp.jasm @@ -0,0 +1,44 @@ +/* + * 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. + * + * 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. + */ + +class UninitializedAcmp version 69:0 +{ + Method "":"()V" + stack 5 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + aload_0; + L1: new class java/lang/Object; + dup; + dup; + dup; + if_acmpne L18; + nop; + L18: stack_frame_type full; + locals_map class UninitializedAcmp; + stack_map class UninitializedAcmp, at L1, at L1; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedAcmp diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmpOld.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmpOld.jasm new file mode 100644 index 00000000000..ce93c00a678 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedAcmpOld.jasm @@ -0,0 +1,41 @@ +/* + * 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. + * + * 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. + */ + +class UninitializedAcmpOld version 49:0 +{ + Method "":"()V" + stack 5 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + aload_0; + L1: new class java/lang/Object; + dup; + dup; + dup; + if_acmpne L18; + nop; + L18: invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedAcmpOld diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Primitive32.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNull.jasm similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/field/copy/Primitive32.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNull.jasm index 6f70bb42548..1465c52cdd9 100644 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Primitive32.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNull.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,23 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.field.copy; -import org.openjdk.bench.valhalla.field.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive32 extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p32int_copy(Primitive32int s, Primitive32int d) { - P32int[] src = s.arr; - P32int[] dst = d.arr; - for(int i=0; i":"()V" + stack 3 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + L1: new class java/lang/Object; + dup; + dup; + ifnonnull L18; + nop; + L18: stack_frame_type full; + locals_map class UninitializedIfNull; + stack_map at L1, at L1; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedIfNull diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNullOld.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNullOld.jasm new file mode 100644 index 00000000000..605ce466cc5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedIfNullOld.jasm @@ -0,0 +1,39 @@ +/* + * 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. + * + * 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. + */ + +class UninitializedIfNullOld version 49:0 +{ + Method "":"()V" + stack 3 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + L1: new class java/lang/Object; + dup; + dup; + ifnonnull L18; + nop; + L18: invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedIfNullOld diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedThisVerificationTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedThisVerificationTest.java new file mode 100644 index 00000000000..85690298575 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/UninitializedThisVerificationTest.java @@ -0,0 +1,58 @@ +/* + * 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. + * + * 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 + * @bug 8366743 + * @summary Test spec rules for uninitialized + * @compile UninitThisAcmp.jasm UninitThisIfNull.jasm + * UninitializedIfNull.jasm UninitializedAcmp.jasm + * UninitThisAcmpOld.jasm UninitThisIfNullOld.jasm + * UninitializedAcmpOld.jasm UninitializedIfNullOld.jasm + * @run main/othervm -Xlog:verification UninitializedThisVerificationTest + */ + +public class UninitializedThisVerificationTest { + + public static void main(String[] args) throws Exception { + String[] testNames = { "UninitThisAcmp", "UninitThisIfNull", + "UninitializedAcmp", "UninitializedIfNull", + "UninitThisAcmpOld", "UninitThisIfNullOld", + "UninitializedAcmpOld", "UninitializedIfNullOld" }; + int fails = 0; + for (String test : testNames) { + System.out.println("Testing " + test); + try { + Class c = Class.forName(test); + System.out.println("Failed"); + fails++; + } catch (java.lang.VerifyError e) { + System.out.println("Passed"); + } + } + + if (fails > 0) { + throw new RuntimeException("Failed: Expected VerifyError in " + fails + " tests"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java b/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java deleted file mode 100644 index 56bb705a0b2..00000000000 --- a/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2021, 2024, 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. - */ -import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/* - * Tests that JNI monitors work correctly with virtual threads, - * There are multiple test scenarios that we check using unified logging output - * (both positive and negative tests). Each test case is handled by its own @-test - * definition so that we can run each sub-test independently. - * - * The original bug was only discovered because the ForkJoinPool worker thread terminated - * and trigerred an assertion failure. So we use a custom scheduler to give us control. - */ - -/** - * @test id=normal - * @bug 8327743 - * @summary Normal lock then unlock - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor Normal - */ - -/** - * @test id=multiNormal - * @bug 8327743 - * @summary Normal lock then unlock by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiNormal - */ - -/** - * @test id=missingUnlock - * @bug 8327743 - * @summary Don't do the unlock and exit normally - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MissingUnlock - */ - -/** - * @test id=multiMissingUnlock - * @bug 8327743 - * @summary Don't do the unlock and exit normally, by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiMissingUnlock - */ - -/** - * @test id=missingUnlockWithThrow - * @bug 8327743 - * @summary Don't do the unlock and exit by throwing - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MissingUnlockWithThrow - */ - -/** - * @test id=multiMissingUnlockWithThrow - * @bug 8327743 - * @summary Don't do the unlock and exit by throwing, by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiMissingUnlockWithThrow - */ - -public class JNIMonitor { - - public static void main(String[] args) throws Exception { - String test = args[0]; - String[] cmdArgs = new String[] { - "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, - // Grant access to ThreadBuilders$VirtualThreadBuilder - "--add-opens=java.base/java.lang=ALL-UNNAMED", - // Enable the JNI warning - "-Xcheck:jni", - "-Xlog:jni=debug", - // Enable thread termination logging as a visual cross-check - "-Xlog:thread+os=info", - // We only count monitors in LM_LEGACY mode - "-XX:LockingMode=1", - // Disable compact headers since that switches locking mode to LM_LIGHTWEIGHT - "-XX:-UseCompactObjectHeaders", - "JNIMonitor$" + test, - }; - OutputAnalyzer oa = ProcessTools.executeTestJava(cmdArgs); - oa.shouldHaveExitValue(0); - oa.stdoutShouldMatch(terminated); - - switch(test) { - case "Normal": - case "MultiNormal": - oa.stdoutShouldNotMatch(stillLocked); - break; - case "MissingUnlock": - oa.stdoutShouldMatch(stillLocked); - break; - case "MultiMissingUnlock": - parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT); - break; - case "MissingUnlockWithThrow": - oa.stdoutShouldMatch(stillLocked); - oa.stderrShouldContain(throwMsg); - break; - case "MultiMissingUnlockWithThrow": - parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT); - parseOutputForPattern(oa.stderrAsLines(), throwMsg, MULTI_THREAD_COUNT); - break; - - default: throw new Error("Unknown arg: " + args[0]); - } - oa.reportDiagnosticSummary(); - } - - // The number of threads for a multi tests. Arbitrarily chosen to be > 1 but small - // enough to not waste too much time. - static final int MULTI_THREAD_COUNT = 5; - - // The logging message for leaving a monitor JNI locked has the form - // [0.187s][debug][jni] VirtualThread (tid: 28, carrier id: 29) exiting with Objects still locked by JNI MonitorEnter. - // but if the test is run with other logging options then whitespace may get introduced in the - // log decorator sections, so ignore those. - static final String stillLocked = "VirtualThread \\(tid:.*exiting with Objects still locked by JNI MonitorEnter"; - // The carrier thread termination logging has the form: - // [1.394s][info][os,thread] JavaThread exiting (name: "pool-1-thread-1", tid: 3090592). - static final String terminated = "JavaThread exiting \\(name: \"pool-1-thread-1\""; - - static final String throwMsg = "Terminating via exception as requested"; - - // Check the process logging output for the given pattern to see if the expected number of - // lines are found. - private static void parseOutputForPattern(List lines, String pattern, int expected) { - Pattern p = Pattern.compile(pattern); - int found = 0; - for (String line : lines) { - Matcher m = p.matcher(line); - if (m.find()) { - found++; - } - } - if (found != expected) { - throw new RuntimeException("Checking for pattern \"" + pattern + "\": expected " - + expected + " but found " + found); - } - } - - - // straight-forward interface to JNI monitor functions - static native int monitorEnter(Object o); - static native int monitorExit(Object o); - - // Isolate the native library loading to the actual test cases, not the class that - // jtreg Driver will load and execute. - static class TestBase { - - static { - System.loadLibrary("JNIMonitor"); - } - - // This gives us a way to control the scheduler used for our virtual threads. The test - // only works as intended when the virtual threads run on the same carrier thread (as - // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it). - // The original issue was also only discovered due to the carrier thread terminating - // unexpectedly, so we can force that condition too by shutting down our custom scheduler. - private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { - Thread.Builder.OfVirtual builder = Thread.ofVirtual(); - try { - Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); - Constructor ctor = clazz.getDeclaredConstructor(Executor.class); - ctor.setAccessible(true); - return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException re) { - throw re; - } - throw new RuntimeException(e); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable { - final Object[] monitors = new Object[nThreads]; - for (int i = 0; i < nThreads; i++) { - monitors[i] = new Object(); - } - final AtomicReference exception = new AtomicReference(); - // Ensure all our VT's operate of the same carrier, sequentially. - ExecutorService scheduler = Executors.newSingleThreadExecutor(); - ThreadFactory factory = virtualThreadBuilder(scheduler).factory(); - for (int i = 0 ; i < nThreads; i++) { - Object monitor = skipUnlock ? monitors[i] : monitors[0]; - Thread th = factory.newThread(() -> { - try { - int res = monitorEnter(monitor); - Asserts.assertTrue(res == 0, "monitorEnter should return 0."); - Asserts.assertTrue(Thread.holdsLock(monitor), "monitor should be owned"); - Thread.yield(); - if (!skipUnlock) { - res = monitorExit(monitor); - Asserts.assertTrue(res == 0, "monitorExit should return 0."); - Asserts.assertFalse(Thread.holdsLock(monitor), "monitor should be unowned"); - } - } catch (Throwable t) { - exception.set(t); - } - if (throwOnExit) { - throw new RuntimeException(throwMsg); - } - }); - th.start(); - th.join(); - if (exception.get() != null) { - throw exception.get(); - } - } - // Now force carrier thread to shutdown. - scheduler.shutdown(); - } - } - - // These are the actual test case classes that get exec'd. - - static class Normal extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, false, false); - } - } - - static class MultiNormal extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, false, false); - } - } - - static class MissingUnlock extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, true, false); - } - } - - static class MultiMissingUnlock extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, true, false); - } - } - - static class MissingUnlockWithThrow extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, true, true); - } - } - - static class MultiMissingUnlockWithThrow extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, true, true); - } - } - -} diff --git a/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java b/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java index 5c41565db8d..e22c1b59394 100644 --- a/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java +++ b/test/hotspot/jtreg/serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Google and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,7 @@ * @summary Verifies that AsyncGetCallTrace is call-able and provides sane information. * @compile ASGCTBaseTest.java * @requires os.family == "linux" - * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="arm" | os.arch=="aarch64" | os.arch=="ppc64" | os.arch=="s390" | os.arch=="riscv64" + * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="arm" | os.arch=="aarch64" | os.arch=="ppc64" | os.arch=="ppc64le" | os.arch=="s390" | os.arch=="riscv64" * @requires vm.jvmti * @run main/othervm/native -agentlib:AsyncGetCallTraceTest MyPackage.ASGCTBaseTest */ diff --git a/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java b/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java index 62dfd6f8a79..bb08be91dac 100644 --- a/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java +++ b/test/hotspot/jtreg/serviceability/HeapDump/UnmountedVThreadNativeMethodAtTop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -38,6 +38,7 @@ import java.util.concurrent.CountDownLatch; import com.sun.management.HotSpotDiagnosticMXBean; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -47,6 +48,17 @@ public class UnmountedVThreadNativeMethodAtTop { + boolean done; + + /** + * The tests accumulate previous heap dumps. Trigger GC before each test to get rid of them. + * This makes dumps smaller, processing faster, and avoids OOMs + */ + @BeforeEach + void doGC() { + System.gc(); + } + /** * Test dumping the heap while a virtual thread is blocked entering a synchronized native method. */ @@ -96,7 +108,9 @@ void VThreadBlockedAtOjectWait() throws Exception { started.countDown(); try { synchronized (lock) { - lock.wait(); + while (!done) { + lock.wait(); + } } } catch (InterruptedException e) { } }); @@ -109,11 +123,11 @@ void VThreadBlockedAtOjectWait() throws Exception { Path dumpFile = dumpHeap(); verifyHeapDump(dumpFile); - + } finally { synchronized (lock) { + done = true; lock.notify(); } - } finally { vthread.join(); } } @@ -159,4 +173,4 @@ private void await(Thread thread, Thread.State expectedState) throws Interrupted static { System.loadLibrary("UnmountedVThreadNativeMethodAtTop"); } -} \ No newline at end of file +} diff --git a/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java index ec41c8b10de..5c8d8c9df65 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -65,7 +65,7 @@ public Process launch() { String cmd = prepareLaunch(java, argHandler.getPipePort()); - Debugee debuggee = binder.startLocalDebugee(cmd); + Debugee debuggee = binder.startDebugee(cmd); debuggee.redirectOutput(log); String line = pipe.readln(); diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java index cc601147714..7e571f7703b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java @@ -32,68 +32,27 @@ * @run main/othervm -javaagent:redefineagent.jar ClassVersionAfterRedefine */ -import java.io.InputStream; import java.lang.reflect.Method; import static jdk.test.lib.Asserts.assertTrue; public class ClassVersionAfterRedefine extends ClassLoader { - private static String myName = ClassVersionAfterRedefine.class.getName(); - - private static byte[] getBytecodes(String name) throws Exception { - InputStream is = ClassVersionAfterRedefine.class.getResourceAsStream(name + ".class"); - byte[] buf = is.readAllBytes(); - System.out.println("sizeof(" + name + ".class) == " + buf.length); - return buf; - } - - private static int getStringIndex(String needle, byte[] buf) { - return getStringIndex(needle, buf, 0); - } - - private static int getStringIndex(String needle, byte[] buf, int offset) { - outer: - for (int i = offset; i < buf.length - offset - needle.length(); i++) { - for (int j = 0; j < needle.length(); j++) { - if (buf[i + j] != (byte)needle.charAt(j)) continue outer; - } - return i; - } - return 0; - } - - private static void replaceString(byte[] buf, String name, int index) { - for (int i = index; i < index + name.length(); i++) { - buf[i] = (byte)name.charAt(i - index); - } - } - - private static void replaceAllStrings(byte[] buf, String oldString, String newString) throws Exception { - assertTrue(oldString.length() == newString.length(), "must have same length"); - int index = -1; - while ((index = getStringIndex(oldString, buf, index + 1)) != 0) { - replaceString(buf, newString, index); - } - } - public static void main(String[] s) throws Exception { - byte[] buf = getBytecodes("TestClassOld"); - // Poor man's renaming of class "TestClassOld" to "TestClassXXX" - replaceAllStrings(buf, "TestClassOld", "TestClassXXX"); ClassVersionAfterRedefine cvar = new ClassVersionAfterRedefine(); + + byte[] buf = RedefineClassHelper.replaceClassName(cvar, "TestClassOld", "TestClassXXX"); Class old = cvar.defineClass(null, buf, 0, buf.length); Method foo = old.getMethod("foo"); Object result = foo.invoke(null); assertTrue("java-lang-String".equals(result)); System.out.println(old.getSimpleName() + ".foo() = " + result); - buf = getBytecodes("TestClassNew"); // Rename class "TestClassNew" to "TestClassXXX" so we can use it for // redefining the original version of "TestClassXXX" (i.e. "TestClassOld"). - replaceAllStrings(buf, "TestClassNew", "TestClassXXX"); - // Now redine the original version of "TestClassXXX" (i.e. "TestClassOld"). + buf = RedefineClassHelper.replaceClassName(cvar, "TestClassNew", "TestClassXXX"); + // Now redefine the original version of "TestClassXXX" (i.e. "TestClassOld"). RedefineClassHelper.redefineClass(old, buf); result = foo.invoke(null); assertTrue("java.lang.String".equals(result)); diff --git a/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c b/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c index 56f285aee41..2f532384fa6 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c +++ b/test/hotspot/jtreg/serviceability/jvmti/VMEvent/libVMEventTest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -47,12 +47,36 @@ extern "C" { #endif +// JVMTI_ERROR_WRONG_PHASE guard +static jrawMonitorID event_mon = NULL; +static int is_vm_dead = 0; + +void lock(jvmtiEnv *jvmti, JNIEnv *jni) { + jvmtiError err = (*jvmti)->RawMonitorEnter(jvmti, event_mon); + if (err != JVMTI_ERROR_NONE) { + JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorEnter failed")); + } +} + +void unlock(jvmtiEnv *jvmti, JNIEnv *jni) { + jvmtiError err = (*jvmti)->RawMonitorExit(jvmti, event_mon); + if (err != JVMTI_ERROR_NONE) { + JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorExit failed")); + } +} + extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread, jobject object, jclass klass, jlong size) { + lock(jvmti, jni); + if (is_vm_dead) { + unlock(jvmti, jni); + return; + } + char *signature = NULL; jvmtiError error = (*jvmti)->GetClassSignature(jvmti, klass, &signature, NULL); @@ -78,25 +102,40 @@ extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti, JNI_ENV_ARGS2(jni, "Failed during the CallObjectMethod call")); } } + unlock(jvmti, jni); } extern JNIEXPORT void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread) { (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL); } +extern JNIEXPORT void JNICALL OnVMDeath(jvmtiEnv *jvmti, JNIEnv *jni) { + lock(jvmti, jni); + is_vm_dead = 1; + unlock(jvmti, jni); +} + extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { jvmtiEnv *jvmti; jvmtiEventCallbacks callbacks; jvmtiCapabilities caps; + jvmtiError err; if ((*jvm)->GetEnv(jvm, (void **) (&jvmti), JVMTI_VERSION) != JNI_OK) { return JNI_ERR; } + err = (*jvmti)->CreateRawMonitor(jvmti, "Event Monitor", &event_mon); + if (err != JVMTI_ERROR_NONE) { + printf("CreateRawMonitor failed: %d\n", err); + return JNI_ERR; + } + memset(&callbacks, 0, sizeof(callbacks)); callbacks.VMObjectAlloc = &VMObjectAlloc; callbacks.VMInit = &OnVMInit; + callbacks.VMDeath = &OnVMDeath; memset(&caps, 0, sizeof(caps)); caps.can_generate_vm_object_alloc_events = 1; @@ -104,6 +143,7 @@ extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); + (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL); return 0; } diff --git a/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/ValueHeapwalkingTest.java b/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/ValueHeapwalkingTest.java new file mode 100644 index 00000000000..7ed13ad1951 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/ValueHeapwalkingTest.java @@ -0,0 +1,351 @@ +/* + * 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. + * + * 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 + * @summary Tests heapwalking API (FollowReferences, IterateThroughHeap, GetObjectsWithTags) for value objects. + * @requires vm.jvmti + * @modules java.base/jdk.internal.vm.annotation java.base/jdk.internal.value + * @enablePreview + * @run main/othervm/native -agentlib:ValueHeapwalkingTest + * -XX:+UnlockDiagnosticVMOptions + * -XX:+UseArrayFlattening + * -XX:+UseFieldFlattening + * -XX:+UseAtomicValueFlattening + * -XX:+UseNullableValueFlattening + * -XX:+PrintInlineLayout + * -XX:+PrintFlatArrayLayout + * -Xlog:jvmti+table + * ValueHeapwalkingTest + */ + +import java.lang.ref.Reference; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; + +import java.lang.reflect.Field; + +public class ValueHeapwalkingTest { + + static value class Value { + int v; + Value() { + this(0); + } + Value(int v) { + this.v = v; + } + } + + // flat object has flat field (address of the field is the same as address of the object) + static value class Value2 { + @Strict + @NullRestricted + public Value v1; + @Strict + @NullRestricted + public Value v2; + Value2() { + this(0); + } + Value2(int i) { + this.v1 = new Value(i); + this.v2 = new Value(i+1); + super(); + } + } + + static value class ValueHolder { + public Value v1; + @Strict + @NullRestricted + public Value v2; + public Value v_null; + + public Value2 v2_1; + @Strict + @NullRestricted + public Value2 v2_2; + + public Value[] v_arr; + public Value2[] v2_arr; + + public ValueHolder(int seed) throws Exception { + v1 = new Value(seed); + v2 = new Value(seed + 1); + v_null = null; + + v2_1 = new Value2(seed + 6); + v2_2 = new Value2(seed + 8); + + v_arr = createValueArray(seed); + v2_arr = createValue2Array(seed); + } + } + + static Value[] createValueArray(int seed) throws Exception { + Value[] arr = (Value[])ValueClass.newNullableAtomicArray(Value.class, 5); + for (int i = 0; i < arr.length; i++) { + arr[i] = i == 2 ? null : new Value(seed + 10 + i); + } + return arr; + } + + static Value2[] createValue2Array(int seed) throws Exception { + Value2[] arr = (Value2[])ValueClass.newNullRestrictedNonAtomicArray(Value2.class, 5, Value2.class.newInstance()); + for (int i = 0; i < arr.length; i++) { + arr[i] = new Value2(seed + 20 + i * 2); + } + return arr; + } + + static final int TAG_VALUE_CLASS = 1; + static final int TAG_VALUE2_CLASS = 2; + static final int TAG_HOLDER_CLASS = 3; + static final int TAG_VALUE_ARRAY = 4; + static final int TAG_VALUE2_ARRAY = 5; + + static final int TAG_MIN = TAG_VALUE_CLASS; + static final int TAG_MAX = TAG_VALUE2_ARRAY; + + static String tagStr(int tag) { + String suffix = " (tag " + tag + ")"; + switch (tag) { + case TAG_VALUE_CLASS: return "Value class" + suffix; + case TAG_VALUE2_CLASS: return "Value2 class" + suffix; + case TAG_HOLDER_CLASS: return "ValueHolder class" + suffix; + case TAG_VALUE_ARRAY: return "Value[] object" + suffix; + case TAG_VALUE2_ARRAY: return "Value2[] object" + suffix; + } + return "Unknown" + suffix; + } + + static native void setTag(Object object, long tag); + static native long getTag(Object object); + + static native void reset(); + + static native void followReferences(); + + static native void iterateThroughHeap(); + + static native int count(int classTag); + static native int refCount(int fromTag, int toTag); + static native int primitiveFieldCount(int tag); + + static native long getMaxTag(); + + static native int getObjectWithTags(long minTag, long maxTag, Object[] objects, long[] tags); + + + // counts non-null elements in the array + static int nonNullCount(T[] array) { + return (int)Arrays.stream(array).filter(e -> e != null).count(); + } + + static void verifyMinCount(int classTag, int minCount) { + int count = count(classTag); + String msg = tagStr(classTag) + " count: " + count + ", min expected: " + minCount; + if (count < minCount) { + throw new RuntimeException(msg); + } + System.out.println(msg); + } + + static void verifyRefCount(int tagFrom, int tagTo, int expectedCount) { + int count = refCount(tagFrom, tagTo); + String msg = "Ref.count from " + tagStr(tagFrom) + " to " + tagStr(tagTo) + ": " + + count + ", expected: " + expectedCount; + if (count != expectedCount) { + throw new RuntimeException(msg); + } + System.out.println(msg); + } + + static void verifyPrimitiveFieldCount(int classTag, int expectedCount) { + int count = primitiveFieldCount(classTag); + String msg = "Primitive field count from " + tagStr(classTag) + ": " + + count + ", expected: " + expectedCount; + if (count != expectedCount) { + throw new RuntimeException(msg); + } + System.out.println(msg); + } + + + static void printObject(Object obj) { + printObject("", obj); + } + + static void printObject(String prefix, Object obj) { + if (obj == null) { + System.out.println(prefix + "null"); + return; + } + + Class clazz = obj.getClass(); + System.out.println(prefix + "Object (class " + clazz.getName() + ", tag = " + getTag(obj) + ", class tag = " + getTag(clazz)); + + if (clazz.isArray()) { + Class elementType = clazz.getComponentType(); + int length = java.lang.reflect.Array.getLength(obj); + System.out.println(prefix + "Array of " + elementType + ", length = " + length + " ["); + for (int i = 0; i < length; i++) { + Object element = java.lang.reflect.Array.get(obj, i); + if (elementType.isPrimitive()) { + if (i == 0) { + System.out.print(prefix + " "); + } else { + System.out.print(", "); + } + System.out.print(prefix + "(" + i + "):" + element); + } else { + System.out.println(prefix + "(" + i + "):" + "NOT primitive"); + printObject(prefix + " ", element); + } + } + System.out.println(prefix + "]"); + } else { + while (clazz != null && clazz != Object.class) { + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + try { + field.setAccessible(true); + Object value = field.get(obj); + Class fieldType = field.getType(); + System.out.println(prefix + "- " + field.getName() + " (" + fieldType + ") = " + value); + + if (!fieldType.isPrimitive()) { + printObject(prefix + " ", value); + } + } catch (IllegalAccessException | java.lang.reflect.InaccessibleObjectException e) { + System.err.println(" Error accessing field " + field.getName() + ": " + e.getMessage()); + } + } + clazz = clazz.getSuperclass(); + } + } + } + + public static void main(String[] args) throws Exception { + System.loadLibrary("ValueHeapwalkingTest"); + ValueHolder holder = new ValueHolder(10); + + setTag(Value.class, TAG_VALUE_CLASS); + setTag(Value2.class, TAG_VALUE2_CLASS); + setTag(ValueHolder.class, TAG_HOLDER_CLASS); + setTag(holder.v_arr, TAG_VALUE_ARRAY); + setTag(holder.v2_arr, TAG_VALUE2_ARRAY); + + reset(); + System.out.println(">>iterateThroughHeap"); + iterateThroughHeap(); + System.out.println("<>followReferences"); + followReferences(); + System.out.println("<>followReferences (2)"); + followReferences(); + System.out.println("<>getObjectWithTags, maxTag = " + maxTag); + int count = getObjectWithTags(1, maxTag, objects, tags); + System.out.println("getObjectWithTags returned " + count); + for (int i = 0; i < count; i++) { + System.out.println(" [" + i + "] " + objects[i] + ", tag = " + tags[i]); + if (objects[i] == null || tags[i] == 0) { + throw new RuntimeException("unexpected object"); + } + } + int expectedTaggedCount = 5 // TAG_VALUE_CLASS/TAG_VALUE2_CLASS/TAG_HOLDER_CLASS/TAG_VALUE_ARRAY/TAG_VALUE2_ARRAY + + reachableValue2Count + reachableValueCount; + if (count != expectedTaggedCount) { + throw new RuntimeException("unexpected getObjectWithTags result: " + count + + ", expected " + expectedTaggedCount); + } + + Reference.reachabilityFence(holder); + } +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/libValueHeapwalkingTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/libValueHeapwalkingTest.cpp new file mode 100644 index 00000000000..eb0f08165dd --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/valhalla/Heapwalking/libValueHeapwalkingTest.cpp @@ -0,0 +1,321 @@ +/* + * 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. + * + * 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 +#include "jvmti_common.hpp" + +static jvmtiEnv *jvmti = nullptr; + +extern "C" JNIEXPORT void JNICALL +Java_ValueHeapwalkingTest_setTag(JNIEnv* jni_env, jclass clazz, jobject object, jlong tag) { + jvmtiError err = jvmti->SetTag(object, tag); + check_jvmti_error(err, "could not set tag"); +} + +extern "C" JNIEXPORT jlong JNICALL +Java_ValueHeapwalkingTest_getTag(JNIEnv* jni_env, jclass clazz, jobject object) { + jlong tag; + check_jvmti_error(jvmti->GetTag(object, &tag), "could not get tag"); + return tag; +} + +const int TAG_VALUE_CLASS = 1; +const int TAG_VALUE2_CLASS = 2; +const int TAG_HOLDER_CLASS = 3; +const int TAG_VALUE_ARRAY = 4; +const int TAG_VALUE3_ARRAY = 5; +const int MAX_TAG = 5; +const int START_TAG = 10; // start value for tagging objects + +static const char* tag_str(jlong tag) { + switch (tag) { + case 0: return "None"; + case TAG_VALUE_CLASS: return "Value class"; + case TAG_VALUE2_CLASS: return "Value2 class"; + case TAG_HOLDER_CLASS: return "ValueHolder class"; + case TAG_VALUE_ARRAY: return "Value[] object"; + case TAG_VALUE3_ARRAY: return "Value2[] object"; + } + return "Unknown"; +} + +struct Callback_Data { + // Updated by heap_iteration_callback. + jint counters[MAX_TAG + 1]; + // Updated by heap_reference_callback. + jint ref_counters[MAX_TAG + 1][MAX_TAG + 1]; + // Updated by primitive_field_callback. + jint primitive_counters[MAX_TAG + 1]; + jlong tag_counter; +}; + +static Callback_Data callbackData; + +extern "C" JNIEXPORT void JNICALL +Java_ValueHeapwalkingTest_reset(JNIEnv* jni_env, jclass clazz) { + memset(&callbackData, 0, sizeof(callbackData)); + callbackData.tag_counter = START_TAG; +} + +extern "C" JNIEXPORT jint JNICALL +Java_ValueHeapwalkingTest_count(JNIEnv* jni_env, jclass clazz, jint tag) { + return callbackData.counters[tag]; +} + +extern "C" JNIEXPORT jint JNICALL +Java_ValueHeapwalkingTest_refCount(JNIEnv* jni_env, jclass clazz, jint fromTag, jint toTag) { + return callbackData.ref_counters[fromTag][toTag]; +} + +extern "C" JNIEXPORT jint JNICALL +Java_ValueHeapwalkingTest_primitiveFieldCount(JNIEnv* jni_env, jclass clazz, jint tag) { + return callbackData.primitive_counters[tag]; +} + +extern "C" JNIEXPORT jlong JNICALL +Java_ValueHeapwalkingTest_getMaxTag(JNIEnv* jni_env, jclass clazz) { + return callbackData.tag_counter; +} + +static jlong safe_deref(jlong* ref) { + return ref == nullptr ? 0 : *ref; +} + +static jint JNICALL +heap_iteration_callback(jlong class_tag, + jlong size, + jlong* tag_ptr, + jint length, + void* user_data) { + Callback_Data* data = (Callback_Data*)user_data; + + if (class_tag != 0 && class_tag <= MAX_TAG) { + data->counters[class_tag]++; + printf("heap_iteration_callback: class_tag = %d (%s), tag = %d (%s), length = %d\n", + (int)class_tag, tag_str(class_tag), (int)*tag_ptr, tag_str(*tag_ptr), length); + fflush(nullptr); + } + return 0; +} + +static jint JNICALL +heap_reference_callback(jvmtiHeapReferenceKind reference_kind, + const jvmtiHeapReferenceInfo* reference_info, + jlong class_tag, + jlong referrer_class_tag, + jlong size, + jlong* tag_ptr, + jlong* referrer_tag_ptr, + jint length, + void* user_data) { + Callback_Data* data = (Callback_Data*)user_data; + + jlong tag = class_tag; + if (tag == 0 && *tag_ptr != 0 && *tag_ptr <= MAX_TAG) { + tag = *tag_ptr; + } + jlong referrer_tag = referrer_class_tag; + if (referrer_tag == 0 && safe_deref(referrer_tag_ptr) != 0 && safe_deref(referrer_tag_ptr) <= MAX_TAG) { + referrer_tag = *referrer_tag_ptr; + } + + if (tag != 0 && referrer_tag != 0) { + // For testing we count only JVMTI_HEAP_REFERENCE_FIELD and JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT references. + if (reference_kind == JVMTI_HEAP_REFERENCE_FIELD || reference_kind == JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT) { + data->ref_counters[referrer_tag][tag]++; + } + + jlong cur_tag = *tag_ptr; + char new_tag_str[64] = {}; + if (*tag_ptr == 0) { // i.e. class_tag != 0, but the object is untagged + *tag_ptr = ++data->tag_counter; + snprintf(new_tag_str, sizeof(new_tag_str), ", set tag to %d", (int)*tag_ptr); + } + printf("heap_reference_callback: kind = %d, class_tag = %d (%s), tag = %d (%s), referrer_tag = %d (%s) %s\n", + (int)reference_kind, (int)class_tag, tag_str(class_tag), (int)cur_tag, tag_str(*tag_ptr), + (int)referrer_tag, tag_str(referrer_tag), new_tag_str); + fflush(nullptr); + } + + return JVMTI_VISIT_OBJECTS; +} + +static jint JNICALL +primitive_field_callback(jvmtiHeapReferenceKind kind, + const jvmtiHeapReferenceInfo* info, + jlong object_class_tag, + jlong* object_tag_ptr, + jvalue value, + jvmtiPrimitiveType value_type, + void* user_data) { + Callback_Data* data = (Callback_Data*)user_data; + if (object_class_tag != 0) { + char value_str[64] = {}; + switch (value_type) { + case JVMTI_PRIMITIVE_TYPE_BOOLEAN: snprintf(value_str, sizeof(value_str), "(boolean) %s", value.z ? "true" : "false"); break; + case JVMTI_PRIMITIVE_TYPE_BYTE: snprintf(value_str, sizeof(value_str), "(byte) %d", value.b); break; + case JVMTI_PRIMITIVE_TYPE_CHAR: snprintf(value_str, sizeof(value_str), "(char) %c", value.c); break; + case JVMTI_PRIMITIVE_TYPE_SHORT: snprintf(value_str, sizeof(value_str), "(short): %d", value.s); break; + case JVMTI_PRIMITIVE_TYPE_INT: snprintf(value_str, sizeof(value_str), "(int): %d", value.i); break; + case JVMTI_PRIMITIVE_TYPE_LONG: snprintf(value_str, sizeof(value_str), "(long): %lld", (long long)value.j); break; + case JVMTI_PRIMITIVE_TYPE_FLOAT: snprintf(value_str, sizeof(value_str), "(float): %f", value.f); break; + case JVMTI_PRIMITIVE_TYPE_DOUBLE: snprintf(value_str, sizeof(value_str), "(double): %f", value.d); break; + default: snprintf(value_str, sizeof(value_str), "invalid_type %d (%c)", (int)value_type, (char)value_type); + } + + if (object_class_tag != 0 && object_class_tag <= MAX_TAG) { + data->primitive_counters[object_class_tag]++; + if (*object_tag_ptr != 0) { + *object_tag_ptr = *object_tag_ptr; + } + } + + printf("primitive_field_callback: kind = %d, class_tag = %d (%s), tag = %d (%s), value = %s\n", + (int)kind, (int)object_class_tag, tag_str(object_class_tag), + (int)*object_tag_ptr, tag_str(*object_tag_ptr), value_str); + fflush(nullptr); + } + return 0; +} + +static jint JNICALL +array_primitive_value_callback(jlong class_tag, + jlong size, + jlong* tag_ptr, + jint element_count, + jvmtiPrimitiveType element_type, + const void* elements, + void* user_data) { + Callback_Data* data = (Callback_Data*)user_data; + if (class_tag != 0 || *tag_ptr != 0) { + printf("array_primitive_value_callback: class_tag = %d (%s), tag = %d (%s), element_count = %d, element_type = %c\n", + (int)class_tag, tag_str(class_tag), (int)*tag_ptr, tag_str(*tag_ptr), element_count, (char)element_type); + fflush(nullptr); + } + return 0; +} + +static jint JNICALL +string_primitive_value_callback(jlong class_tag, + jlong size, + jlong* tag_ptr, + const jchar* value, + jint value_length, + void* user_data) { + Callback_Data* data = (Callback_Data*)user_data; + if (class_tag != 0 || *tag_ptr != 0) { + jchar value_copy[1024] = {}; // fills with 0 + if (value_length > 1023) { + value_length = 1023; + } + memcpy(value_copy, value, value_length * sizeof(jchar)); + printf("string_primitive_value_callback: class_tag = %d (%s), tag = %d (%s), value=\"%ls\"\n", + (int)class_tag, tag_str(class_tag), (int)*tag_ptr, tag_str(*tag_ptr), (wchar_t*)value_copy); + fflush(nullptr); + } + return 0; +} + +extern "C" JNIEXPORT void JNICALL +Java_ValueHeapwalkingTest_followReferences(JNIEnv* jni_env, jclass clazz) { + jvmtiHeapCallbacks callbacks = {}; + callbacks.heap_iteration_callback = heap_iteration_callback; + callbacks.heap_reference_callback = heap_reference_callback; + callbacks.primitive_field_callback = primitive_field_callback; + callbacks.array_primitive_value_callback = array_primitive_value_callback; + callbacks.string_primitive_value_callback = string_primitive_value_callback; + + jvmtiError err = jvmti->FollowReferences(0 /* filter nothing */, + nullptr /* no class filter */, + nullptr /* no initial object, follow roots */, + &callbacks, + &callbackData); + check_jvmti_error(err, "FollowReferences failed"); +} + +extern "C" JNIEXPORT void JNICALL +Java_ValueHeapwalkingTest_iterateThroughHeap(JNIEnv* jni_env, jclass clazz) { + jvmtiHeapCallbacks callbacks = {}; + callbacks.heap_iteration_callback = heap_iteration_callback; + callbacks.heap_reference_callback = heap_reference_callback; + callbacks.primitive_field_callback = primitive_field_callback; + callbacks.array_primitive_value_callback = array_primitive_value_callback; + callbacks.string_primitive_value_callback = string_primitive_value_callback; + + jvmtiError err = jvmti->IterateThroughHeap(0 /* filter nothing */, + nullptr /* no class filter */, + &callbacks, + &callbackData); + check_jvmti_error(err, "IterateThroughHeap failed"); +} + +extern "C" JNIEXPORT jint JNICALL +Java_ValueHeapwalkingTest_getObjectWithTags(JNIEnv* jni_env, jclass clazz, jlong minTag, jlong maxTag, jobjectArray objects, jlongArray tags) { + jsize len = jni_env->GetArrayLength(objects); + + jint tag_count = (jint)(maxTag - minTag + 1); + jlong* scan_tags = nullptr; + check_jvmti_error(jvmti->Allocate(tag_count * sizeof(jlong), (unsigned char**)&scan_tags), + "Allocate failed"); + + for (jlong i = 0; i < tag_count; i++) { + scan_tags[i] = i + minTag; + } + + jint count = 0; + jobject* object_result = nullptr; + jlong* tag_result = nullptr; + + check_jvmti_error(jvmti->GetObjectsWithTags(tag_count, scan_tags, &count, &object_result, &tag_result), + "GetObjectsWithTags failed"); + + if (count > len) { + printf("GetObjectsWithTags returned too many entries: %d (object length is %d)\n", count, (int)len); + fflush(nullptr); + abort(); + } + + for (jint i = 0; i < count; i++) { + jni_env->SetObjectArrayElement(objects, i, object_result[i]); + } + jni_env->SetLongArrayRegion(tags, 0, count, tag_result); + + jvmti->Deallocate((unsigned char*)scan_tags); + jvmti->Deallocate((unsigned char*)object_result); + jvmti->Deallocate((unsigned char*)tag_result); + + return count; +} + +extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { + if (vm->GetEnv(reinterpret_cast(&jvmti), JVMTI_VERSION) != JNI_OK || !jvmti) { + LOG("Could not initialize JVMTI\n"); + abort(); + } + jvmtiCapabilities capabilities; + memset(&capabilities, 0, sizeof(capabilities)); + capabilities.can_tag_objects = 1; + check_jvmti_error(jvmti->AddCapabilities(&capabilities), "adding capabilities"); + return JVMTI_ERROR_NONE; +} + diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java index d455a16c998..4693040fa6b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -46,9 +46,6 @@ import jdk.test.lib.Platform; import java.lang.AssertionError; -import com.sun.management.HotSpotDiagnosticMXBean; -import java.lang.management.ManagementFactory; - /* * The test exercises the JVMTI function: StopThread(jthread). * The test creates a new virtual or platform thread. @@ -277,8 +274,6 @@ static void C() { } static boolean preemptableVirtualThread() { - boolean legacyLockingMode = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - return is_virtual && !isBoundVThread && !legacyLockingMode; + return is_virtual && !isBoundVThread; } } diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java index 43926941a1a..64080b252c5 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { theApp = new LingeredAppWithConcurrentLock(); // Use a small heap so the scan is quick. - LingeredApp.startApp(theApp, "-Xmx4m"); + LingeredApp.startApp(theApp, "-Xmx8m"); System.out.println("Started LingeredApp with pid " + theApp.getPid()); // Run the 'jstack -l' command to get the stack and have java.util.concurrent diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java index dfe1a8f12dc..933f2b86ff5 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GarbageProducerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -25,6 +25,7 @@ import utils.GarbageProducer; import common.TmTool; import utils.JstatResults; +import utils.JstatGcCauseTool; /** * Base class for jstat testing which uses GarbageProducer to allocate garbage. @@ -36,19 +37,19 @@ public class GarbageProducerTest { private final static float TARGET_MEMORY_USAGE = 0.7f; private final static float MEASUREMENT_TOLERANCE = 0.05f; private final GarbageProducer garbageProducer; - private final TmTool jstatTool; + private final JstatGcCauseTool jstatTool; - public GarbageProducerTest(TmTool tool) { + public GarbageProducerTest(JstatGcCauseTool tool) { garbageProducer = new GarbageProducer(TARGET_MEMORY_USAGE); // We will be running jstat tool jstatTool = tool; } public void run() throws Exception { - // Run once and get the results asserting that they are reasonable - JstatResults measurement1 = jstatTool.measure(); - measurement1.assertConsistency(); - // Eat metaspace and heap then run the tool again and get the results asserting that they are reasonable + // Run once and get the results asserting that they are reasonable + JstatResults measurement1 = jstatTool.measureAndAssertConsistency(); + + // Eat metaspace and heap then run the tool again and get the results, asserting that they are reasonable System.gc(); garbageProducer.allocateMetaspaceAndHeap(); // Collect garbage. Also update VM statistics diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java index abe80074770..52bc41c3fe3 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -44,15 +44,13 @@ public static void main(String[] args) throws Exception { JstatGcNewTool jstatGcTool = new JstatGcNewTool(ProcessHandle.current().pid()); // Run once and get the results asserting that they are reasonable - JstatGcNewResults measurement1 = jstatGcTool.measure(); - measurement1.assertConsistency(); + JstatGcNewResults measurement1 = jstatGcTool.measureAndAssertConsistency(); GcProvoker gcProvoker = new GcProvoker(); // Provoke GC and run the tool again gcProvoker.provokeGc(); - JstatGcNewResults measurement2 = jstatGcTool.measure(); - measurement2.assertConsistency(); + JstatGcNewResults measurement2 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements assertThat(measurement2.getFloatValue("YGC") > measurement1.getFloatValue("YGC"), "YGC didn't increase between measurements 1 and 2"); @@ -60,8 +58,7 @@ public static void main(String[] args) throws Exception { // Provoke GC and run the tool again gcProvoker.provokeGc(); - JstatGcNewResults measurement3 = jstatGcTool.measure(); - measurement3.assertConsistency(); + JstatGcNewResults measurement3 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements assertThat(measurement3.getFloatValue("YGC") > measurement2.getFloatValue("YGC"), "YGC didn't increase between measurements 1 and 2"); diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java index 74ac7132109..6d062d4fee5 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -47,17 +47,15 @@ public static void main(String[] args) throws Exception { // We will be running "jstat -gc" tool JstatGcTool jstatGcTool = new JstatGcTool(ProcessHandle.current().pid()); - // Run once and get the results asserting that they are reasonable - JstatGcResults measurement1 = jstatGcTool.measure(); - measurement1.assertConsistency(); + // Run once and get the results asserting that they are reasonable + JstatGcResults measurement1 = jstatGcTool.measureAndAssertConsistency(); GcProvoker gcProvoker = new GcProvoker(); // Provoke GC then run the tool again and get the results // asserting that they are reasonable gcProvoker.provokeGc(); - JstatGcResults measurement2 = jstatGcTool.measure(); - measurement2.assertConsistency(); + JstatGcResults measurement2 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements JstatResults.assertGCEventsIncreased(measurement1, measurement2); @@ -66,13 +64,10 @@ public static void main(String[] args) throws Exception { // Provoke GC again and get the results // asserting that they are reasonable gcProvoker.provokeGc(); - JstatGcResults measurement3 = jstatGcTool.measure(); - measurement3.assertConsistency(); + JstatGcResults measurement3 = jstatGcTool.measureAndAssertConsistency(); // Assert the increase in GC events and time between the measurements JstatResults.assertGCEventsIncreased(measurement2, measurement3); JstatResults.assertGCTimeIncreased(measurement2, measurement3); - } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java index 0a3102625d6..c223a09ba45 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -42,6 +42,6 @@ public class GcTest02 { public static void main(String[] args) throws Exception { - new GarbageProducerTest(new JstatGcTool(ProcessHandle.current().pid())).run(); + new GarbageProducerTest(new JstatGcCauseTool(ProcessHandle.current().pid())).run(); } } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java index 74cffa150ce..0fb24bbd109 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gccapacity " and returns the results as * JstatGcCapacityoolResults */ -public class JstatGcCapacityTool extends TmTool { +public class JstatGcCapacityTool extends JstatTool { public JstatGcCapacityTool(long pid) { super(JstatGcCapacityResults.class, "jstat", "-gccapacity " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java index c0dd36d8abb..65bea8d36bd 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gc " and returns the results as * JstatGcToolResults */ -public class JstatGcCauseTool extends TmTool { +public class JstatGcCauseTool extends JstatTool { public JstatGcCauseTool(long pid) { super(JstatGcCauseResults.class, "jstat", "-gc " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java index ed3f20a6c20..7bea437cb28 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gcnew " and returns the results as * JstatGcNewResults */ -public class JstatGcNewTool extends TmTool { +public class JstatGcNewTool extends JstatTool { public JstatGcNewTool(long pid) { super(JstatGcNewResults.class, "jstat", "-gcnew " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java index e046768a46f..f4f86038906 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -28,10 +28,9 @@ * This tool executes "jstat -gc " and returns the results as * JstatGcToolResults */ -public class JstatGcTool extends TmTool { +public class JstatGcTool extends JstatTool { public JstatGcTool(long pid) { super(JstatGcResults.class, "jstat", "-gc " + pid); } - } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java index 97368d89b3a..01425d4c5b6 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -31,7 +31,7 @@ * Results of running the jstat tool Concrete subclasses will detail the jstat * tool options */ -abstract public class JstatResults extends ToolResults { +public abstract class JstatResults extends ToolResults { private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f; @@ -181,5 +181,5 @@ public static boolean checkFloatIsSum(float sum, float... floats) { return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE; } - abstract public void assertConsistency(); + public abstract void assertConsistency(); } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.java new file mode 100644 index 00000000000..404581b1ae7 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatTool.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. + * + * 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. + */ +package utils; + +import common.TmTool; + +/** + * Common base class for Jstat tools. + */ +public class JstatTool extends TmTool { + + private static final int TRIES = 3; + + public JstatTool(Class resultsClz, String toolName, String otherArgs) { + super(resultsClz, toolName, otherArgs); + } + + /** + * Measure, and call assertConsistency() on the results, + * tolerating a set number of failures to account for inconsistencies in PerfData. + */ + public T measureAndAssertConsistency() throws Exception { + T results = null; + for (int i = 1; i <= TRIES; i++) { + try { + results = measure(); + results.assertConsistency(); + } catch (RuntimeException e) { + System.out.println("Attempt " + i + ": " + e); + if (i == TRIES) { + System.out.println("Too many failures."); + throw(e); + } + // Will retry. + } + } + return results; + } +} diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java index b8f2919e594..0ff9cae8169 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java @@ -28,7 +28,9 @@ import jdk.internal.reflect.ConstantPool; import jdk.test.whitebox.WhiteBox; +import java.lang.reflect.Constructor; import java.lang.reflect.Executable; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.Executor; @@ -79,26 +81,53 @@ public static void compileClass(Class aClass, long id, Executor executor) { preloadClasses(aClass.getName(), id, constantPool); } - // Make sure the class is initialized. - UNSAFE.ensureClassInitialized(aClass); + // Attempt to initialize the class. If initialization is not possible + // due to NCDFE, accept this, and try compile anyway. + try { + UNSAFE.ensureClassInitialized(aClass); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to init class : %s%n", + id, aClass.getName(), e); + } compileClinit(aClass, id); + // Getting constructor/methods with unresolvable signatures would fail with NCDFE. + // Try to get as much as possible, and compile everything else. + // TODO: Would be good to have a Whitebox method that returns the subset of resolvable + // constructors/methods without throwing NCDFE. This would extend the testing scope. + Constructor[] constructors = new Constructor[0]; + Method[] methods = new Method[0]; + + try { + constructors = aClass.getDeclaredConstructors(); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to get constructors : %s%n", + id, aClass.getName(), e); + } + + try { + methods = aClass.getDeclaredMethods(); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to get methods : %s%n", + id, aClass.getName(), e); + } + // Populate profile for all methods to expand the scope of // compiler optimizations. Do this before compilations start. - for (Executable e : aClass.getDeclaredConstructors()) { + for (Executable e : constructors) { WHITE_BOX.markMethodProfiled(e); } - for (Executable e : aClass.getDeclaredMethods()) { + for (Executable e : methods) { WHITE_BOX.markMethodProfiled(e); } // Now schedule the compilations. long methodCount = 0; - for (Executable e : aClass.getDeclaredConstructors()) { + for (Executable e : constructors) { ++methodCount; executor.execute(new CompileMethodCommand(id, e)); } - for (Executable e : aClass.getDeclaredMethods()) { + for (Executable e : methods) { ++methodCount; executor.execute(new CompileMethodCommand(id, e)); } @@ -127,9 +156,12 @@ private static void preloadClasses(String className, long id, if (constantPool.getTagAt(i) == ConstantPool.Tag.CLASS) { constantPool.getClassAt(i); } + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to preload : %s%n", + id, className, e); } catch (Throwable t) { - CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING preloading failed : %s", - id, className, t)); + CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING preloading failed : %s%n", + id, className, t); t.printStackTrace(CompileTheWorld.ERR); } } @@ -170,17 +202,22 @@ public CompileMethodCommand(long classId, Executable method) { @Override public final void run() { + // Make sure method is not compiled at any level before starting + // progressive compilations. No deopt in-between tiers is needed, + // as long as we increase the compilation levels one by one. + WHITE_BOX.deoptimizeMethod(method); + int compLevel = Utils.INITIAL_COMP_LEVEL; if (Utils.TIERED_COMPILATION) { for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) { - WHITE_BOX.deoptimizeMethod(method); compileAtLevel(i); } } else { compileAtLevel(compLevel); } - // Make the method eligible for sweeping sooner + // Ditch all the compiled versions of the code, make the method + // eligible for sweeping sooner. WHITE_BOX.deoptimizeMethod(method); } diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 573b70faabe..d721c7d63c5 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -308,6 +308,8 @@ private String[] cmd(long classStart, long classStop) { // Do not pay extra stack trace generation cost for normally thrown exceptions "-XX:-StackTraceInThrowable", "-XX:+IgnoreUnrecognizedVMOptions", + // Do not pay extra for verifying inline caches during nmethod cleanups + "-XX:-VerifyInlineCaches", // Do not pay extra zapping cost for explicit GC invocations "-XX:-ZapUnusedHeapArea", // Stress* are c2-specific stress flags, so IgnoreUnrecognizedVMOptions is needed @@ -316,6 +318,7 @@ private String[] cmd(long classStart, long classStop) { "-XX:+StressIGVN", "-XX:+StressCCP", "-XX:+StressMacroExpansion", + "-XX:+StressMacroElimination", "-XX:+StressIncrementalInlining", // StressSeed is uint "-XX:StressSeed=" + rng.nextInt(Integer.MAX_VALUE), diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java index 5e36cf0f7f9..a31098a055c 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java @@ -245,9 +245,12 @@ protected final void processClass(String name, Executor executor) { CompileTheWorld.OUT.println(String.format("[%d]\t%s", id, name)); aClass = entry.loader().loadClass(name); Compiler.compileClass(aClass, id, executor); + } catch (NoClassDefFoundError e) { + CompileTheWorld.OUT.printf("[%d]\t%s\tNOTE unable to load/compile, skipped: %s%n", + id, name, e); } catch (Throwable e) { - CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING skipped: %s", - id, name, e)); + CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING skipped: %s%n", + id, name, e); e.printStackTrace(CompileTheWorld.ERR); } } diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst b/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst index befd0ed66db..f8db44b1463 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst +++ b/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst @@ -31,3 +31,6 @@ java/lang/System::nanoTime() java/lang/annotation/IncompleteAnnotationException::IncompleteAnnotationException(Ljava/lang/Class;Ljava/lang/String;) java/util/AbstractSet::toString() java/util/HashSet::toString() + +#Unstable methods +*::hashCode diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/MethodTemplate.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/MethodTemplate.java new file mode 100644 index 00000000000..5f136dc3e05 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/MethodTemplate.java @@ -0,0 +1,256 @@ +/* + * 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. + * + * 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. + */ + +package jdk.test.lib.jittester; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Asserts; + +import static java.util.function.Predicate.not; + + +/** + * A wrapper for string method templates, similar to the CompileCommand patterns. + */ +public final class MethodTemplate { + + /** + * String that can have wildcard symbols on its ends, allowing it to match a family of strings. + * For example, "abc*" matches "abc123", and so on. + */ + public static class WildcardString { + private final String pattern; + private final boolean frontWildcarded; + private final boolean tailWildcarded; + + /** + * Creates a WildcardString from given string. + * @param pattern string pattern, like "some*" + */ + public WildcardString(String pattern) { + // check for the leading '*' + frontWildcarded = pattern.charAt(0) == '*'; + pattern = frontWildcarded ? pattern.substring(1) : pattern; + + // check for the trailing '*' + tailWildcarded = pattern.length() > 0 && pattern.charAt(pattern.length() - 1) == '*'; + pattern = tailWildcarded ? pattern.substring(0, pattern.length() - 1) : pattern; + + this.pattern = pattern; + } + + /** + * Returns true it this WildcardString matches given other string. + * @param other the string that this WildcardString should be matched against + * @return true in case of a match. + */ + public boolean matches(String other) { + boolean result = pattern.equals(other); + result |= frontWildcarded ? other.endsWith(pattern) : result; + result |= tailWildcarded ? other.startsWith(pattern) : result; + result |= tailWildcarded && frontWildcarded ? other.contains(pattern) : result; + return result; + } + } + + private static final Pattern METHOD_PATTERN = Pattern.compile(generateMethodPattern()); + + private final WildcardString klassName; + private final WildcardString methodName; + private final Optional>> signature; + + private MethodTemplate(String klassName, String methodName, Optional>> signature) { + this.klassName = new WildcardString(klassName); + this.methodName = new WildcardString(methodName); + this.signature = signature; + } + + private static String generateMethodPattern() { + // Sample valid template(s): java/lang/String::indexOf(Ljava/lang/String;I) + // java/lang/::*(Ljava/lang/String;I) + // *String::indexOf(*) + // java/lang/*::indexOf + + String primitiveType = "[ZBSCIJFD]"; // Simply a letter, like 'I' + String referenceType = "L[\\w/$]+;"; // Like 'Ljava/lang/String;' + String primOrRefType = + "\\[?" + primitiveType + // Bracket is optional: '[Z', or 'Z' + "|" + + "\\[?" + referenceType; // Bracket is optional: '[LSomeObject;' or 'LSomeObject;' + String argTypesOrWildcard = "(" + // Method argument(s) Ljava/lang/String;Z... + "(" + primOrRefType + ")*" + + ")|\\*"; // .. or a wildcard: + + return + "(?[\\w/$]*\\*?)" + // Class name, like 'java/lang/String' + "::" + // Simply '::' + "(?\\*?[\\w$]+\\*?)" + // method name, 'indexOf'' + "(\\((?" + // Method argument(s) in brackets: + argTypesOrWildcard + // (Ljava/lang/String;Z) or '*' or nothing + ")\\))?"; + } + + /** + * Returns true iff none of the given MethodTemplates matches the given Executable. + * + * @param templates the collection of templates to check + * @param method the executable to match the colletions templates + * @return true if none of the given templates matches the method, false otherwise + */ + public static boolean noneMatches(Collection templates, Executable method) { + for (MethodTemplate template : templates) { + if (template.matches(method)) { + return false; + } + } + return true; + } + + /** + * Returns true if this MethodTemplate matches the given Executable. + * + * @param other the Executable to try to match to + * @return whether the other matches this MethodTemplate + */ + public boolean matches(Executable other) { + boolean result = klassName.matches(other.getDeclaringClass().getName()); + + result &= (other instanceof Constructor) + ? result + : methodName.matches(other.getName()); + + return result && + signature.map(Arrays.asList(other.getParameterTypes())::equals) + .orElse(true); + } + + /** + * Parses the given string and returs a MethodTemplate. + * + * @param methodStr the string to parse + * @return created MethodTemplate + */ + public static MethodTemplate parse(String methodStr) { + Matcher matcher = METHOD_PATTERN.matcher(methodStr); + String msg = String.format("Format of the methods exclude input file is incorrect," + + " methodStr \"%s\" has wrong format", methodStr); + Asserts.assertTrue(matcher.matches(), msg); + + String klassName = matcher.group("klassName").replaceAll("/", "\\."); + String methodName = matcher.group("methodName"); + Optional>> signature = Optional.ofNullable(matcher.group("argTypes")) + .filter(not("*"::equals)) + .map(MethodTemplate::parseSignature); + return new MethodTemplate(klassName, methodName, signature); + } + + private static List> parseSignature(String signature) { + List> sigClasses = new ArrayList<>(); + char typeChar; + boolean isArray; + String klassName; + StringBuilder sb; + StringBuilder arrayDim; + try (StringReader str = new StringReader(signature)) { + int symbol = str.read(); + while (symbol != -1) { + typeChar = (char) symbol; + arrayDim = new StringBuilder(); + Class primArrayClass = null; + if (typeChar == '[') { + isArray = true; + arrayDim.append('['); + symbol = str.read(); + while (symbol == '[') { + arrayDim.append('['); + symbol = str.read(); + } + typeChar = (char) symbol; + if (typeChar != 'L') { + primArrayClass = Class.forName(arrayDim.toString() + typeChar); + } + } else { + isArray = false; + } + switch (typeChar) { + case 'Z': + sigClasses.add(isArray ? primArrayClass : boolean.class); + break; + case 'I': + sigClasses.add(isArray ? primArrayClass : int.class); + break; + case 'J': + sigClasses.add(isArray ? primArrayClass : long.class); + break; + case 'F': + sigClasses.add(isArray ? primArrayClass : float.class); + break; + case 'D': + sigClasses.add(isArray ? primArrayClass : double.class); + break; + case 'B': + sigClasses.add(isArray ? primArrayClass : byte.class); + break; + case 'S': + sigClasses.add(isArray ? primArrayClass : short.class); + break; + case 'C': + sigClasses.add(isArray ? primArrayClass : char.class); + break; + case 'L': + sb = new StringBuilder(); + symbol = str.read(); + while (symbol != ';') { + sb.append((char) symbol); + symbol = str.read(); + } + klassName = sb.toString().replaceAll("/", "\\."); + if (isArray) { + klassName = arrayDim.toString() + "L" + klassName + ";"; + } + Class klass = Class.forName(klassName); + sigClasses.add(klass); + break; + default: + throw new Error("Unknown type " + typeChar); + } + symbol = str.read(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new Error("Unexpected exception while parsing exclude methods file", ex); + } + return sigClasses; + } + +} diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java index bfe5a3224b6..ba956692af7 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,9 +23,7 @@ package jdk.test.lib.jittester; -import java.io.File; import java.io.IOException; -import java.io.StringReader; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -35,22 +33,31 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; -import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import jdk.test.lib.Asserts; import jdk.test.lib.jittester.functions.FunctionInfo; import jdk.test.lib.jittester.types.TypeArray; import jdk.test.lib.jittester.types.TypeKlass; +import static java.util.function.Predicate.not; + /** * Class used for parsing included classes file and excluded methods file */ public class TypesParser { + private List methodsToExclude; + private static final HashMap, Type> TYPE_CACHE = new HashMap<>(); + private static String trimComment(String source) { + int commentStart = source.indexOf('#'); + return commentStart == -1 ? source : source.substring(0, commentStart); + } + /** * Parses included classes file and excluded methods file to TypeList and SymbolTable. * This routine takes all classes named in the classes file and puts them to the TypeList, @@ -62,27 +69,21 @@ public class TypesParser { public static void parseTypesAndMethods(String klassesFileName, String exMethodsFileName) { Asserts.assertNotNull(klassesFileName, "Classes input file name is null"); Asserts.assertFalse(klassesFileName.isEmpty(), "Classes input file name is empty"); - List> klasses = parseKlasses(klassesFileName); - Set methodsToExclude; - if (exMethodsFileName != null && !exMethodsFileName.isEmpty()) { - methodsToExclude = parseMethods(exMethodsFileName); - } else { - methodsToExclude = new HashSet<>(); - } - klasses.stream().forEach(klass -> { - TypeKlass typeKlass = (TypeKlass) getType(klass); - if (TypeList.isReferenceType(typeKlass)) { - return; - } - TypeList.add(typeKlass); - Set methods = new HashSet<>(); - methods.addAll(Arrays.asList(klass.getMethods())); - methods.addAll(Arrays.asList(klass.getConstructors())); - methods.removeAll(methodsToExclude); - methods.stream().forEach(method -> { - if (method.isSynthetic()) { - return; - } + TypesParser theParser = new TypesParser(); + theParser.initMethodsToExclude(exMethodsFileName); + parseKlasses(klassesFileName) + .stream() + .filter(klass -> !TypeList.isReferenceType(getTypeKlass(klass))) + .forEach(theParser::processKlass); + } + + private void processKlass(Class klass) { + TypeKlass typeKlass = getTypeKlass(klass); + TypeList.add(typeKlass); + Stream.concat(Arrays.stream(klass.getMethods()), Arrays.stream(klass.getConstructors())) + .filter(not(Executable::isSynthetic)) + .filter(method -> MethodTemplate.noneMatches(methodsToExclude, method)) + .forEach(method -> { String name = method.getName(); boolean isConstructor = false; Type returnType; @@ -106,10 +107,8 @@ public static void parseTypesAndMethods(String klassesFileName, String exMethods paramList.add(new VariableInfo("arg" + argNum, typeKlass, paramType, VariableInfo.LOCAL | VariableInfo.INITIALIZED)); } - typeKlass.addSymbol(new FunctionInfo(name, typeKlass, returnType, 1, flags, - paramList)); + typeKlass.addSymbol(new FunctionInfo(name, typeKlass, returnType, 1, flags, paramList)); }); - }); } private static Type getType(Class klass) { @@ -155,6 +154,10 @@ private static Type getType(Class klass) { return type; } + private static TypeKlass getTypeKlass(Class klass) { + return (TypeKlass) getType(klass); + } + private static int getArrayClassDimension(Class klass) { if (!klass.isArray()) { return 0; @@ -234,133 +237,24 @@ private static List> parseKlasses(String klassesFileName) { return klassesList; } - private static Set parseMethods(String methodsFileName) { - Asserts.assertNotNull(methodsFileName, "Methods exclude input file name is null"); - Asserts.assertFalse(methodsFileName.isEmpty(), "Methods exclude input file name is empty"); - LinkedList methodNamesList = new LinkedList<>(); - Path klassesFilePath = Paths.get(methodsFileName); - try { - Files.lines(klassesFilePath).forEach(line -> { - line = line.trim(); - if (line.isEmpty()) { - return; - } - String msg = String.format("Format of the methods exclude input file \"%s\" is incorrect," - + " line \"%s\" has wrong format", methodsFileName, line); - Asserts.assertTrue(line.matches("\\w[\\w/$]*::[\\w$]+\\((\\[?[ZBSCIJFD]|\\[?L[\\w/$]+;)*\\)"), msg); - methodNamesList.add(line.substring(0, line.length() - 1)); - }); - } catch (IOException ex) { - throw new Error("Error reading exclude method file", ex); - } - Set methodsList = new HashSet<>(); - methodNamesList.forEach(methodName -> { - String[] klassAndNameAndSig = methodName.split("::"); - String klassName = klassAndNameAndSig[0].replaceAll("/", "\\."); - String[] nameAndSig = klassAndNameAndSig[1].split("[\\(\\)]"); - String name = nameAndSig[0]; - String signature = ""; - if (nameAndSig.length > 1) { - signature = nameAndSig[1]; - } - Class klass = null; - List> signatureTypes = null; + private void initMethodsToExclude(String methodsFileName) { + if (methodsFileName != null && !methodsFileName.isEmpty()) { + Path methodsFilePath = Paths.get(methodsFileName); try { - klass = Class.forName(klassName); - signatureTypes = parseSignature(signature); - } catch (ClassNotFoundException ex) { - throw new Error("Unexpected exception while parsing exclude methods file", ex); - } - try { - Executable method; - if (name.equals(klass.getSimpleName())) { - method = klass.getConstructor(signatureTypes.toArray(new Class[0])); - } else { - method = klass.getMethod(name, signatureTypes.toArray(new Class[0])); - } - methodsList.add(method); - } catch (NoSuchMethodException | SecurityException ex) { - throw new Error("Unexpected exception while parsing exclude methods file", ex); - } - }); - return methodsList; - } + methodsToExclude = Files.lines(methodsFilePath) + // Cleaning nonimportant parts + .map(TypesParser::trimComment) + .map(String::trim) + .filter(not(String::isEmpty)) - private static List> parseSignature(String signature) throws ClassNotFoundException { - LinkedList> sigClasses = new LinkedList<>(); - char typeChar; - boolean isArray; - String klassName; - StringBuilder sb; - StringBuilder arrayDim; - try (StringReader str = new StringReader(signature)) { - int symbol = str.read(); - while (symbol != -1){ - typeChar = (char) symbol; - arrayDim = new StringBuilder(); - Class primArrayClass = null; - if (typeChar == '[') { - isArray = true; - arrayDim.append('['); - symbol = str.read(); - while (symbol == '['){ - arrayDim.append('['); - symbol = str.read(); - } - typeChar = (char) symbol; - if (typeChar != 'L') { - primArrayClass = Class.forName(arrayDim.toString() + typeChar); - } - } else { - isArray = false; - } - switch (typeChar) { - case 'Z': - sigClasses.add(isArray ? primArrayClass : boolean.class); - break; - case 'I': - sigClasses.add(isArray ? primArrayClass : int.class); - break; - case 'J': - sigClasses.add(isArray ? primArrayClass : long.class); - break; - case 'F': - sigClasses.add(isArray ? primArrayClass : float.class); - break; - case 'D': - sigClasses.add(isArray ? primArrayClass : double.class); - break; - case 'B': - sigClasses.add(isArray ? primArrayClass : byte.class); - break; - case 'S': - sigClasses.add(isArray ? primArrayClass : short.class); - break; - case 'C': - sigClasses.add(isArray ? primArrayClass : char.class); - break; - case 'L': - sb = new StringBuilder(); - symbol = str.read(); - while (symbol != ';') { - sb.append((char) symbol); - symbol = str.read(); - } - klassName = sb.toString().replaceAll("/", "\\."); - if (isArray) { - klassName = arrayDim.toString() + "L" + klassName + ";"; - } - Class klass = Class.forName(klassName); - sigClasses.add(klass); - break; - default: - throw new Error("Unknown type " + typeChar); - } - symbol = str.read(); + // Actual parsing + .map(MethodTemplate::parse) + .collect(Collectors.toList()); + } catch (IOException ex) { + throw new Error("Error reading exclude method file", ex); } - } catch (IOException ex) { - throw new Error("Unexpected exception while parsing exclude methods file", ex); + } else { + methodsToExclude = new ArrayList<>(); } - return sigClasses; } } diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java index 5e0cee5d2a4..a1d1253776c 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java @@ -125,6 +125,12 @@ public static void main(String[] args) { GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 10) ); + runCheck( + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 1), + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 2), + BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 3) + ); + runCheck(BadFailOnConstraint.create(AllocArray.class, "allocArray()", 1), BadFailOnConstraint.create(AllocArray.class, "allocArray()", 2), GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 3), @@ -972,6 +978,13 @@ class AllocInstance { public void allocInstance() { myClass = new MyClass(); } + + static class Nested {} + @Test + @IR(failOn = {IRNode.ALLOC_OF, "Nested"}) + @IR(failOn = {IRNode.ALLOC_OF, "AllocInstance\\$Nested"}) + @IR(failOn = {IRNode.ALLOC_OF, "AllocInst\\w+\\$Nested"}) + public Nested allocNested() { return new Nested(); } } class AllocArray { diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java index a2d98d00502..fe21dce73b5 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java @@ -60,6 +60,7 @@ public class TestPhaseIRMatching { public static void main(String[] args) { run(Basics.class); run(NoCompilationOutput.class); + run(LoadStore.class); } private static void run(Class testClass) { @@ -549,3 +550,239 @@ public static List sort(Set failures) { .thenComparing(Failure::constraintId)).collect(Collectors.toList()); } } + +// Test load and store regexes +class LoadStore { + int i; + float f; + interface I1 {} + static class Base implements I1 { + int i; + } + interface I2 {} + static class Derived extends Base implements I2 { + long l; + } + Base base = new Base(); + Derived derived = new Derived(); + + static class SingleNest { + static class DoubleNest { + int i; + } + } + + SingleNest.DoubleNest doubleNest = new SingleNest.DoubleNest(); + + + @Test + @IR(failOn = {IRNode.LOAD_OF_CLASS, ".*", IRNode.STORE_OF_CLASS, ".*"}) + public void triviallyFailBoth() { + } + + @Test + @IR(counts = { + IRNode.LOAD_OF_CLASS, "LoadS[a-z]+", "1", + IRNode.LOAD_OF_CLASS, "Load.tore", "1", + IRNode.LOAD_OF_CLASS, "LoadStore", "1", + IRNode.LOAD_OF_CLASS, "/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "/tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "ir_framework/tests/LoadStore", "1", + IRNode.LOAD_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1", // To assert it's the whole qualification + IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_OF_CLASS, "oadStore", + IRNode.LOAD_OF_CLASS, "LoadStor", + IRNode.LOAD_OF_CLASS, "/ir_framework/tests/LoadStore", + IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore+12 * + public float simpleLoad() { + return f; + } + + @Test + @IR(counts = { + IRNode.STORE_OF_CLASS, "LoadS[a-z]+", "1", + IRNode.STORE_OF_CLASS, "Load.tore", "1", + IRNode.STORE_OF_CLASS, "LoadStore", "1", + IRNode.STORE_OF_CLASS, "/LoadStore", "1", + IRNode.STORE_OF_CLASS, "tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "ir_framework/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1", + IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_OF_CLASS, "oadStore", + IRNode.STORE_OF_CLASS, "LoadStor", + IRNode.STORE_OF_CLASS, "/ir_framework/tests/LoadStore", + IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore+12 * + public void simpleStore() { + i = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_I_OF_CLASS, "Base", "1", + IRNode.LOAD_I_OF_CLASS, "\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "Load.tore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_I_OF_CLASS, "/Base", + IRNode.LOAD_I_OF_CLASS, "oadStore\\$Base", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Bas", + IRNode.LOAD_I_OF_CLASS, "LoadStore", + IRNode.LOAD_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base", + IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 * + public int loadWithInterface() { + return base.i; + } + + @Test + @IR(counts = { + IRNode.STORE_I_OF_CLASS, "Base", "1", + IRNode.STORE_I_OF_CLASS, "\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "Load.tore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_I_OF_CLASS, "/Base", + IRNode.STORE_I_OF_CLASS, "oadStore\\$Base", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$Bas", + IRNode.STORE_I_OF_CLASS, "LoadStore", + IRNode.STORE_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base", + IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 * + public void storeWithInterface() { + base.i = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_L_OF_CLASS, "Derived", "1", + IRNode.LOAD_L_OF_CLASS, "\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "Load.tore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.LOAD_L_OF_CLASS, "/Derived", + IRNode.LOAD_L_OF_CLASS, "oadStore\\$Derived", + IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derive", + IRNode.LOAD_L_OF_CLASS, "LoadStore", + IRNode.LOAD_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived", + IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 * + public long loadWithInterfaces() { + return derived.l; + } + + @Test + @IR(counts = { + IRNode.STORE_L_OF_CLASS, "Derived", "1", + IRNode.STORE_L_OF_CLASS, "\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "Load.tore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1", + }, + failOn = { + IRNode.STORE_L_OF_CLASS, "/Derived", + IRNode.STORE_L_OF_CLASS, "oadStore\\$Derived", + IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derive", + IRNode.STORE_L_OF_CLASS, "LoadStore", + IRNode.STORE_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived", + IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*", + } + ) + // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 * + public void storeWithInterfaces() { + derived.l = 1; + } + + @Test + @IR(counts = { + IRNode.LOAD_I_OF_CLASS, "DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + }, + failOn = { + IRNode.LOAD_I_OF_CLASS, "SingleNest", + IRNode.LOAD_I_OF_CLASS, "LoadStore", + IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest", + } + ) + // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 * + public int loadDoubleNested() { + return doubleNest.i; + } + + @Test + @IR(counts = { + IRNode.STORE_I_OF_CLASS, "DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1", + }, + failOn = { + IRNode.STORE_I_OF_CLASS, "SingleNest", + IRNode.STORE_I_OF_CLASS, "LoadStore", + IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest", + } + ) + // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 * + public void storeDoubleNested() { + doubleNest.i = 1; + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphApplet.java b/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphApplet.java deleted file mode 100644 index a648ce348e0..00000000000 --- a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphApplet.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2008, 2020, 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 - * @key headful - * - * @summary converted from VM Testbase jit/misctests/fpustack. - * VM Testbase keywords: [jit, desktop, jdk_desktop, quick] - * - * @library /vmTestbase - * /test/lib - * @run main/othervm jit.misctests.fpustack.GraphApplet - */ - -package jit.misctests.fpustack; - -import java.util.*; -import java.awt.*; -import java.applet.Applet; -import nsk.share.TestFailure; - - -public class GraphApplet extends Applet { - private GraphPanel panel; - private boolean isApplet = true; - private boolean initialized = false; - - /** - ** main method for testing that class - ** - **/ - public static void main( String[] args ) { - Frame f = new Frame("GraphApplet"); - GraphApplet app = new GraphApplet(); - app.isApplet = false; - app.setSize(600,400); - f.setLayout( new BorderLayout() ); - f.add("Center",app); - f.setSize(600,400); - - app.init(); - // f.pack(); - f.show(true); - app.start(); - - try { - Thread.currentThread().sleep(5*1000); - } catch (InterruptedException e) { - } - - f.show(false); - app.stop(); - f.dispose(); - return; - } - - /** - ** init-Method in applet's lifecycle. - ** the graphic panel is build up and the date is filled. - **/ - public synchronized void init() { - System.out.println( "GraphApplet : init"); - setLayout(new BorderLayout()); - - panel = new GraphPanel(this, new layout() ); - fill( panel ); - add("Center", panel); - Panel p = new Panel(); - add("South", p); - initialized = true; - } - - public synchronized void start() { - System.out.println( "GraphApplet : start"); - panel.formatNodes(); - } - public synchronized void stop() { - initialized = false; - System.out.println( "GraphApplet : stop"); - } - - public synchronized void destroy() { - System.out.println( "GraphApplet : destroy"); - } - - /** - ** paint the Applet - **/ - public synchronized void paint(Graphics g) { - try { - while ( ! initialized ) - Thread.currentThread().sleep(5); - } catch (InterruptedException e) {} - if (g instanceof PrintGraphics ) - System.out.println( "printing GraphApplet ..."); - } - - public synchronized void print(Graphics g) { - try { - while ( ! initialized ) - Thread.currentThread().sleep(5); - } catch (InterruptedException e) {} - System.out.println( "Print Applet " + g); - panel.print(g); - } - - public void print() { - // System.out.println( "Print Applet"); - Toolkit kit = getToolkit(); - try { - - PrintJob job = kit.getPrintJob( new Frame("x"), "PrintableFrame print job", - null); - // do the printing if the user didn't cancel the print job - if (job != null) { - Graphics g = job.getGraphics(); - printAll(g); // not paint(g) - g.dispose(); // finish with this page - job.end(); // finish with the PrintJob - } - } catch (Exception ex) { - System.out.println( "print exception " + ex); - } - } - - /** - ** - ** @param panel the container for nodes - ** - **/ - private void - fill( GraphPanel panel ) { - panel.addNodes("Node1", "Node2", "Node3" ); - } -} diff --git a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphPanel.java b/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphPanel.java deleted file mode 100644 index db36e0a3101..00000000000 --- a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/GraphPanel.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2008, 2018, 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. - */ -package jit.misctests.fpustack; - -import java.util.*; -import java.awt.*; -import java.applet.Applet; -import nsk.share.TestFailure; - -public class GraphPanel extends Panel { - private Panel graph; // the container - - private ilayout layout = null; // the strategy - - - private int nodesN; // number of nodes - private Node nodes[] = new Node[200]; // nodes container - - /** - ** constructor - ** - ** @param Panel the container - ** @param layout a strategy to layout the nodes - ** - **/ - GraphPanel(Panel graph, layout ls ) { - this.graph = graph; - layout = ls; - } - - - - - /** - ** add a node via label text. - ** - ** @param lbl the label - ** @return the index of the node in array nodes[] - ** - **/ - - public int addNode(String lbl) { - Node n = new Node(); - if (nodesN > 0) { - n.x = nodes[nodesN-1].x + 30; - n.y = nodes[nodesN-1].y + 30; - } - n.lbl = lbl; - - nodes[nodesN] = n; - return nodesN++; - } - - - - /** - ** add a node via label text. - ** - ** @param lbl the label - ** @return the index of the node in array nodes[] - ** - **/ - - public void addNodes(String lb1, String lb2, String lb3) { - addNode(lb1); - addNode(lb2); - addNode(lb3); - } - - - - /** - ** layout the nodes on the panel. the layout is used - ** - ** - **/ - public synchronized void formatNodes( ) { - - // format nodes - FontMetrics fm = getFontMetrics(getFont()); - Dimension d = getSize(); - - Node[] ns = new Node[ nodesN ]; - System.arraycopy(nodes, 0, ns, 0, nodesN); - layout.formatNodes( ns, d, fm ); - - } - - - -} diff --git a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/Node.java b/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/Node.java deleted file mode 100644 index 8bee7fb7265..00000000000 --- a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/Node.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2008, 2018, 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. - */ -package jit.misctests.fpustack; - -import nsk.share.TestFailure; - -public class Node { - - double x = 0.0; - double y = 0.0; - - String lbl; - - } diff --git a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/ilayout.java b/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/ilayout.java deleted file mode 100644 index 9550dd08415..00000000000 --- a/test/hotspot/jtreg/vmTestbase/jit/misctests/fpustack/ilayout.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2008, 2018, 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. - */ -package jit.misctests.fpustack; - -import java.util.*; -import java.awt.*; -import nsk.share.TestFailure; - -interface ilayout { - - public void formatNodes( Node[] n, Dimension d, FontMetrics fm ); - -} diff --git a/test/hotspot/jtreg/vmTestbase/jit/removal_candidates.txt b/test/hotspot/jtreg/vmTestbase/jit/removal_candidates.txt index f9628bfa685..f1df1ecee05 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/removal_candidates.txt +++ b/test/hotspot/jtreg/vmTestbase/jit/removal_candidates.txt @@ -27,7 +27,6 @@ questions. * common/misctests/classes * common/misctests/FileViewer * common/misctests/Foo -* common/misctests/fpustack * common/misctests/NoHeader * common/misctests/noop * common/misctests/Pi diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java index fe24c654361..93b4c542f75 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -105,7 +105,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); JDWP.ListenAddress listenAddress = debugee.redirectOutputAndDetectListeningAddress(log); String port = listenAddress.address(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java index 4b5fd75a88c..9132b986a07 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -110,7 +110,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); if ((vm = attachTarget(name)) == null) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java index facfe9c2c48..46b8eab14b9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -105,7 +105,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); JDWP.ListenAddress listenAddress = debugee.redirectOutputAndDetectListeningAddress(log); String port = listenAddress.address(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java index 142d6387610..7c022bb48fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -116,7 +116,7 @@ private int run() { //vm.setDebugTraceMode(VirtualMachine.TRACE_ALL); Binder binder = new Binder(argHandler, log); - Debugee debugee = binder.makeLocalDebugee(vm.process()); + Debugee debugee = binder.makeDebugee(vm.process()); debugee.redirectOutput(log); debugee.setupVM(vm); //debugee.waitForVMInit(1000); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java index 11aada10a61..539d4e732c6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -89,7 +89,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); if ((vm = attachTarget()) == null) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java index 2f5a966098a..a35b4541071 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -90,7 +90,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); if ((vm = attachTarget()) == null) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java index 2c63d6dc0fa..1bf68896c1d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -89,7 +89,7 @@ private int runIt(String argv[], PrintStream out) { Binder binder = new Binder(argHandler, log); log.display("command: " + cmd); - Debugee debugee = binder.startLocalDebugee(cmd); + Debugee debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); if ((vm = attachTarget()) == null) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java index 381fdced516..18da5969917 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -168,7 +168,7 @@ private int runIt(String argv[], PrintStream out) { log.display("command: " + cmd); try { - debugee = binder.startLocalDebugee(cmd); + debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); } catch (Exception e) { stopListen(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java index ddae7cb364f..4f43bba75a5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -143,7 +143,7 @@ private int runIt(String argv[], PrintStream out) { log.display("command: " + cmd); try { - debugee = binder.startLocalDebugee(cmd); + debugee = binder.startDebugee(cmd); debugee.redirectOutput(log); } catch (Exception e) { stopListen(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java index eb43ca30b59..dee135fbfed 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -150,7 +150,7 @@ private int runThis (String argv[], PrintStream out) { logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); - debugee = binder.startLocalDebugee(commandToRun); + debugee = binder.startDebugee(commandToRun); debugee.redirectOutput(logHandler); processToRun = debugee.getProcess(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java index 00a35be2102..d1e8f67b293 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -151,7 +151,7 @@ private int runThis (String argv[], PrintStream out) { logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); - debugee = binder.startLocalDebugee(commandToRun); + debugee = binder.startDebugee(commandToRun); debugee.redirectOutput(logHandler); processToRun = debugee.getProcess(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java index 07aa33e6ec6..804a92b2b49 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -154,7 +154,7 @@ private int runThis (String argv[], PrintStream out) { logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); - debugee = binder.startLocalDebugee(commandToRun); + debugee = binder.startDebugee(commandToRun); debugee.redirectOutput(logHandler); processToRun = debugee.getProcess(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java index 1ec79a02d9e..aef6720f917 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -150,7 +150,7 @@ private int runThis (String argv[], PrintStream out) { logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); - debugee = binder.startLocalDebugee(commandToRun); + debugee = binder.startDebugee(commandToRun); debugee.redirectOutput(logHandler); processToRun = debugee.getProcess(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetErrorName/geterrname002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetErrorName/geterrname002/TestDescription.java index 7f3745d6701..763ebeccd02 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetErrorName/geterrname002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetErrorName/geterrname002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -35,6 +35,9 @@ * JVMTI_ERROR_NULL_POINTER if name_ptr is NULL. * COMMENTS * + * @comment We test with arguments out of scope of the jvmti enums, which causes + * ubsan issues. + * @requires !vm.ubsan * @library /vmTestbase * /test/lib * @run main/othervm/native diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorEnter/rawmonenter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorEnter/rawmonenter003/TestDescription.java index 3120d355679..e743efe83cb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorEnter/rawmonenter003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorEnter/rawmonenter003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,9 @@ * 4431533: TEST_BUG: destroyed raw monitor can be occasionally valid * Ported from JVMDI. * + * @comment The test intentionally passes a bad argument to the function to verify error checking, + which causes a false positive from the ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run main/othervm/native -agentlib:rawmonenter003 nsk.jvmti.RawMonitorEnter.rawmonenter003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorExit/rawmonexit003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorExit/rawmonexit003/TestDescription.java index d7feb765293..5d0753e95f2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorExit/rawmonexit003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorExit/rawmonexit003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,9 @@ * 4431533: TEST_BUG: destroyed raw monitor can be occasionally valid * Ported from JVMDI. * + * @comment The test intentionally passes a bad argument to the function to verify error checking, + which causes a false positive from the ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run main/othervm/native -agentlib:rawmonexit003 nsk.jvmti.RawMonitorExit.rawmonexit003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotify/rawmnntfy003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotify/rawmnntfy003/TestDescription.java index a95d3da890f..d83f338a49f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotify/rawmnntfy003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotify/rawmnntfy003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,9 @@ * 4431533: TEST_BUG: destroyed raw monitor can be occasionally valid * Ported from JVMDI. * + * @comment The test intentionally passes a bad argument to the function to verify error checking, + which causes a false positive from the ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run main/othervm/native -agentlib:rawmnntfy003 nsk.jvmti.RawMonitorNotify.rawmnntfy003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotifyAll/rawmnntfyall003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotifyAll/rawmnntfyall003/TestDescription.java index 2f706b0c299..8c5fd95ea86 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotifyAll/rawmnntfyall003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorNotifyAll/rawmnntfyall003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,9 @@ * 4431533: TEST_BUG: destroyed raw monitor can be occasionally valid * Ported from JVMDI. * + * @comment The test intentionally passes a bad argument to the function to verify error checking, + which causes a false positive from the ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run main/othervm/native -agentlib:rawmnntfyall003 nsk.jvmti.RawMonitorNotifyAll.rawmnntfyall003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorWait/rawmnwait003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorWait/rawmnwait003/TestDescription.java index 8291f168ada..aab0b8d9e21 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorWait/rawmnwait003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RawMonitorWait/rawmnwait003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -37,6 +37,9 @@ * 4431533: TEST_BUG: destroyed raw monitor can be occasionally valid * Ported from JVMDI. * + * @comment The test intentionally passes a bad argument to the function to verify error checking, + which causes a false positive from the ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run main/othervm/native -agentlib:rawmnwait003 nsk.jvmti.RawMonitorWait.rawmnwait003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetVerboseFlag/setvrbflag002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetVerboseFlag/setvrbflag002/TestDescription.java index e42e086f588..d85da6d7128 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetVerboseFlag/setvrbflag002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetVerboseFlag/setvrbflag002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -34,6 +34,9 @@ * if flag is not a jvmtiVerboseFlag. * COMMENTS * + * @comment We test with arguments out of scope of the jvmti enums, which causes + * ubsan issues. + * @requires !vm.ubsan * @library /vmTestbase * /test/lib * @run main/othervm/native diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM07/em07t002/em07t002.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM07/em07t002/em07t002.cpp index 86d5f5de9f7..9a402a17eda 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM07/em07t002/em07t002.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM07/em07t002/em07t002.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -237,10 +237,6 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { } jvmti->RawMonitorExit(syncLock); - - if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock))) - nsk_jvmti_setFailStatus(); - } /* ============================================================================= */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TestDescription.java index f431b8e779f..e1d23cb7bd5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -47,5 +47,5 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm nsk.monitoring.stress.thread.strace010 -depth=100 -threadCount=30 + * @run main/othervm/native nsk.monitoring.stress.thread.strace010 -depth=100 -threadCount=30 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TestDescription.java index b90efd3c49b..2415c503a9a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -depth=100 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TestDescription.java index 36cad4e3dd1..2a4a73f10bc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -MBeanServer=custom diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TestDescription.java index 61a2ef6438b..5941b3f5702 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -depth=100 * -threadCount=30 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TestDescription.java index 6db3b3403ce..de9f087384c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -depth=100 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TestDescription.java index 8844d3bc84e..44a95761e3d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -MBeanServer=custom diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TestDescription.java index fb515c9b33e..39a2af62cbc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -depth=100 * -threadCount=30 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TestDescription.java index ffd822acae7..d1f0b2c7661 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -depth=100 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TestDescription.java index 3ec4bd943d8..add0bbcb739 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -44,7 +44,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm/native * nsk.monitoring.stress.thread.strace010 * -testMode=server * -MBeanServer=custom diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Debuggee.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Debuggee.java index f7472e2db03..880771881e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Debuggee.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Debuggee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -56,10 +56,10 @@ public class Debuggee extends LocalProcess { } /** - * Launch debuggee on local host. + * Launch debuggee. */ public void launch(String[] args) throws IOException { - launcher.display("Starting local debuggee."); + launcher.display("Starting debuggee."); super.launch(args); redirectStdout(launcher.getLog(), DEBUGEE_STDOUT_LOG_PREFIX ); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index 1735cc1e18d..32d4bd8b865 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -31,8 +31,8 @@ import java.util.*; /** - * This class provides launching of jdb and debuggee in local - * mode according to test command line options. + * This class provides launching of jdb and debuggee + * according to test command line options. */ public class Launcher extends DebugeeBinder { @@ -94,27 +94,27 @@ public Launcher (JdbArgumentHandler argumentHandler, Log log) { } /** - * Defines mode (local) and type of connector (default, launching, + * Defines type of connector (default, launching, * raw launching, attaching or listening) according to options * parsed by JdbArgumentHandler. And then launches jdb - * and debuggee in defined mode. + * and debuggee. */ public void launchJdbAndDebuggee (String classToExecute) throws IOException { String[] jdbCmdArgs = makeJdbCmdLine(classToExecute); if (argumentHandler.isDefaultConnector()) { - localDefaultLaunch(jdbCmdArgs, classToExecute); + defaultLaunch(jdbCmdArgs, classToExecute); } else if (argumentHandler.isRawLaunchingConnector()) { - localRawLaunch(jdbCmdArgs, classToExecute); + rawLaunch(jdbCmdArgs, classToExecute); } else if (argumentHandler.isLaunchingConnector()) { - localLaunch(jdbCmdArgs, classToExecute); + launchFromJdb(jdbCmdArgs, classToExecute); } else if (argumentHandler.isAttachingConnector()) { - localLaunchAndAttach(jdbCmdArgs, classToExecute); + launchAndAttach(jdbCmdArgs, classToExecute); } else if (argumentHandler.isListeningConnector()) { - localLaunchAndListen(jdbCmdArgs, classToExecute); + launchAndListen(jdbCmdArgs, classToExecute); } else { - throw new TestBug("Unexpected connector type for local launch mode" + throw new TestBug("Unexpected connector type: " + argumentHandler.getConnectorType()); } @@ -255,29 +255,29 @@ private String[] makeJdbCmdLine (String classToExecute) { // ---------------------------------------------- // /** - * Run test in local mode using default connector. + * Run test using default connector. */ - private void localDefaultLaunch + private void defaultLaunch (String[] jdbCmdArgs, String classToExecute) throws IOException { - localLaunch(jdbCmdArgs, classToExecute); + launchFromJdb(jdbCmdArgs, classToExecute); } /** - * Run test in local mode using raw launching connector. + * Run test using raw launching connector. */ - private void localRawLaunch + private void rawLaunch (String[] jdbCmdArgs, String classToExecute) throws IOException { - localLaunch(jdbCmdArgs, classToExecute); + launchFromJdb(jdbCmdArgs, classToExecute); } /** - * Run test in local mode using launching connector. + * Run test using launching connector. */ - private void localLaunch + private void launchFromJdb (String[] jdbCmdArgs, String classToExecute) throws IOException { jdb = new Jdb(this); - display("Starting jdb launching local debuggee"); + display("Starting jdb launching debuggee"); jdb.launch(jdbCmdArgs); if (classToExecute != null) @@ -287,9 +287,9 @@ private String[] makeJdbCmdLine (String classToExecute) { } /** - * Run test in local mode using attaching connector. + * Run test using attaching connector. */ - private void localLaunchAndAttach + private void launchAndAttach (String[] jdbCmdArgs, String classToExecute) throws IOException { debuggee = new Debuggee(this); @@ -297,19 +297,19 @@ private String[] makeJdbCmdLine (String classToExecute) { String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address); debuggee.launch(javaCmdArgs); - display("Start jdb attaching to local debuggee"); + display("Starting jdb attaching to debuggee"); jdb = Jdb.startAttachingJdb (this, jdbCmdArgs, JDB_STARTED); // jdb.waitForPrompt(0, false); } /** - * Run test in local mode using listening connector. + * Run test using listening connector. */ - private void localLaunchAndListen + private void launchAndListen (String[] jdbCmdArgs, String classToExecute) throws IOException { jdb = new Jdb(this); - display("Starting jdb listening to local debuggee"); + display("Starting jdb listening to debuggee"); jdb.launch(jdbCmdArgs); String address = jdb.waitForListeningJdb(); display("Listening address found: " + address); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java index 3f924c6ac47..08bfad05a04 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -474,14 +474,6 @@ protected void checkOptions() { + "jvmdi.strict: non default JVMDI strict mode is not supported now" + getJVMDIStrictMode()); } -/* - if (! isLaunchedLocally() && ! isDefaultJVMDIStrictMode()) { - throw new BadOption("inconsistent options: " - + "-launch.mode=" + getLaunchMode() - + " and -jvmdi.strict=" + getJVMDIStrictMode()); - } - */ - super.checkOptions(); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java index 646d6e9e39e..a30afed77d8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java @@ -123,29 +123,29 @@ public Binder (ArgumentHandler argumentHandler, Log log) { // -------------------------------------------------- // /** - * Make initial Debugee object for local debuggee process + * Make initial Debugee object for debuggee process * started with launching connector. */ - public Debugee makeLocalDebugee(Process process) { + public Debugee makeDebugee(Process process) { return new Debugee(process, this); } /** - * Launch local debuggee process with specified command line + * Launch debuggee process with specified command line * and make initial Debugee object. */ - public Debugee startLocalDebugee(String cmd) { + public Debugee startDebugee(String cmd) { Process process = null; try { process = launchProcess(cmd); } catch (IOException e) { e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while launching local debuggee VM process:\n\t" + throw new Failure("Caught exception while launching debuggee VM process:\n\t" + e); } - return makeLocalDebugee(process); + return makeDebugee(process); } /** @@ -154,7 +154,7 @@ public Debugee startLocalDebugee(String cmd) { * VMStartEvent is received and debuggee is initialized. */ public Debugee enwrapDebugee(VirtualMachine vm, Process proc) { - Debugee debugee = makeLocalDebugee(proc); + Debugee debugee = makeDebugee(proc); display("Redirecting VM output"); debugee.redirectOutput(log); @@ -189,17 +189,17 @@ public Debugee bindToDebugeeNoWait(String classToExecute) { prepareForPipeConnection(argumentHandler); if (argumentHandler.isDefaultConnector()) { - debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath); + debugee = defaultLaunchDebugee(vmm, classToExecute, classPath); } else if (argumentHandler.isRawLaunchingConnector()) { - debugee = localRawLaunchDebugee(vmm, classToExecute, classPath); + debugee = rawLaunchDebugee(vmm, classToExecute, classPath); } else if (argumentHandler.isLaunchingConnector()) { - debugee = localLaunchDebugee(vmm, classToExecute, classPath); + debugee = launchDebugee(vmm, classToExecute, classPath); } else if (argumentHandler.isAttachingConnector()) { - debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath); + debugee = launchAndAttachDebugee(vmm, classToExecute, classPath); } else if (argumentHandler.isListeningConnector()) { - debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath); + debugee = launchAndListenDebugee(vmm, classToExecute, classPath); } else { - throw new TestBug("Unexpected connector type for local debugee launch mode" + throw new TestBug("Unexpected connector type for debugee: " + argumentHandler.getConnectorType()); } @@ -231,9 +231,9 @@ public Debugee bindToDebugee(String classToExecute) { // -------------------------------------------------- // /** - * Launch debugee locally via the default LaunchingConnector. + * Launch debugee via the default LaunchingConnector. */ - private Debugee localDefaultLaunchDebugee (VirtualMachineManager vmm, + private Debugee defaultLaunchDebugee (VirtualMachineManager vmm, String classToExecute, String classPath) { display("Finding connector: " + "default" ); @@ -257,7 +257,7 @@ private Debugee localDefaultLaunchDebugee (VirtualMachineManager vmm, }; Process process = vm.process(); - Debugee debugee = makeLocalDebugee(process); + Debugee debugee = makeDebugee(process); debugee.redirectOutput(log); debugee.setupVM(vm); @@ -266,9 +266,9 @@ private Debugee localDefaultLaunchDebugee (VirtualMachineManager vmm, /** - * Launch debugee locally via the default LaunchingConnector. + * Launch debugee via the default LaunchingConnector. */ - private Debugee localLaunchDebugee (VirtualMachineManager vmm, + private Debugee launchDebugee (VirtualMachineManager vmm, String classToExecute, String classPath) { @@ -295,7 +295,7 @@ private Debugee localLaunchDebugee (VirtualMachineManager vmm, }; Process process = vm.process(); - Debugee debugee = makeLocalDebugee(process); + Debugee debugee = makeDebugee(process); debugee.redirectOutput(log); debugee.setupVM(vm); @@ -303,9 +303,9 @@ private Debugee localLaunchDebugee (VirtualMachineManager vmm, } /** - * Launch debugee locally via the RawLaunchingConnector. + * Launch debugee via the RawLaunchingConnector. */ - private Debugee localRawLaunchDebugee (VirtualMachineManager vmm, + private Debugee rawLaunchDebugee (VirtualMachineManager vmm, String classToExecute, String classPath) { display("Finding connector: " + argumentHandler.getConnectorName() ); @@ -331,7 +331,7 @@ private Debugee localRawLaunchDebugee (VirtualMachineManager vmm, }; Process process = vm.process(); - Debugee debugee = makeLocalDebugee(process); + Debugee debugee = makeDebugee(process); debugee.redirectOutput(log); debugee.setupVM(vm); @@ -339,10 +339,9 @@ private Debugee localRawLaunchDebugee (VirtualMachineManager vmm, } /** - * Launch debugee VM locally as a local process and connect to it using - * AttachingConnector. + * Launch debugee VM and connect to it using AttachingConnector. */ - private Debugee localLaunchAndAttachDebugee (VirtualMachineManager vmm, + private Debugee launchAndAttachDebugee (VirtualMachineManager vmm, String classToExecute, String classPath) { display("FindingConnector: " + argumentHandler.getConnectorName() ); @@ -356,7 +355,7 @@ private Debugee localLaunchAndAttachDebugee (VirtualMachineManager vmm, String javaCmdLine = makeCommandLineString(classToExecute, address, "\""); display("Starting java process:\n\t" + javaCmdLine); - Debugee debugee = startLocalDebugee(cmdLineArgs); + Debugee debugee = startDebugee(cmdLineArgs); debugee.redirectOutput(log); display("Attaching to debugee"); @@ -391,10 +390,9 @@ private Debugee localLaunchAndAttachDebugee (VirtualMachineManager vmm, } /** - * Launch debugee VM locally as a local process and connect to it using - * ListeningConnector. + * Launch debugee VM and connect to it using ListeningConnector. */ - private Debugee localLaunchAndListenDebugee (VirtualMachineManager vmm, + private Debugee launchAndListenDebugee (VirtualMachineManager vmm, String classToExecute, String classPath) { display("Finding connector: " + argumentHandler.getConnectorName() ); @@ -419,7 +417,7 @@ private Debugee localLaunchAndListenDebugee (VirtualMachineManager vmm, String javaCmdLine = makeCommandLineString(classToExecute, address, "\""); display("Starting java process:\n\t" + javaCmdLine); - Debugee debugee = startLocalDebugee(cmdLineArgs); + Debugee debugee = startDebugee(cmdLineArgs); debugee.redirectOutput(log); display("Waiting for connection from debugee"); @@ -685,21 +683,21 @@ private Connector findConnector(String connectorName, List connectors) { // -------------------------------------------------- // /** - * Launch local debuggee process with specified command line arguments + * Launch debuggee process with specified command line arguments * and make initial Debugee mirror. */ - protected Debugee startLocalDebugee(String[] cmdArgs) { + protected Debugee startDebugee(String[] cmdArgs) { Process process = null; try { process = launchProcess(cmdArgs); } catch (IOException e) { e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while launching local debuggee VM process:\n\t" + throw new Failure("Caught exception while launching debuggee VM process:\n\t" + e); } - return makeLocalDebugee(process); + return makeDebugee(process); } public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java index 55ee5366582..6ddf432751c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java @@ -38,11 +38,6 @@ * redirect standard output streams, wait for process terminates * or kill the process, and so on. *

          - * This is an abstract class that declares abstract methods to control - * debugee VM process. - * Derived classes should implement these methods corresponding to the mode - * that the process should be started in (locally). - *

          * Particular derived classes nsk.share.jdi.Debugee and * nsk.share.jdwp.Debugee provides additional abilities * to control debugee VM using JDI or JDWP specific features. @@ -52,7 +47,7 @@ * @see nsk.share.jdi.Debugee * @see nsk.share.jdwp.Debugee */ -abstract public class DebugeeProcess { +public class DebugeeProcess { /** Default prefix for log messages. */ public static final String LOG_PREFIX = "binder> "; diff --git a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ConflictingDefaultsTest.java b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ConflictingDefaultsTest.java index c5de16d583e..64217972980 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ConflictingDefaultsTest.java +++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ConflictingDefaultsTest.java @@ -82,6 +82,8 @@ public static void main(String[] args) { * class C implements I, J {} * * TEST: C c = new C(); c.m() ==> ICCE + * TEST: I c = new C(); c.m() ==> ICCE + * TEST: J c = new C(); c.m() ==> ICCE */ public void testConflict(TestBuilder b) { Interface I = b.intf("I") @@ -95,7 +97,13 @@ public void testConflict(TestBuilder b) { ConcreteClass C = b.clazz("C").implement(I,J).build(); b.test().callSite(C, C, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) + .done() + .test().callSite(I, C, "m","()I") + .throwsExact(IncompatibleClassChangeError.class) + .done() + .test().callSite(J, C, "m","()I") + .throwsExact(IncompatibleClassChangeError.class) .done(); } @@ -145,7 +153,7 @@ public void testReabstract(TestBuilder b) { ConcreteClass C = b.clazz("C").implement(J).build(); b.test().callSite(C, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done(); } @@ -177,16 +185,16 @@ public void testReabstract2(TestBuilder b) { .build(); b.test().callSite(C, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done() .test().callSite(J, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done() .test().callSite(I, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done() .test().callSite(D, D, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done(); } @@ -218,7 +226,7 @@ public void testReabstractConflictingDefaults(TestBuilder b) { ConcreteClass C = b.clazz("C").extend(A).implement(K).build(); b.test().callSite(A, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done(); } @@ -259,13 +267,13 @@ public void testReabstractConflictingDefaultsInvokeInterface(TestBuilder b) { ConcreteClass D = b.clazz("D").extend(C).implement(L).build(); b.test().callSite(I, A, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) .done() .test().callSite(K, C, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done() .test().callSite(L, D, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done(); } @@ -307,10 +315,10 @@ public void testReabstractConflictingDefaultsSuper(TestBuilder b) { .build(); b.test().callSite(I, A, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) .done() .test().callSite(L, D, "m","()I") - .throws_(AbstractMethodError.class) + .throwsExact(AbstractMethodError.class) .done(); } @@ -370,22 +378,22 @@ public void testReabstractResolveMethod00705m2(TestBuilder b) { } b.test().callSite(A, C, "m", "()I") - .throws_(expectedError2) + .throwsExact(expectedError2) .done() .test().callSite(C, C, "m", "()I") - .throws_(expectedError2) + .throwsExact(expectedError2) .done() .test().callSite(J, C, "m", "()I") - .throws_(expectedError1) + .throwsExact(expectedError1) .done() .test().callSite(I, C, "m", "()I") - .throws_(expectedError1) + .throwsExact(expectedError1) .done() .test().callSite(C, C, "test_Cmethod_ISMR", "()V") - .throws_(expectedError2) + .throwsExact(expectedError2) .done() .test().callSite(A, C, "test_Amethod_ISIMR", "()V") - .throws_(expectedError2) + .throwsExact(expectedError2) .done(); } @@ -486,13 +494,13 @@ public void testMixedArity1(TestBuilder b) { .test() .callSite(I, C, "m","(I)I") .params(0) - .throws_(NoSuchMethodError.class) + .throwsExact(NoSuchMethodError.class) .done() // J j = new C(); ... .test() .callSite(J, C, "m","()I") - .throws_(NoSuchMethodError.class) + .throwsExact(NoSuchMethodError.class) .done() .test() .callSite(J, C, "m","(I)I") @@ -539,19 +547,19 @@ public void testMixedArity2(TestBuilder b) { // I i = new C(); ... b.test() .callSite(I, C, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) .done() // J j = new C(); ... .test() .callSite(J, C, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) .done() // C c = new C(); ... .test() .callSite(C, C, "m","()I") - .throws_(IncompatibleClassChangeError.class) + .throwsExact(IncompatibleClassChangeError.class) .done() .test() .callSite(C, C, "m","(I)I") diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/DOMTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/DOMTest.java index b5eeed48290..cb0a106183a 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/DOMTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/DOMTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -22,8 +22,12 @@ */ package common.catalog; -/** - * @test @bug 8306055 +import java.net.ProxySelector; + +/* + * @test + * @bug 8306055 8359337 + * @summary verifies DOM's support of the JDK Catalog. * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @modules java.xml/jdk.xml.internal * @run driver common.catalog.DOMTest 0 // verifies default setting catalog.resolve=allow @@ -36,11 +40,18 @@ * @run driver common.catalog.DOMTest 7 // verifies external DTD resolution with a custom Catalog while resolve=strict in API setting * @run driver common.catalog.DOMTest 8 // verifies external parameter are resolved with a custom Catalog though resolve=strict in API setting * @run driver common.catalog.DOMTest 9 // verifies XInclude are resolved with a custom Catalog though resolve=strict in API setting - * @summary verifies DOM's support of the JDK Catalog. */ public class DOMTest extends CatalogTestBase { - public static void main(String args[]) throws Exception { - new DOMTest().run(args[0]); + public static void main(String[] args) throws Exception { + final ProxySelector previous = ProxySelector.getDefault(); + // disable proxy + ProxySelector.setDefault(ProxySelector.of(null)); + try { + new DOMTest().run(args[0]); + } finally { + // reset to the previous proxy selector + ProxySelector.setDefault(previous); + } } public void run(String index) throws Exception { diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/SAXTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/SAXTest.java index 109568de287..8cbb1612c1a 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/SAXTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/SAXTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -22,8 +22,12 @@ */ package common.catalog; -/** - * @test @bug 8306055 +import java.net.ProxySelector; + +/* + * @test + * @bug 8306055 8359337 + * @summary verifies DOM's support of the JDK Catalog. * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @modules java.xml/jdk.xml.internal * @run driver common.catalog.SAXTest 0 // verifies default setting catalog.resolve=allow @@ -36,12 +40,18 @@ * @run driver common.catalog.SAXTest 7 // verifies external DTD resolution with a custom Catalog while resolve=strict in API setting * @run driver common.catalog.SAXTest 8 // verifies external parameter are resolved with a custom Catalog though resolve=strict in API setting * @run driver common.catalog.SAXTest 9 // verifies XInclude are resolved with a custom Catalog though resolve=strict in API setting - * @summary verifies DOM's support of the JDK Catalog. - */ public class SAXTest extends CatalogTestBase { - public static void main(String args[]) throws Exception { - new SAXTest().run(args[0]); + public static void main(String[] args) throws Exception { + final ProxySelector previous = ProxySelector.getDefault(); + // disable proxy + ProxySelector.setDefault(ProxySelector.of(null)); + try { + new SAXTest().run(args[0]); + } finally { + // reset to the previous proxy selector + ProxySelector.setDefault(previous); + } } public void run(String index) throws Exception { diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DOMTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DOMTest.java index 34d8893d43e..d6df7061a73 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DOMTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DOMTest.java @@ -1,11 +1,33 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * Copyright (c) 2023, 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. + * + * 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. */ package common.dtd; -/** - * @test @bug 8306632 +import java.net.ProxySelector; + +/* + * @test + * @bug 8306632 8359337 + * @summary verifies DOM's support of the property jdk.xml.dtd.support. * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @modules java.xml/jdk.xml.internal * @run driver common.dtd.DOMTest 0 // verifies default setting dtd.support=allow @@ -15,11 +37,18 @@ * @run driver common.dtd.DOMTest 4 // verifies DTD=ignore * @run driver common.dtd.DOMTest 5 // verifies disallow-doctype-decl=false * @run driver common.dtd.DOMTest 6 // verifies disallow-doctype-decl=true - * @summary verifies DOM's support of the property jdk.xml.dtd.support. */ public class DOMTest extends DTDTestBase { - public static void main(String args[]) throws Exception { - new DOMTest().run(args[0]); + public static void main(String[] args) throws Exception { + final ProxySelector previous = ProxySelector.getDefault(); + // disable proxy + ProxySelector.setDefault(ProxySelector.of(null)); + try { + new DOMTest().run(args[0]); + } finally { + // reset to the previous proxy selector + ProxySelector.setDefault(previous); + } } public void run(String index) throws Exception { diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/SAXTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/SAXTest.java index 219753dbb5e..569b070d242 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/SAXTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/SAXTest.java @@ -1,13 +1,35 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * Copyright (c) 2023, 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. + * + * 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. */ package common.dtd; +import java.net.ProxySelector; + import common.util.TestBase; -/** - * @test @bug 8306632 +/* + * @test + * @bug 8306632 8359337 + * @summary verifies SAX's support of the property jdk.xml.dtd.support. * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @modules java.xml/jdk.xml.internal * @run driver common.dtd.SAXTest 0 // verifies default setting dtd.support=allow @@ -17,11 +39,18 @@ * @run driver common.dtd.SAXTest 4 // verifies DTD=ignore * @run driver common.dtd.SAXTest 5 // verifies disallow-doctype-decl=false * @run driver common.dtd.SAXTest 6 // verifies disallow-doctype-decl=true - * @summary verifies SAX's support of the property jdk.xml.dtd.support. */ public class SAXTest extends DTDTestBase { - public static void main(String args[]) throws Exception { - new SAXTest().run(args[0]); + public static void main(String[] args) throws Exception { + final ProxySelector previous = ProxySelector.getDefault(); + // disable proxy + ProxySelector.setDefault(ProxySelector.of(null)); + try { + new SAXTest().run(args[0]); + } finally { + // reset to the previous proxy selector + ProxySelector.setDefault(previous); + } } public void run(String index) throws Exception { diff --git a/test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java b/test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java index febd9e70d5d..6f2be7ae9db 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,10 +25,13 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.ProxySelector; + import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.testng.Assert; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.w3c.dom.Document; @@ -40,10 +43,11 @@ /* * @test - * @bug 8206132 - * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng dom.DOMFeatureTest + * @bug 8206132 8359337 * @summary Tests DOM features. + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @comment we use othervm because the test configures a system wide ProxySelector + * @run testng/othervm dom.DOMFeatureTest */ public class DOMFeatureTest { @@ -105,6 +109,13 @@ Object[][] getData1() throws Exception { {true, XML3}, }; } + + @BeforeClass + static void beforeClass() { + // disable proxy + ProxySelector.setDefault(ProxySelector.of(null)); + } + /** * Verifies the EntityExpansion feature. * @param caseNo the case number diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 3cfa65c6eb3..849bbd08bbb 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -119,6 +119,7 @@ java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generi java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all +java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java 8361521 linux-all java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340374 macosx-all java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all @@ -824,6 +825,7 @@ java/awt/font/GlyphVector/TestGlyphVectorLayout.java 8354987 generic-all java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all +java/awt/FileDialog/DoubleActionESC.java 8356981 linux-all java/awt/print/PageFormat/Orient.java 8016055 macosx-all java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all java/awt/TextComponent/CorrectTextComponentSelectionTest.java 8237220 macosx-all @@ -844,13 +846,13 @@ java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all java/awt/Menu/MenuVisibilityTest.java 8161110 macosx-all java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all +java/awt/Cursor/CursorDragTest/ListDragCursor.java 7177297 macosx-all ############################################################################ # jdk_since_checks -tools/sincechecker/modules/java.base/JavaBaseCheckSince.java 8358627 generic-all tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java 8354921 generic-all ############################################################################ @@ -860,8 +862,6 @@ jdk/classfile/AccessFlagsTest.java 8366270 generic-all java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessValue.java 8367346 generic-all -jdk/jfr/event/runtime/TestSyncOnValueBasedClassEvent.java 8328777 generic-all - jdk/jfr/event/runtime/TestClassLoaderStatsEvent.java 8366820 generic-all com/sun/jdi/valhalla/FieldWatchpointsTest.java 8366806 generic-all diff --git a/test/jdk/com/sun/jdi/EATests.java b/test/jdk/com/sun/jdi/EATests.java index b2a2cad49db..321855b4969 100644 --- a/test/jdk/com/sun/jdi/EATests.java +++ b/test/jdk/com/sun/jdi/EATests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024 SAP SE. All rights reserved. + * Copyright (c) 2020, 2025 SAP SE. 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 @@ -34,42 +34,6 @@ * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run compile -g EATests.java - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 * * @run driver EATests * -XX:+UnlockDiagnosticVMOptions @@ -79,7 +43,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -88,7 +51,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -97,7 +59,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -106,7 +67,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * * @comment Excercise -XX:+DeoptimizeObjectsALot. Mostly to prevent bit-rot because the option is meant to stress object deoptimization * with non-synthetic workloads. @@ -124,16 +84,6 @@ * @comment Regression test for using the wrong thread when logging during re-locking from deoptimization. * * @comment DiagnoseSyncOnValueBasedClasses=2 will cause logging when locking on \@ValueBased objects. - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * -XX:DiagnoseSyncOnValueBasedClasses=2 * * @comment Re-lock may inflate monitors when re-locking, which cause monitorinflation trace logging. * @run driver EATests @@ -144,23 +94,10 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * -Xlog:monitorinflation=trace:file=monitorinflation.log * - * @comment Re-lock may race with deflation. - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=0 - * -XX:GuaranteedAsyncDeflationInterval=1000 - * * @bug 8341819 - * @comment Regression test for re-locking racing with deflation with LM_LIGHTWEIGHT. + * @comment Regression test for re-locking racing with deflation with lightweight locking. * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -169,7 +106,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * -XX:GuaranteedAsyncDeflationInterval=1 */ @@ -1815,8 +1751,8 @@ public void dontinline_testMethod() { /** * Like {@link EARelockingSimple}. The difference is that there are many * lightweight locked objects when the relocking is done. With - * -XX:LockingMode=2 the lock stack of the thread will be full - * because of this. + * lightweight the lock stack of the thread will be full because of + * this. */ class EARelockingWithManyLightweightLocks extends EATestCaseBaseDebugger { diff --git a/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsWithEliminatedLock.java b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsWithEliminatedLock.java index a2dce62792b..4cbd0de460c 100644 --- a/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsWithEliminatedLock.java +++ b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/DumpThreadsWithEliminatedLock.java @@ -26,14 +26,14 @@ * @bug 8356870 * @summary Test HotSpotDiagnosticMXBean.dumpThreads with a thread owning a monitor for * an object that is scalar replaced - * @requires !vm.debug & (vm.compMode != "Xcomp") + * @requires vm.compMode != "Xcomp" * @requires (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) * @modules jdk.management * @library /test/lib - * @run main/othervm DumpThreadsWithEliminatedLock plain platform - * @run main/othervm DumpThreadsWithEliminatedLock plain virtual - * @run main/othervm DumpThreadsWithEliminatedLock json platform - * @run main/othervm DumpThreadsWithEliminatedLock json virtual + * @run main/othervm -XX:CompileCommand=inline,java/lang/String*.* DumpThreadsWithEliminatedLock plain platform + * @run main/othervm -XX:CompileCommand=inline,java/lang/String*.* DumpThreadsWithEliminatedLock plain virtual + * @run main/othervm -XX:CompileCommand=inline,java/lang/String*.* DumpThreadsWithEliminatedLock json platform + * @run main/othervm -XX:CompileCommand=inline,java/lang/String*.* DumpThreadsWithEliminatedLock json virtual */ import java.io.IOException; @@ -168,4 +168,4 @@ private static Path genOutputPath(String suffix) throws IOException { Files.delete(file); return file; } -} \ No newline at end of file +} diff --git a/test/jdk/com/sun/net/httpserver/FileServerHandler.java b/test/jdk/com/sun/net/httpserver/FileServerHandler.java index 849b5fd06de..509adf7bf72 100644 --- a/test/jdk/com/sun/net/httpserver/FileServerHandler.java +++ b/test/jdk/com/sun/net/httpserver/FileServerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -43,7 +43,6 @@ public FileServerHandler (String docroot) { this.docroot = docroot; } - int invocation = 1; public void handle (HttpExchange t) throws IOException { @@ -87,16 +86,16 @@ public void handle (HttpExchange t) rmap.set ("Content-Type", "text/html"); t.sendResponseHeaders (200, 0); String[] list = f.list(); - OutputStream os = t.getResponseBody(); - PrintStream p = new PrintStream (os); - p.println ("

          Directory listing for: " + path+ "

          "); - p.println ("
            "); - for (int i=0; i"+list[i]+""); + try (final OutputStream os = t.getResponseBody(); + final PrintStream p = new PrintStream (os)) { + p.println("

            Directory listing for: " + path + "

            "); + p.println("
              "); + for (int i = 0; i < list.length; i++) { + p.println("
            • " + list[i] + "
            • "); + } + p.println("


            "); + p.flush(); } - p.println ("


          "); - p.flush(); - p.close(); } else { int clen; if (fixedrequest != null) { @@ -105,10 +104,9 @@ public void handle (HttpExchange t) clen = 0; } t.sendResponseHeaders (200, clen); - OutputStream os = t.getResponseBody(); - FileInputStream fis = new FileInputStream (f); int count = 0; - try { + try (final OutputStream os = t.getResponseBody(); + final FileInputStream fis = new FileInputStream (f)) { byte[] buf = new byte [16 * 1024]; int len; while ((len=fis.read (buf)) != -1) { @@ -118,8 +116,6 @@ public void handle (HttpExchange t) } catch (IOException e) { e.printStackTrace(); } - fis.close(); - os.close(); } } diff --git a/test/jdk/com/sun/net/httpserver/Test12.java b/test/jdk/com/sun/net/httpserver/Test12.java index ab1d9d548e7..2a0ee1fc0a4 100644 --- a/test/jdk/com/sun/net/httpserver/Test12.java +++ b/test/jdk/com/sun/net/httpserver/Test12.java @@ -21,23 +21,12 @@ * questions. */ -/* - * @test - * @bug 6270015 - * @library /test/lib - * @build jdk.test.lib.Asserts - * jdk.test.lib.Utils - * jdk.test.lib.net.SimpleSSLContext - * jdk.test.lib.net.URIBuilder - * @run main/othervm Test12 - * @run main/othervm -Djava.net.preferIPv6Addresses=true Test12 - * @summary Light weight HTTP server - */ - import com.sun.net.httpserver.*; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.*; import java.io.*; import java.net.*; @@ -49,11 +38,19 @@ import static jdk.test.lib.Asserts.assertFileContentsEqual; import static jdk.test.lib.Utils.createTempFileOfSize; -/* basic http/s connectivity test - * Tests: - * - same as Test1, but in parallel +/* + * @test + * @bug 6270015 8359477 + * @summary Light weight HTTP server - basic http/s connectivity test, same as Test1, + * but in parallel + * @library /test/lib + * @build jdk.test.lib.Asserts + * jdk.test.lib.Utils + * jdk.test.lib.net.SimpleSSLContext + * jdk.test.lib.net.URIBuilder + * @run main/othervm Test12 + * @run main/othervm -Djava.net.preferIPv6Addresses=true Test12 */ - public class Test12 extends Test { private static final String TEMP_FILE_PREFIX = @@ -61,14 +58,12 @@ public class Test12 extends Test { static SSLContext ctx; - static boolean fail = false; - public static void main (String[] args) throws Exception { HttpServer s1 = null; HttpsServer s2 = null; - ExecutorService executor=null; Path smallFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23); Path largeFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 2730088); + final ExecutorService executor = Executors.newCachedThreadPool(); try { System.out.print ("Test12: "); InetAddress loopback = InetAddress.getLoopbackAddress(); @@ -80,7 +75,6 @@ public static void main (String[] args) throws Exception { HttpHandler h = new FileServerHandler(smallFilePath.getParent().toString()); HttpContext c1 = s1.createContext ("/", h); HttpContext c2 = s2.createContext ("/", h); - executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); ctx = new SimpleSSLContext().get(); @@ -90,7 +84,7 @@ public static void main (String[] args) throws Exception { int port = s1.getAddress().getPort(); int httpsport = s2.getAddress().getPort(); - Runner r[] = new Runner[8]; + final Runner[] r = new Runner[8]; r[0] = new Runner (true, "http", port, smallFilePath); r[1] = new Runner (true, "http", port, largeFilePath); r[2] = new Runner (true, "https", httpsport, smallFilePath); @@ -99,95 +93,83 @@ public static void main (String[] args) throws Exception { r[5] = new Runner (false, "http", port, largeFilePath); r[6] = new Runner (false, "https", httpsport, smallFilePath); r[7] = new Runner (false, "https", httpsport, largeFilePath); - start (r); - join (r); - System.out.println ("OK"); + // submit the tasks + final List> futures = new ArrayList<>(); + for (Runner runner : r) { + futures.add(executor.submit(runner)); + } + // wait for the tasks' completion + for (Future f : futures) { + f.get(); + } + System.out.println ("All " + futures.size() + " tasks completed successfully"); } finally { - if (s1 != null) + if (s1 != null) { s1.stop(0); - if (s2 != null) + } + if (s2 != null) { s2.stop(0); - if (executor != null) - executor.shutdown (); + } + executor.close(); + // it's OK to delete these files since the server side handlers + // serving these files have completed (guaranteed by the completion of Executor.close()) + System.out.println("deleting " + smallFilePath); Files.delete(smallFilePath); + System.out.println("deleting " + largeFilePath); Files.delete(largeFilePath); } } - static void start (Runner[] x) { - for (int i=0; i { boolean fixedLen; String protocol; int port; private final Path filePath; - Runner (boolean fixedLen, String protocol, int port, Path filePath) { + Runner(boolean fixedLen, String protocol, int port, Path filePath) { this.fixedLen=fixedLen; this.protocol=protocol; this.port=port; this.filePath = filePath; } - public void run () { - try { - URL url = URIBuilder.newBuilder() - .scheme(protocol) - .loopback() - .port(port) - .path("/" + filePath.getFileName()) - .toURL(); - HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); - if (urlc instanceof HttpsURLConnection) { - HttpsURLConnection urlcs = (HttpsURLConnection) urlc; - urlcs.setHostnameVerifier (new HostnameVerifier () { - public boolean verify (String s, SSLSession s1) { - return true; - } - }); - urlcs.setSSLSocketFactory (ctx.getSocketFactory()); - } - byte [] buf = new byte [4096]; - - if (fixedLen) { - urlc.setRequestProperty ("XFixed", "yes"); - } - InputStream is = urlc.getInputStream(); - File temp = File.createTempFile ("Test1", null); - temp.deleteOnExit(); - OutputStream fout = new BufferedOutputStream (new FileOutputStream(temp)); - int c, count = 0; - while ((c=is.read(buf)) != -1) { - count += c; - fout.write (buf, 0, c); - } - is.close(); - fout.close(); - - if (count != filePath.toFile().length()) { - throw new RuntimeException ("wrong amount of data returned"); - } - assertFileContentsEqual(filePath, temp.toPath()); - temp.delete(); - } catch (Exception e) { - e.printStackTrace(); - fail = true; + @Override + public Void call() throws Exception { + final URL url = URIBuilder.newBuilder() + .scheme(protocol) + .loopback() + .port(port) + .path("/" + filePath.getFileName()) + .toURL(); + final HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); + if (urlc instanceof HttpsURLConnection) { + HttpsURLConnection urlcs = (HttpsURLConnection) urlc; + urlcs.setHostnameVerifier (new HostnameVerifier () { + public boolean verify (String s, SSLSession s1) { + return true; + } + }); + urlcs.setSSLSocketFactory (ctx.getSocketFactory()); } + if (fixedLen) { + urlc.setRequestProperty ("XFixed", "yes"); + } + final Path temp = Files.createTempFile(Path.of("."), "Test12", null); + final long numReceived; + try (InputStream is = urlc.getInputStream(); + OutputStream fout = new BufferedOutputStream(new FileOutputStream(temp.toFile()))) { + numReceived = is.transferTo(fout); + } + System.out.println("received " + numReceived + " response bytes for " + url); + final long expected = filePath.toFile().length(); + if (numReceived != expected) { + throw new RuntimeException ("expected " + expected + " bytes, but received " + + numReceived); + } + assertFileContentsEqual(filePath, temp); + Files.delete(temp); + return null; } } - } diff --git a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java index 32923f1d78b..da0394a1392 100644 --- a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java +++ b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,42 +25,60 @@ * @test * @bug 4313052 * @summary Test cursor changes after mouse dragging ends - * @library /java/awt/regtesthelpers - * @build PassFailJFrame * @run main/manual ListDragCursor */ +import java.awt.BorderLayout; +import java.awt.Button; import java.awt.Cursor; +import java.awt.EventQueue; import java.awt.Frame; import java.awt.List; import java.awt.Panel; import java.awt.TextArea; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class ListDragCursor { - public static void main(String[] args) throws Exception { - String INSTRUCTIONS = """ + private static final String INSTRUCTIONS = """ 1. Move mouse to the TextArea. 2. Press the left mouse button. 3. Drag mouse to the list. 4. Release the left mouse button. - If the mouse cursor starts as a Text Line Cursor and changes - to a regular Pointer Cursor, then Hand Cursor when hovering - the list, pass the test. This test fails if the cursor does - not update at all when pointing over the different components. + The mouse cursor should appear as an I-beam cursor + and should stay the same while dragging across the + components. Once you reach the list, release the + left mouse button. As soon as you release the left + mouse button, the cursor should change to a Hand + cursor. If true, this test passes. + + The test fails if the cursor updates while dragging + over the components before releasing the left + mouse button. """; - PassFailJFrame.builder() - .title("Test Instructions") - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(35) - .testUI(ListDragCursor::createUI) - .build() - .awaitAndCheck(); + private static Frame testFrame; + private static Frame instructionsFrame; + + private static final CountDownLatch countDownLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> { + instructionsFrame = createInstructionsFrame(); + testFrame = createTestFrame(); + }); + if (!countDownLatch.await(5, TimeUnit.MINUTES)) { + throw new RuntimeException("Test timeout : No action was" + + " taken on the test."); + } + } finally { + EventQueue.invokeAndWait(ListDragCursor::disposeFrames); + } } - public static Frame createUI() { + static Frame createTestFrame() { Frame frame = new Frame("Cursor change after drag"); Panel panel = new Panel(); @@ -78,7 +96,51 @@ public static Frame createUI() { panel.add(list); frame.add(panel); - frame.setBounds(300, 100, 300, 150); + frame.setSize(300, 150); + frame.setLocation(instructionsFrame.getX() + + instructionsFrame.getWidth(), + instructionsFrame.getY()); + frame.setVisible(true); + return frame; + } + + static Frame createInstructionsFrame() { + Frame frame = new Frame("Test Instructions"); + Panel mainPanel = new Panel(new BorderLayout()); + TextArea textArea = new TextArea(INSTRUCTIONS, + 15, 35, TextArea.SCROLLBARS_NONE); + + Panel btnPanel = new Panel(); + Button passBtn = new Button("Pass"); + Button failBtn = new Button("Fail"); + btnPanel.add(passBtn); + btnPanel.add(failBtn); + + passBtn.addActionListener(e -> { + countDownLatch.countDown(); + System.out.println("Test passed."); + }); + failBtn.addActionListener(e -> { + countDownLatch.countDown(); + throw new RuntimeException("Test Failed."); + }); + + mainPanel.add(textArea, BorderLayout.CENTER); + mainPanel.add(btnPanel, BorderLayout.SOUTH); + + frame.add(mainPanel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); return frame; } + + static void disposeFrames() { + if (testFrame != null) { + testFrame.dispose(); + } + if (instructionsFrame != null) { + instructionsFrame.dispose(); + } + } } diff --git a/test/jdk/java/awt/FileDialog/DoubleActionESC.java b/test/jdk/java/awt/FileDialog/DoubleActionESC.java index 748c3aeb5e4..e8bb4963aa0 100644 --- a/test/jdk/java/awt/FileDialog/DoubleActionESC.java +++ b/test/jdk/java/awt/FileDialog/DoubleActionESC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -34,12 +34,15 @@ import java.awt.event.KeyEvent; import java.util.concurrent.CountDownLatch; +import static java.util.concurrent.TimeUnit.SECONDS; + /* * @test * @bug 5097243 * @summary Tests that FileDialog can be closed by ESC any time * @key headful * @run main DoubleActionESC + * @run main/othervm -Dsun.awt.disableGtkFileDialogs=true DoubleActionESC */ public class DoubleActionESC { @@ -49,47 +52,48 @@ public class DoubleActionESC { private static Robot robot; private static volatile Point p; private static volatile Dimension d; - private static volatile CountDownLatch latch; private static final int REPEAT_COUNT = 2; + private static final long LATCH_TIMEOUT = 10; - public static void main(String[] args) throws Exception { - latch = new CountDownLatch(1); + private static final CountDownLatch latch = new CountDownLatch(REPEAT_COUNT); + public static void main(String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(100); + robot.setAutoDelay(50); try { EventQueue.invokeAndWait(() -> { createAndShowUI(); }); + robot.waitForIdle(); robot.delay(1000); + EventQueue.invokeAndWait(() -> { p = showBtn.getLocationOnScreen(); d = showBtn.getSize(); }); for (int i = 0; i < REPEAT_COUNT; ++i) { - Thread thread = new Thread(() -> { - robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - }); - thread.start(); - robot.delay(3000); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(1000); - Thread thread1 = new Thread(() -> { - robot.keyPress(KeyEvent.VK_ESCAPE); - robot.keyRelease(KeyEvent.VK_ESCAPE); - robot.waitForIdle(); - }); - thread1.start(); - robot.delay(3000); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(1000); } - latch.await(); - if (fd.isVisible()) { - throw new RuntimeException("File Dialog is not closed"); + if (!latch.await(LATCH_TIMEOUT, SECONDS)) { + throw new RuntimeException("Test failed: Latch timeout reached"); } + EventQueue.invokeAndWait(() -> { + if (fd.isVisible()) { + throw new RuntimeException("File Dialog is not closed"); + } + }); } finally { EventQueue.invokeAndWait(() -> { if (f != null) { diff --git a/test/jdk/javax/swing/Headless/HeadlessJApplet.java b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java similarity index 61% rename from test/jdk/javax/swing/Headless/HeadlessJApplet.java rename to test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java index e0ac858ac09..64621796b4f 100644 --- a/test/jdk/javax/swing/Headless/HeadlessJApplet.java +++ b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright Amazon.com Inc. 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 @@ -21,24 +21,30 @@ * questions. */ -import javax.swing.JApplet; -import java.awt.HeadlessException; +import java.awt.Window; -/* +/** * @test - * @summary Check that JApplet constructor throws HeadlessException in headless mode - * @run main/othervm -Djava.awt.headless=true HeadlessJApplet + * @bug 8346952 + * @summary Verifies no exception occurs when triggering updateCG() + * for an ownerless window. + * @key headful */ +public final class BogusFocusableWindowState { -public class HeadlessJApplet { - public static void main(String args[]) { - boolean exceptions = false; + public static void main(String[] args) { + Window frame = new Window(null) { + @Override + public boolean getFocusableWindowState() { + removeNotify(); + return true; + } + }; try { - new JApplet(); - } catch (HeadlessException e) { - exceptions = true; + frame.pack(); + frame.setVisible(true); + } finally { + frame.dispose(); } - if (!exceptions) - throw new RuntimeException("HeadlessException did not occur when expected"); } } diff --git a/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java b/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java index 96febfb6744..52961d2827f 100644 --- a/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java +++ b/test/jdk/java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java @@ -27,7 +27,7 @@ /** * @test - * @bug 8235638 8235739 8285094 + * @bug 8235638 8235739 8285094 8346952 * @key headful */ public final class GetGraphicsStressTest { diff --git a/test/jdk/java/awt/GraphicsDevice/FullScreenWindowRace.java b/test/jdk/java/awt/GraphicsDevice/FullScreenWindowRace.java new file mode 100644 index 00000000000..fcc95546764 --- /dev/null +++ b/test/jdk/java/awt/GraphicsDevice/FullScreenWindowRace.java @@ -0,0 +1,65 @@ +/* + * Copyright Amazon.com Inc. 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. + */ + +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Window; + +/** + * @test + * @key headful + * @bug 8359266 + * @summary Tests for a race condition when setting a full-screen window + */ +public final class FullScreenWindowRace { + + public static void main(String[] args) throws InterruptedException { + Window window = new Window(null); + GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice(); + + Thread thread = new Thread(() -> { + while (gd.getFullScreenWindow() == null) { + // Busy wait - can be optimized away without volatile + } + }); + + thread.setDaemon(true); + thread.start(); + + // Give thread some time to start and begin the loop + Thread.sleep(2000); + + gd.setFullScreenWindow(window); + + thread.join(15000); + + boolean alive = thread.isAlive(); + + gd.setFullScreenWindow(null); + window.dispose(); + if (alive) { + throw new RuntimeException("Full screen window is NOT detected!"); + } + } +} diff --git a/test/jdk/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java b/test/jdk/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java deleted file mode 100644 index 44332df94b4..00000000000 --- a/test/jdk/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2008, 2021, 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 - * @key headful - * @bug 6683728 - * @summary Tests that a JApplet in a translucent JFrame works properly - * @compile -XDignore.symbol.file=true TranslucentJAppletTest.java - * @run main/othervm -Dsun.java2d.uiScale=1 TranslucentJAppletTest - */ - -import java.awt.*; -import java.awt.image.*; - -import javax.swing.*; - -public class TranslucentJAppletTest { - - private static volatile GraphicsConfiguration graphicsConfig = null; - private static JFrame frame; - private static volatile boolean paintComponentCalled = false; - - private static void initAndShowGUI() { - frame = new JFrame(graphicsConfig); - JApplet applet = new JApplet(); - applet.setBackground(new Color(0, 0, 0, 0)); - JPanel panel = new JPanel() { - protected void paintComponent(Graphics g) { - paintComponentCalled = true; - g.setColor(Color.RED); - g.fillOval(0, 0, getWidth(), getHeight()); - } - }; - panel.setDoubleBuffered(false); - panel.setOpaque(false); - applet.add(panel); - frame.add(applet); - frame.setBounds(100, 100, 200, 200); - frame.setUndecorated(true); - frame.setBackground(new Color(0, 0, 0, 0)); - frame.setVisible(true); - } - - public static void main(String[] args) - throws Exception - { - - final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - for (GraphicsDevice gd : ge.getScreenDevices()) { - if (gd.isWindowTranslucencySupported( - GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) - { - for (GraphicsConfiguration gc : gd.getConfigurations()) { - if (gc.isTranslucencyCapable()) { - graphicsConfig = gc; - break; - } - } - } - if (graphicsConfig != null) { - break; - } - } - if (graphicsConfig == null) { - System.out.println("The system does not support translucency. Consider the test passed."); - return; - } - - Robot r = new Robot(); - Color color1 = r.getPixelColor(100, 100); // (0, 0) in frame coordinates - - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - initAndShowGUI(); - } - }); - r.waitForIdle(); - - if (!paintComponentCalled) { - throw new RuntimeException("Test FAILED: panel's paintComponent() method is not called"); - } - Thread.sleep(1500); - - Color newColor1 = r.getPixelColor(100, 100); - Color newColor2 = r.getPixelColor(200, 200); - - // Frame must be transparent at (100, 100) in screen coords - if (!color1.equals(newColor1)) { - System.err.println("color1 = " + color1); - System.err.println("newColor1 = " + newColor1); - throw new RuntimeException("Test FAILED: frame pixel at (0, 0) is not transparent"); - } - - // Frame must be RED at (200, 200) in screen coords - if (!newColor2.equals(Color.RED)) { - System.err.println("newColor2 = " + newColor2); - throw new RuntimeException("Test FAILED: frame pixel at (100, 100) is not red (transparent?)"); - } - - System.out.println("Test PASSED"); - } -} diff --git a/test/jdk/java/awt/applet/Applet/AppletFlipBuffer.java b/test/jdk/java/awt/applet/Applet/AppletFlipBuffer.java deleted file mode 100644 index bb541e133be..00000000000 --- a/test/jdk/java/awt/applet/Applet/AppletFlipBuffer.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2015, 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. - */ - -import java.applet.Applet; -import java.awt.AWTException; -import java.awt.BufferCapabilities; -import java.awt.BufferCapabilities.FlipContents; -import java.awt.Frame; -import java.awt.ImageCapabilities; -import java.util.HashSet; -import java.util.Set; - -import sun.awt.AWTAccessor; -import sun.awt.AWTAccessor.ComponentAccessor; - -import static java.awt.BufferCapabilities.FlipContents.BACKGROUND; -import static java.awt.BufferCapabilities.FlipContents.COPIED; -import static java.awt.BufferCapabilities.FlipContents.PRIOR; -import static java.awt.BufferCapabilities.FlipContents.UNDEFINED; - -/** - * @test - * @key headful - * @bug 8130390 8134732 - * @summary Applet fails to launch on virtual desktop - * @modules java.desktop/sun.awt - * @author Semyon Sadetsky - */ -public final class AppletFlipBuffer { - - static final ImageCapabilities[] ics = {new ImageCapabilities(true), - new ImageCapabilities(false)}; - static final FlipContents[] cntx = {UNDEFINED, BACKGROUND, PRIOR, COPIED}; - static final Set bcs = new HashSet<>(); - - static { - for (final ImageCapabilities icFront : ics) { - for (final ImageCapabilities icBack : ics) { - for (final FlipContents cnt : cntx) { - bcs.add(new BufferCapabilities(icFront, icBack, cnt)); - } - } - } - } - - public static void main(final String[] args) throws Exception { - Applet applet = new Applet(); - Frame frame = new Frame(); - try { - frame.setSize(10, 10); - frame.add(applet); - frame.setUndecorated(true); - frame.setVisible(true); - test(applet); - System.out.println("ok"); - } finally { - frame.dispose(); - } - } - - private static void test(final Applet applet) { - ComponentAccessor acc = AWTAccessor.getComponentAccessor(); - for (int i = 1; i < 10; ++i) { - for (final BufferCapabilities caps : bcs) { - try { - acc.createBufferStrategy(applet, i, caps); - } catch (final AWTException ignored) { - // this kind of buffer strategy is not supported - } - } - } - } -} diff --git a/test/jdk/java/awt/color/ICC_Profile/CheckVersions.java b/test/jdk/java/awt/color/ICC_Profile/CheckVersions.java new file mode 100644 index 00000000000..bb497209f00 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/CheckVersions.java @@ -0,0 +1,61 @@ +/* + * Copyright Amazon.com Inc. 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. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; + +/** + * @test + * @bug 8358623 + * @summary Verifies ICC profile version of built-in color spaces + */ +public final class CheckVersions { + + public static void main(String[] args) { + test(ColorSpace.CS_CIEXYZ, 2, 3, 0); + test(ColorSpace.CS_GRAY, 2, 3, 0); + test(ColorSpace.CS_LINEAR_RGB, 2, 3, 0); + test(ColorSpace.CS_PYCC, 4, 0, 0); + test(ColorSpace.CS_sRGB, 2, 3, 0); + } + + private static void test(int cs, int expMajor, int expMinor, int expPatch) { + ICC_Profile profile = ICC_Profile.getInstance(cs); + + int major = profile.getMajorVersion(); + int minorRaw = profile.getMinorVersion(); + int minor = (minorRaw >> 4) & 0x0F; + int patch = minorRaw & 0x0F; + + if (major != expMajor || minor != expMinor || patch != expPatch) { + System.err.println("Expected major: " + expMajor); + System.err.println("Expected minor: " + expMinor); + System.err.println("Expected patch: " + expPatch); + + System.err.println("Actual major: " + major); + System.err.println("Actual minor: " + minor); + System.err.println("Actual patch: " + patch); + throw new RuntimeException("Test failed for ColorSpace: " + cs); + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java b/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java index 83b6e7735ea..819c041308c 100644 --- a/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java +++ b/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -23,7 +23,7 @@ /* @test - @bug 5013984 + @bug 5013984 8360647 @summary Tests KEY_PRESSED has the same KeyChar as KEY_RELEASED @key headful @run main KeyCharTest @@ -37,7 +37,7 @@ import java.util.HashMap; public class KeyCharTest extends Frame implements KeyListener { - HashMap transMap = new HashMap(); + HashMap transMap = new HashMap<>(); public void keyTyped(KeyEvent e){ } @@ -47,22 +47,35 @@ public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ - Object value = transMap.get(e.getKeyCode()); - if (value != null && e.getKeyChar() != ((Character)value).charValue()) { + Character value = transMap.get(e.getKeyCode()); + if (value != null && e.getKeyChar() != value) { throw new RuntimeException("Wrong KeyChar on KEY_RELEASED "+ KeyEvent.getKeyText(e.getKeyCode())); } } - public void start () { + private void testKeyRange(Robot robot, int start, int end) { + System.out.printf("\nTesting range on %d to %d\n", start, end); + for(int vkey = start; vkey <= end; vkey++) { + try { + robot.keyPress(vkey); + robot.keyRelease(vkey); + System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey); + } catch (RuntimeException ignored) {} + } + robot.delay(100); + } + + public void start() throws Exception { + Robot robot = new Robot(); addKeyListener(this); setLocationRelativeTo(null); setSize(200, 200); setVisible(true); requestFocus(); + boolean wasNumlockPressed = false; try { - Robot robot = new Robot(); robot.setAutoDelay(10); robot.setAutoWaitForIdle(true); robot.delay(100); @@ -72,22 +85,25 @@ public void start () { robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); - for(int vkey = 0x20; vkey < 0x7F; vkey++) { - try { - robot.keyPress(vkey); - robot.keyRelease(vkey); - System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey); - } catch (RuntimeException e) { - } - } - robot.delay(100); + testKeyRange(robot, 0x20, 0x7E); + + // Try again with a different numpad state. + robot.keyPress(KeyEvent.VK_NUM_LOCK); + robot.keyRelease(KeyEvent.VK_NUM_LOCK); + wasNumlockPressed = true; + + testKeyRange(robot, KeyEvent.VK_NUMPAD0, KeyEvent.VK_DIVIDE); } catch(Exception e){ - e.printStackTrace(); throw new RuntimeException("Exception while performing Robot actions."); + } finally { + if (wasNumlockPressed) { + robot.keyPress(KeyEvent.VK_NUM_LOCK); + robot.keyRelease(KeyEvent.VK_NUM_LOCK); + } } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { KeyCharTest test = new KeyCharTest(); try { test.start(); diff --git a/test/jdk/java/beans/Introspector/4520754/Test4520754.java b/test/jdk/java/beans/Introspector/4520754/Test4520754.java index affb71257dc..3ad890c57db 100644 --- a/test/jdk/java/beans/Introspector/4520754/Test4520754.java +++ b/test/jdk/java/beans/Introspector/4520754/Test4520754.java @@ -41,7 +41,6 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; -import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JCheckBox; @@ -61,7 +60,7 @@ public static void main(String[] args) { // AWT classes (com.sun.beans.infos.ComponentBeanInfo) test(null, Button.class, Component.class, List.class, Menu.class, Panel.class); // Swing classes (dt.jar) - test(null, JApplet.class, JButton.class, JCheckBox.class); + test(null, JButton.class, JCheckBox.class); // user defined classes test(Boolean.TRUE, Wombat.class, Foo.class, FooBar.class); } diff --git a/test/jdk/java/beans/Performance/TestIntrospector.java b/test/jdk/java/beans/Performance/TestIntrospector.java index 70f68397e66..749a6de5b4c 100644 --- a/test/jdk/java/beans/Performance/TestIntrospector.java +++ b/test/jdk/java/beans/Performance/TestIntrospector.java @@ -25,7 +25,7 @@ * @test * @summary Tests just a benchmark of introspector performance * @author Mark Davidson - * @run main/manual TestIntrospector + * @run main TestIntrospector */ import java.beans.BeanInfo; @@ -43,7 +43,6 @@ public class TestIntrospector { javax.swing.DefaultComboBoxModel.class, javax.swing.DefaultListModel.class, javax.swing.ImageIcon.class, - javax.swing.JApplet.class, javax.swing.JButton.class, javax.swing.JCheckBox.class, javax.swing.JColorChooser.class, diff --git a/test/jdk/java/beans/PropertyChangeSupport/Test4682386.java b/test/jdk/java/beans/PropertyChangeSupport/Test4682386.java index df912e75e25..72a7c0b5084 100644 --- a/test/jdk/java/beans/PropertyChangeSupport/Test4682386.java +++ b/test/jdk/java/beans/PropertyChangeSupport/Test4682386.java @@ -38,7 +38,6 @@ import java.lang.reflect.Method; -import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -70,7 +69,6 @@ public class Test4682386 { private static final boolean DEBUG = true; private static final Class[] TYPES = { - JApplet.class, JButton.class, JCheckBox.class, JComboBox.class, diff --git a/test/jdk/java/io/File/EmptyPath.java b/test/jdk/java/io/File/EmptyPath.java index d3211f917dd..d0c9beddc08 100644 --- a/test/jdk/java/io/File/EmptyPath.java +++ b/test/jdk/java/io/File/EmptyPath.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4842706 8024695 + * @bug 4842706 8024695 8361587 * @summary Test some file operations with empty path * @run junit EmptyPath */ @@ -36,13 +36,14 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; import static org.junit.jupiter.api.Assertions.*; @@ -105,6 +106,11 @@ public void exists() { assertTrue(f.exists()); } + @Test + public void getAbsoluteFile() { + assertEquals(p.toAbsolutePath().toFile(), f.getAbsoluteFile()); + } + @Test public void getAbsolutePath() { System.out.println(p.toAbsolutePath().toString() + "\n" + @@ -112,6 +118,16 @@ public void getAbsolutePath() { assertEquals(p.toAbsolutePath().toString(), f.getAbsolutePath()); } + @Test + public void getCanonicalFile() throws IOException { + assertEquals(p.toRealPath().toFile(), f.getCanonicalFile()); + } + + @Test + public void getCanonicalPath() throws IOException { + assertEquals(p.toRealPath().toString(), f.getCanonicalPath()); + } + private void checkSpace(long expected, long actual) { if (expected == 0) { assertEquals(0L, actual); @@ -136,6 +152,11 @@ public void getParent() { assertNull(f.getParent()); } + @Test + public void getParentFile() { + assertNull(f.getParentFile()); + } + @Test public void getPath() { assertEquals(p.toString(), f.getPath()); @@ -198,11 +219,57 @@ public void list() throws IOException { assertEquals(nioSet, ioSet); } + @Test + public void listFiles() throws IOException { + File child = new File(f.getAbsoluteFile(), "child"); + assertTrue(child.createNewFile()); + child.deleteOnExit(); + + File[] files = f.listFiles(); + for (File file : files) + assertEquals(-1, f.toString().indexOf(File.separatorChar)); + + Set ioSet = Arrays.stream(files) + .map(File::getName) + .collect(Collectors.toSet()); + + assertTrue(ioSet.contains(child.getName())); + + Set nioSet = Files.list(p) + .map(Path::getFileName) + .map(Path::toString) + .collect(Collectors.toSet()); + assertEquals(nioSet, ioSet); + } + + @Test + public void listRoots() { + Set expected = Arrays.stream(f.getAbsoluteFile().listRoots()) + .map(File::toString) + .collect(Collectors.toSet()); + Set actual = Arrays.stream(f.listRoots()) + .map(File::toString) + .collect(Collectors.toSet()); + assertEquals(expected, actual); + } + @Test public void mkdir() { assertFalse(f.mkdir()); } + @Test + public void mkdirs() { + assertFalse(f.mkdirs()); + } + + @Test + public void renameTo() throws IOException { + File tmp = File.createTempFile("foo", "bar", f.getAbsoluteFile()); + assertTrue(tmp.exists()); + assertFalse(f.renameTo(tmp)); + } + @Test public void setLastModified() { long t0 = f.lastModified(); @@ -271,6 +338,12 @@ public void toPath() { assertEquals(p, f.toPath()); } + @Test + public String toString() { + assertEquals(EMPTY_STRING, f.toString()); + return EMPTY_STRING; + } + @Test public void toURI() { assertEquals(f.toPath().toUri(), f.toURI()); diff --git a/test/jdk/java/io/Reader/ReadAll.java b/test/jdk/java/io/Reader/ReadAll.java index 72fcf459eca..fbe1d5a6431 100644 --- a/test/jdk/java/io/Reader/ReadAll.java +++ b/test/jdk/java/io/Reader/ReadAll.java @@ -66,12 +66,55 @@ public static void setup() throws IOException { int size = rnd.nextInt(2, 16386); int plen = PHRASE.length(); - List strings = new ArrayList(size); + StringBuilder sb = new StringBuilder(plen); + List strings = new ArrayList<>(size); while (strings.size() < size) { int fromIndex = rnd.nextInt(0, plen / 2); int toIndex = rnd.nextInt(fromIndex, plen); - strings.add(PHRASE.substring(fromIndex, toIndex)); + String s = PHRASE.substring(fromIndex, toIndex); + sb.append(s); + int bound = toIndex - fromIndex; + if (bound > 0) { + int offset = bound/2; + int n = rnd.nextInt(0, bound); + for (int i = 0; i < n; i++) { + String f = null; + switch (rnd.nextInt(7)) { + case 0 -> f = ""; + case 1 -> f = "\r"; + case 2 -> f = "\n"; + case 3 -> f = "\r\n"; + case 4 -> f = "\r\r"; + case 5 -> f = "\n\n"; + case 6 -> f = " "; + } + sb.insert(offset, f); + } + } + strings.add(sb.toString()); + sb.setLength(0); } + + String p4096 = PHRASE.repeat((4096 + plen - 1)/plen); + String p8192 = PHRASE.repeat((8192 + plen - 1)/plen); + String p16384 = PHRASE.repeat((16384 + plen - 1)/plen); + + for (int i = 0; i < 64; i++) { + for (int j = 0; j < 32; j++) { + switch (rnd.nextInt(8)) { + case 0 -> sb.append(""); + case 1 -> sb.append(" "); + case 2 -> sb.append("\n"); + case 3 -> sb.append(PHRASE); + case 5 -> sb.append(p4096); + case 6 -> sb.append(p8192); + case 7 -> sb.append(p16384); + } + } + strings.add(sb.toString()); + sb.setLength(0); + } + Files.write(path, strings); System.out.println(strings.size() + " lines written"); } @@ -85,6 +128,7 @@ public static void cleanup() throws IOException { @Test public void readAllLines() throws IOException { // Reader implementation + System.out.println("Reader implementation"); List lines; try (FileReader fr = new FileReader(file)) { lines = fr.readAllLines(); @@ -92,9 +136,21 @@ public void readAllLines() throws IOException { System.out.println(lines.size() + " lines read"); List linesExpected = Files.readAllLines(path); - assertEquals(linesExpected, lines); + int count = linesExpected.size(); + if (lines.size() != count) + throw new RuntimeException("Size mismatch: " + lines.size() + " != " + count); + for (int i = 0; i < count; i++) { + String expected = linesExpected.get(i); + String actual = lines.get(i); + if (!actual.equals(expected)) { + String msg = String.format("%d: \"%s\" != \"%s\"", + i, actual, expected); + throw new RuntimeException(msg); + } + } // Reader.of implementation + System.out.println("Reader.of implementation"); String stringExpected = Files.readString(path); int n = rnd.nextInt(stringExpected.length()/2); String substringExpected = stringExpected.substring(n); @@ -103,7 +159,18 @@ public void readAllLines() throws IOException { r.skip(n); lines = r.readAllLines(); } - assertEquals(linesExpected, lines); + count = linesExpected.size(); + if (lines.size() != count) + throw new RuntimeException("Size mismatch: " + lines.size() + " != " + count); + for (int i = 0; i < count; i++) { + String expected = linesExpected.get(i); + String actual = lines.get(i); + if (!actual.equals(expected)) { + String msg = String.format("%d: \"%s\" != \"%s\"", + i, actual, expected); + throw new RuntimeException(msg); + } + } } @Test diff --git a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java index 61a3bfb0de1..014a4dedc0f 100644 --- a/test/jdk/java/lang/Math/FusedMultiplyAddTests.java +++ b/test/jdk/java/lang/Math/FusedMultiplyAddTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4851642 8253409 + * @bug 4851642 8253409 8362207 * @summary Tests for Math.fusedMac and StrictMath.fusedMac. * @build Tests * @build FusedMultiplyAddTests @@ -352,8 +352,9 @@ private static int testSimpleF() { {1.0f+Math.ulp(1.0f), 1.0f+Math.ulp(1.0f), -1.0f-2.0f*Math.ulp(1.0f), Math.ulp(1.0f)*Math.ulp(1.0f)}, - // Double-rounding if done in double precision - {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f} + // Double-rounding if done in double precision and/or double fma + {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f}, + {0x1.001p0f, 0x1.001p0f, 0x1p-100f, 0x1.002002p0f}, }; for (float[] testCase: testCases) diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties new file mode 100644 index 00000000000..8e24f2cb34d --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-ALL.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to ALL +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = ALL diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties index 6afd902c2d0..b9076403cea 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINE.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to FINE ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties new file mode 100644 index 00000000000..a31f4a35e93 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-FINER.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to FINER +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = FINER diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties index d44a836c760..c09c0adf1ed 100644 --- a/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-INFO.properties @@ -1,5 +1,5 @@ ############################################################ -# Enable logging java.lang.Runtime to the console +# java.lang.Runtime logging level to console to INFO ############################################################ handlers= java.util.logging.ConsoleHandler diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties new file mode 100644 index 00000000000..6e284846e92 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-OFF.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to OFF +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = OFF diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties new file mode 100644 index 00000000000..cb6d32581fc --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-SEVERE.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to SEVERE +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = SEVERE diff --git a/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties new file mode 100644 index 00000000000..5cd99c8d6c5 --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/ExitLogging-WARNING.properties @@ -0,0 +1,8 @@ +############################################################ +# java.lang.Runtime logging level to console to WARNING +############################################################ + +handlers= java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = ALL +java.lang.Runtime.level = WARNING diff --git a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java index da40cdbd742..291c9895e19 100644 --- a/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java +++ b/test/jdk/java/lang/RuntimeTests/RuntimeExitLogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -49,7 +49,7 @@ public class RuntimeExitLogTest { private static final String TEST_JDK = System.getProperty("test.jdk"); private static final String TEST_SRC = System.getProperty("test.src"); - + private static final String NEW_LINE = System.lineSeparator(); private static Object HOLD_LOGGER; /** @@ -64,31 +64,80 @@ public static void main(String[] args) throws InterruptedException { System.exit(status); } + /** + * Generate a regular expression pattern that match the expected log output for a Runtime.exit() call. + * The pattern includes the method call stack trace and the exit status. + * @param status the exit status passed to the Runtime.exit() call + * @return the regex pattern as a string + */ + private static String generateStackTraceLogPattern(int status) { + return "(?s)^.+ java\\.lang\\.Shutdown logRuntimeExit\\n" + + ".*: Runtime\\.exit\\(\\) called with status: " + status + "\\n" + + "java\\.lang\\.Throwable: Runtime\\.exit\\(" + status + "\\)\\n" + + "\\s+at java\\.base/java\\.lang\\.Shutdown\\.logRuntimeExit\\(Shutdown\\.java:\\d+\\)\\n" + + "\\s+at(?: .+)"; + } + /** * Test various log level settings, and none. * @return a stream of arguments for parameterized test */ private static Stream logParamProvider() { return Stream.of( - // Logging enabled with level DEBUG + // Logging configuration using the java.util.logging.config.file property + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-ALL.properties").toString()), 1, + generateStackTraceLogPattern(1)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-FINER.properties").toString()), 2, + generateStackTraceLogPattern(2)), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 1, - "Runtime.exit() called with status: 1"), - // Logging disabled due to level + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 3, + generateStackTraceLogPattern(3)), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 4, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-WARNING.properties").toString()), 5, + ""), + Arguments.of(List.of("-Djava.util.logging.config.file=" + + Path.of(TEST_SRC, "ExitLogging-SEVERE.properties").toString()), 6, + ""), Arguments.of(List.of("-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-INFO.properties").toString()), 2, + Path.of(TEST_SRC, "ExitLogging-OFF.properties").toString()), 7, ""), - // Console logger + + // Logging configuration using the jdk.system.logger.level property + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ALL"), 8, + generateStackTraceLogPattern(8)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=TRACE"), 9, + generateStackTraceLogPattern(9)), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=DEBUG"), 10, + generateStackTraceLogPattern(10)), Arguments.of(List.of("--limit-modules", "java.base", - "-Djdk.system.logger.level=DEBUG"), 3, - "Runtime.exit() called with status: 3"), - // Console logger - Arguments.of(List.of(), 4, ""), + "-Djdk.system.logger.level=INFO"), 11, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=WARNING"), 12, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=ERROR"), 13, + ""), + Arguments.of(List.of("--limit-modules", "java.base", + "-Djdk.system.logger.level=OFF"), 14, + ""), + // Throwing Handler Arguments.of(List.of("-DThrowingHandler", "-Djava.util.logging.config.file=" + - Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 5, - "Runtime.exit(5) logging failed: Exception in publish") + Path.of(TEST_SRC, "ExitLogging-FINE.properties").toString()), 15, + "Runtime\\.exit\\(15\\) logging failed: Exception in publish"), + + // Default console logging configuration with no additional parameters + Arguments.of(List.of(), 16, "") ); } @@ -115,13 +164,14 @@ public void checkLogger(List logProps, int status, String expectMessage) try (BufferedReader reader = process.inputReader()) { List lines = reader.lines().toList(); boolean match = (expectMessage.isEmpty()) - ? lines.size() == 0 - : lines.stream().filter(s -> s.contains(expectMessage)).findFirst().isPresent(); + ? lines.isEmpty() + : String.join("\n", lines).matches(expectMessage); if (!match) { // Output lines for debug - System.err.println("Expected: \"" + expectMessage + "\""); + System.err.println("Expected pattern (line-break):"); + System.err.println(expectMessage.replaceAll("\\n", NEW_LINE)); System.err.println("---- Actual output begin"); - lines.forEach(l -> System.err.println(l)); + lines.forEach(System.err::println); System.err.println("---- Actual output end"); fail("Unexpected log contents"); } diff --git a/test/jdk/java/lang/System/OsVersionTest.java b/test/jdk/java/lang/System/OsVersionTest.java index d35f71453b1..9a1cb976db8 100644 --- a/test/jdk/java/lang/System/OsVersionTest.java +++ b/test/jdk/java/lang/System/OsVersionTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2021 SAP SE. All rights reserved. + * 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 @@ -28,56 +29,65 @@ /* * @test - * @bug 8132374 + * @bug 8132374 8359830 * @summary Check that the value of the os.version property is equal * to the value of the corresponding OS provided tools. * @library /test/lib + * @build jtreg.SkippedException * @run main OsVersionTest * @author Volker Simonis */ public class OsVersionTest { - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { final String osVersion = System.getProperty("os.version"); if (osVersion == null) { - throw new Error("Cant query 'os.version' property!"); + throw new Error("Missing value for os.version system property"); } if (Platform.isLinux()) { OutputAnalyzer output = ProcessTools.executeProcess("uname", "-r"); + output.shouldHaveExitValue(0); if (!osVersion.equals(output.getOutput().trim())) { throw new Error(osVersion + " != " + output.getOutput().trim()); } - } - else if (Platform.isOSX()) { - OutputAnalyzer output = ProcessTools.executeProcess("sw_vers", "-productVersion"); - String swVersOutput = output.getOutput().trim(); - if (!osVersion.equals(swVersOutput)) { - // This section can be removed if minimum build SDK is xcode 12+ - if (swVersOutput.startsWith(osVersion)) { - throw new SkippedException("MacOS version only matches in parts, this is expected when " + - "JDK was built with Xcode < 12 and MacOS version patch is > 0"); - } - throw new Error(osVersion + " != " + swVersOutput); - } - } - else if (Platform.isAix()) { + } else if (Platform.isOSX()) { + testMacOS(osVersion); + } else if (Platform.isAix()) { OutputAnalyzer output1 = ProcessTools.executeProcess("uname", "-v"); + output1.shouldHaveExitValue(0); OutputAnalyzer output2 = ProcessTools.executeProcess("uname", "-r"); + output2.shouldHaveExitValue(0); String version = output1.getOutput().trim() + "." + output2.getOutput().trim(); if (!osVersion.equals(version)) { throw new Error(osVersion + " != " + version); } - } - else if (Platform.isWindows()) { + } else if (Platform.isWindows()) { OutputAnalyzer output = ProcessTools.executeProcess("cmd", "/c", "ver"); + output.shouldHaveExitValue(0); String version = output.firstMatch(".+\\[Version ([0-9.]+)\\]", 1); if (version == null || !version.startsWith(osVersion)) { throw new Error(osVersion + " != " + version); } - } - else { - System.out.println("This test is currently not supported on " + + } else { + throw new jtreg.SkippedException("This test is currently not supported on " + Platform.getOsName()); } } + + private static void testMacOS(final String sysPropOsVersion) throws Exception { + final ProcessBuilder pb = new ProcessBuilder("sw_vers", "-productVersion"); + // if the test was launched with SYSTEM_VERSION_COMPAT environment variable set, + // then propagate that to the sw_vers too + final String versionCompat = System.getenv().get("SYSTEM_VERSION_COMPAT"); + if (versionCompat != null) { + pb.environment().put("SYSTEM_VERSION_COMPAT", versionCompat); + } + final OutputAnalyzer output = ProcessTools.executeCommand(pb); + output.shouldHaveExitValue(0); + final String swVersOutput = output.getOutput().trim(); + if (!sysPropOsVersion.equals(swVersOutput)) { + throw new Error("sw_vers reports macOS version: " + swVersOutput + + " but os.version system property reports version: " + sysPropOsVersion); + } + } } diff --git a/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java b/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java index 75ef0376a7e..6260c8e9bda 100644 --- a/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java +++ b/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -31,30 +31,6 @@ * @run junit CarrierThreadInfo */ -/** - * @test id=LM_LIGHTWEIGHT - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=2 CarrierThreadInfo - */ - -/** - * @test id=LM_LEGACY - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=1 CarrierThreadInfo - */ - -/** - * @test id=LM_MONITOR - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=0 CarrierThreadInfo - */ - import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; diff --git a/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java b/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java index 1f909b214c2..b512aa75789 100644 --- a/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java +++ b/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -25,7 +25,7 @@ * @test id=default * @summary Tests for object monitors that have been useful to find bugs * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm MiscMonitorTests */ @@ -33,7 +33,7 @@ /* * @test id=Xint * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xint MiscMonitorTests */ @@ -41,7 +41,7 @@ /* * @test id=Xcomp * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp MiscMonitorTests */ @@ -49,7 +49,7 @@ /* * @test id=Xcomp-TieredStopAtLevel3 * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp -XX:TieredStopAtLevel=3 MiscMonitorTests */ @@ -58,14 +58,14 @@ * @test id=Xcomp-noTieredCompilation * @summary Test virtual threads using synchronized * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp -XX:-TieredCompilation MiscMonitorTests */ /* * @test id=gc - * @requires vm.debug == true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug == true & vm.continuations * @library /test/lib * @modules java.base/java.lang:+open * @run junit/othervm -XX:+UnlockDiagnosticVMOptions -XX:+FullGCALot -XX:FullGCALotInterval=1000 MiscMonitorTests diff --git a/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java b/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java index 858f7625386..3a7eecd054e 100644 --- a/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java +++ b/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java @@ -26,88 +26,35 @@ * @summary Test virtual thread with monitor enter/exit * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=LM_LEGACY + * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xint --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=LM_LIGHTWEIGHT + * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=Xint-LM_LEGACY + * @test id=Xcomp-TieredStopAtLevel1 * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=Xint-LM_LIGHTWEIGHT + * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp -XX:-TieredCompilation --enable-native-access=ALL-UNNAMED MonitorEnterExit */ import java.time.Duration; @@ -129,7 +76,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ValueSource; @@ -234,7 +180,6 @@ private void testReenter(Object lock, int depth) { * Test monitor reenter when there are other threads blocked trying to enter. */ @Test - @DisabledIf("LockingMode#isLegacy") void testReenterWithContention() throws Exception { var lock = new Object(); VThreadRunner.run(() -> { @@ -359,7 +304,6 @@ private void testEnterWithContentionWhenPinned() throws Exception { * Test that blocking waiting to enter a monitor releases the carrier. */ @Test - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenBlocked() throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -403,7 +347,6 @@ void testReleaseWhenBlocked() throws Exception { * carriers aren't released. */ @Test - @DisabledIf("LockingMode#isLegacy") void testManyBlockedThreads() throws Exception { Thread[] vthreads = new Thread[MAX_VTHREAD_COUNT]; var lock = new Object(); diff --git a/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java b/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java index 0ec0adb0faf..d5df8eb97d0 100644 --- a/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java +++ b/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java @@ -26,88 +26,35 @@ * @summary Test virtual threads using Object.wait/notifyAll * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=LM_LEGACY + * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xint --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=LM_LIGHTWEIGHT + * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=Xint-LM_LEGACY + * @test id=Xcomp-TieredStopAtLevel1 * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=Xint-LM_LIGHTWEIGHT + * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp -XX:-TieredCompilation --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ import java.util.ArrayList; @@ -131,7 +78,6 @@ import jdk.test.lib.thread.VThreadPinner; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -306,7 +252,6 @@ static Stream threadCounts() { */ @ParameterizedTest @MethodSource("threadCounts") - @DisabledIf("LockingMode#isLegacy") void testNotifyOneThread(int nPlatformThreads, int nVirtualThreads) throws Exception { int nThreads = nPlatformThreads + nVirtualThreads; @@ -364,7 +309,6 @@ void testNotifyOneThread(int nPlatformThreads, int nVirtualThreads) throws Excep */ @ParameterizedTest @MethodSource("threadCounts") - @DisabledIf("LockingMode#isLegacy") void testNotifyAllThreads(int nPlatformThreads, int nVirtualThreads) throws Exception { int nThreads = nPlatformThreads + nVirtualThreads; @@ -702,7 +646,6 @@ void testParkingPermitNotOffered() throws Exception { */ @ParameterizedTest @ValueSource(ints = { 0, 30000, Integer.MAX_VALUE }) - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenWaiting1(int timeout) throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -759,7 +702,6 @@ void testReleaseWhenWaiting1(int timeout) throws Exception { */ @ParameterizedTest @ValueSource(ints = { 0, 10, 20, 100, 500, 30000, Integer.MAX_VALUE }) - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenWaiting2(int timeout) throws Exception { int VTHREAD_COUNT = 4 * Runtime.getRuntime().availableProcessors(); CountDownLatch latch = new CountDownLatch(VTHREAD_COUNT); diff --git a/test/jdk/java/lang/Thread/virtual/Parking.java b/test/jdk/java/lang/Thread/virtual/Parking.java index 41f7f283bdd..574707e637c 100644 --- a/test/jdk/java/lang/Thread/virtual/Parking.java +++ b/test/jdk/java/lang/Thread/virtual/Parking.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -26,7 +26,6 @@ * @summary Test virtual threads using park/unpark * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit Parking */ @@ -34,7 +33,6 @@ * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xint Parking */ @@ -42,7 +40,6 @@ * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xcomp Parking */ @@ -50,7 +47,6 @@ * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xcomp -XX:-TieredCompilation Parking */ @@ -66,7 +62,6 @@ import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadScheduler; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.*; @@ -385,7 +380,6 @@ void testParkNanos11() throws Exception { */ @ParameterizedTest @ValueSource(booleans = { true, false }) - @DisabledIf("LockingMode#isLegacy") void testParkWhenHoldingMonitor(boolean reenter) throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -435,7 +429,6 @@ void testParkWhenHoldingMonitor(boolean reenter) throws Exception { * parking doesn't release the carrier. */ @Test - @DisabledIf("LockingMode#isLegacy") void testManyParkedWhenHoldingMonitor() throws Exception { Thread[] vthreads = new Thread[MAX_VTHREAD_COUNT]; var done = new AtomicBoolean(); diff --git a/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java b/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java index fa754a88b80..1c7177d9f38 100644 --- a/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java @@ -29,7 +29,6 @@ * can't continue because there are no carriers available. * @modules java.base/java.lang:+open * @library /test/lib - * @requires vm.opt.LockingMode != 1 * @run main/othervm/native --enable-native-access=ALL-UNNAMED RetryMonitorEnterWhenPinned */ diff --git a/test/jdk/java/lang/Thread/virtual/ThreadAPI.java b/test/jdk/java/lang/Thread/virtual/ThreadAPI.java index a3d85660b99..b7fdeb8ec84 100644 --- a/test/jdk/java/lang/Thread/virtual/ThreadAPI.java +++ b/test/jdk/java/lang/Thread/virtual/ThreadAPI.java @@ -27,7 +27,6 @@ * @summary Test Thread API with virtual threads * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED ThreadAPI */ @@ -36,7 +35,6 @@ * @requires vm.continuations * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations * --enable-native-access=ALL-UNNAMED ThreadAPI */ @@ -70,7 +68,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; @@ -1112,7 +1109,6 @@ void testYieldReleasesCarrier() throws Exception { * Test Thread.yield releases carrier thread when virtual thread holds a monitor. */ @Test - @DisabledIf("LockingMode#isLegacy") void testYieldReleasesCarrierWhenHoldingMonitor() throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); var list = new CopyOnWriteArrayList(); diff --git a/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java b/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java index c63a4b0c947..da45c610e82 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java +++ b/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -24,18 +24,10 @@ /* * @test id=default * @summary Test virtual threads entering a lot of monitors with contention - * @requires vm.opt.LockingMode != 1 * @library /test/lib * @run main LotsOfContendedMonitorEnter */ -/* - * @test id=LM_LIGHTWEIGHT - * @requires vm.opt.LockingMode != 1 - * @library /test/lib - * @run main/othervm -XX:LockingMode=2 LotsOfContendedMonitorEnter - */ - import java.util.concurrent.CountDownLatch; import jdk.test.lib.thread.VThreadRunner; diff --git a/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java b/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java index da5fdd1161d..e1a8fb82bd6 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java +++ b/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -28,18 +28,6 @@ * @run main LotsOfUncontendedMonitorEnter */ -/* - * @test id=LM_LEGACY - * @library /test/lib - * @run main/othervm -XX:LockingMode=1 LotsOfUncontendedMonitorEnter - */ - -/* - * @test id=LM_LIGHTWEIGHT - * @library /test/lib - * @run main/othervm -XX:LockingMode=2 LotsOfUncontendedMonitorEnter - */ - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; diff --git a/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java b/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java index 9487de6b862..7949529af60 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java +++ b/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -26,13 +26,13 @@ * @summary Stress test virtual threads with a variation of the Skynet 1M benchmark that uses * a channel implementation based on object monitors. This variant uses a reduced number of * 100k virtual threads at the final level. - * @requires vm.debug != true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug != true & vm.continuations * @run main/othervm/timeout=300 Skynet100kWithMonitors 50 */ /* * @test - * @requires vm.debug == true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug == true & vm.continuations * @run main/othervm/timeout=300 Skynet100kWithMonitors 10 */ diff --git a/test/jdk/java/net/ServerSocket/LargeBacklogTest.java b/test/jdk/java/net/ServerSocket/LargeBacklogTest.java new file mode 100644 index 00000000000..bda976998a7 --- /dev/null +++ b/test/jdk/java/net/ServerSocket/LargeBacklogTest.java @@ -0,0 +1,110 @@ +/* + * 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. + * + * 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.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.channels.AsynchronousServerSocketChannel; +import java.nio.channels.ServerSocketChannel; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +/* + * @test + * @bug 8330940 + * @summary verify that java.net.ServerSocket and the server socket channels in java.nio.channels + * when configured with a backlog of >=200 on Windows, will allow for those many + * backlogged Socket connections + * @requires os.family == "windows" + * @run junit LargeBacklogTest + */ +class LargeBacklogTest { + + @Test + void testServerSocket() throws Exception { + final int backlog = 242; + // Create a ServerSocket configured with the given backlog. + // The ServerSocket never accept()s a connection so each connect() attempt + // will be backlogged. + try (var server = new ServerSocket(0, backlog, InetAddress.getLoopbackAddress())) { + final int serverPort = server.getLocalPort(); + testBackloggedConnects(backlog, serverPort); + } + } + + @Test + void testServerSocketChannel() throws Exception { + final int backlog = 213; + // Create a ServerSocketChannel configured with the given backlog. + // The channel never accept()s a connection so each connect() attempt + // will be backlogged. + try (var serverChannel = ServerSocketChannel.open()) { + serverChannel.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), backlog); + final int serverPort = ((InetSocketAddress) serverChannel.getLocalAddress()).getPort(); + testBackloggedConnects(backlog, serverPort); + } + } + + @Test + void testAsynchronousServerSocketChannel() throws Exception { + final int backlog = 209; + // Create a AsynchronousServerSocketChannel configured with the given backlog. + // The channel never accept()s a connection so each connect() attempt + // will be backlogged. + try (var serverChannel = AsynchronousServerSocketChannel.open()) { + serverChannel.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), backlog); + final int serverPort = ((InetSocketAddress) serverChannel.getLocalAddress()).getPort(); + testBackloggedConnects(backlog, serverPort); + } + } + + private static void testBackloggedConnects(final int backlog, final int serverPort) { + int numSuccessfulConnects = 0; + System.err.println("attempting " + backlog + " connections to port " + serverPort); + // attempt the Socket connections + for (int i = 1; i <= backlog; i++) { + try (final Socket sock = new Socket(InetAddress.getLoopbackAddress(), serverPort)) { + numSuccessfulConnects++; + System.err.println("connection " + i + " established " + sock); + } catch (IOException ioe) { + System.err.println("connection attempt " + i + " failed: " + ioe); + // do not attempt any more connections + break; + } + } + System.err.println(numSuccessfulConnects + " connections successfully established"); + // ideally we expect the number of successful connections to be equal to the backlog value. + // however in certain environments, it's possible that some other process attempts a + // connection to the server's port. so we allow for a small number of connection attempts + // to fail (due to exceeding the backlog) + final int minimumExpectedSuccessfulConns = backlog - 5; + if (numSuccessfulConnects < minimumExpectedSuccessfulConns) { + fail("expected at least " + minimumExpectedSuccessfulConns + + " successful connections for a backlog of " + backlog + ", but only " + + numSuccessfulConnects + " were successful"); + } + } +} diff --git a/test/jdk/java/net/httpclient/DigestEchoClient.java b/test/jdk/java/net/httpclient/DigestEchoClient.java index 7b4f7fd3462..0aa70a26586 100644 --- a/test/jdk/java/net/httpclient/DigestEchoClient.java +++ b/test/jdk/java/net/httpclient/DigestEchoClient.java @@ -261,8 +261,9 @@ public static void main(String[] args) throws Exception { } try { for (DigestEchoServer.HttpAuthType authType : types) { - // The test server does not support PROXY305 properly - if (authType == DigestEchoServer.HttpAuthType.PROXY305) continue; + // The test server does not support PROXY305 or SERVER307 properly + if (authType == DigestEchoServer.HttpAuthType.PROXY305 || + authType == DigestEchoServer.HttpAuthType.SERVER307) continue; EnumSet basics = EnumSet.of(DigestEchoServer.HttpAuthSchemeType.BASICSERVER, DigestEchoServer.HttpAuthSchemeType.BASIC); diff --git a/test/jdk/java/net/httpclient/OriginTest.java b/test/jdk/java/net/httpclient/OriginTest.java new file mode 100644 index 00000000000..58310ecd9ad --- /dev/null +++ b/test/jdk/java/net/httpclient/OriginTest.java @@ -0,0 +1,185 @@ +/* + * 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. + * + * 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.net.URI; +import java.util.Locale; + +import jdk.internal.net.http.Origin; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +/* + * @test + * @summary verify the behaviour of jdk.internal.net.http.Origin + * @modules java.net.http/jdk.internal.net.http + * @run junit OriginTest + */ +class OriginTest { + + @ParameterizedTest + @ValueSource(strings = {"foo", "Bar", "HttPS", "HTTP"}) + void testInvalidScheme(final String scheme) throws Exception { + final String validHost = "127.0.0.1"; + final int validPort = 80; + final IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> { + new Origin(scheme, validHost, validPort); + }); + assertTrue(iae.getMessage().contains("scheme"), + "unexpected exception message: " + iae.getMessage()); + } + + @ParameterizedTest + @ValueSource(strings = {"http", "https"}) + void testValidScheme(final String scheme) throws Exception { + final String validHost = "127.0.0.1"; + final int validPort = 80; + final Origin o1 = new Origin(scheme, validHost, validPort); + assertEquals(validHost, o1.host(), "unexpected host"); + assertEquals(validPort, o1.port(), "unexpected port"); + assertEquals(scheme, o1.scheme(), "unexpected scheme"); + + final URI uri = URI.create(scheme + "://" + validHost + ":" + validPort); + final Origin o2 = Origin.from(uri); + assertNotNull(o2, "null Origin for URI " + uri); + assertEquals(validHost, o2.host(), "unexpected host"); + assertEquals(validPort, o2.port(), "unexpected port"); + assertEquals(scheme, o2.scheme(), "unexpected scheme"); + } + + @ParameterizedTest + @ValueSource(strings = {"JDK.java.net", "[::1]", "[0:0:0:0:0:0:0:1]"}) + void testInvalidHost(final String host) throws Exception { + final String validScheme = "http"; + final int validPort = 8000; + final IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> { + new Origin(validScheme, host, validPort); + }); + assertTrue(iae.getMessage().contains("host"), + "unexpected exception message: " + iae.getMessage()); + } + + @ParameterizedTest + @ValueSource(strings = {"127.0.0.1", "localhost", "jdk.java.net", "::1", "0:0:0:0:0:0:0:1"}) + void testValidHost(final String host) throws Exception { + final String validScheme = "https"; + final int validPort = 42; + final Origin o1 = new Origin(validScheme, host, validPort); + assertEquals(host, o1.host(), "unexpected host"); + assertEquals(validPort, o1.port(), "unexpected port"); + assertEquals(validScheme, o1.scheme(), "unexpected scheme"); + + String uriHost = host; + if (host.contains(":")) { + uriHost = "[" + host + "]"; + } + final URI uri = URI.create(validScheme + "://" + uriHost + ":" + validPort); + final Origin o2 = Origin.from(uri); + assertNotNull(o2, "null Origin for URI " + uri); + assertEquals(host, o2.host(), "unexpected host"); + assertEquals(validPort, o2.port(), "unexpected port"); + assertEquals(validScheme, o2.scheme(), "unexpected scheme"); + } + + @ParameterizedTest + @ValueSource(ints = {-1, 0}) + void testInvalidPort(final int port) throws Exception { + final String validScheme = "http"; + final String validHost = "127.0.0.1"; + final IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, + () -> new Origin(validScheme, validHost, port)); + assertTrue(iae.getMessage().contains("port"), + "unexpected exception message: " + iae.getMessage()); + } + + @ParameterizedTest + @ValueSource(ints = {100, 1024, 80, 8080, 42}) + void testValidPort(final int port) throws Exception { + final String validScheme = "https"; + final String validHost = "localhost"; + final Origin o1 = new Origin(validScheme, validHost, port); + assertEquals(validHost, o1.host(), "unexpected host"); + assertEquals(port, o1.port(), "unexpected port"); + assertEquals(validScheme, o1.scheme(), "unexpected scheme"); + + final URI uri = URI.create(validScheme + "://" + validHost + ":" + port); + final Origin o2 = Origin.from(uri); + assertNotNull(o2, "null Origin for URI " + uri); + assertEquals(validHost, o2.host(), "unexpected host"); + assertEquals(port, o2.port(), "unexpected port"); + assertEquals(validScheme, o2.scheme(), "unexpected scheme"); + } + + @Test + void testInferredPort() throws Exception { + final URI httpURI = URI.create("http://localhost"); + final Origin httpOrigin = Origin.from(httpURI); + assertNotNull(httpOrigin, "null Origin for URI " + httpURI); + assertEquals("localhost", httpOrigin.host(), "unexpected host"); + assertEquals(80, httpOrigin.port(), "unexpected port"); + assertEquals("http", httpOrigin.scheme(), "unexpected scheme"); + + + final URI httpsURI = URI.create("https://[::1]"); + final Origin httpsOrigin = Origin.from(httpsURI); + assertNotNull(httpsOrigin, "null Origin for URI " + httpsURI); + assertEquals("::1", httpsOrigin.host(), "unexpected host"); + assertEquals(443, httpsOrigin.port(), "unexpected port"); + assertEquals("https", httpsOrigin.scheme(), "unexpected scheme"); + } + + @Test + void testFromURI() { + // non-lower case URI scheme is expected to be converted to lowercase in the Origin + // constructed through Origin.from(URI) + for (final String scheme : new String[]{"httPs", "HTTP"}) { + final String expectedScheme = scheme.toLowerCase(Locale.ROOT); + final URI uri = URI.create(scheme + "://localhost:1234"); + final Origin origin = Origin.from(uri); + assertNotNull(origin, "null Origin for URI " + uri); + assertEquals("localhost", origin.host(), "unexpected host"); + assertEquals(1234, origin.port(), "unexpected port"); + assertEquals(expectedScheme, origin.scheme(), "unexpected scheme"); + } + // URI without a port is expected to be defaulted to port 80 or 443 for http and https + // schemes respectively + for (final String scheme : new String[]{"http", "https"}) { + final int expectedPort = switch (scheme) { + case "http" -> 80; + case "https" -> 443; + default -> fail("unexpected scheme: " + scheme); + }; + final URI uri = URI.create(scheme + "://localhost"); + final Origin origin = Origin.from(uri); + assertNotNull(origin, "null Origin for URI " + uri); + assertEquals("localhost", origin.host(), "unexpected host"); + assertEquals(expectedPort, origin.port(), "unexpected port"); + assertEquals(scheme, origin.scheme(), "unexpected scheme"); + } + } +} diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java index 729fdb084e1..27d2b98a34d 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java @@ -33,6 +33,7 @@ import java.net.Socket; import java.net.SocketAddress; import java.net.SocketOption; +import java.net.URI; import java.net.http.HttpHeaders; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; @@ -459,7 +460,9 @@ public HttpConnectionStub( InetSocketAddress address, InetSocketAddress proxy, boolean secured) { - super(address, impl, "testConn-" + IDS.incrementAndGet()); + final Origin originServer = Origin.from( + URI.create("http://"+ address.getHostString() + ":" + address.getPort())); + super(originServer, address, impl, "testConn-" + IDS.incrementAndGet()); this.key = ConnectionPool.cacheKey(secured, address, proxy); this.address = address; this.proxy = proxy; diff --git a/test/jdk/java/nio/Buffer/GetChars.java b/test/jdk/java/nio/Buffer/GetChars.java index 86334828717..65aeca70328 100644 --- a/test/jdk/java/nio/Buffer/GetChars.java +++ b/test/jdk/java/nio/Buffer/GetChars.java @@ -36,7 +36,7 @@ /** * @test - * @bug 8343110 + * @bug 8343110 8361299 * @summary Check for expected behavior of CharBuffer.getChars(). * @run testng GetChars * @key randomness @@ -71,6 +71,19 @@ public void testSrcBeginIsNegative() { () -> CB.getChars(-1, 3, new char[4], 0)); } + @Test + public void testSrcBeginIsNegationOfPosition() { + CB.position(1); + Assert.assertThrows(IndexOutOfBoundsException.class, + () -> { + try { + CB.getChars(-1, 3, new char[4], 0); + } finally { + CB.position(0); + } + }); + } + @Test public void testDstBeginIsNegative() { Assert.assertThrows(IndexOutOfBoundsException.class, @@ -200,7 +213,7 @@ public void testGetChars(String type, CharBuffer cb) { System.out.format("%s position=%d, limit=%d%n", type, cb.position(), cb.limit()); int expected = intSum(cb); var dst = new char[cb.remaining()]; - cb.getChars(cb.position(), cb.limit(), dst, 0); + cb.getChars(0, cb.remaining(), dst, 0); int actual = intSum(dst); assertEquals(actual, expected); } diff --git a/test/jdk/java/nio/file/FileStore/Basic.java b/test/jdk/java/nio/file/FileStore/Basic.java index 9bba08de71f..0a7b3d5e2f6 100644 --- a/test/jdk/java/nio/file/FileStore/Basic.java +++ b/test/jdk/java/nio/file/FileStore/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6873621 6979526 7006126 7020517 8264400 + * @bug 4313887 6873621 6979526 7006126 7020517 8264400 8360887 * @summary Unit test for java.nio.file.FileStore * @key intermittent * @library .. /test/lib @@ -67,6 +67,16 @@ static void checkWithin1GB(String space, long expected, long actual) { } } + static void testFileAttributes(Path file, + Class viewClass, + String viewName) throws IOException { + FileStore store = Files.getFileStore(file); + boolean supported = store.supportsFileAttributeView(viewClass); + assertTrue(store.supportsFileAttributeView(viewName) == supported); + boolean haveView = Files.getFileAttributeView(file, viewClass) != null; + assertTrue(haveView == supported); + } + static void doTests(Path dir) throws IOException { /** * Test: Directory should be on FileStore that is writable @@ -97,15 +107,11 @@ static void doTests(Path dir) throws IOException { * Test: File and FileStore attributes */ assertTrue(store1.supportsFileAttributeView("basic")); - assertTrue(store1.supportsFileAttributeView(BasicFileAttributeView.class)); - assertTrue(store1.supportsFileAttributeView("posix") == - store1.supportsFileAttributeView(PosixFileAttributeView.class)); - assertTrue(store1.supportsFileAttributeView("dos") == - store1.supportsFileAttributeView(DosFileAttributeView.class)); - assertTrue(store1.supportsFileAttributeView("acl") == - store1.supportsFileAttributeView(AclFileAttributeView.class)); - assertTrue(store1.supportsFileAttributeView("user") == - store1.supportsFileAttributeView(UserDefinedFileAttributeView.class)); + testFileAttributes(dir, BasicFileAttributeView.class, "basic"); + testFileAttributes(dir, PosixFileAttributeView.class, "posix"); + testFileAttributes(dir, DosFileAttributeView.class, "dos"); + testFileAttributes(dir, AclFileAttributeView.class, "acl"); + testFileAttributes(dir, UserDefinedFileAttributeView.class, "user"); /** * Test: Space atributes diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java index b8e9a1736c4..0f52bc67f08 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -45,15 +45,6 @@ * @run main/timeout=1600 MapLoops */ -/* - * @test - * @summary Exercise multithreaded maps, using only heavy monitors. - * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" | os.arch == "s390x" - * @requires vm.debug - * @library /test/lib - * @run main/othervm/timeout=1600 -XX:LockingMode=0 -XX:+VerifyHeavyMonitors MapLoops - */ - import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; diff --git a/test/jdk/java/util/regex/CaseFoldingTest.java b/test/jdk/java/util/regex/CaseFoldingTest.java new file mode 100644 index 00000000000..c478577d7c9 --- /dev/null +++ b/test/jdk/java/util/regex/CaseFoldingTest.java @@ -0,0 +1,165 @@ +/* + * 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. + * + * 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 + * @summary tests RegExp unicode case-insensitive match (?ui) + * @bug 8360459 + * @library /lib/testlibrary/java/lang + * @run junit CaseFoldingTest + */ + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CaseFoldingTest { + + @Test + void testUnicodeCaseInsensitiveMatch() throws Throwable { + var testAll = true; // true to test all codepoints defined in CaseFolding.txt + var verbose = true; // true to display all codepoints being tested + var filter = "^.*; [CTS]; .*$"; // update C,T,S to test different type + var excluded = Set.of( + // these 'S' characters failed for known reason. they don't map to their + // folding form with toUpperCase or toLowerCase, only map with case-folding. + // exclude them for now. + 0x1fd3, // 1FD3 [lo: 1fd3, up: 1fd3] 0390 [lo: 0390, up: 0390] + 0x1fe3, // 1FE3 [lo: 1fe3, up: 1fe3] 03B0 [lo: 03b0, up: 03b0] + 0xfb05 // FB05 [lo: fb05, up: fb05] FB06 [lo: fb06, up: fb06] + ); + + var results = Files.lines(UCDFiles.CASEFOLDING) + .filter(line -> !line.startsWith("#") && line.matches(filter)) + .map(line -> { + var strs = line.split("; "); + return new String[] {strs[0], strs[1], strs[2]}; + }) + .filter(cps -> { + var cp1 = Integer.parseInt(cps[0], 16); + var cp2 = Integer.parseInt(cps[2], 16); + if (excluded.contains(cp1)) + return false; + if (testAll) { + return true; + } + // the folding codepoint doesn't map back to the original codepoint. + return Character.toUpperCase(cp2) != cp1 && Character.toLowerCase(cp2) != cp1; + }) + .flatMap(cps -> { + // test slice, single & range + var cp = Integer.parseInt(cps[0], 16); + var folding = Integer.parseInt(cps[2], 16); + var errors = testCaseFolding(cp, folding); + if (verbose) + System.out.format(" [%s] %s [lo: %04x, up: %04x] %s [lo: %04x, up: %04x]\n", + cps[1], + cps[0], + Character.toLowerCase(cp), + Character.toUpperCase(cp), + cps[2], + Character.toLowerCase(folding), + Character.toUpperCase(folding) + ); + errors.forEach(error -> System.out.print(error)); + return errors.stream(); + }) + .collect(Collectors.toList()); + assertEquals(results.size(), 0); + } + + private static ArrayList testCaseFolding(int cp, int folding) { + ArrayList errors = new ArrayList<>(); + testCaseFolding0(cp, folding, errors, "s-t"); + testCaseFolding0(folding, cp, errors, "t-s"); + // test all uppercase, lowercase combinations + var up = Character.toUpperCase(cp); + var lo = Character.toLowerCase(cp); + var folding_up = Character.toUpperCase(folding); // folding should be normally lowercase + if (up != cp) { + testCaseFolding0(up, folding, errors, "s(u)-t"); + testCaseFolding0(folding, up, errors, "t-s(u)"); + if (folding_up != folding) { + testCaseFolding0(up, folding_up, errors, "s(u)-t(u)"); + testCaseFolding0(folding_up, up, errors, "t(u)-s(u)"); + } + } + if (lo != cp) { + testCaseFolding0(lo, folding, errors, "s(l)-t"); + testCaseFolding0(folding, lo, errors, "t-s(l)"); + if (folding_up != folding) { + testCaseFolding0(lo, folding_up, errors, "s(l)-t(u)"); + testCaseFolding0(folding_up, lo, errors, "t(u)-s(l)"); + } + } + return errors; + } + + private static void testCaseFolding0(int cp, int folding, ArrayList errors, String type) { + var cp_str = Character.isSupplementaryCodePoint(cp) + ? String.format("\\u%04x\\u%04x", (int)Character.highSurrogate(cp), (int)Character.lowSurrogate(cp)) + : String.format("\\u%04x", cp); + + var t = new String(Character.toChars(folding)); + var p = String.format("(?iu)%s", cp_str); + + if (Pattern.compile(p).matcher(t).matches() == false) { + errors.add(String.format(" [FAILED] slice: %-20s t: u+%04x (%s)\n", p, folding, type)); + } + + p = String.format("(?iu)[%s]", cp_str); + if (Pattern.compile(p).matcher(t).matches() == false) { + errors.add(String.format(" [FAILED] single: %-20s t: u+%04x (%s)\n", p, folding, type)); + } + + p = String.format("(?iu)[%s-%s]", cp_str, cp_str); + if (Pattern.compile(p).matcher(t).matches() == false) { + errors.add(String.format(" [FAILED] range: %-20s t: u+%04x (%s)\n", p, folding, type)); + } + + // small range + var end_cp = cp + 16; + var end_cp_str = Character.isSupplementaryCodePoint(end_cp) + ? String.format("\\u%04x\\u%04x", (int)Character.highSurrogate(end_cp), (int)Character.lowSurrogate(end_cp)) + : String.format("\\u%04x", end_cp); + p = String.format("(?iu)[%s-%s]", cp_str, end_cp_str); + if (Pattern.compile(p).matcher(t).matches() == false) { + errors.add(String.format(" [FAILED] range: %-20s t: u+%04x (%s)\n", p, folding, type)); + } + + end_cp = cp + 128; // bigger than the expanded_casefolding_map. + end_cp_str = Character.isSupplementaryCodePoint(end_cp) + ? String.format("\\u%04x\\u%04x", (int)Character.highSurrogate(end_cp), (int)Character.lowSurrogate(end_cp)) + : String.format("\\u%04x", end_cp); + p = String.format("(?iu)[%s-%s]", cp_str, end_cp_str); + if (Pattern.compile(p).matcher(t).matches() == false) { + errors.add(String.format(" [FAILED] range: %-20s t: u+%04x (%s)\n", p, folding, type)); + } + } +} diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java index 3338b4f5c2d..2bd2dc3e38d 100644 --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -2324,6 +2324,21 @@ public static void ceTest() { check(p, "test\u00e4\u0300\u0323", true); Object[][] data = new Object[][] { + // JDK-8354490 + // emoji + emoji_component pair forms a single grapheme but remains + // as 2 separate characters in nfc. match & find should still work with the + // CANON_EQ flag, as long as the character class is appropriately specified. + {"^[^/]*\\.[^/]*$", "\u2764\ufe0ffile.txt", "m", true}, + { "\\p{IsEmoji}", "ab\u2764\ufe0fcd", "f", true }, + { "[\\p{IsEmoji}]", "ab\u2764\ufe0fcd", "f", true }, + { "\\p{IsEmoji}\\p{IsEmoji_Component}", "\u2764\ufe0f", "m", true }, + { "[\\p{IsEmoji}\\p{IsEmoji_Component}]{2}", "\u2764\ufe0f", "m", true }, + // greek with extra combining character + {"\\p{IsGreek}", "\u1f80\u0345", "f", true}, + {"[\\p{IsGreek}]", "\u1f80\u0345", "f", true}, + {"\\p{IsGreek}\\p{IsAlphabetic}", "\u1f80\u0345", "m", true}, + {"\\p{IsAlphabetic}*", "\u1f80\u0345", "m", true}, + {"[\\p{IsAlphabetic}]*", "\u1f80\u0345", "m", true}, // JDK-4867170 { "[\u1f80-\u1f82]", "ab\u1f80cd", "f", true }, diff --git a/test/jdk/java/util/regex/TestCases.txt b/test/jdk/java/util/regex/TestCases.txt index 3b367782643..3353335f84d 100644 --- a/test/jdk/java/util/regex/TestCases.txt +++ b/test/jdk/java/util/regex/TestCases.txt @@ -1273,3 +1273,28 @@ true 11111111 1 1111 ^(1{2,})\1+$ 11111111 true 11111111 1 1111 + +// +(?ui)\u00df +\u1e9e +true \u1e9e 0 + +(?ui)[\u00df] +\u1e9e +true \u1e9e 0 + +(?ui)[\u00df-\u00df] +\u1e9e +true \u1e9e 0 + +(?ui)\u1e9e +\u00df +true \u00df 0 + +(?ui)[\u1e9e] +\u00df +true \u00df 0 + +(?ui)[\u1e9e-\u1e9e] +\u00df +true \u00df 0 diff --git a/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java index bd36e7f3ca7..56e35f2a72a 100644 --- a/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java +++ b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java @@ -24,33 +24,63 @@ /* * @test - * @bug 8358159 - * @summary test that the Cipher.getInstance() handles - * transformations with empty mode and/or padding - * @run main TestEmptyModePadding + * @bug 8359388 + * @summary test that the Cipher.getInstance() would reject improper + * transformations with empty mode and/or padding. */ - -import java.security.*; -import javax.crypto.*; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.Cipher; public class TestEmptyModePadding { public static void main(String[] args) throws Exception { - Provider provider = Security.getProvider(System.getProperty("test.provider.name", "SunJCE")); + Provider provider = Security.getProvider( + System.getProperty("test.provider.name", "SunJCE")); + + System.out.println("Testing against " + provider.getName()); - test("AES", provider); - test("AES/ECB/PKCS5Padding", provider); - test("AES//PKCS5Padding", provider); // Empty mode - test("AES/CBC/", provider); // Empty padding - test("AES/ /NoPadding", provider); // Mode is a space - test("AES/CBC/ ", provider); // Padding is a space - test("AES/ / ", provider); // Both mode and padding are spaces - test("AES//", provider); // Both mode and padding are missing + String[] testTransformations = { + // transformations w/ only 1 component, i.e. algo + " ", + // transformations w/ only 2 components + "AES/", + "AES/ ", + "AES/CBC", + "PBEWithHmacSHA512/224AndAES_128/", + "PBEWithHmacSHA512/256AndAES_128/ ", + "PBEWithHmacSHA512/224AndAES_128/CBC", + // 3-component transformations w/ empty component(s) + "AES//", + "AES/ /", + "AES// ", + "AES/ / ", + "AES/CBC/", "AES/CBC/ ", + "AES//PKCS5Padding", "AES/ /NoPadding", + "PBEWithHmacSHA512/224AndAES_128//", + "PBEWithHmacSHA512/224AndAES_128/ /", + "PBEWithHmacSHA512/224AndAES_128// ", + "PBEWithHmacSHA512/224AndAES_128/ / ", + "PBEWithHmacSHA512/256AndAES_128/CBC/", + "PBEWithHmacSHA512/256AndAES_128/CBC/ ", + "PBEWithHmacSHA512/256AndAES_128//PKCS5Padding", + "PBEWithHmacSHA512/256AndAES_128/ /PKCS5Padding", + }; + for (String t : testTransformations) { + test(t, provider); + } } - private static void test(String transformation, Provider provider) throws Exception { - Cipher c = Cipher.getInstance(transformation, provider); + private static void test(String t, Provider p) throws Exception { + try { + Cipher c = Cipher.getInstance(t, p); + throw new RuntimeException("Should throw NSAE for \'" + t + "\'"); + } catch (NoSuchAlgorithmException nsae) { + // transformation info is already in the NSAE message + System.out.println("Expected NSAE: " + nsae.getMessage()); + } } } diff --git a/test/jdk/javax/crypto/SecretKeyFactory/P1.jar b/test/jdk/javax/crypto/SecretKeyFactory/P1.jar index f8aae381141..4f17f44fa85 100644 Binary files a/test/jdk/javax/crypto/SecretKeyFactory/P1.jar and b/test/jdk/javax/crypto/SecretKeyFactory/P1.jar differ diff --git a/test/jdk/javax/crypto/SecretKeyFactory/P2.jar b/test/jdk/javax/crypto/SecretKeyFactory/P2.jar index d828f45ebdd..f7b82410c8c 100644 Binary files a/test/jdk/javax/crypto/SecretKeyFactory/P2.jar and b/test/jdk/javax/crypto/SecretKeyFactory/P2.jar differ diff --git a/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java b/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java index 602e1f2ebd2..219632784f0 100644 --- a/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java +++ b/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6336968 + * @bug 6336968 8359809 * @summary Test adding non-Attribute values to an AttributeList. * @author Eamonn McManus */ @@ -38,28 +38,14 @@ public class AttributeListTypeSafeTest { private static String failure; public static void main(String[] args) throws Exception { - // Test calling asList after adding non-Attribute by various means + // Test adding non-Attribute by various means for (Op op : Op.values()) { AttributeList alist = new AttributeList(); - alist.add(new Attribute("foo", "bar")); - doOp(alist, op); - String what = "asList() after calling " + op + " with non-Attribute"; + alist.add(new Attribute("foo", "bar")); // Add actual Attribute + alist.add(null); + String what = "Using " + op + " with non-Attribute"; try { - List lista = alist.asList(); - fail(what + ": succeeded but should not have"); - } catch (IllegalArgumentException e) { - System.out.println("OK: " + what + ": got IllegalArgumentException"); - } - } - - // Test adding non-Attribute by various means after calling asList - for (Op op : Op.values()) { - AttributeList alist = new AttributeList(); - List lista = alist.asList(); - lista.add(new Attribute("foo", "bar")); - String what = op + " with non-Attribute after calling asList()"; - try { - doOp(alist, op); + doOp(alist, op); // Add some other non-Attribute, should fail fail(what + ": succeeded but should not have"); } catch (IllegalArgumentException e) { System.out.println("OK: " + what + ": got IllegalArgumentException"); diff --git a/test/jdk/javax/management/MBeanServer/ExceptionFactory.java b/test/jdk/javax/management/MBeanServer/ExceptionFactory.java index a615c5252da..dd82cf288f4 100644 --- a/test/jdk/javax/management/MBeanServer/ExceptionFactory.java +++ b/test/jdk/javax/management/MBeanServer/ExceptionFactory.java @@ -46,7 +46,6 @@ import javax.management.ServiceNotFoundException; import javax.management.StringValueExp; import javax.management.modelmbean.InvalidTargetObjectTypeException; -import javax.management.modelmbean.XMLParseException; import javax.management.monitor.MonitorSettingException; import javax.management.openmbean.InvalidKeyException; import javax.management.openmbean.InvalidOpenTypeException; @@ -100,7 +99,6 @@ public class ExceptionFactory { exceptions.add(new RuntimeOperationsException(new RuntimeException(mes), mes)); exceptions.add(new ServiceNotFoundException()); exceptions.add(new InvalidTargetObjectTypeException()); - exceptions.add(new XMLParseException()); exceptions.add(new MonitorSettingException()); exceptions.add(new InvalidKeyException()); exceptions.add(new InvalidOpenTypeException()); diff --git a/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java b/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java new file mode 100644 index 00000000000..2fe8bf8034b --- /dev/null +++ b/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java @@ -0,0 +1,76 @@ +/* + * 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. + * + * 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 + * @bug 8358624 + * @summary Test ImmutableDescriptor hashcode and serialization + * + * @run main ImmutableDescriptorSerialHashCodeTest + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; + +public class ImmutableDescriptorSerialHashCodeTest { + public static void main(String[] args) throws Exception { + + Descriptor d1 = new ImmutableDescriptor("a=aval", "B=Bval", "cC=cCval"); + Descriptor d2 = new ImmutableDescriptor("a=aval", "B=Bval", "cC=cCval"); + + test (d1, d2, "Objects created from same String"); // Sanity check + Descriptor dSer = serialize(d1); + test(d1, dSer, "After serialization"); // Actual test + System.out.println("PASSED"); + } + + /** + * Test that two Descriptor objects are both equal, and have equal hashcodes. + */ + private static void test(Descriptor d1, Descriptor d2, String msg) throws Exception { + if (!d1.equals(d2)) { + throw new RuntimeException(msg + ": Descriptors not equal: " + + "\nd1: " + d1 + + "\nd2: " + d2); + } + if (d1.hashCode() != d2.hashCode()) { + throw new RuntimeException(msg + ": Hash code mismatch. hash1: " + d1.hashCode() + + ", hash2: " + d2.hashCode()); + } + } + + private static T serialize(T x) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(bout); + oout.writeObject(x); + oout.close(); + byte[] bytes = bout.toByteArray(); + ByteArrayInputStream bin = new ByteArrayInputStream(bytes); + ObjectInputStream oin = new ObjectInputStream(bin); + return (T) oin.readObject(); + } +} diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index a28ffba92d4..c1e312d22a0 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -23,8 +23,8 @@ /* * @test - * @bug 6250772 - * @summary Test that *List objects are checked after asList is called. + * @bug 6250772 8359809 + * @summary Test that *List objects are checked * @author Eamonn McManus * * @run clean ListTypeCheckTest @@ -39,39 +39,45 @@ /* For compatibility reasons, the classes AttributeList, RoleList, * and RoleUnresolvedList all extend ArrayList even though - * logically they should extend ArrayList etc. They are - * all specified to have a method asList() with return type - * List etc, and to refuse to add any object other than - * an Attribute etc once this method has been called, but not before. + * logically they should extend ArrayList etc. + * + * Before JDK-8359809, their method asList() had to be called, to make + * the class refuse to add any object other than the intended type. */ public class ListTypeCheckTest { public static void main(String[] args) throws Exception { Class[] classes = { AttributeList.class, RoleList.class, RoleUnresolvedList.class, }; - for (Class c : classes) - test((Class) c); + Object[] objects = { + new Attribute("myAttr", "myVal"), new Role("myRole", new ArrayList()), + new RoleUnresolved("myRoleUnresolved", new ArrayList(), RoleStatus.NO_ROLE_WITH_NAME) + }; + for (int i = 0; i < classes.length; i++) { + test((Class) classes[i], objects[i]); + } } - private static void test(Class c) throws Exception { + private static void test(Class c, Object o) throws Exception { System.out.println("Testing " + c.getName()); ArrayList al = c.newInstance(); - test(al); + test(al, o); } - private static void test(ArrayList al) throws Exception { - test(al, true); + private static void test(ArrayList al, Object o) throws Exception { + test0(al, o); al.clear(); Method m = al.getClass().getMethod("asList"); - m.invoke(al); - test(al, false); + m.invoke(al); // Calling asList() does not change behaviour + test0(al, o); } - private static void test(ArrayList al, boolean allowsBogus) throws Exception { - for (int i = 0; i < 5; i++) { + private static void test0(ArrayList al, Object o) throws Exception { + for (int i = 0; i < 7; i++) { try { switch (i) { case 0: + // Add the wrong kind of element, will fail: al.add("yo"); break; case 1: @@ -86,14 +92,27 @@ private static void test(ArrayList al, boolean allowsBogus) throws Exception { case 4: al.set(0, "foo"); break; + case 5: + // Add the correct kind of element, so we can test ListIterator. + al.add(o); + ListIterator iter = al.listIterator(); + Object x = iter.next(); + iter.set("blah"); // Test "set", should fail like the others. + break; + case 6: + // Add the correct kind of element, so we can test ListIterator. + al.add(o); + ListIterator iter2 = al.listIterator(); + Object x2 = iter2.next(); + iter2.add("blah"); // Test "add", should fail like the others. + break; default: throw new Exception("test wrong"); } - if (!allowsBogus) - throw new Exception("op allowed but should fail"); + // All cases above should have caused an Exception: + throw new Exception("op " + i + " allowed but should fail on " + al.getClass()); } catch (IllegalArgumentException e) { - if (allowsBogus) - throw new Exception("got exception but should not", e); + System.out.println("op " + i + " got expected " + e + " on " + al.getClass()); } } } diff --git a/test/jdk/javax/management/modelmbean/DescriptorSupportTest.java b/test/jdk/javax/management/modelmbean/DescriptorSupportTest.java index ed33c737175..45c397f987e 100644 --- a/test/jdk/javax/management/modelmbean/DescriptorSupportTest.java +++ b/test/jdk/javax/management/modelmbean/DescriptorSupportTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -183,9 +183,6 @@ public static void main(String[] args) throws Exception { ok &= caseTest(new DescriptorSupport(d1), "DescriptorSupport(Descriptor)"); d1 = new DescriptorSupport(new String[] {"NAME=blah"}); - ok &= caseTest(new DescriptorSupport(d1.toXMLString()), - "DescriptorSupport(String)"); - d1 = new DescriptorSupport(new String[] {"NAME=blah"}); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(d1); diff --git a/test/jdk/javax/management/modelmbean/DescriptorSupportXMLTest.java b/test/jdk/javax/management/modelmbean/DescriptorSupportXMLTest.java deleted file mode 100644 index dc66b2ad794..00000000000 --- a/test/jdk/javax/management/modelmbean/DescriptorSupportXMLTest.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2003, 2015, 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 - * @bug 4957393 - * @summary Test that DescriptorSupport.toXMLString() can be used to - * reconstruct an equivalent DescriptorSupport - * @author Eamonn McManus - * - * @run clean DescriptorSupportXMLTest - * @run build DescriptorSupportXMLTest - * @run main DescriptorSupportXMLTest - */ - -import java.util.Arrays; - -import javax.management.RuntimeOperationsException; -import javax.management.modelmbean.DescriptorSupport; - -public class DescriptorSupportXMLTest { - public static void main(String[] args) throws Exception { - System.out.println("Testing that DescriptorSupport.toXMLString() " + - "can be used to reconstruct an equivalent " + - "DescriptorSupport"); - int failed = 0; - - final Object[] testValues = { - // Values that should be encodable. - "", - "ok", - "null", - "(open", - "close)", - "(parens)", - "quote\"quote", - "a description with several words", - "magic&\"\\<> \r\t\n\f;&;magic", - "<descriptor>&&&</descriptor>", - "<descriptor>&&&</blahblahblah>", - null, - new Integer(10), - Boolean.TRUE, - new Float(1.0f), - - // Values that are not encodable: it is important that we throw - // an exception during encoding rather than waiting until decode - // time to discover the problem. These classes are not encodable - // because they don't have a (String) constructor. - new Character('!'), - new java.util.HashMap(), - }; - - for (int i = 0; i < testValues.length; i++) { - final Object v = testValues[i]; - final String what = - (v == null) ? "null" : - (v.getClass().getName() + "{" + v + "}"); - - final DescriptorSupport in = - new DescriptorSupport(new String[] {"bloo"}, new Object[] {v}); - - final String xml; - try { - xml = in.toXMLString(); - } catch (RuntimeOperationsException e) { - final Throwable cause = e.getCause(); - if (cause instanceof IllegalArgumentException) { - System.out.println("OK: " + what + ": got a " + - "RuntimeOperationsException wrapping " + - "an IllegalArgumentException: " + - cause.getMessage()); - } else { - final String causeString = - (cause == null) ? "null" : cause.getClass().getName(); - System.out.println("FAILED: " + what + ": got a " + - "RuntimeOperationException wrapping " + - causeString); - failed++; - } - continue; - } - - System.out.println("Encoded " + what + " as " + xml); - - final DescriptorSupport out; - try { - out = new DescriptorSupport(xml); - } catch (Exception e) { - System.out.println("FAILED: " + what + ": got an exception:"); - e.printStackTrace(System.out); - failed++; - continue; - } - - final String[] names = out.getFieldNames(); - if (names.length != 1 || !"bloo".equals(names[0])) { - System.out.println("FAILED: decoded names wrong: " + - Arrays.asList(names)); - failed++; - continue; - } - - final Object[] values = out.getFieldValues(names); - if (values.length != 1) { - System.out.println("FAILED: wrong number of values: " + - Arrays.asList(values)); - failed++; - continue; - } - - final Object outValue = values[0]; - - if (v == null) { - if (outValue == null) - System.out.println("OK: decoded null value"); - else { - System.out.println("FAILED: decoded null value as " + - outValue.getClass().getName() + "{" + - outValue + "}"); - failed++; - } - continue; - } - - if (outValue == null) { - System.out.println("FAILED: decoded non-null value as null"); - failed++; - continue; - } - - if (v.getClass() != outValue.getClass()) { - System.out.println("FAILED: decoded value has class " + - outValue.getClass().getName() + "{" + - outValue + "}"); - failed++; - continue; - } - - if (v.equals(outValue)) - System.out.println("OK: decoded value is equal to original"); - else { - System.out.println("FAILED: decoded value is different: {" + - outValue + "}"); - failed++; - } - } - - if (failed == 0) - System.out.println("OK: all tests passed"); - else { - System.out.println("TEST FAILED: fail count: " + failed); - System.exit(1); - } - } -} diff --git a/test/jdk/javax/management/modelmbean/LoggingExceptionTest.java b/test/jdk/javax/management/modelmbean/LoggingExceptionTest.java index 94dfee092ea..c47e67b6afb 100644 --- a/test/jdk/javax/management/modelmbean/LoggingExceptionTest.java +++ b/test/jdk/javax/management/modelmbean/LoggingExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -47,7 +47,6 @@ public class LoggingExceptionTest { private static final String tests[] = new String[] { "DescriptorSupport()", "DescriptorSupport(int)", - "DescriptorSupport(String)", "DescriptorSupport(String...)", "DescriptorSupport(String[], Object[])", "DescriptorSupport(DescriptorSupport)", @@ -72,18 +71,15 @@ public static void main(String[] args) { ds = new DescriptorSupport(10); break; case 2: - ds = new DescriptorSupport(new DescriptorSupport().toXMLString()); - break; - case 3: ds = new DescriptorSupport("name1=value1", "name2=value2"); break; - case 4: + case 3: ds = new DescriptorSupport(new String[] {"name"}, new Object[] {"value"}); break; - case 5: + case 4: ds = new DescriptorSupport(new DescriptorSupport()); break; - case 6: + case 5: RequiredModelMBean mbean = new RequiredModelMBean(); NotificationListener nl = new NotificationListener() { public void handleNotification(Notification notification, diff --git a/test/jdk/javax/sound/sampled/Clip/AudioContentHandlers.java b/test/jdk/javax/sound/sampled/Clip/AudioContentHandlers.java index cb0875a5320..702afb34111 100644 --- a/test/jdk/javax/sound/sampled/Clip/AudioContentHandlers.java +++ b/test/jdk/javax/sound/sampled/Clip/AudioContentHandlers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -21,7 +21,6 @@ * questions. */ -import java.applet.AudioClip; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -31,6 +30,7 @@ import java.util.LinkedList; import java.util.List; +import javax.sound.SoundClip; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; @@ -44,8 +44,8 @@ /** * @test - * @bug 8204454 - * @summary URL.getContent() should return AudioClip for supported formats + * @bug 8204454 8359053 + * @summary URL.getContent() should return SoundClip for supported formats * @run main/othervm -Xmx128m AudioContentHandlers */ public final class AudioContentHandlers { @@ -77,10 +77,10 @@ public static void main(final String[] args) throws Exception { } catch (IOException | IllegalArgumentException ignored) { continue; } - AudioClip content; + SoundClip content; try { - content = (AudioClip) file.toURL().getContent(); - // We need to generate OOM because the stream in AudioClip + content = (SoundClip) file.toURL().getContent(); + // We need to generate OOM because the stream in SoundClip // will be closed in finalize(). generateOOME(); } finally { diff --git a/test/jdk/javax/sound/sampled/Clip/AutoCloseTimeCheck.java b/test/jdk/javax/sound/sampled/Clip/AutoCloseTimeCheck.java index 940124b244b..f823175ede8 100644 --- a/test/jdk/javax/sound/sampled/Clip/AutoCloseTimeCheck.java +++ b/test/jdk/javax/sound/sampled/Clip/AutoCloseTimeCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -21,7 +21,6 @@ * questions. */ -import java.applet.AudioClip; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -29,6 +28,7 @@ import java.nio.file.Files; import java.util.concurrent.TimeUnit; +import javax.sound.SoundClip; import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; @@ -66,7 +66,7 @@ public static void main(final String[] args) throws Exception { * and the "Direct Clip" thread will stop. */ private static void testBigDelay(final File file) throws Exception { - AudioClip clip = (AudioClip) file.toURL().getContent(); + SoundClip clip = SoundClip.createSoundClip(file); clip.loop(); clip.stop(); sleep(20000); // 20 sec for slow systems @@ -80,7 +80,7 @@ private static void testBigDelay(final File file) throws Exception { * closed and the "Direct Clip" thread will alive. */ private static void testSmallDelay(final File file) throws IOException { - AudioClip clip = (AudioClip) file.toURL().getContent(); + SoundClip clip = SoundClip.createSoundClip(file); long threadID = 0; // Will run the test no more than 15 seconds long endtime = System.nanoTime() + TimeUnit.SECONDS.toNanos(15); diff --git a/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java b/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java index 58e0f0d6011..3e1135ca19c 100644 --- a/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java +++ b/test/jdk/javax/sound/sampled/Clip/DataPusherThreadCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,7 +30,7 @@ import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; -import java.applet.AudioClip; +import javax.sound.SoundClip; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; @@ -70,7 +70,7 @@ public static void main(String[] args) throws Exception { } private static void checkThread(File file) throws Exception { - AudioClip clip = (AudioClip) file.toURL().getContent(); + SoundClip clip = SoundClip.createSoundClip(file); clip.loop(); try { Thread.sleep(2000); diff --git a/test/jdk/javax/swing/JComboBox/bug4276920.java b/test/jdk/javax/swing/JComboBox/bug4276920.java index f5de26091b3..e5f541dcb8e 100644 --- a/test/jdk/javax/swing/JComboBox/bug4276920.java +++ b/test/jdk/javax/swing/JComboBox/bug4276920.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -44,7 +44,7 @@ public static void main(String[] args) throws Exception { SwingUtilities.invokeAndWait(combo::hidePopup); int after = combo.getRepaintCount(); if (after > before) { - throw new Error("Failed 4276920: BasicComboPopup.hide() caused unnecessary repaint()"); + throw new RuntimeException("Failed 4276920: BasicComboPopup.hide() caused unnecessary repaint()"); } } finally { if (frame != null) { diff --git a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java index 6c7185b547a..7080f03ad2a 100644 --- a/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java +++ b/test/jdk/javax/swing/JMenuItem/RightLeftOrientation.java @@ -22,18 +22,36 @@ */ /* - * @test + * @test id=metal * @bug 4211052 * @requires (os.family == "windows") - * @summary - * This test checks if menu items lay out correctly when their + * @summary Verifies if menu items lay out correctly when their * ComponentOrientation property is set to RIGHT_TO_LEFT. - * The tester is asked to compare left-to-right and - * right-to-left menus and judge whether they are mirror images of each - * other. * @library /java/awt/regtesthelpers * @build PassFailJFrame - * @run main/manual RightLeftOrientation + * @run main/manual RightLeftOrientation metal + */ + +/* + * @test id=motif + * @bug 4211052 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation motif + */ + +/* + * @test id=windows + * @bug 4211052 + * @requires (os.family == "windows") + * @summary Verifies if menu items lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation windows */ import java.awt.Color; @@ -52,29 +70,47 @@ import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; -import javax.swing.LookAndFeel; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.UIManager; public class RightLeftOrientation { private static final String INSTRUCTIONS = """ - A menu bar is shown containing a menu for each look and feel. - A disabled menu means that the look and feel is not available for - testing in this environment. - Every effort should be made to run this test - in an environment that covers all look and feels. + A menu bar is shown with a menu. - Each menu is divided into two halves. The upper half is oriented + The menu is divided into two halves. The upper half is oriented left-to-right and the lower half is oriented right-to-left. - For each menu, ensure that the lower half mirrors the upper half. + Ensure that the lower half mirrors the upper half. Note that when checking the positioning of the sub-menus, it helps to position the frame away from the screen edges."""; public static void main(String[] args) throws Exception { + if (args.length < 1) { + throw new IllegalArgumentException("Look-and-Feel keyword is required"); + } + + final String lafClassName; + switch (args[0]) { + case "metal" -> lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + case "motif" -> lafClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + case "windows" -> lafClassName = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + default -> throw new IllegalArgumentException( + "Unsupported Look-and-Feel keyword for this test: " + args[0]); + } + + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel(lafClassName); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + System.out.println("Test for LookAndFeel " + lafClassName); + PassFailJFrame.builder() - .title("RightLeftOrientation Instructions") .instructions(INSTRUCTIONS) .columns(35) .testUI(RightLeftOrientation::createTestUI) @@ -86,32 +122,19 @@ private static JFrame createTestUI() { JFrame frame = new JFrame("RightLeftOrientation"); JMenuBar menuBar = new JMenuBar(); - menuBar.add(createMenu("javax.swing.plaf.metal.MetalLookAndFeel", - "Metal")); - menuBar.add(createMenu("com.sun.java.swing.plaf.motif.MotifLookAndFeel", - "Motif")); - menuBar.add(createMenu("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", - "Windows")); + menuBar.add(createMenu()); frame.setJMenuBar(menuBar); - frame.pack(); + frame.setSize(250, 70); return frame; } - static JMenu createMenu(String laf, String name) { - JMenu menu = new JMenu(name); - try { - LookAndFeel save = UIManager.getLookAndFeel(); - UIManager.setLookAndFeel(laf); - addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); - menu.addSeparator(); - addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); - UIManager.setLookAndFeel(save); - } catch (Exception e) { - menu = new JMenu(name); - menu.setEnabled(false); - } + static JMenu createMenu() { + JMenu menu = new JMenu(UIManager.getLookAndFeel().getID()); + addMenuItems(menu, ComponentOrientation.LEFT_TO_RIGHT); + menu.addSeparator(); + addMenuItems(menu, ComponentOrientation.RIGHT_TO_LEFT); return menu; } diff --git a/test/jdk/javax/swing/JTree/TestTreeRowSelection.java b/test/jdk/javax/swing/JTree/TestTreeRowSelection.java new file mode 100644 index 00000000000..20dbc433e52 --- /dev/null +++ b/test/jdk/javax/swing/JTree/TestTreeRowSelection.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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 + * @key headful + * @requires (os.family == "mac") + * @bug 8360462 + * @summary Verifies ctrl+shift+down selects next row + * and ctrl+shift+up selects previous row in Aqua L&F + * @run main TestTreeRowSelection + */ + +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.tree.DefaultMutableTreeNode; + +public class TestTreeRowSelection { + static JTree tree; + static JFrame frame; + static volatile int selectedRowCount; + static volatile int curSelectedRowCount; + + public static void main(String[] args) throws Exception { + + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + DefaultMutableTreeNode sports = new DefaultMutableTreeNode("sports"); + sports.add(new DefaultMutableTreeNode("basketball")); + sports.add(new DefaultMutableTreeNode("football")); + sports.add(new DefaultMutableTreeNode("cricket")); + sports.add(new DefaultMutableTreeNode("tennis")); + + tree = new JTree(sports); + tree.setSelectionRow(2); + + frame.getContentPane().add(tree); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + selectedRowCount = tree.getSelectionCount(); + }); + System.out.println("rows selected " + selectedRowCount); + for (int i = 0; i < 2; i++) { + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + robot.delay(500); + } + SwingUtilities.invokeAndWait(() -> { + curSelectedRowCount = tree.getSelectionCount(); + }); + System.out.println("rows selected " + curSelectedRowCount); + if (curSelectedRowCount != selectedRowCount + 2) { + throw new RuntimeException("ctrl+shift+down doesn't select next row"); + } + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_UP); + robot.keyRelease(KeyEvent.VK_UP); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { + curSelectedRowCount = tree.getSelectionCount(); + }); + System.out.println("rows selected " + curSelectedRowCount); + if (curSelectedRowCount != selectedRowCount + 1) { + throw new RuntimeException("ctrl+shift+up doesn't select previous row"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java index fc83b49597d..80faeed460e 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -42,15 +42,18 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify LineBorder edges have the same width * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledLineBorderTest */ public class ScaledLineBorderTest { - private static final Dimension SIZE = new Dimension(120, 25); + private static final Dimension SIZE = new Dimension(250, 50); private static final Color OUTER_COLOR = Color.BLACK; private static final Color BORDER_COLOR = Color.RED; @@ -59,12 +62,19 @@ public class ScaledLineBorderTest { private static final double[] scales = {1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00}; + private static final int[] thickness = {1, 4, 10, 15}; + + private record TestImage(BufferedImage image, + List panelLocations, + double scale, + int thickness) { + } - private static final List images = - new ArrayList<>(scales.length); + private record TestUI(JComponent content, + List panelLocations, + int thickness) { + } - private static final List panelLocations = - new ArrayList<>(4); public static void main(String[] args) throws Exception { Collection params = Arrays.asList(args); @@ -74,29 +84,38 @@ public static void main(String[] args) throws Exception { } private static void testScaling(boolean showFrame, boolean saveImages) { - JComponent content = createUI(); - if (showFrame) { - showFrame(content); + for (int thickness : thickness) { + TestUI testUI = createUI(thickness); + if (showFrame) { + showFrame(testUI.content); + } + + List images = paintToImages(testUI, saveImages); + verifyBorderRendering(images, saveImages); + } + + if (errorCount > 0) { + throw new Error("Test failed: " + + errorCount + " error(s) detected - " + + errorMessage); } - paintToImages(content, saveImages); - verifyBorderRendering(saveImages); } - private static void verifyBorderRendering(final boolean saveImages) { - String errorMessage = null; - int errorCount = 0; - for (int i = 0; i < images.size(); i++) { - BufferedImage img = images.get(i); - double scaling = scales[i]; - try { - int thickness = (int) Math.floor(scaling); + private static String errorMessage = null; + private static int errorCount = 0; - checkVerticalBorders(SIZE.width / 2, thickness, img); + private static void verifyBorderRendering(final List images, + final boolean saveImages) { + for (TestImage test : images) { + final BufferedImage img = test.image; + final int effectiveThickness = clipRound(test.thickness * test.scale); + try { + checkVerticalBorders((int) (SIZE.width * test.scale / 2), effectiveThickness, img); - for (Point p : panelLocations) { - int y = (int) (p.y * scaling) + SIZE.height / 2; - checkHorizontalBorder(y, thickness, img); + for (Point p : test.panelLocations) { + int y = (int) ((p.y + (SIZE.height / 2)) * test.scale); + checkHorizontalBorder(y, effectiveThickness, img); } } catch (Error e) { if (errorMessage == null) { @@ -104,21 +123,13 @@ private static void verifyBorderRendering(final boolean saveImages) { } errorCount++; - System.err.printf("Scaling: %.2f\n", scaling); + System.err.printf("Scale: %.2f; thickness: %d, effective: %d\n", + test.scale, test.thickness, effectiveThickness); e.printStackTrace(); - // Save the image if it wasn't already saved - if (!saveImages) { - saveImage(img, getImageFileName(scaling)); - } + saveImage(img, getImageFileName(test.scale, test.thickness)); } } - - if (errorCount > 0) { - throw new Error("Test failed: " - + errorCount + " error(s) detected - " - + errorMessage); - } } private static void checkVerticalBorders(final int x, @@ -220,17 +231,19 @@ private static void throwUnexpectedColor(int x, int y, int color) { x, y, color)); } - private static JComponent createUI() { + private static TestUI createUI(int thickness) { Box contentPanel = Box.createVerticalBox(); contentPanel.setBackground(OUTER_COLOR); + List panelLocations = new ArrayList<>(4); + Dimension childSize = null; for (int i = 0; i < 4; i++) { JComponent filler = new JPanel(null); filler.setBackground(INSIDE_COLOR); filler.setPreferredSize(SIZE); filler.setBounds(i, 0, SIZE.width, SIZE.height); - filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, thickness)); JPanel childPanel = new JPanel(new BorderLayout()); childPanel.setBorder(BorderFactory.createEmptyBorder(0, i, 4, 4)); @@ -248,7 +261,7 @@ private static JComponent createUI() { contentPanel.setSize(childSize.width, childSize.height * 4); - return contentPanel; + return new TestUI(contentPanel, panelLocations, thickness); } private static void showFrame(JComponent content) { @@ -260,28 +273,33 @@ private static void showFrame(JComponent content) { frame.setVisible(true); } - private static void paintToImages(final JComponent content, - final boolean saveImages) { - for (double scaling : scales) { + private static List paintToImages(final TestUI testUI, + final boolean saveImages) { + final List images = new ArrayList<>(scales.length); + final JComponent content = testUI.content; + for (double scale : scales) { BufferedImage image = - new BufferedImage((int) Math.ceil(content.getWidth() * scaling), - (int) Math.ceil(content.getHeight() * scaling), + new BufferedImage((int) Math.ceil(content.getWidth() * scale), + (int) Math.ceil(content.getHeight() * scale), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); - g2d.scale(scaling, scaling); + g2d.scale(scale, scale); content.paint(g2d); g2d.dispose(); if (saveImages) { - saveImage(image, getImageFileName(scaling)); + saveImage(image, getImageFileName(scale, testUI.thickness)); } - images.add(image); + images.add(new TestImage(image, testUI.panelLocations, + scale, testUI.thickness)); } + return images; } - private static String getImageFileName(final double scaling) { - return String.format("test%.2f.png", scaling); + private static String getImageFileName(final double scaling, + final int thickness) { + return String.format("test%02d@%.2f.png", thickness, scaling); } private static void saveImage(BufferedImage image, String filename) { diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index 4b076977313..2a732812e38 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -44,12 +44,15 @@ import javax.swing.SwingUtilities; import javax.swing.border.LineBorder; +import static sun.java2d.pipe.Region.clipRound; + /* * @test - * @bug 8282958 + * @bug 8282958 8349188 * @summary Verify all the borders are rendered consistently for a JTextField * in Windows LaF which uses LineBorder * @requires (os.family == "windows") + * @modules java.desktop/sun.java2d.pipe * @run main ScaledTextFieldBorderTest */ public class ScaledTextFieldBorderTest { @@ -92,7 +95,7 @@ private static void verifyBorderRendering(final boolean saveImages) { BufferedImage img = images.get(i); double scaling = scales[i]; try { - int thickness = (int) Math.floor(scaling); + int thickness = clipRound(scaling); checkVerticalBorders(textFieldSize.width / 2, thickness, img); diff --git a/test/jdk/jdk/classfile/BuilderParamTest.java b/test/jdk/jdk/classfile/BuilderParamTest.java index 9809f5f71c3..2bce2633be3 100644 --- a/test/jdk/jdk/classfile/BuilderParamTest.java +++ b/test/jdk/jdk/classfile/BuilderParamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,6 +23,7 @@ /* * @test + * @bug 8361615 * @summary Testing ClassFile builder parameters. * @run junit BuilderParamTest */ @@ -46,19 +47,26 @@ void testDirectBuilder() { cc.build(ClassDesc.of("Foo"), cb -> { cb.withMethod("foo", MethodTypeDesc.ofDescriptor("(IJI)V"), 0, mb -> mb.withCode(xb -> { + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(-1)); assertEquals(xb.receiverSlot(), 0); assertEquals(xb.parameterSlot(0), 1); assertEquals(xb.parameterSlot(1), 2); assertEquals(xb.parameterSlot(2), 4); + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(3)); + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(Integer.MAX_VALUE)); xb.return_(); })); }); cc.build(ClassDesc.of("Foo"), cb -> { cb.withMethod("foo", MethodTypeDesc.ofDescriptor("(IJI)V"), ACC_STATIC, mb -> mb.withCode(xb -> { + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(Integer.MIN_VALUE)); + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(-1)); + assertThrows(IllegalStateException.class, () -> xb.receiverSlot()); assertEquals(xb.parameterSlot(0), 0); assertEquals(xb.parameterSlot(1), 1); assertEquals(xb.parameterSlot(2), 3); + assertThrows(IndexOutOfBoundsException.class, () -> xb.parameterSlot(3)); xb.return_(); })); }); diff --git a/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java b/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java index ac1292b1062..8c60c379569 100644 --- a/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java +++ b/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8304031 8338406 8338546 + * @bug 8304031 8338406 8338546 8361909 * @summary Testing handling of various constant descriptors in ClassFile API. * @modules java.base/jdk.internal.constant * java.base/jdk.internal.classfile.impl @@ -58,6 +58,13 @@ final class ConstantDescSymbolsTest { + @Test + void testNulls() { + var cpb = ConstantPoolBuilder.of(); + assertThrows(NullPointerException.class, () -> cpb.loadableConstantEntry(null)); + assertThrows(NullPointerException.class, () -> cpb.constantValueEntry(null)); + } + // Testing that primitive class descs are encoded properly as loadable constants. @Test void testPrimitiveClassDesc() throws Throwable { diff --git a/test/jdk/jdk/classfile/FilterDeadLabelsTest.java b/test/jdk/jdk/classfile/FilterDeadLabelsTest.java index 53c0f4f7a65..c013b8516b6 100644 --- a/test/jdk/jdk/classfile/FilterDeadLabelsTest.java +++ b/test/jdk/jdk/classfile/FilterDeadLabelsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,15 +23,18 @@ /* * @test + * @bug 8361908 * @summary Testing filtering of dead labels. * @run junit FilterDeadLabelsTest */ import java.lang.classfile.ClassFile; +import java.lang.classfile.instruction.ExceptionCatch; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.MethodTypeDesc; import java.util.List; +import java.util.Optional; import java.util.function.Consumer; import java.lang.classfile.Attributes; import java.lang.classfile.CodeBuilder; @@ -41,6 +44,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import static java.lang.constant.ConstantDescs.*; + class FilterDeadLabelsTest { static List> deadLabelFragments() { @@ -71,6 +76,21 @@ void testFilterDeadLabels() { code.findAttribute(Attributes.characterRangeTable()).ifPresent(a -> assertTrue(a.characterRangeTable().isEmpty())); } + @Test // JDK-8361908 + void testFilterMixedExceptionCatch() { + var cc = ClassFile.of(ClassFile.DeadLabelsOption.DROP_DEAD_LABELS); + var code = cc.parse(cc.build(CD_Void, clb -> + clb.withMethodBody("m", MTD_void, 0, cob -> { + cob.return_(); + var l = cob.newBoundLabel(); + cob.pop().return_(); + cob.exceptionCatch(cob.startLabel(), l, l, Optional.empty()); + cob.exceptionCatch(cob.newLabel(), l, l, CD_Exception); + }))).methods().get(0).code().get(); + assertEquals(1, code.exceptionHandlers().size(), () -> code.exceptionHandlers().toString()); + assertEquals(Optional.empty(), code.exceptionHandlers().getFirst().catchType()); + } + @ParameterizedTest @MethodSource("deadLabelFragments") void testThrowOnDeadLabels(Consumer fragment) { diff --git a/test/jdk/jdk/classfile/InstructionValidationTest.java b/test/jdk/jdk/classfile/InstructionValidationTest.java index 3e065260abf..9d5b4198adf 100644 --- a/test/jdk/jdk/classfile/InstructionValidationTest.java +++ b/test/jdk/jdk/classfile/InstructionValidationTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8341277 + * @bug 8341277 8361102 * @summary Testing ClassFile instruction argument validation. * @run junit InstructionValidationTest */ @@ -32,24 +32,77 @@ import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.instruction.*; -import java.lang.constant.ClassDesc; -import java.lang.reflect.Parameter; +import java.util.Collections; import java.util.List; import java.util.function.Consumer; import java.util.function.ObjIntConsumer; import java.util.stream.Stream; +import helpers.TestUtil; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; -import static java.lang.classfile.ClassFile.ACC_STATIC; import static java.lang.constant.ConstantDescs.*; +import static helpers.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; import static java.lang.classfile.Opcode.*; import static org.junit.jupiter.api.Assertions.assertThrows; class InstructionValidationTest { + @Test + void testOpcodeInCodeBuilder() { + TestUtil.runCodeHandler(cob -> { + var mref = cob.constantPool().methodRefEntry(CD_System, "exit", MTD_INT_VOID); + var fref = cob.constantPool().fieldRefEntry(CD_System, "out", CD_PrintStream); + var label = cob.newLabel(); + + // Sanity + cob.iconst_0(); + assertDoesNotThrow(() -> cob.invoke(INVOKESTATIC, mref)); + assertDoesNotThrow(() -> cob.fieldAccess(GETSTATIC, fref)); + cob.pop(); + assertDoesNotThrow(() -> cob.branch(GOTO, label)); + + // Opcode NPE + assertThrows(NullPointerException.class, () -> cob.invoke(null, mref)); + assertThrows(NullPointerException.class, () -> cob.fieldAccess(null, fref)); + assertThrows(NullPointerException.class, () -> cob.branch(null, label)); + + // Opcode IAE + assertThrows(IllegalArgumentException.class, () -> cob.invoke(IFNE, mref)); + assertThrows(IllegalArgumentException.class, () -> cob.fieldAccess(JSR, fref)); + assertThrows(IllegalArgumentException.class, () -> cob.branch(CHECKCAST, label)); + + // Wrap up + cob.labelBinding(label); + cob.return_(); + }); + } + + @Test + void testLongJump() { + TestUtil.runCodeHandler(cob -> { + assertThrows(NullPointerException.class, () -> cob.goto_w(null)); + // Ensures nothing redundant is written in case of failure + cob.return_(); + }); + } + + @Test + void testSwitch() { + TestUtil.runCodeHandler(cob -> { + assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, cob.startLabel(), null)); + assertThrows(NullPointerException.class, () -> cob.lookupswitch(cob.startLabel(), null)); + assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, cob.startLabel(), Collections.singletonList(null))); + assertThrows(NullPointerException.class, () -> cob.lookupswitch(cob.startLabel(), Collections.singletonList(null))); + assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, null, List.of())); + assertThrows(NullPointerException.class, () -> cob.lookupswitch(null, List.of())); + // Ensures nothing redundant is written in case of failure + cob.return_(); + }); + } + @Test void testArgumentConstant() { assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, 0)); @@ -63,6 +116,14 @@ void testArgumentConstant() { assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(SIPUSH, (int) Short.MAX_VALUE + 1)); assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int) Byte.MIN_VALUE - 1)); assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int) Byte.MAX_VALUE + 1)); + + TestUtil.runCodeHandler(cob -> { + assertThrows(IllegalArgumentException.class, () -> cob.sipush((int) Short.MIN_VALUE - 1)); + assertThrows(IllegalArgumentException.class, () -> cob.sipush((int) Short.MAX_VALUE + 1)); + assertThrows(IllegalArgumentException.class, () -> cob.bipush((int) Byte.MIN_VALUE - 1)); + assertThrows(IllegalArgumentException.class, () -> cob.bipush((int) Byte.MAX_VALUE + 1)); + cob.return_(); + }); } /** @@ -163,26 +224,15 @@ record Result(boolean shouldFail, int slot) { // CodeBuilder can fail with IAE due to other reasons, so we cannot check // "success" but can ensure things fail fast static void ensureFailFast(int value, Consumer action) { - // Can fail with AssertionError instead of IAE Consumer checkedAction = cob -> { - action.accept(cob); - fail("Bad slot access did not fail fast: " + value); + assertThrows(IllegalArgumentException.class, () -> action.accept(cob)); + cob.return_(); }; - var cf = ClassFile.of(); - CodeTransform noopCodeTransform = CodeBuilder::with; - // Direct builders - assertThrows(IllegalArgumentException.class, () -> cf.build(ClassDesc.of("Test"), clb -> clb - .withMethodBody("test", MTD_void, ACC_STATIC, checkedAction))); - // Chained builders - assertThrows(IllegalArgumentException.class, () -> cf.build(ClassDesc.of("Test"), clb -> clb - .withMethodBody("test", MTD_void, ACC_STATIC, cob -> cob - .transforming(CodeTransform.ACCEPT_ALL, checkedAction)))); - var classTemplate = cf.build(ClassDesc.of("Test"), clb -> clb - .withMethodBody("test", MTD_void, ACC_STATIC, CodeBuilder::return_)); - // Indirect builders - assertThrows(IllegalArgumentException.class, () -> cf.transformClass(cf.parse(classTemplate), - ClassTransform.transformingMethodBodies(CodeTransform.endHandler(checkedAction) - .andThen(noopCodeTransform)))); + try { + TestUtil.runCodeHandler(checkedAction); + } catch (Throwable _) { + System.out.printf("Erroneous value %d%n", value); + } } static void check(boolean fails, Executable exec) { @@ -200,7 +250,10 @@ void testIincConstant() { IncrementInstruction.of(0, Short.MIN_VALUE); for (int i : new int[] {Short.MIN_VALUE - 1, Short.MAX_VALUE + 1}) { assertThrows(IllegalArgumentException.class, () -> IncrementInstruction.of(0, i)); - ensureFailFast(i, cob -> cob.iinc(0, i)); + TestUtil.runCodeHandler(cob -> { + assertThrows(IllegalArgumentException.class, () -> cob.iinc(0, i)); + cob.return_(); + }); } } @@ -215,5 +268,14 @@ void testNewMultiArrayDimension() { assertThrows(IllegalArgumentException.class, () -> NewMultiArrayInstruction.of(ce, -1)); assertThrows(IllegalArgumentException.class, () -> NewMultiArrayInstruction.of(ce, Integer.MIN_VALUE)); assertThrows(IllegalArgumentException.class, () -> NewMultiArrayInstruction.of(ce, Integer.MAX_VALUE)); + + TestUtil.runCodeHandler(cob -> { + assertThrows(IllegalArgumentException.class, () -> cob.multianewarray(ce, 0)); + assertThrows(IllegalArgumentException.class, () -> cob.multianewarray(ce, 0x100)); + assertThrows(IllegalArgumentException.class, () -> cob.multianewarray(ce, -1)); + assertThrows(IllegalArgumentException.class, () -> cob.multianewarray(ce, Integer.MIN_VALUE)); + assertThrows(IllegalArgumentException.class, () -> cob.multianewarray(ce, Integer.MAX_VALUE)); + cob.return_(); + }); } } diff --git a/test/jdk/jdk/classfile/TEST.properties b/test/jdk/jdk/classfile/TEST.properties index 2d8d20cf1f4..009b85888d1 100644 --- a/test/jdk/jdk/classfile/TEST.properties +++ b/test/jdk/jdk/classfile/TEST.properties @@ -2,4 +2,5 @@ maxOutputSize = 2500000 modules = \ java.base/jdk.internal.classfile.components \ java.base/jdk.internal.classfile.impl \ - java.base/jdk.internal.classfile.impl.verifier \ No newline at end of file + java.base/jdk.internal.classfile.impl.verifier +lib.dirs = helpers diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java index 80ee89d5fda..1a51e5047cc 100644 --- a/test/jdk/jdk/classfile/VerifierSelfTest.java +++ b/test/jdk/jdk/classfile/VerifierSelfTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,24 +24,30 @@ /* * @test * @summary Testing ClassFile Verifier. - * @bug 8333812 + * @bug 8333812 8361526 * @run junit VerifierSelfTest */ import java.io.IOException; import java.lang.classfile.constantpool.PoolEntry; import java.lang.constant.ClassDesc; +import static java.lang.classfile.ClassFile.ACC_STATIC; +import static java.lang.classfile.ClassFile.JAVA_8_VERSION; import static java.lang.constant.ConstantDescs.*; +import java.lang.constant.MethodTypeDesc; import java.lang.invoke.MethodHandleInfo; +import java.lang.invoke.MethodHandles; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -55,6 +61,9 @@ import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.*; @@ -413,4 +422,92 @@ private static List> patch(Attribute... attrs) { } return lst; } + + @Test // JDK-8350029 + void testInvokeSpecialInterfacePatch() { + var runClass = ClassDesc.of("Run"); + var testClass = ClassDesc.of("Test"); + var runnableClass = Runnable.class.describeConstable().orElseThrow(); + var chr = ClassHierarchyResolver.of(List.of(), Map.of(runClass, CD_Object)) + .orElse(ClassHierarchyResolver.defaultResolver()).cached(); + var context = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(chr)); + + for (var isInterface : new boolean[] {true, false}) { + var bytes = context.build(testClass, clb -> clb + .withVersion(JAVA_8_VERSION, 0) + .withSuperclass(runClass) + .withMethodBody("test", MethodTypeDesc.of(CD_void, testClass), ACC_STATIC, cob -> cob + .aload(0) + .invokespecial(runnableClass, "run", MTD_void, isInterface) + .return_())); + var errors = context.verify(bytes); + assertNotEquals(List.of(), errors, "invokespecial, isInterface = " + isInterface); + assertTrue(errors.getFirst().getMessage().contains("interface method to invoke is not in a direct superinterface"), errors.getFirst().getMessage()); + } + } + + enum ComparisonInstruction { + IF_ACMPEQ(Opcode.IF_ACMPEQ, 2), + IF_ACMPNE(Opcode.IF_ACMPNE, 2), + IFNONNULL(Opcode.IFNONNULL, 1), + IFNULL(Opcode.IFNULL, 1); + final Opcode opcode; + final int argCount; + ComparisonInstruction(Opcode opcode, int argCount) { + this.opcode = opcode; + this.argCount = argCount; + } + } + + enum UninitializeKind { + UNINITIALIZED, UNINITIALIZED_THIS + } + + @ParameterizedTest + @MethodSource("uninitializedInBytecodeClasses") + public void testUninitializedInComparisons(ComparisonInstruction inst, UninitializeKind kind) throws Throwable { + var bytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(ClassDesc.of("Test"), clb -> clb + .withMethodBody(INIT_NAME, MTD_void, 0, cob -> { + StackMapFrameInfo.VerificationTypeInfo uninitializeInfo; + if (kind == UninitializeKind.UNINITIALIZED) { + uninitializeInfo = StackMapFrameInfo.UninitializedVerificationTypeInfo.of(cob.newBoundLabel()); + cob.new_(CD_Object); + } else { + uninitializeInfo = StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS; + cob.aload(0); + } + + // Stack: uninitializeInfo + for (int i = 0; i < inst.argCount; i++) { + cob.dup(); + } + var dest = cob.newLabel(); + cob.branch(inst.opcode, dest) + .nop() + .labelBinding(dest) + .with(StackMapTableAttribute.of(List.of(StackMapFrameInfo.of(dest, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS), + List.of(uninitializeInfo))))) + .invokespecial(CD_Object, INIT_NAME, MTD_void); + if (kind == UninitializeKind.UNINITIALIZED) { + // still need to call super constructor + cob.aload(0) + .invokespecial(CD_Object, INIT_NAME, MTD_void); + } + cob.return_(); + })); + var errors = ClassFile.of().verify(bytes); + assertNotEquals(List.of(), errors, () -> errors + " : " + ClassFile.of().parse(bytes).toDebugString()); + var lookup = MethodHandles.lookup(); + assertThrows(VerifyError.class, () -> lookup.defineHiddenClass(bytes, true)); // force JVM verification + } + + public static Stream uninitializedInBytecodeClasses() { + return Arrays.stream(ComparisonInstruction.values()) + .mapMulti((inst, sink) -> { + for (var kind : UninitializeKind.values()) { + sink.accept(Arguments.of(inst, kind)); + } + }); + } } diff --git a/test/jdk/jdk/classfile/helpers/TestUtil.java b/test/jdk/jdk/classfile/helpers/TestUtil.java index 6baaea7800c..2ff4e5f275d 100644 --- a/test/jdk/jdk/classfile/helpers/TestUtil.java +++ b/test/jdk/jdk/classfile/helpers/TestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,29 +24,44 @@ import jdk.internal.classfile.impl.LabelContext; import jdk.internal.classfile.impl.LabelImpl; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeTransform; import java.lang.classfile.instruction.LocalVariable; import java.lang.classfile.instruction.LocalVariableType; -import java.io.FileOutputStream; +import java.lang.constant.ClassDesc; import java.util.Collection; - -public class TestUtil { +import java.util.function.Consumer; + +import static java.lang.classfile.ClassFile.ACC_STATIC; +import static java.lang.constant.ConstantDescs.MTD_void; + +public final class TestUtil { + + /// Run a code handler in different builders. + public static void runCodeHandler(Consumer handler) { + ClassFile cf = ClassFile.of(); + // Direct builders + cf.build(ClassDesc.of("Test"), clb -> clb.withMethodBody("test", MTD_void, ACC_STATIC, handler)); + // Chained builders + cf.build(ClassDesc.of("Test"), clb -> clb + .withMethodBody("test", MTD_void, ACC_STATIC, cob -> cob + .transforming(CodeTransform.ACCEPT_ALL, handler))); + // Indirect builders + var classTemplate = cf.build(ClassDesc.of("Test"), clb -> clb + .withMethodBody("test", MTD_void, ACC_STATIC, CodeBuilder::return_)); + cf.transformClass(cf.parse(classTemplate), + ClassTransform.transformingMethodBodies(CodeTransform.endHandler(handler) + .andThen(CodeBuilder::with))); + } public static void assertEmpty(Collection col) { if (!col.isEmpty()) throw new AssertionError(col); } - public static void writeClass(byte[] bytes, String fn) { - try { - FileOutputStream out = new FileOutputStream(fn); - out.write(bytes); - out.close(); - } catch (Exception ex) { - throw new InternalError(ex); - } - } - - public static class ExpectedLvRecord { int slot; String desc; diff --git a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java index 4ed95f698cf..0c08099031a 100644 --- a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java +++ b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8329817 8334432 8339076 8341260 + * @bug 8329817 8334432 8339076 8341260 8362207 * @modules jdk.incubator.vector * @summary Basic tests of Float16 arithmetic and similar operations */ @@ -186,7 +186,7 @@ private static void checkNegate() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = negate(valueOf(arg)); + Float16 result = negate(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "negate(" + arg + ")"); @@ -213,7 +213,7 @@ private static void checkAbs() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = abs(valueOf(arg)); + Float16 result = abs(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "abs(" + arg + ")"); @@ -238,7 +238,7 @@ private static void checkIsNaN() { }; for(var testCase : testCases) { - boolean result = isNaN(valueOf(testCase)); + boolean result = isNaN(valueOfExact(testCase)); if (result) { throwRE("isNaN returned true for " + testCase); } @@ -254,8 +254,8 @@ private static void checkFiniteness() { }; for(var infinity : infinities) { - boolean result1 = isFinite(valueOf(infinity)); - boolean result2 = isInfinite(valueOf(infinity)); + boolean result1 = isFinite(valueOfExact(infinity)); + boolean result2 = isInfinite(valueOfExact(infinity)); if (result1) { throwRE("Float16.isFinite returned true for " + infinity); @@ -282,8 +282,8 @@ private static void checkFiniteness() { }; for(var finity : finities) { - boolean result1 = isFinite(valueOf(finity)); - boolean result2 = isInfinite(valueOf(finity)); + boolean result1 = isFinite(valueOfExact(finity)); + boolean result2 = isInfinite(valueOfExact(finity)); if (!result1) { throwRE("Float16.isFinite returned true for " + finity); @@ -301,12 +301,12 @@ private static void checkMinMax() { float small = 1.0f; float large = 2.0f; - if (min(valueOf(small), valueOf(large)).floatValue() != small) { + if (min(valueOfExact(small), valueOfExact(large)).floatValue() != small) { throwRE(String.format("min(%g, %g) not equal to %g)", small, large, small)); } - if (max(valueOf(small), valueOf(large)).floatValue() != large) { + if (max(valueOfExact(small), valueOfExact(large)).floatValue() != large) { throwRE(String.format("max(%g, %g) not equal to %g)", small, large, large)); } @@ -318,10 +318,10 @@ private static void checkMinMax() { */ private static void checkArith() { float a = 1.0f; - Float16 a16 = valueOf(a); + Float16 a16 = valueOfExact(a); float b = 2.0f; - Float16 b16 = valueOf(b); + Float16 b16 = valueOfExact(b); if (add(a16, b16).floatValue() != (a + b)) { throwRE("failure with " + a16 + " + " + b16); @@ -371,7 +371,7 @@ private static void checkSqrt() { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - Float16 result = sqrt(valueOf(arg)); + Float16 result = sqrt(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "sqrt(" + arg + ")"); @@ -409,7 +409,7 @@ private static void checkGetExponent() { float arg = testCase[0]; float expected = testCase[1]; // Exponents are in-range for Float16 - Float16 result = valueOf(getExponent(valueOf(arg))); + Float16 result = valueOfExact(getExponent(valueOfExact(arg))); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "getExponent(" + arg + ")"); @@ -445,7 +445,7 @@ private static void checkUlp() { float arg = testCase[0]; float expected = testCase[1]; // Exponents are in-range for Float16 - Float16 result = ulp(valueOf(arg)); + Float16 result = ulp(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "ulp(" + arg + ")"); @@ -602,7 +602,7 @@ private static void checkValueOfString() { String input = testCase.input(); float expected = testCase.expected(); Float16 result = Float16.valueOf(input); - checkFloat16(result, expected, "Float16.valueOf(String) " + input); + checkFloat16(result, expected, "Float16.valueOfExact(String) " + input); } List negativeCases = List.of("0x1", @@ -747,7 +747,7 @@ private static void testZeroes() { } private static void testSimple() { - final float ulpOneFp16 = ulp(valueOf(1.0f)).floatValue(); + final float ulpOneFp16 = ulp(valueOfExact(1.0f)).floatValue(); float [][] testCases = { {1.0f, 2.0f, 3.0f, @@ -781,7 +781,7 @@ private static void testSimple() { } private static void testRounding() { - final float ulpOneFp16 = ulp(valueOf(1.0f)).floatValue(); + final float ulpOneFp16 = ulp(valueOfExact(1.0f)).floatValue(); float [][] testCases = { // The product is equal to @@ -816,6 +816,11 @@ private static void testRounding() { {0x1.ffcp-14f, 0x1.0p-24f, 0x1.0p14f, // *Cannot* be held exactly 0x1.0p14f}, + // Arguments where using float fma or uniform float + // arithmetic gives the wrong result + {0x1.08p7f, 0x1.04p7f, 0x1.0p-24f, + 0x1.0c4p14f}, + // Check values where the exact result cannot be // exactly stored in a double. {0x1.0p-24f, 0x1.0p-24f, 0x1.0p10f, @@ -839,10 +844,10 @@ private static void testRounding() { } private static void testFusedMacCase(float input1, float input2, float input3, float expected) { - Float16 a = valueOf(input1); - Float16 b = valueOf(input2); - Float16 c = valueOf(input3); - Float16 d = valueOf(expected); + Float16 a = valueOfExact(input1); + Float16 b = valueOfExact(input2); + Float16 c = valueOfExact(input3); + Float16 d = valueOfExact(expected); test("Float16.fma(float)", a, b, c, Float16.fma(a, b, c), d); @@ -865,4 +870,20 @@ private static void test(String testName, throw new RuntimeException(); } } + + /** + * {@return a Float16 value converted from the {@code float} + * argument throwing an {@code ArithmeticException} if the + * conversion is inexact}. + * + * @param f the {@code float} value to convert exactly + * @throws ArithmeticException + */ + private static Float16 valueOfExact(float f) { + Float16 f16 = valueOf(f); + if (Float.compare(f16.floatValue(), f) != 0) { + throw new ArithmeticException("Inexact conversion to Float16 of float value " + f); + } + return f16; + } } diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index 5ead28c47f0..fd017ce183b 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(byte[] r, byte[] a, byte[] b, FBinOp f) { int i = 0; try { @@ -1016,6 +1062,21 @@ static byte bits(byte e) { }) ); + static final List> BYTE_SATURATING_GENERATORS_ASSOC = List.of( + withToString("byte[Byte.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE)); + }), + withToString("byte[Byte.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE - 100)); + }), + withToString("byte[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> BYTE_GENERATOR_PAIRS = @@ -1028,6 +1089,12 @@ static byte bits(byte e) { flatMap(fa -> BYTE_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> BYTE_SATURATING_GENERATOR_TRIPLETS = + Stream.of(BYTE_GENERATORS.get(1)) + .flatMap(fa -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1064,6 +1131,22 @@ public Object[][] byteSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocProvider() { + return BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] byteIndexedOpProvider() { return BYTE_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3420,6 +3503,51 @@ static void maxByte128VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Byte128VectorTests::max); } + @Test(dataProvider = "byteSaturatingBinaryOpAssocProvider") + static void SUADDAssocByte128VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Byte128VectorTests::SUADD); + } + + @Test(dataProvider = "byteSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocByte128VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Byte128VectorTests::SUADD); + } static byte ANDReduce(byte[] a, int idx) { byte res = -1; diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index 22d645b2502..17ab56f2540 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(byte[] r, byte[] a, byte[] b, FBinOp f) { int i = 0; try { @@ -1016,6 +1062,21 @@ static byte bits(byte e) { }) ); + static final List> BYTE_SATURATING_GENERATORS_ASSOC = List.of( + withToString("byte[Byte.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE)); + }), + withToString("byte[Byte.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE - 100)); + }), + withToString("byte[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> BYTE_GENERATOR_PAIRS = @@ -1028,6 +1089,12 @@ static byte bits(byte e) { flatMap(fa -> BYTE_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> BYTE_SATURATING_GENERATOR_TRIPLETS = + Stream.of(BYTE_GENERATORS.get(1)) + .flatMap(fa -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1064,6 +1131,22 @@ public Object[][] byteSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocProvider() { + return BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] byteIndexedOpProvider() { return BYTE_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3420,6 +3503,51 @@ static void maxByte256VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Byte256VectorTests::max); } + @Test(dataProvider = "byteSaturatingBinaryOpAssocProvider") + static void SUADDAssocByte256VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Byte256VectorTests::SUADD); + } + + @Test(dataProvider = "byteSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocByte256VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Byte256VectorTests::SUADD); + } static byte ANDReduce(byte[] a, int idx) { byte res = -1; diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 738d6898374..4c43b995c2f 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(byte[] r, byte[] a, byte[] b, FBinOp f) { int i = 0; try { @@ -1016,6 +1062,21 @@ static byte bits(byte e) { }) ); + static final List> BYTE_SATURATING_GENERATORS_ASSOC = List.of( + withToString("byte[Byte.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE)); + }), + withToString("byte[Byte.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE - 100)); + }), + withToString("byte[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> BYTE_GENERATOR_PAIRS = @@ -1028,6 +1089,12 @@ static byte bits(byte e) { flatMap(fa -> BYTE_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> BYTE_SATURATING_GENERATOR_TRIPLETS = + Stream.of(BYTE_GENERATORS.get(1)) + .flatMap(fa -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1064,6 +1131,22 @@ public Object[][] byteSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocProvider() { + return BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] byteIndexedOpProvider() { return BYTE_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3420,6 +3503,51 @@ static void maxByte512VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Byte512VectorTests::max); } + @Test(dataProvider = "byteSaturatingBinaryOpAssocProvider") + static void SUADDAssocByte512VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Byte512VectorTests::SUADD); + } + + @Test(dataProvider = "byteSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocByte512VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Byte512VectorTests::SUADD); + } static byte ANDReduce(byte[] a, int idx) { byte res = -1; diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 6d80672f3eb..d30afe30fe2 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(byte[] r, byte[] a, byte[] b, FBinOp f) { int i = 0; try { @@ -1016,6 +1062,21 @@ static byte bits(byte e) { }) ); + static final List> BYTE_SATURATING_GENERATORS_ASSOC = List.of( + withToString("byte[Byte.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE)); + }), + withToString("byte[Byte.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE - 100)); + }), + withToString("byte[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> BYTE_GENERATOR_PAIRS = @@ -1028,6 +1089,12 @@ static byte bits(byte e) { flatMap(fa -> BYTE_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> BYTE_SATURATING_GENERATOR_TRIPLETS = + Stream.of(BYTE_GENERATORS.get(1)) + .flatMap(fa -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1064,6 +1131,22 @@ public Object[][] byteSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocProvider() { + return BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] byteIndexedOpProvider() { return BYTE_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3420,6 +3503,51 @@ static void maxByte64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFu assertBroadcastArraysEquals(r, a, b, Byte64VectorTests::max); } + @Test(dataProvider = "byteSaturatingBinaryOpAssocProvider") + static void SUADDAssocByte64VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Byte64VectorTests::SUADD); + } + + @Test(dataProvider = "byteSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocByte64VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Byte64VectorTests::SUADD); + } static byte ANDReduce(byte[] a, int idx) { byte res = -1; diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index 276ee98fd62..8738191f5ca 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -410,6 +410,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(byte[] rl, byte[] rr, byte[] a, byte[] b, byte[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(byte[] r, byte[] a, byte[] b, FBinOp f) { int i = 0; try { @@ -1021,6 +1067,21 @@ static byte bits(byte e) { }) ); + static final List> BYTE_SATURATING_GENERATORS_ASSOC = List.of( + withToString("byte[Byte.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE)); + }), + withToString("byte[Byte.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(Byte.MAX_VALUE - 100)); + }), + withToString("byte[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (byte)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> BYTE_GENERATOR_PAIRS = @@ -1033,6 +1094,12 @@ static byte bits(byte e) { flatMap(fa -> BYTE_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> BYTE_SATURATING_GENERATOR_TRIPLETS = + Stream.of(BYTE_GENERATORS.get(1)) + .flatMap(fa -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1069,6 +1136,22 @@ public Object[][] byteSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocProvider() { + return BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] byteSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> BYTE_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] byteIndexedOpProvider() { return BYTE_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3425,6 +3508,51 @@ static void maxByteMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, ByteMaxVectorTests::max); } + @Test(dataProvider = "byteSaturatingBinaryOpAssocProvider") + static void SUADDAssocByteMaxVectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, ByteMaxVectorTests::SUADD); + } + + @Test(dataProvider = "byteSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocByteMaxVectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] b = fb.apply(SPECIES.length()); + byte[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + byte[] rl = fr.apply(SPECIES.length()); + byte[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ByteVector bv = ByteVector.fromArray(SPECIES, b, i); + ByteVector cv = ByteVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, ByteMaxVectorTests::SUADD); + } static byte ANDReduce(byte[] a, int idx) { byte res = -1; diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index 9aea4137a3c..f15ce88ddb8 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(double[] r, double[] a, double[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index b0d9825fa9d..e6c3662e0ad 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(double[] r, double[] a, double[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index 672c943bae2..7c37c9878e8 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(double[] r, double[] a, double[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 415763c5882..85b96288b37 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(double[] r, double[] a, double[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index 992f16006db..7245990d66c 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java @@ -428,6 +428,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(double[] rl, double[] rr, double[] a, double[] b, double[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(double[] r, double[] a, double[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index 4fc6d1bdb45..c4f4ed1b966 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(float[] r, float[] a, float[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 59104c40b9e..87cbc165d59 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(float[] r, float[] a, float[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index 3cc45a88e84..beb9561d882 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(float[] r, float[] a, float[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index 70aaeb134a6..ee630abd8e0 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -423,6 +423,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(float[] r, float[] a, float[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index c22b2d329f1..41e4d6e4a5d 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java @@ -428,6 +428,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(float[] rl, float[] rr, float[] a, float[] b, float[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(float[] r, float[] a, float[] b, FBinOp f) { int i = 0; try { diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index a88dcf27888..0bd77cc1008 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(int[] r, int[] a, int[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static int bits(int e) { }) ); + static final List> INT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("int[Integer.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE)); + }), + withToString("int[Integer.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE - 100)); + }), + withToString("int[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> INT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static int bits(int e) { flatMap(fa -> INT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> INT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(INT_GENERATORS.get(1)) + .flatMap(fa -> INT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] intSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] intSaturatingBinaryOpAssocProvider() { + return INT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] intSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] intIndexedOpProvider() { return INT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3464,6 +3547,51 @@ static void maxInt128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFun assertBroadcastArraysEquals(r, a, b, Int128VectorTests::max); } + @Test(dataProvider = "intSaturatingBinaryOpAssocProvider") + static void SUADDAssocInt128VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Int128VectorTests::SUADD); + } + + @Test(dataProvider = "intSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocInt128VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Int128VectorTests::SUADD); + } static int ANDReduce(int[] a, int idx) { int res = -1; diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index 1b88adf9c21..a4a0a2bd88e 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(int[] r, int[] a, int[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static int bits(int e) { }) ); + static final List> INT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("int[Integer.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE)); + }), + withToString("int[Integer.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE - 100)); + }), + withToString("int[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> INT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static int bits(int e) { flatMap(fa -> INT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> INT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(INT_GENERATORS.get(1)) + .flatMap(fa -> INT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] intSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] intSaturatingBinaryOpAssocProvider() { + return INT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] intSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] intIndexedOpProvider() { return INT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3464,6 +3547,51 @@ static void maxInt256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFun assertBroadcastArraysEquals(r, a, b, Int256VectorTests::max); } + @Test(dataProvider = "intSaturatingBinaryOpAssocProvider") + static void SUADDAssocInt256VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Int256VectorTests::SUADD); + } + + @Test(dataProvider = "intSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocInt256VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Int256VectorTests::SUADD); + } static int ANDReduce(int[] a, int idx) { int res = -1; diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index a9da97d66ce..0679b410e59 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(int[] r, int[] a, int[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static int bits(int e) { }) ); + static final List> INT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("int[Integer.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE)); + }), + withToString("int[Integer.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE - 100)); + }), + withToString("int[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> INT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static int bits(int e) { flatMap(fa -> INT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> INT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(INT_GENERATORS.get(1)) + .flatMap(fa -> INT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] intSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] intSaturatingBinaryOpAssocProvider() { + return INT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] intSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] intIndexedOpProvider() { return INT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3464,6 +3547,51 @@ static void maxInt512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFun assertBroadcastArraysEquals(r, a, b, Int512VectorTests::max); } + @Test(dataProvider = "intSaturatingBinaryOpAssocProvider") + static void SUADDAssocInt512VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Int512VectorTests::SUADD); + } + + @Test(dataProvider = "intSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocInt512VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Int512VectorTests::SUADD); + } static int ANDReduce(int[] a, int idx) { int res = -1; diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index b41bf7b95d5..c77e246473b 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(int[] r, int[] a, int[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static int bits(int e) { }) ); + static final List> INT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("int[Integer.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE)); + }), + withToString("int[Integer.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE - 100)); + }), + withToString("int[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> INT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static int bits(int e) { flatMap(fa -> INT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> INT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(INT_GENERATORS.get(1)) + .flatMap(fa -> INT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] intSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] intSaturatingBinaryOpAssocProvider() { + return INT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] intSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] intIndexedOpProvider() { return INT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3464,6 +3547,51 @@ static void maxInt64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunc assertBroadcastArraysEquals(r, a, b, Int64VectorTests::max); } + @Test(dataProvider = "intSaturatingBinaryOpAssocProvider") + static void SUADDAssocInt64VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Int64VectorTests::SUADD); + } + + @Test(dataProvider = "intSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocInt64VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Int64VectorTests::SUADD); + } static int ANDReduce(int[] a, int idx) { int res = -1; diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index d2b910ba8ae..4f7338c50cb 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -410,6 +410,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(int[] rl, int[] rr, int[] a, int[] b, int[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(int[] r, int[] a, int[] b, FBinOp f) { int i = 0; try { @@ -1011,6 +1057,21 @@ static int bits(int e) { }) ); + static final List> INT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("int[Integer.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE)); + }), + withToString("int[Integer.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(Integer.MAX_VALUE - 100)); + }), + withToString("int[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (int)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> INT_GENERATOR_PAIRS = @@ -1023,6 +1084,12 @@ static int bits(int e) { flatMap(fa -> INT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> INT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(INT_GENERATORS.get(1)) + .flatMap(fa -> INT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1059,6 +1126,22 @@ public Object[][] intSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] intSaturatingBinaryOpAssocProvider() { + return INT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] intSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> INT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] intIndexedOpProvider() { return INT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3469,6 +3552,51 @@ static void maxIntMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFun assertBroadcastArraysEquals(r, a, b, IntMaxVectorTests::max); } + @Test(dataProvider = "intSaturatingBinaryOpAssocProvider") + static void SUADDAssocIntMaxVectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, IntMaxVectorTests::SUADD); + } + + @Test(dataProvider = "intSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocIntMaxVectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + int[] a = fa.apply(SPECIES.length()); + int[] b = fb.apply(SPECIES.length()); + int[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + int[] rl = fr.apply(SPECIES.length()); + int[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + IntVector bv = IntVector.fromArray(SPECIES, b, i); + IntVector cv = IntVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, IntMaxVectorTests::SUADD); + } static int ANDReduce(int[] a, int idx) { int res = -1; diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 5bc29f498ba..01cac6a505e 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -362,6 +362,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(long[] r, long[] a, long[] b, FBinOp f) { int i = 0; try { @@ -996,6 +1042,21 @@ static long bits(long e) { }) ); + static final List> LONG_SATURATING_GENERATORS_ASSOC = List.of( + withToString("long[Long.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE)); + }), + withToString("long[Long.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE - 100)); + }), + withToString("long[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> LONG_GENERATOR_PAIRS = @@ -1008,6 +1069,12 @@ static long bits(long e) { flatMap(fa -> LONG_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> LONG_SATURATING_GENERATOR_TRIPLETS = + Stream.of(LONG_GENERATORS.get(1)) + .flatMap(fa -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1044,6 +1111,22 @@ public Object[][] longSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] longSaturatingBinaryOpAssocProvider() { + return LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] longIndexedOpProvider() { return LONG_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3486,6 +3569,51 @@ static void maxLong128VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Long128VectorTests::max); } + @Test(dataProvider = "longSaturatingBinaryOpAssocProvider") + static void SUADDAssocLong128VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Long128VectorTests::SUADD); + } + + @Test(dataProvider = "longSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocLong128VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Long128VectorTests::SUADD); + } static long ANDReduce(long[] a, int idx) { long res = -1; diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 25a73d1916e..9e571c3cbe9 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -362,6 +362,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(long[] r, long[] a, long[] b, FBinOp f) { int i = 0; try { @@ -996,6 +1042,21 @@ static long bits(long e) { }) ); + static final List> LONG_SATURATING_GENERATORS_ASSOC = List.of( + withToString("long[Long.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE)); + }), + withToString("long[Long.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE - 100)); + }), + withToString("long[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> LONG_GENERATOR_PAIRS = @@ -1008,6 +1069,12 @@ static long bits(long e) { flatMap(fa -> LONG_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> LONG_SATURATING_GENERATOR_TRIPLETS = + Stream.of(LONG_GENERATORS.get(1)) + .flatMap(fa -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1044,6 +1111,22 @@ public Object[][] longSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] longSaturatingBinaryOpAssocProvider() { + return LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] longIndexedOpProvider() { return LONG_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3486,6 +3569,51 @@ static void maxLong256VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Long256VectorTests::max); } + @Test(dataProvider = "longSaturatingBinaryOpAssocProvider") + static void SUADDAssocLong256VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Long256VectorTests::SUADD); + } + + @Test(dataProvider = "longSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocLong256VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Long256VectorTests::SUADD); + } static long ANDReduce(long[] a, int idx) { long res = -1; diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index dab8ac0621a..5cb3cc32a68 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -362,6 +362,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(long[] r, long[] a, long[] b, FBinOp f) { int i = 0; try { @@ -996,6 +1042,21 @@ static long bits(long e) { }) ); + static final List> LONG_SATURATING_GENERATORS_ASSOC = List.of( + withToString("long[Long.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE)); + }), + withToString("long[Long.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE - 100)); + }), + withToString("long[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> LONG_GENERATOR_PAIRS = @@ -1008,6 +1069,12 @@ static long bits(long e) { flatMap(fa -> LONG_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> LONG_SATURATING_GENERATOR_TRIPLETS = + Stream.of(LONG_GENERATORS.get(1)) + .flatMap(fa -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1044,6 +1111,22 @@ public Object[][] longSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] longSaturatingBinaryOpAssocProvider() { + return LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] longIndexedOpProvider() { return LONG_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3486,6 +3569,51 @@ static void maxLong512VectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, Long512VectorTests::max); } + @Test(dataProvider = "longSaturatingBinaryOpAssocProvider") + static void SUADDAssocLong512VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Long512VectorTests::SUADD); + } + + @Test(dataProvider = "longSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocLong512VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Long512VectorTests::SUADD); + } static long ANDReduce(long[] a, int idx) { long res = -1; diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index f62ffc6554c..d5595395b0a 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -362,6 +362,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(long[] r, long[] a, long[] b, FBinOp f) { int i = 0; try { @@ -996,6 +1042,21 @@ static long bits(long e) { }) ); + static final List> LONG_SATURATING_GENERATORS_ASSOC = List.of( + withToString("long[Long.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE)); + }), + withToString("long[Long.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE - 100)); + }), + withToString("long[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> LONG_GENERATOR_PAIRS = @@ -1008,6 +1069,12 @@ static long bits(long e) { flatMap(fa -> LONG_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> LONG_SATURATING_GENERATOR_TRIPLETS = + Stream.of(LONG_GENERATORS.get(1)) + .flatMap(fa -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1044,6 +1111,22 @@ public Object[][] longSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] longSaturatingBinaryOpAssocProvider() { + return LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] longIndexedOpProvider() { return LONG_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3486,6 +3569,51 @@ static void maxLong64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFu assertBroadcastArraysEquals(r, a, b, Long64VectorTests::max); } + @Test(dataProvider = "longSaturatingBinaryOpAssocProvider") + static void SUADDAssocLong64VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Long64VectorTests::SUADD); + } + + @Test(dataProvider = "longSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocLong64VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Long64VectorTests::SUADD); + } static long ANDReduce(long[] a, int idx) { long res = -1; diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index 70441d0d763..cec3e0756b2 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -367,6 +367,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(long[] rl, long[] rr, long[] a, long[] b, long[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(long[] r, long[] a, long[] b, FBinOp f) { int i = 0; try { @@ -1001,6 +1047,21 @@ static long bits(long e) { }) ); + static final List> LONG_SATURATING_GENERATORS_ASSOC = List.of( + withToString("long[Long.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE)); + }), + withToString("long[Long.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(Long.MAX_VALUE - 100)); + }), + withToString("long[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (long)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> LONG_GENERATOR_PAIRS = @@ -1013,6 +1074,12 @@ static long bits(long e) { flatMap(fa -> LONG_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> LONG_SATURATING_GENERATOR_TRIPLETS = + Stream.of(LONG_GENERATORS.get(1)) + .flatMap(fa -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1049,6 +1116,22 @@ public Object[][] longSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] longSaturatingBinaryOpAssocProvider() { + return LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] longSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> LONG_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] longIndexedOpProvider() { return LONG_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3491,6 +3574,51 @@ static void maxLongMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntF assertBroadcastArraysEquals(r, a, b, LongMaxVectorTests::max); } + @Test(dataProvider = "longSaturatingBinaryOpAssocProvider") + static void SUADDAssocLongMaxVectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, LongMaxVectorTests::SUADD); + } + + @Test(dataProvider = "longSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocLongMaxVectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + long[] a = fa.apply(SPECIES.length()); + long[] b = fb.apply(SPECIES.length()); + long[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + long[] rl = fr.apply(SPECIES.length()); + long[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + LongVector bv = LongVector.fromArray(SPECIES, b, i); + LongVector cv = LongVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, LongMaxVectorTests::SUADD); + } static long ANDReduce(long[] a, int idx) { long res = -1; diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index b4240dabc87..1ce486eb709 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static short bits(short e) { }) ); + static final List> SHORT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("short[Short.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE)); + }), + withToString("short[Short.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE - 100)); + }), + withToString("short[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> SHORT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static short bits(short e) { flatMap(fa -> SHORT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> SHORT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(SHORT_GENERATORS.get(1)) + .flatMap(fa -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] shortSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocProvider() { + return SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] shortIndexedOpProvider() { return SHORT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3411,6 +3494,51 @@ static void maxShort128VectorTestsBroadcastSmokeTest(IntFunction fa, In assertBroadcastArraysEquals(r, a, b, Short128VectorTests::max); } + @Test(dataProvider = "shortSaturatingBinaryOpAssocProvider") + static void SUADDAssocShort128VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Short128VectorTests::SUADD); + } + + @Test(dataProvider = "shortSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocShort128VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Short128VectorTests::SUADD); + } static short ANDReduce(short[] a, int idx) { short res = -1; diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 902cac11eb6..8361c59923f 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static short bits(short e) { }) ); + static final List> SHORT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("short[Short.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE)); + }), + withToString("short[Short.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE - 100)); + }), + withToString("short[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> SHORT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static short bits(short e) { flatMap(fa -> SHORT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> SHORT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(SHORT_GENERATORS.get(1)) + .flatMap(fa -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] shortSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocProvider() { + return SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] shortIndexedOpProvider() { return SHORT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3411,6 +3494,51 @@ static void maxShort256VectorTestsBroadcastSmokeTest(IntFunction fa, In assertBroadcastArraysEquals(r, a, b, Short256VectorTests::max); } + @Test(dataProvider = "shortSaturatingBinaryOpAssocProvider") + static void SUADDAssocShort256VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Short256VectorTests::SUADD); + } + + @Test(dataProvider = "shortSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocShort256VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Short256VectorTests::SUADD); + } static short ANDReduce(short[] a, int idx) { short res = -1; diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 39ab2da2925..a9c1a5eb7ed 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static short bits(short e) { }) ); + static final List> SHORT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("short[Short.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE)); + }), + withToString("short[Short.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE - 100)); + }), + withToString("short[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> SHORT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static short bits(short e) { flatMap(fa -> SHORT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> SHORT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(SHORT_GENERATORS.get(1)) + .flatMap(fa -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] shortSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocProvider() { + return SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] shortIndexedOpProvider() { return SHORT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3411,6 +3494,51 @@ static void maxShort512VectorTestsBroadcastSmokeTest(IntFunction fa, In assertBroadcastArraysEquals(r, a, b, Short512VectorTests::max); } + @Test(dataProvider = "shortSaturatingBinaryOpAssocProvider") + static void SUADDAssocShort512VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Short512VectorTests::SUADD); + } + + @Test(dataProvider = "shortSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocShort512VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Short512VectorTests::SUADD); + } static short ANDReduce(short[] a, int idx) { short res = -1; diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index ff3cea2e051..d10b4ca7196 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -405,6 +405,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { int i = 0; try { @@ -1006,6 +1052,21 @@ static short bits(short e) { }) ); + static final List> SHORT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("short[Short.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE)); + }), + withToString("short[Short.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE - 100)); + }), + withToString("short[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> SHORT_GENERATOR_PAIRS = @@ -1018,6 +1079,12 @@ static short bits(short e) { flatMap(fa -> SHORT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> SHORT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(SHORT_GENERATORS.get(1)) + .flatMap(fa -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1054,6 +1121,22 @@ public Object[][] shortSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocProvider() { + return SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] shortIndexedOpProvider() { return SHORT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3411,6 +3494,51 @@ static void maxShort64VectorTestsBroadcastSmokeTest(IntFunction fa, Int assertBroadcastArraysEquals(r, a, b, Short64VectorTests::max); } + @Test(dataProvider = "shortSaturatingBinaryOpAssocProvider") + static void SUADDAssocShort64VectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, Short64VectorTests::SUADD); + } + + @Test(dataProvider = "shortSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocShort64VectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, Short64VectorTests::SUADD); + } static short ANDReduce(short[] a, int idx) { short res = -1; diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index 25b219f8abc..cca15c4e941 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -410,6 +410,52 @@ static FBinMaskOp lift(FBinOp f) { } } + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative(short[] rl, short[] rr, short[] a, short[] b, short[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals(short[] r, short[] a, short[] b, FBinOp f) { int i = 0; try { @@ -1011,6 +1057,21 @@ static short bits(short e) { }) ); + static final List> SHORT_SATURATING_GENERATORS_ASSOC = List.of( + withToString("short[Short.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE)); + }), + withToString("short[Short.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(Short.MAX_VALUE - 100)); + }), + withToString("short[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> (short)(-1)); + }) + ); + // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 static final List>> SHORT_GENERATOR_PAIRS = @@ -1023,6 +1084,12 @@ static short bits(short e) { flatMap(fa -> SHORT_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> SHORT_SATURATING_GENERATOR_TRIPLETS = + Stream.of(SHORT_GENERATORS.get(1)) + .flatMap(fa -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + @DataProvider public Object[][] boolUnaryOpProvider() { return BOOL_ARRAY_GENERATORS.stream(). @@ -1059,6 +1126,22 @@ public Object[][] shortSaturatingBinaryOpProvider() { toArray(Object[][]::new); } + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocProvider() { + return SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] shortSaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> SHORT_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + @DataProvider public Object[][] shortIndexedOpProvider() { return SHORT_GENERATOR_PAIRS.stream().map(List::toArray). @@ -3416,6 +3499,51 @@ static void maxShortMaxVectorTestsBroadcastSmokeTest(IntFunction fa, In assertBroadcastArraysEquals(r, a, b, ShortMaxVectorTests::max); } + @Test(dataProvider = "shortSaturatingBinaryOpAssocProvider") + static void SUADDAssocShortMaxVectorTests(IntFunction fa, IntFunction fb, IntFunction fc) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, ShortMaxVectorTests::SUADD); + } + + @Test(dataProvider = "shortSaturatingBinaryOpAssocMaskProvider") + static void SUADDAssocShortMaxVectorTestsMasked(IntFunction fa, IntFunction fb, + IntFunction fc, IntFunction fm) { + short[] a = fa.apply(SPECIES.length()); + short[] b = fb.apply(SPECIES.length()); + short[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + short[] rl = fr.apply(SPECIES.length()); + short[] rr = fr.apply(SPECIES.length()); + + VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ShortVector bv = ShortVector.fromArray(SPECIES, b, i); + ShortVector cv = ShortVector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } + + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, ShortMaxVectorTests::SUADD); + } static short ANDReduce(short[] a, int idx) { short res = -1; diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index da5585b1305..71dc4a1ef0a 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -46,6 +46,8 @@ binary_memop="Binary-mem-op" binary_masked_memop="Binary-Masked-mem-op" saturating_binary="SaturatingBinary-op" saturating_binary_masked="SaturatingBinary-Masked-op" +saturating_binary_assocative="SaturatingBinary-op-associative" +saturating_binary_assocative_masked="SaturatingBinary-Masked-op-associative" binary_broadcast="Binary-Broadcast-op" binary_broadcast_masked="Binary-Broadcast-Masked-op" binary_broadcast_long="Binary-Broadcast-Long-op" @@ -326,6 +328,12 @@ function gen_saturating_binary_op { gen_op_tmpl $saturating_binary_masked "$@" } +function gen_saturating_binary_op_associative { + echo "Generating saturating binary associative op $1 ($2)..." + gen_op_tmpl $saturating_binary_assocative "$@" + gen_op_tmpl $saturating_binary_assocative_masked "$@" +} + function gen_binary_op_no_masked { echo "Generating binary op $1 ($2)..." # gen_op_tmpl $binary_scalar "$@" @@ -487,6 +495,7 @@ gen_saturating_binary_op "SUADD" "VectorMath.addSaturatingUnsigned(a, b)" "BITWI gen_saturating_binary_op "SUSUB" "VectorMath.subSaturatingUnsigned(a, b)" "BITWISE" gen_binary_bcst_op_no_masked "MIN+min" "Math.min(a, b)" gen_binary_bcst_op_no_masked "MAX+max" "Math.max(a, b)" +gen_saturating_binary_op_associative "SUADD" "VectorMath.addSaturatingUnsigned(a, b)" "BITWISE" # Reductions. gen_reduction_op "AND" "\&" "BITWISE" "-1" diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-Masked-op-associative.template b/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-Masked-op-associative.template new file mode 100644 index 00000000000..c79a8937f2c --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-Masked-op-associative.template @@ -0,0 +1,18 @@ + $type$[] a = fa.apply(SPECIES.length()); + $type$[] b = fb.apply(SPECIES.length()); + $type$[] c = fc.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + $type$[] rl = fr.apply(SPECIES.length()); + $type$[] rr = fr.apply(SPECIES.length()); + + VectorMask<$Wideboxtype$> vmask = VectorMask.fromArray(SPECIES, mask, 0); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); + $abstractvectortype$ bv = $abstractvectortype$.fromArray(SPECIES, b, i); + $abstractvectortype$ cv = $abstractvectortype$.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv, vmask).lanewise(VectorOperators.SUADD, cv, vmask).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv, vmask), vmask).intoArray(rr, i); + } + } diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-op-associative.template b/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-op-associative.template new file mode 100644 index 00000000000..a5b42239e4c --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-SaturatingBinary-op-associative.template @@ -0,0 +1,15 @@ + $type$[] a = fa.apply(SPECIES.length()); + $type$[] b = fb.apply(SPECIES.length()); + $type$[] c = fc.apply(SPECIES.length()); + $type$[] rl = fr.apply(SPECIES.length()); + $type$[] rr = fr.apply(SPECIES.length()); + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + $Type$Vector av = $Type$Vector.fromArray(SPECIES, a, i); + $Type$Vector bv = $Type$Vector.fromArray(SPECIES, b, i); + $Type$Vector cv = $Type$Vector.fromArray(SPECIES, c, i); + av.lanewise(VectorOperators.SUADD, bv).lanewise(VectorOperators.SUADD, cv).intoArray(rl, i); + av.lanewise(VectorOperators.SUADD, bv.lanewise(VectorOperators.SUADD, cv)).intoArray(rr, i); + } + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-Masked-op-associative.template b/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-Masked-op-associative.template new file mode 100644 index 00000000000..8670e39e60d --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-Masked-op-associative.template @@ -0,0 +1,7 @@ + + @Test(dataProvider = "$type$SaturatingBinaryOpAssocMaskProvider") + static void [[TEST]]Assoc$vectorteststype$Masked(IntFunction<$type$[]> fa, IntFunction<$type$[]> fb, + IntFunction<$type$[]> fc, IntFunction fm) { +[[KERNEL]] + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, $vectorteststype$::[[TEST]]); + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-op-associative.template b/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-op-associative.template new file mode 100644 index 00000000000..f4c7e5f74a4 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Unit-SaturatingBinary-op-associative.template @@ -0,0 +1,5 @@ + @Test(dataProvider = "$type$SaturatingBinaryOpAssocProvider") + static void [[TEST]]Assoc$vectorteststype$(IntFunction<$type$[]> fa, IntFunction<$type$[]> fb, IntFunction<$type$[]> fc) { +[[KERNEL]] + assertArraysEqualsAssociative(rl, rr, a, b, c, $vectorteststype$::[[TEST]]); + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index 66646b15918..d50267318f5 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -502,6 +502,52 @@ relativeError)); } } + static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, FBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i])); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i]))); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i]), c[i]), "left associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i])), "right associative test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i]); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + + static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FBinOp f) { + assertArraysEqualsAssociative(rl, rr, a, b, c, mask, FBinMaskOp.lift(f)); + } + + static void assertArraysEqualsAssociative($type$[] rl, $type$[] rr, $type$[] a, $type$[] b, $type$[] c, boolean[] mask, FBinMaskOp f) { + int i = 0; + boolean mask_bit = false; + try { + for (; i < a.length; i++) { + mask_bit = mask[i % SPECIES.length()]; + //Left associative + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit)); + + //Right associative + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit)); + + //Results equal sanity check + Assert.assertEquals(rl[i], rr[i]); + } + } catch (AssertionError e) { + Assert.assertEquals(rl[i], f.apply(f.apply(a[i], b[i], mask_bit), c[i], mask_bit), "left associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rr[i], f.apply(a[i], f.apply(b[i], c[i], mask_bit), mask_bit), "right associative masked test at index #" + i + ", input1 = " + a[i] + ", input2 = " + b[i] + ", input3 = " + c[i] + ", mask = " + mask_bit); + Assert.assertEquals(rl[i], rr[i], "Result checks not equal at index #" + i + "leftRes = " + rl[i] + ", rightRes = " + rr[i]); + } + } + static void assertArraysEquals($type$[] r, $type$[] a, $type$[] b, FBinOp f) { int i = 0; try { @@ -1278,6 +1324,21 @@ relativeError)); }) ); + static final List> $TYPE$_SATURATING_GENERATORS_ASSOC = List.of( + withToString("$type$[$Boxtype$.MAX_VALUE]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ($type$)($Boxtype$.MAX_VALUE)); + }), + withToString("$type$[$Boxtype$.MAX_VALUE - 100]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ($type$)($Boxtype$.MAX_VALUE - 100)); + }), + withToString("$type$[-1]", (int s) -> { + return fill(s * BUFFER_REPS, + i -> ($type$)(-1)); + }) + ); + #end[!FP] // Create combinations of pairs // @@@ Might be sensitive to order e.g. div by 0 @@ -1292,6 +1353,12 @@ relativeError)); flatMap(fa -> $TYPE$_SATURATING_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + static final List>> $TYPE$_SATURATING_GENERATOR_TRIPLETS = + Stream.of($TYPE$_GENERATORS.get(1)) + .flatMap(fa -> $TYPE$_SATURATING_GENERATORS_ASSOC.stream().map(fb -> List.of(fa, fb))) + .flatMap(pair -> $TYPE$_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) + .collect(Collectors.toList()); + #end[!FP] @DataProvider public Object[][] boolUnaryOpProvider() { @@ -1330,6 +1397,22 @@ relativeError)); toArray(Object[][]::new); } + @DataProvider + public Object[][] $type$SaturatingBinaryOpAssocProvider() { + return $TYPE$_SATURATING_GENERATOR_TRIPLETS.stream().map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] $type$SaturatingBinaryOpAssocMaskProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + flatMap(fm -> $TYPE$_SATURATING_GENERATOR_TRIPLETS.stream().map(lfa -> { + return Stream.concat(lfa.stream(), Stream.of(fm)).toArray(); + })). + toArray(Object[][]::new); + } + + #end[!FP] @DataProvider public Object[][] $type$IndexedOpProvider() { diff --git a/test/jdk/jdk/internal/jimage/ImageReaderTest.java b/test/jdk/jdk/internal/jimage/ImageReaderTest.java new file mode 100644 index 00000000000..74ae7b3a20a --- /dev/null +++ b/test/jdk/jdk/internal/jimage/ImageReaderTest.java @@ -0,0 +1,497 @@ +/* + * 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. + * + * 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 jdk.internal.jimage.ImageReader; +import jdk.internal.jimage.ImageReader.Node; +import jdk.internal.jimage.PreviewMode; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.util.JarBuilder; +import jdk.tools.jlink.internal.LinkableRuntimeImage; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import tests.Helper; +import tests.JImageGenerator; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toSet; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; + +/* + * @test + * @summary Tests for ImageReader. + * @modules java.base/jdk.internal.jimage + * jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jimage + * @library /test/jdk/tools/lib + * /test/lib + * @build tests.* + * @run junit/othervm -esa ImageReaderTest + */ + +/// Using PER_CLASS lifecycle means the (expensive) image file is only build once. +/// There is no mutable test instance state to worry about. +@TestInstance(PER_CLASS) +public class ImageReaderTest { + // The '@' prefix marks the entry as a preview entry which will be placed in + // the '/modules//META-INF/preview/...' namespace. + private static final Map> IMAGE_ENTRIES = Map.of( + "modfoo", Arrays.asList( + "com.foo.HasPreviewVersion", + "com.foo.NormalFoo", + "com.foo.bar.NormalBar", + // Replaces original class in preview mode. + "@com.foo.HasPreviewVersion", + // New class in existing package in preview mode. + "@com.foo.bar.IsPreviewOnly"), + "modbar", Arrays.asList( + "com.bar.One", + "com.bar.Two", + // Two new packages in preview mode (new symbolic links). + "@com.bar.preview.stuff.Foo", + "@com.bar.preview.stuff.Bar"), + "modgus", Arrays.asList( + // A second module with a preview-only empty package (preview). + "@com.bar.preview.other.Gus")); + private final Path image = buildJImage(IMAGE_ENTRIES); + + @ParameterizedTest + @ValueSource(strings = { + "/", + "/modules", + "/modules/modfoo", + "/modules/modbar", + "/modules/modfoo/com", + "/modules/modfoo/com/foo", + "/modules/modfoo/com/foo/bar"}) + public void testModuleDirectories_expected(String name) throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertDir(reader, name); + } + } + + @ParameterizedTest + @ValueSource(strings = { + "", + "//", + "/modules/", + "/modules/unknown", + "/modules/modbar/", + "/modules/modfoo//com", + "/modules/modfoo/com/"}) + public void testModuleNodes_absent(String name) throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertAbsent(reader, name); + } + } + + @Test + public void testModuleResources() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertNode(reader, "/modules/modfoo/com/foo/HasPreviewVersion.class"); + assertNode(reader, "/modules/modbar/com/bar/One.class"); + + ImageClassLoader loader = new ImageClassLoader(reader, IMAGE_ENTRIES.keySet()); + assertEquals("Class: com.foo.HasPreviewVersion", loader.loadAndGetToString("modfoo", "com.foo.HasPreviewVersion")); + assertEquals("Class: com.foo.NormalFoo", loader.loadAndGetToString("modfoo", "com.foo.NormalFoo")); + assertEquals("Class: com.foo.bar.NormalBar", loader.loadAndGetToString("modfoo", "com.foo.bar.NormalBar")); + assertEquals("Class: com.bar.One", loader.loadAndGetToString("modbar", "com.bar.One")); + } + } + + @ParameterizedTest + @CsvSource(delimiter = ':', value = { + "modfoo:com/foo/HasPreviewVersion.class", + "modbar:com/bar/One.class", + }) + public void testResource_present(String modName, String resPath) throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertNotNull(reader.findResourceNode(modName, resPath)); + assertTrue(reader.containsResource(modName, resPath)); + + String canonicalNodeName = "/modules/" + modName + "/" + resPath; + Node node = reader.findNode(canonicalNodeName); + assertTrue(node != null && node.isResource()); + } + } + + @ParameterizedTest + @CsvSource(delimiter = ':', value = { + // Absolute resource names are not allowed. + "modfoo:/com/bar/One.class", + // Resource in wrong module. + "modfoo:com/bar/One.class", + "modbar:com/foo/HasPreviewVersion.class", + // Directories are not returned. + "modfoo:com/foo", + "modbar:com/bar", + // JImage entries exist for these, but they are not resources. + "modules:modfoo/com/foo/HasPreviewVersion.class", + "packages:com.foo/modfoo", + // Empty module names/paths do not find resources. + "'':modfoo/com/foo/HasPreviewVersion.class", + "modfoo:''"}) + public void testResource_absent(String modName, String resPath) throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertNull(reader.findResourceNode(modName, resPath)); + assertFalse(reader.containsResource(modName, resPath)); + + // Non-existent resources names should either not be found, + // or (in the case of directory nodes) not be resources. + String canonicalNodeName = "/modules/" + modName + "/" + resPath; + Node node = reader.findNode(canonicalNodeName); + assertTrue(node == null || !node.isResource()); + } + } + + @ParameterizedTest + @CsvSource(delimiter = ':', value = { + // Don't permit module names to contain paths. + "modfoo/com/bar:One.class", + "modfoo/com:bar/One.class", + "modules/modfoo/com:foo/HasPreviewVersion.class", + }) + public void testResource_invalid(String modName, String resPath) throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertThrows(IllegalArgumentException.class, () -> reader.containsResource(modName, resPath)); + assertThrows(IllegalArgumentException.class, () -> reader.findResourceNode(modName, resPath)); + } + } + + @Test + public void testPackageDirectories() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + Node root = assertDir(reader, "/packages"); + Set pkgNames = root.getChildNames().collect(toSet()); + assertTrue(pkgNames.contains("/packages/com")); + assertTrue(pkgNames.contains("/packages/com.foo")); + assertTrue(pkgNames.contains("/packages/com.bar")); + + // Even though no classes exist directly in the "com" package, it still + // creates a directory with links back to all the modules which contain it. + Set comLinks = assertDir(reader, "/packages/com").getChildNames().collect(Collectors.toSet()); + assertTrue(comLinks.contains("/packages/com/modfoo")); + assertTrue(comLinks.contains("/packages/com/modbar")); + } + } + + @Test + public void testPackageLinks() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + Node moduleFoo = assertDir(reader, "/modules/modfoo"); + Node moduleBar = assertDir(reader, "/modules/modbar"); + assertSame(assertLink(reader, "/packages/com.foo/modfoo").resolveLink(), moduleFoo); + assertSame(assertLink(reader, "/packages/com.bar/modbar").resolveLink(), moduleBar); + } + } + + @Test + public void testPreviewResources_disabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + ImageClassLoader loader = new ImageClassLoader(reader, IMAGE_ENTRIES.keySet()); + + // No preview classes visible. + assertEquals("Class: com.foo.HasPreviewVersion", loader.loadAndGetToString("modfoo", "com.foo.HasPreviewVersion")); + assertEquals("Class: com.foo.NormalFoo", loader.loadAndGetToString("modfoo", "com.foo.NormalFoo")); + assertEquals("Class: com.foo.bar.NormalBar", loader.loadAndGetToString("modfoo", "com.foo.bar.NormalBar")); + + // NormalBar exists but IsPreviewOnly doesn't. + assertResource(reader, "modfoo", "com/foo/bar/NormalBar.class"); + assertAbsent(reader, "/modules/modfoo/com/foo/bar/IsPreviewOnly.class"); + assertDirContents(reader, "/modules/modfoo/com/foo", "HasPreviewVersion.class", "NormalFoo.class", "bar"); + assertDirContents(reader, "/modules/modfoo/com/foo/bar", "NormalBar.class"); + } + } + + @Test + public void testPreviewResources_enabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.ENABLED)) { + ImageClassLoader loader = new ImageClassLoader(reader, IMAGE_ENTRIES.keySet()); + + // Preview version of classes either overwrite existing entries or are added to directories. + assertEquals("Preview: com.foo.HasPreviewVersion", loader.loadAndGetToString("modfoo", "com.foo.HasPreviewVersion")); + assertEquals("Class: com.foo.NormalFoo", loader.loadAndGetToString("modfoo", "com.foo.NormalFoo")); + assertEquals("Class: com.foo.bar.NormalBar", loader.loadAndGetToString("modfoo", "com.foo.bar.NormalBar")); + assertEquals("Preview: com.foo.bar.IsPreviewOnly", loader.loadAndGetToString("modfoo", "com.foo.bar.IsPreviewOnly")); + + // Both NormalBar and IsPreviewOnly exist (direct lookup and as child nodes). + assertResource(reader, "modfoo", "com/foo/bar/NormalBar.class"); + assertResource(reader, "modfoo", "com/foo/bar/IsPreviewOnly.class"); + assertDirContents(reader, "/modules/modfoo/com/foo", "HasPreviewVersion.class", "NormalFoo.class", "bar"); + assertDirContents(reader, "/modules/modfoo/com/foo/bar", "NormalBar.class", "IsPreviewOnly.class"); + } + } + + @Test + public void testPreviewOnlyPackages_disabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + ImageClassLoader loader = new ImageClassLoader(reader, IMAGE_ENTRIES.keySet()); + + // No 'preview' package or anything inside it. + assertDirContents(reader, "/modules/modbar/com/bar", "One.class", "Two.class"); + assertAbsent(reader, "/modules/modbar/com/bar/preview"); + assertAbsent(reader, "/modules/modbar/com/bar/preview/stuff/Foo.class"); + + // And no package link. + assertAbsent(reader, "/packages/com.bar.preview"); + } + } + + @Test + public void testPreviewOnlyPackages_enabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.ENABLED)) { + ImageClassLoader loader = new ImageClassLoader(reader, IMAGE_ENTRIES.keySet()); + + // In preview mode 'preview' package exists with preview only content. + assertDirContents(reader, "/modules/modbar/com/bar", "One.class", "Two.class", "preview"); + assertDirContents(reader, "/modules/modbar/com/bar/preview/stuff", "Foo.class", "Bar.class"); + assertResource(reader, "modbar", "com/bar/preview/stuff/Foo.class"); + + // And package links exists. + assertDirContents(reader, "/packages/com.bar.preview", "modbar", "modgus"); + } + } + + @Test + public void testPreviewModeLinks_disabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.DISABLED)) { + assertDirContents(reader, "/packages/com.bar", "modbar"); + // Missing symbolic link and directory when not in preview mode. + assertAbsent(reader, "/packages/com.bar.preview"); + assertAbsent(reader, "/packages/com.bar.preview.stuff"); + assertAbsent(reader, "/modules/modbar/com/bar/preview"); + assertAbsent(reader, "/modules/modbar/com/bar/preview/stuff"); + } + } + + @Test + public void testPreviewModeLinks_enabled() throws IOException { + try (ImageReader reader = ImageReader.open(image, PreviewMode.ENABLED)) { + // In preview mode there is a new preview-only module visible. + assertDirContents(reader, "/packages/com.bar", "modbar", "modgus"); + // And additional packages are present. + assertDirContents(reader, "/packages/com.bar.preview", "modbar", "modgus"); + assertDirContents(reader, "/packages/com.bar.preview.stuff", "modbar"); + assertDirContents(reader, "/packages/com.bar.preview.other", "modgus"); + // And the preview-only content appears as we expect. + assertDirContents(reader, "/modules/modbar/com/bar", "One.class", "Two.class", "preview"); + assertDirContents(reader, "/modules/modbar/com/bar/preview", "stuff"); + assertDirContents(reader, "/modules/modbar/com/bar/preview/stuff", "Foo.class", "Bar.class"); + // In both modules in which it was added. + assertDirContents(reader, "/modules/modgus/com/bar", "preview"); + assertDirContents(reader, "/modules/modgus/com/bar/preview", "other"); + assertDirContents(reader, "/modules/modgus/com/bar/preview/other", "Gus.class"); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testPreviewEntriesAlwaysHidden(boolean previewMode) throws IOException { + try (ImageReader reader = ImageReader.open(image, previewMode ? PreviewMode.ENABLED : PreviewMode.DISABLED)) { + // The META-INF directory exists, but does not contain the preview directory. + Node dir = assertDir(reader, "/modules/modfoo/META-INF"); + assertEquals(0, dir.getChildNames().filter(n -> n.endsWith("/preview")).count()); + // Neither the preview directory, nor anything in it, can be looked-up directly. + assertAbsent(reader, "/modules/modfoo/META-INF/preview"); + assertAbsent(reader, "/modules/modfoo/META-INF/preview/com/foo"); + // HasPreviewVersion.class is a preview class in the test data, and thus appears in + // two places in the jimage). Ensure the preview version is always hidden. + String alphaPath = "com/foo/HasPreviewVersion.class"; + assertNode(reader, "/modules/modfoo/" + alphaPath); + assertAbsent(reader, "/modules/modfoo/META-INF/preview/" + alphaPath); + } + } + + private static ImageReader.Node assertNode(ImageReader reader, String name) throws IOException { + ImageReader.Node node = reader.findNode(name); + assertNotNull(node, "Could not find node: " + name); + return node; + } + + private static ImageReader.Node assertDir(ImageReader reader, String name) throws IOException { + ImageReader.Node dir = assertNode(reader, name); + assertTrue(dir.isDirectory(), "Node was not a directory: " + name); + return dir; + } + + private static void assertDirContents(ImageReader reader, String name, String... expectedChildNames) throws IOException { + Node dir = assertDir(reader, name); + Set localChildNames = dir.getChildNames() + .peek(s -> assertTrue(s.startsWith(name + "/"))) + .map(s -> s.substring(name.length() + 1)) + .collect(toSet()); + assertEquals( + Set.of(expectedChildNames), + localChildNames, + String.format("Unexpected child names in directory '%s'", name)); + } + + private static void assertResource(ImageReader reader, String modName, String resPath) throws IOException { + assertTrue(reader.containsResource(modName, resPath), "Resource should exist: " + modName + "/" + resPath); + Node resNode = reader.findResourceNode(modName, resPath); + assertTrue(resNode.isResource(), "Node should be a resource: " + resNode.getName()); + String nodeName = "/modules/" + modName + "/" + resPath; + assertEquals(nodeName, resNode.getName()); + assertSame(resNode, reader.findNode(nodeName)); + } + + private static ImageReader.Node assertLink(ImageReader reader, String name) throws IOException { + ImageReader.Node link = assertNode(reader, name); + assertTrue(link.isLink(), "Node should be a symbolic link: " + link.getName()); + return link; + } + + private static void assertAbsent(ImageReader reader, String name) throws IOException { + assertNull(reader.findNode(name), "Should not be able to find node: " + name); + } + + /// Builds a jimage file with the specified class entries. The classes in the built + /// image can be loaded and executed to return their names via `toString()` to confirm + /// the correct bytes were returned. + public static Path buildJImage(Map> entries) { + Helper helper = getHelper(); + Path outDir = helper.createNewImageDir("test"); + JImageGenerator.JLinkTask jlink = JImageGenerator.getJLinkTask() + .modulePath(helper.defaultModulePath()) + .output(outDir); + + Path jarDir = helper.getJarDir(); + entries.forEach((module, classes) -> { + JarBuilder jar = new JarBuilder(jarDir.resolve(module + ".jar").toString()); + String moduleInfo = "module " + module + " {}"; + jar.addEntry("module-info.class", InMemoryJavaCompiler.compile("module-info", moduleInfo)); + + classes.forEach(fqn -> { + boolean isPreviewEntry = fqn.startsWith("@"); + if (isPreviewEntry) { + fqn = fqn.substring(1); + } + int lastDot = fqn.lastIndexOf('.'); + String pkg = fqn.substring(0, lastDot); + String cls = fqn.substring(lastDot + 1); + String source = String.format( + """ + package %s; + public class %s { + public String toString() { + return "%s: %s"; + } + } + """, pkg, cls, isPreviewEntry ? "Preview" : "Class", fqn); + String path = (isPreviewEntry ? "META-INF/preview/" : "") + fqn.replace('.', '/') + ".class"; + jar.addEntry(path, InMemoryJavaCompiler.compile(fqn, source)); + }); + try { + jar.build(); + } catch (IOException e) { + throw new RuntimeException(e); + } + jlink.addMods(module); + }); + return jlink.call().assertSuccess().resolve("lib", "modules"); + } + + /// Returns the helper for building JAR and jimage files. + private static Helper getHelper() { + Helper helper; + try { + boolean isLinkableRuntime = LinkableRuntimeImage.isLinkableRuntime(); + helper = Helper.newHelper(isLinkableRuntime); + } catch (IOException e) { + throw new RuntimeException(e); + } + Assumptions.assumeTrue(helper != null, "Cannot create test helper, skipping test!"); + return helper; + } + + /// Loads and performs actions on classes stored in a given `ImageReader`. + private static class ImageClassLoader extends ClassLoader { + private final ImageReader reader; + private final Set testModules; + + private ImageClassLoader(ImageReader reader, Set testModules) { + this.reader = reader; + this.testModules = testModules; + } + + @FunctionalInterface + public interface ClassAction { + R call(Class cls) throws T; + } + + String loadAndGetToString(String module, String fqn) { + return loadAndCall(module, fqn, c -> c.getDeclaredConstructor().newInstance().toString()); + } + + R loadAndCall(String module, String fqn, ClassAction action) { + Class cls = findClass(module, fqn); + assertNotNull(cls, "Could not load class: " + module + "/" + fqn); + try { + return action.call(cls); + } catch (Exception e) { + fail("Class loading failed", e); + return null; + } + } + + @Override + protected Class findClass(String module, String fqn) { + assumeTrue(testModules.contains(module), "Can only load classes in modules: " + testModules); + String name = "/modules/" + module + "/" + fqn.replace('.', '/') + ".class"; + Class cls = findLoadedClass(fqn); + if (cls == null) { + try { + ImageReader.Node node = reader.findNode(name); + if (node != null && node.isResource()) { + byte[] classBytes = reader.getResource(node); + cls = defineClass(fqn, classBytes, 0, classBytes.length); + resolveClass(cls); + return cls; + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return null; + } + } +} diff --git a/test/jdk/jdk/internal/jimage/JImageReadTest.java b/test/jdk/jdk/internal/jimage/JImageReadTest.java index ea700d03a4f..46e93a8996c 100644 --- a/test/jdk/jdk/internal/jimage/JImageReadTest.java +++ b/test/jdk/jdk/internal/jimage/JImageReadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -42,6 +42,7 @@ import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageLocation; +import jdk.internal.jimage.PreviewMode; import org.testng.annotations.DataProvider; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; @@ -49,6 +50,9 @@ import org.testng.Assert; import org.testng.TestNG; +import static java.nio.ByteOrder.BIG_ENDIAN; +import static java.nio.ByteOrder.LITTLE_ENDIAN; + @Test public class JImageReadTest { @@ -333,32 +337,21 @@ static void test4_nameTooLong() throws IOException { */ @Test static void test5_imageReaderEndianness() throws IOException { - ImageReader nativeReader = ImageReader.open(imageFile); - Assert.assertEquals(nativeReader.getByteOrder(), ByteOrder.nativeOrder()); - - try { - ImageReader leReader = ImageReader.open(imageFile, ByteOrder.LITTLE_ENDIAN); - Assert.assertEquals(leReader.getByteOrder(), ByteOrder.LITTLE_ENDIAN); - leReader.close(); - } catch (IOException io) { - // IOException expected if LITTLE_ENDIAN not the nativeOrder() - Assert.assertNotEquals(ByteOrder.nativeOrder(), ByteOrder.LITTLE_ENDIAN); - } - - try { - ImageReader beReader = ImageReader.open(imageFile, ByteOrder.BIG_ENDIAN); - Assert.assertEquals(beReader.getByteOrder(), ByteOrder.BIG_ENDIAN); - beReader.close(); - } catch (IOException io) { - // IOException expected if LITTLE_ENDIAN not the nativeOrder() - Assert.assertNotEquals(ByteOrder.nativeOrder(), ByteOrder.BIG_ENDIAN); + // Will be opened with native byte order. + try (ImageReader nativeReader = ImageReader.open(imageFile, PreviewMode.DISABLED)) { + // Just ensure something works as expected. + Assert.assertNotNull(nativeReader.findNode("/")); + } catch (IOException unexpected) { + Assert.fail("Reader should be openable with native byte order."); } - nativeReader.close(); + // Reader should not be openable with the wrong byte order. + ByteOrder otherOrder = ByteOrder.nativeOrder() == BIG_ENDIAN ? LITTLE_ENDIAN : BIG_ENDIAN; + Assert.assertThrows(IOException.class, () -> ImageReader.open(imageFile, otherOrder, PreviewMode.DISABLED)); } - // main method to run standalone from jtreg - @Test(enabled=false) + // main method to run standalone from jtreg + @Test(enabled = false) @Parameters({"x"}) @SuppressWarnings("raw_types") public static void main(@Optional String[] args) { diff --git a/test/jdk/jdk/internal/jimage/ModuleReferenceTest.java b/test/jdk/jdk/internal/jimage/ModuleReferenceTest.java new file mode 100644 index 00000000000..82b96a98e5c --- /dev/null +++ b/test/jdk/jdk/internal/jimage/ModuleReferenceTest.java @@ -0,0 +1,240 @@ +/* + * 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. + * + * 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 jdk.internal.jimage.ModuleReference; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +import static java.util.function.Predicate.not; +import static jdk.internal.jimage.ModuleReference.forEmptyPackage; +import static jdk.internal.jimage.ModuleReference.forResource; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/* + * @test + * @summary Tests for ModuleReference. + * @modules java.base/jdk.internal.jimage + * @run junit/othervm -esa ModuleReferenceTest + */ +public final class ModuleReferenceTest { + // Copied (not referenced) for testing. + private static final int FLAGS_HAS_CONTENT = 0x1; + private static final int FLAGS_HAS_NORMAL_VERSION = 0x2; + private static final int FLAGS_HAS_PREVIEW_VERSION = 0x4; + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void emptyRefs(boolean isPreview) { + ModuleReference ref = forEmptyPackage("module", isPreview); + + assertEquals("module", ref.name()); + assertFalse(ref.hasContent()); + assertEquals(isPreview, ref.hasPreviewVersion()); + assertEquals(isPreview, ref.isPreviewOnly()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void resourceRefs(boolean isPreview) { + ModuleReference ref = forResource("module", isPreview); + + assertEquals("module", ref.name()); + assertTrue(ref.hasContent()); + assertEquals(isPreview, ref.hasPreviewVersion()); + assertEquals(isPreview, ref.isPreviewOnly()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void mergedRefs(boolean isPreview) { + ModuleReference emptyRef = forEmptyPackage("module", true); + ModuleReference resourceRef = forResource("module", isPreview); + ModuleReference merged = emptyRef.merge(resourceRef); + + // Merging preserves whether there's content. + assertTrue(merged.hasContent()); + // And clears the preview-only status unless it was set in both. + assertEquals(isPreview, merged.isPreviewOnly()); + } + + @Test + public void writeBuffer() { + List refs = Arrays.asList( + forEmptyPackage("alpha", true), + forEmptyPackage("beta", false).merge(forEmptyPackage("beta", true)), + forResource("gamma", false), + forEmptyPackage("zeta", false)); + IntBuffer buffer = IntBuffer.allocate(2 * refs.size()); + ModuleReference.write(refs, buffer, testEncoder()); + assertArrayEquals( + new int[]{ + FLAGS_HAS_PREVIEW_VERSION, 100, + FLAGS_HAS_NORMAL_VERSION | FLAGS_HAS_PREVIEW_VERSION, 101, + FLAGS_HAS_NORMAL_VERSION | FLAGS_HAS_CONTENT, 102, + FLAGS_HAS_NORMAL_VERSION, 103}, + buffer.array()); + } + + @Test + public void writeBuffer_emptyList() { + IntBuffer buffer = IntBuffer.allocate(0); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.write(List.of(), buffer, null)); + assertTrue(err.getMessage().contains("non-empty")); + } + + @Test + public void writeBuffer_badCapacity() { + List refs = Arrays.asList( + forResource("first", false), + forEmptyPackage("alpha", false)); + IntBuffer buffer = IntBuffer.allocate(10); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.write(refs, buffer, null)); + assertTrue(err.getMessage().contains("buffer capacity")); + } + + @Test + public void writeBuffer_multipleContent() { + // Only one module reference (at most) can have resources. + List refs = Arrays.asList( + forResource("alpha", false), + forResource("beta", false)); + IntBuffer buffer = IntBuffer.allocate(2 * refs.size()); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.write(refs, buffer, null)); + assertTrue(err.getMessage().contains("content")); + } + + @Test + public void writeBuffer_badOrdering() { + // Badly ordered because preview references should come first. + List refs = Arrays.asList( + forEmptyPackage("alpha", false), + forEmptyPackage("beta", true)); + IntBuffer buffer = IntBuffer.allocate(2 * refs.size()); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.write(refs, buffer, null)); + assertTrue(err.getMessage().contains("strictly ordered")); + } + + @Test + public void writeBuffer_duplicateRef() { + // Technically distinct, and correctly sorted, but with duplicate names. + List refs = Arrays.asList( + forEmptyPackage("duplicate", true), + forEmptyPackage("duplicate", false)); + IntBuffer buffer = IntBuffer.allocate(2 * refs.size()); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.write(refs, buffer, null)); + assertTrue(err.getMessage().contains("unique")); + } + + @Test + public void readNameOffsets() { + // Preview versions must be first (important for early exit). + IntBuffer buffer = IntBuffer.wrap(new int[]{ + FLAGS_HAS_NORMAL_VERSION | FLAGS_HAS_PREVIEW_VERSION, 100, + FLAGS_HAS_PREVIEW_VERSION, 101, + FLAGS_HAS_NORMAL_VERSION | FLAGS_HAS_CONTENT, 102, + FLAGS_HAS_NORMAL_VERSION, 103}); + + List normalOffsets = asList(ModuleReference.readNameOffsets(buffer, true, false)); + List previewOffsets = asList(ModuleReference.readNameOffsets(buffer, false, true)); + List allOffsets = asList(ModuleReference.readNameOffsets(buffer, true, true)); + + assertEquals(List.of(100, 102, 103), normalOffsets); + assertEquals(List.of(100, 101), previewOffsets); + assertEquals(List.of(100, 101, 102, 103), allOffsets); + } + + @Test + public void readNameOffsets_badBufferSize() { + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.readNameOffsets(IntBuffer.allocate(3), true, false)); + assertTrue(err.getMessage().contains("buffer size")); + } + + @Test + public void readNameOffsets_badFlags() { + IntBuffer buffer = IntBuffer.wrap(new int[]{FLAGS_HAS_CONTENT, 100}); + var err = assertThrows( + IllegalArgumentException.class, + () -> ModuleReference.readNameOffsets(buffer, false, false)); + assertTrue(err.getMessage().contains("flags")); + } + + @Test + public void sortOrder_previewFirst() { + List refs = Arrays.asList( + forEmptyPackage("normal.beta", false), + forResource("preview.beta", true), + forEmptyPackage("preview.alpha", true), + forEmptyPackage("normal.alpha", false)); + refs.sort(Comparator.naturalOrder()); + // Non-empty first with remaining sorted by name. + assertEquals( + List.of("preview.alpha", "preview.beta", "normal.alpha", "normal.beta"), + refs.stream().map(ModuleReference::name).toList()); + } + + private static List asList(Iterator src) { + List list = new ArrayList<>(); + src.forEachRemaining(list::add); + return list; + } + + // Encodes strings sequentially starting from index 100. + private static Function testEncoder() { + List cache = new ArrayList<>(); + return s -> { + int i = cache.indexOf(s); + if (i == -1) { + cache.add(s); + return 100 + (cache.size() - 1); + } else { + return 100 + i; + } + }; + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/types/ByByte.java b/test/jdk/jdk/internal/jrtfs/whitebox/ExplodedImageTestDriver.java similarity index 74% rename from test/micro/org/openjdk/bench/valhalla/types/ByByte.java rename to test/jdk/jdk/internal/jrtfs/whitebox/ExplodedImageTestDriver.java index 1072ee5796b..884024454d4 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/ByByte.java +++ b/test/jdk/jdk/internal/jrtfs/whitebox/ExplodedImageTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,10 +20,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; -public interface ByByte { - - public byte byteSum(); - -} +/* + * @test + * @summary Whitebox tests for ExplodedImage to ensure compatibility with ImageReader. + * @modules java.base/jdk.internal.jrtfs java.base/jdk.internal.jimage + * @run junit/othervm java.base/jdk.internal.jrtfs.ExplodedImageTest + */ +public class ExplodedImageTestDriver {} \ No newline at end of file diff --git a/test/jdk/jdk/internal/jrtfs/whitebox/TEST.properties b/test/jdk/jdk/internal/jrtfs/whitebox/TEST.properties new file mode 100644 index 00000000000..6e60bee4991 --- /dev/null +++ b/test/jdk/jdk/internal/jrtfs/whitebox/TEST.properties @@ -0,0 +1,4 @@ +modules = \ + java.base/jdk.internal.jimage \ + java.base/jdk.internal.jrtfs +bootclasspath.dirs=. diff --git a/test/jdk/jdk/internal/jrtfs/whitebox/java.base/jdk/internal/jrtfs/ExplodedImageTest.java b/test/jdk/jdk/internal/jrtfs/whitebox/java.base/jdk/internal/jrtfs/ExplodedImageTest.java new file mode 100644 index 00000000000..c63e163467b --- /dev/null +++ b/test/jdk/jdk/internal/jrtfs/whitebox/java.base/jdk/internal/jrtfs/ExplodedImageTest.java @@ -0,0 +1,232 @@ +/* + * 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. + * + * 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. + */ + +package jdk.internal.jrtfs; + +import jdk.internal.jimage.ImageReader; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests an {@link ExplodedImage} view of a class-file hierarchy. + * + *

          For simplicity and performance, only a subset of the JRT files are copied + * to disk for testing. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class ExplodedImageTest { + + private Path modulesRoot; + private SystemImage explodedImage; + private String pathSeparator; + + @BeforeAll + public void createTestDirectory(@TempDir Path modulesRoot) throws IOException { + this.modulesRoot = modulesRoot; + this.pathSeparator = modulesRoot.getFileSystem().getSeparator(); + // Copy only a useful subset of files for testing. Use at least two + // modules with "overlapping" packages to test /package links better. + unpackModulesDirectoriesFromJrtFileSystem(modulesRoot, + "java.base/java/util", + "java.base/java/util/zip", + "java.logging/java/util/logging"); + this.explodedImage = new ExplodedImage(modulesRoot); + } + + /** Unpacks a list of "/modules/..." directories non-recursively into the specified root directory. */ + private static void unpackModulesDirectoriesFromJrtFileSystem(Path modulesRoot, String... dirNames) + throws IOException { + FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); + List srcDirs = Arrays.stream(dirNames).map(s -> "/modules/" + s).map(jrtfs::getPath).toList(); + for (Path srcDir : srcDirs) { + // Skip-1 to remove "modules" segment (not part of the file system path). + Path dstDir = StreamSupport.stream(srcDir.spliterator(), false) + .skip(1) + .reduce(modulesRoot, (path, segment) -> path.resolve(segment.toString())); + Files.createDirectories(dstDir); + try (DirectoryStream files = Files.newDirectoryStream(srcDir)) { + for (Path srcFile : files) { + Files.copy(srcFile, dstDir.resolve(srcFile.getFileName().toString())); + } + } + } + } + + @Test + public void topLevelNodes() throws IOException { + ImageReader.Node root = explodedImage.findNode("/"); + ImageReader.Node modules = explodedImage.findNode("/modules"); + ImageReader.Node packages = explodedImage.findNode("/packages"); + assertEquals( + Set.of(modules.getName(), packages.getName()), + root.getChildNames().collect(Collectors.toSet())); + } + + @ParameterizedTest + @ValueSource(strings = { + "/modules/java.base/java/util/List.class", + "/modules/java.base/java/util/zip/ZipEntry.class", + "/modules/java.logging/java/util/logging/Logger.class"}) + public void basicLookupResource(String expectedResourceName) throws IOException { + ImageReader.Node node = assertResourceNode(expectedResourceName); + + Path fsRelPath = getRelativePath(expectedResourceName); + assertArrayEquals( + Files.readAllBytes(modulesRoot.resolve(fsRelPath)), + explodedImage.getResource(node)); + } + + @ParameterizedTest + @ValueSource(strings = { + "/modules/java.base", + "/modules/java.logging", + "/modules/java.base/java", + "/modules/java.base/java/util", + "/modules/java.logging/java/util", + }) + public void basicLookupDirectory(String expectedDirectoryName) throws IOException { + ImageReader.Node node = assertDirectoryNode(expectedDirectoryName); + + Path fsRelPath = getRelativePath(expectedDirectoryName); + List fsChildBaseNames; + try (DirectoryStream paths = Files.newDirectoryStream(modulesRoot.resolve(fsRelPath))) { + fsChildBaseNames = StreamSupport.stream(paths.spliterator(), false) + .map(Path::getFileName) + .map(Path::toString) + .toList(); + } + List nodeChildBaseNames = node.getChildNames() + .map(s -> s.substring(node.getName().length() + 1)) + .toList(); + assertEquals(fsChildBaseNames, nodeChildBaseNames, "expected same child names"); + } + + @ParameterizedTest + @ValueSource(strings = { + "/packages/java/java.base", + "/packages/java/java.logging", + "/packages/java.util/java.base", + "/packages/java.util/java.logging", + "/packages/java.util.zip/java.base"}) + public void basicLookupPackageLinks(String expectedLinkName) throws IOException { + ImageReader.Node node = assertLinkNode(expectedLinkName); + ImageReader.Node resolved = node.resolveLink(); + assertSame(explodedImage.findNode(resolved.getName()), resolved); + String moduleName = expectedLinkName.substring(expectedLinkName.lastIndexOf('/') + 1); + assertEquals("/modules/" + moduleName, resolved.getName()); + } + + @ParameterizedTest + @ValueSource(strings = { + "/packages/java", + "/packages/java.util", + "/packages/java.util.zip"}) + public void packageDirectories(String expectedDirectoryName) throws IOException { + ImageReader.Node node = assertDirectoryNode(expectedDirectoryName); + assertTrue(node.getChildNames().findFirst().isPresent(), + "Package directories should not be empty: " + node); + } + + @ParameterizedTest + @ValueSource(strings = { + "", + ".", + "/.", + "modules", + "packages", + "/modules/", + "/modules/xxxx", + "/modules/java.base/java/lang/Xxxx.class", + "/packages/", + "/packages/xxxx", + "/packages/java.xxxx", + "/packages/java.util.", + // Mismatched module. + "/packages/java.util.logging/java.base", + "/packages/java.util.zip/java.logging", + // Links are not resolved as they are fetched (old/broken behaviour). + "/packages/java.util/java.base/java/util/Vector.class", + }) + public void invalidNames(String invalidName) throws IOException { + assertNull(explodedImage.findNode(invalidName), "No node expected for: " + invalidName); + } + + private ImageReader.Node assertResourceNode(String name) throws IOException { + ImageReader.Node node = explodedImage.findNode(name); + assertNotNull(node); + assertEquals(name, node.getName(), "expected node name: " + name); + assertTrue(node.isResource(), "expected a resource: " + node); + assertFalse(node.isDirectory(), "resources are not directories: " + node); + assertFalse(node.isLink(), "resources are not links: " + node); + return node; + } + + private ImageReader.Node assertDirectoryNode(String name) throws IOException { + ImageReader.Node node = explodedImage.findNode(name); + assertNotNull(node); + assertEquals(name, node.getName(), "expected node name: " + name); + assertTrue(node.isDirectory(), "expected a directory: " + node); + assertFalse(node.isResource(), "directories are not resources: " + node); + assertFalse(node.isLink(), "directories are not links: " + node); + return node; + } + + private ImageReader.Node assertLinkNode(String name) throws IOException { + ImageReader.Node node = explodedImage.findNode(name); + assertNotNull(node); + assertEquals(name, node.getName(), "expected node name: " + name); + assertTrue(node.isLink(), "expected a link: " + node); + assertFalse(node.isResource(), "links are not resources: " + node); + assertFalse(node.isDirectory(), "links are not directories: " + node); + return node; + } + + private Path getRelativePath(String name) { + return Path.of(name.substring("/modules/".length()).replace("/", pathSeparator)); + } +} diff --git a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java index 8289505d469..1076771be0f 100644 --- a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java +++ b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -26,33 +26,33 @@ import java.math.BigDecimal; import java.util.Random; -import static java.lang.Double.*; +import static java.lang.Double.doubleToRawLongBits; +import static java.lang.Double.longBitsToDouble; import static java.lang.Long.numberOfTrailingZeros; -import static java.lang.StrictMath.scalb; -import static jdk.internal.math.MathUtils.flog10pow2; -public class DoubleToDecimalChecker extends ToDecimalChecker { +public final class DoubleToDecimalChecker extends ToDecimalChecker { - private static final int P = - numberOfTrailingZeros(doubleToRawLongBits(3)) + 2; - private static final int W = (SIZE - 1) - (P - 1); - private static final int Q_MIN = (-1 << (W - 1)) - P + 3; - private static final int Q_MAX = (1 << (W - 1)) - P; - private static final long C_MIN = 1L << (P - 1); - private static final long C_MAX = (1L << P) - 1; + private static final int P = numberOfTrailingZeros(doubleToRawLongBits(3)) + 2; + private static final int W = w(P); - private static final int K_MIN = flog10pow2(Q_MIN); - private static final int K_MAX = flog10pow2(Q_MAX); - private static final int H = flog10pow2(P) + 2; + private static final int Q_MIN = q_min(P); + private static final int Q_MAX = q_max(P); + private static final long C_MIN = c_min(P); + private static final long C_MAX = c_max(P); - private static final double MIN_VALUE = scalb(1.0, Q_MIN); - private static final double MIN_NORMAL = scalb((double) C_MIN, Q_MIN); - private static final double MAX_VALUE = scalb((double) C_MAX, Q_MAX); + private static final int E_MIN = e_min(P); + private static final int E_MAX = e_max(P); + private static final int E_THR_Z = e_thr_z(P); + private static final int E_THR_I = e_thr_i(P); + private static final int K_MIN = k_min(P); + private static final int K_MAX = k_max(P); - private static final int E_MIN = e(MIN_VALUE); - private static final int E_MAX = e(MAX_VALUE); + private static final int C_TINY = c_tiny(P); + private static final int H = h(P); - private static final long C_TINY = cTiny(Q_MIN, K_MIN); + private static final BigDecimal MIN_VALUE = min_value(P); + private static final BigDecimal MIN_NORMAL = min_normal(P); + private static final BigDecimal MAX_VALUE = max_value(P); private static final int Z = 1_024; @@ -60,10 +60,19 @@ public class DoubleToDecimalChecker extends ToDecimalChecker { private DoubleToDecimalChecker(double v) { super(DoubleToDecimal.toString(v)); -// super(Double.toString(v)); this.v = v; } + @Override + int eMin() { + return E_MIN; + } + + @Override + int eMax() { + return E_MAX; + } + @Override int h() { return H; @@ -86,32 +95,22 @@ boolean recovers(BigDecimal bd) { @Override boolean recovers(String s) { - return parseDouble(s) == v; + return Double.parseDouble(s) == v; } @Override String hexString() { - return toHexString(v) + "D"; - } - - @Override - int minExp() { - return E_MIN; - } - - @Override - int maxExp() { - return E_MAX; + return Double.toHexString(v) + "D"; } @Override boolean isNegativeInfinity() { - return v == NEGATIVE_INFINITY; + return v == Double.NEGATIVE_INFINITY; } @Override boolean isPositiveInfinity() { - return v == POSITIVE_INFINITY; + return v == Double.POSITIVE_INFINITY; } @Override @@ -149,17 +148,17 @@ private static void testAround(double v, int z) { } private static void testExtremeValues() { - testDec(NEGATIVE_INFINITY); - testAround(-MAX_VALUE, Z); - testAround(-MIN_NORMAL, Z); - testAround(-MIN_VALUE, Z); + testDec(Double.NEGATIVE_INFINITY); + testAround(-Double.MAX_VALUE, Z); + testAround(-Double.MIN_NORMAL, Z); + testAround(-Double.MIN_VALUE, Z); testDec(-0.0); testDec(0.0); - testAround(MIN_VALUE, Z); - testAround(MIN_NORMAL, Z); - testAround(MAX_VALUE, Z); - testDec(POSITIVE_INFINITY); - testDec(NaN); + testAround(Double.MIN_VALUE, Z); + testAround(Double.MIN_NORMAL, Z); + testAround(Double.MAX_VALUE, Z); + testDec(Double.POSITIVE_INFINITY); + testDec(Double.NaN); /* * Quiet NaNs have the most significant bit of the mantissa as 1, @@ -176,7 +175,7 @@ private static void testExtremeValues() { * All values treated specially by Schubfach */ for (int c = 1; c < C_TINY; ++c) { - testDec(c * MIN_VALUE); + testDec(c * Double.MIN_VALUE); } } @@ -186,7 +185,7 @@ private static void testExtremeValues() { */ private static void testPowersOf10() { for (int e = E_MIN; e <= E_MAX; ++e) { - testAround(parseDouble("1e" + e), Z); + testAround(Double.parseDouble("1e" + e), Z); } } @@ -195,7 +194,7 @@ private static void testPowersOf10() { * The rendering is either too long or it is not the closest decimal. */ private static void testPowersOf2() { - for (double v = MIN_VALUE; v <= MAX_VALUE; v *= 2) { + for (double v = Double.MIN_VALUE; v <= Double.MAX_VALUE; v *= 2) { testAround(v, Z); } } @@ -224,7 +223,7 @@ private static void testPowersOf2() { private static void testSomeAnomalies() { for (String dec : Anomalies) { - testDec(parseDouble(dec)); + testDec(Double.parseDouble(dec)); } } @@ -331,7 +330,7 @@ private static void testSomeAnomalies() { private static void testPaxson() { for (int i = 0; i < PaxsonSignificands.length; ++i) { - testDec(scalb(PaxsonSignificands[i], PaxsonExponents[i])); + testDec(StrictMath.scalb(PaxsonSignificands[i], PaxsonExponents[i])); } } @@ -441,28 +440,34 @@ private static void testRandomShortDecimals(Random r) { int e = r.nextInt(E_MAX - E_MIN + 1) + E_MIN; for (int pow10 = 1; pow10 < 10_000; pow10 *= 10) { /* randomly generate an int in [pow10, 10 pow10) */ - testAround(parseDouble((r.nextInt(9 * pow10) + pow10) + "e" + e), Z); + testAround(Double.parseDouble((r.nextInt(9 * pow10) + pow10) + "e" + e), Z); } } private static void testConstants() { addOnFail(P == DoubleToDecimal.P, "P"); - addOnFail((long) (double) C_MIN == C_MIN, "C_MIN"); - addOnFail((long) (double) C_MAX == C_MAX, "C_MAX"); - addOnFail(MIN_VALUE == Double.MIN_VALUE, "MIN_VALUE"); - addOnFail(MIN_NORMAL == Double.MIN_NORMAL, "MIN_NORMAL"); - addOnFail(MAX_VALUE == Double.MAX_VALUE, "MAX_VALUE"); + addOnFail(W == DoubleToDecimal.W, "W"); addOnFail(Q_MIN == DoubleToDecimal.Q_MIN, "Q_MIN"); addOnFail(Q_MAX == DoubleToDecimal.Q_MAX, "Q_MAX"); + addOnFail(C_MIN == DoubleToDecimal.C_MIN, "C_MIN"); + addOnFail(C_MAX == DoubleToDecimal.C_MAX, "C_MAX"); + addOnFail((long) (double) C_MIN == C_MIN, "C_MIN"); + addOnFail((long) (double) C_MAX == C_MAX, "C_MAX"); + addOnFail(E_MIN == DoubleToDecimal.E_MIN, "E_MIN"); + addOnFail(E_MAX == DoubleToDecimal.E_MAX, "E_MAX"); + addOnFail(E_THR_Z == DoubleToDecimal.E_THR_Z, "E_THR_Z"); + addOnFail(E_THR_I == DoubleToDecimal.E_THR_I, "E_THR_I"); addOnFail(K_MIN == DoubleToDecimal.K_MIN, "K_MIN"); addOnFail(K_MAX == DoubleToDecimal.K_MAX, "K_MAX"); - addOnFail(H == DoubleToDecimal.H, "H"); - addOnFail(E_MIN == DoubleToDecimal.E_MIN, "E_MIN"); - addOnFail(E_MAX == DoubleToDecimal.E_MAX, "E_MAX"); addOnFail(C_TINY == DoubleToDecimal.C_TINY, "C_TINY"); + addOnFail(H == DoubleToDecimal.H, "H"); + + addOnFail(MIN_VALUE.compareTo(new BigDecimal(Double.MIN_VALUE)) == 0, "MIN_VALUE"); + addOnFail(MIN_NORMAL.compareTo(new BigDecimal(Double.MIN_NORMAL)) == 0, "MIN_NORMAL"); + addOnFail(MAX_VALUE.compareTo(new BigDecimal(Double.MAX_VALUE)) == 0, "MAX_VALUE"); } public static void test(int randomCount, Random r) { diff --git a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java index a1929288494..0bc9dd80568 100644 --- a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java +++ b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -26,33 +26,33 @@ import java.math.BigDecimal; import java.util.Random; -import static java.lang.Float.*; +import static java.lang.Float.floatToRawIntBits; +import static java.lang.Float.intBitsToFloat; import static java.lang.Integer.numberOfTrailingZeros; -import static java.lang.StrictMath.scalb; -import static jdk.internal.math.MathUtils.flog10pow2; -public class FloatToDecimalChecker extends ToDecimalChecker { +public final class FloatToDecimalChecker extends ToDecimalChecker { - private static final int P = - numberOfTrailingZeros(floatToRawIntBits(3)) + 2; - private static final int W = (SIZE - 1) - (P - 1); - private static final int Q_MIN = (-1 << (W - 1)) - P + 3; - private static final int Q_MAX = (1 << (W - 1)) - P; - private static final int C_MIN = 1 << (P - 1); - private static final int C_MAX = (1 << P) - 1; + private static final int P = numberOfTrailingZeros(floatToRawIntBits(3)) + 2; + private static final int W = w(P); - private static final int K_MIN = flog10pow2(Q_MIN); - private static final int K_MAX = flog10pow2(Q_MAX); - private static final int H = flog10pow2(P) + 2; + private static final int Q_MIN = q_min(P); + private static final int Q_MAX = q_max(P); + private static final long C_MIN = c_min(P); + private static final long C_MAX = c_max(P); - private static final float MIN_VALUE = scalb(1.0f, Q_MIN); - private static final float MIN_NORMAL = scalb((float) C_MIN, Q_MIN); - private static final float MAX_VALUE = scalb((float) C_MAX, Q_MAX); + private static final int E_MIN = e_min(P); + private static final int E_MAX = e_max(P); + private static final int E_THR_Z = e_thr_z(P); + private static final int E_THR_I = e_thr_i(P); + private static final int K_MIN = k_min(P); + private static final int K_MAX = k_max(P); - private static final int E_MIN = e(MIN_VALUE); - private static final int E_MAX = e(MAX_VALUE); + private static final int C_TINY = c_tiny(P); + private static final int H = h(P); - private static final long C_TINY = cTiny(Q_MIN, K_MIN); + private static final BigDecimal MIN_VALUE = min_value(P); + private static final BigDecimal MIN_NORMAL = min_normal(P); + private static final BigDecimal MAX_VALUE = max_value(P); private static final int Z = 1_024; @@ -60,10 +60,19 @@ public class FloatToDecimalChecker extends ToDecimalChecker { private FloatToDecimalChecker(float v) { super(FloatToDecimal.toString(v)); -// super(Float.toString(v)); this.v = v; } + @Override + int eMin() { + return E_MIN; + } + + @Override + int eMax() { + return E_MAX; + } + @Override int h() { return H; @@ -86,42 +95,32 @@ boolean recovers(BigDecimal bd) { @Override boolean recovers(String s) { - return parseFloat(s) == v; + return Float.parseFloat(s) == v; } @Override String hexString() { - return toHexString(v) + "F"; - } - - @Override - int minExp() { - return E_MIN; - } - - @Override - int maxExp() { - return E_MAX; + return Float.toHexString(v) + "F"; } @Override boolean isNegativeInfinity() { - return v == NEGATIVE_INFINITY; + return v == Float.NEGATIVE_INFINITY; } @Override boolean isPositiveInfinity() { - return v == POSITIVE_INFINITY; + return v == Float.POSITIVE_INFINITY; } @Override boolean isMinusZero() { - return floatToIntBits(v) == 0x8000_0000; + return floatToRawIntBits(v) == 0x8000_0000; } @Override boolean isPlusZero() { - return floatToIntBits(v) == 0x0000_0000; + return floatToRawIntBits(v) == 0x0000_0000; } @Override @@ -139,7 +138,7 @@ private static void testDec(float v) { * as any value returned by intBitsToFloat() is valid. */ private static void testAround(float v, int z) { - int bits = floatToIntBits(v); + int bits = floatToRawIntBits(v); for (int i = -z; i <= z; ++i) { testDec(intBitsToFloat(bits + i)); } @@ -149,17 +148,17 @@ private static void testAround(float v, int z) { * MIN_NORMAL is incorrectly rendered by older JDKs. */ private static void testExtremeValues() { - testDec(NEGATIVE_INFINITY); - testAround(-MAX_VALUE, Z); - testAround(-MIN_NORMAL, Z); - testAround(-MIN_VALUE, Z); + testDec(Float.NEGATIVE_INFINITY); + testAround(-Float.MAX_VALUE, Z); + testAround(-Float.MIN_NORMAL, Z); + testAround(-Float.MIN_VALUE, Z); testDec(-0.0f); testDec(0.0f); - testAround(MIN_VALUE, Z); - testAround(MIN_NORMAL, Z); - testAround(MAX_VALUE, Z); - testDec(POSITIVE_INFINITY); - testDec(NaN); + testAround(Float.MIN_VALUE, Z); + testAround(Float.MIN_NORMAL, Z); + testAround(Float.MAX_VALUE, Z); + testDec(Float.POSITIVE_INFINITY); + testDec(Float.NaN); /* * Quiet NaNs have the most significant bit of the mantissa as 1, @@ -176,7 +175,7 @@ private static void testExtremeValues() { * All values treated specially by Schubfach */ for (int c = 1; c < C_TINY; ++c) { - testDec(c * MIN_VALUE); + testDec(c * Float.MIN_VALUE); } } @@ -186,7 +185,7 @@ private static void testExtremeValues() { */ private static void testPowersOf10() { for (int e = E_MIN; e <= E_MAX; ++e) { - testAround(parseFloat("1e" + e), Z); + testAround(Float.parseFloat("1e" + e), Z); } } @@ -195,7 +194,7 @@ private static void testPowersOf10() { * The rendering is either too long or it is not the closest decimal. */ private static void testPowersOf2() { - for (float v = MIN_VALUE; v <= MAX_VALUE; v *= 2) { + for (float v = Float.MIN_VALUE; v <= Float.MAX_VALUE; v *= 2) { testAround(v, Z); } } @@ -218,7 +217,7 @@ private static void testPowersOf2() { private static void testSomeAnomalies() { for (String dec : Anomalies) { - testDec(parseFloat(dec)); + testDec(Float.parseFloat(dec)); } } @@ -285,7 +284,7 @@ private static void testSomeAnomalies() { private static void testPaxson() { for (int i = 0; i < PaxsonSignificands.length; ++i) { - testDec(scalb(PaxsonSignificands[i], PaxsonExponents[i])); + testDec(StrictMath.scalb(PaxsonSignificands[i], PaxsonExponents[i])); } } @@ -366,29 +365,34 @@ private static void testRandomShortDecimals(Random r) { int e = r.nextInt(E_MAX - E_MIN + 1) + E_MIN; for (int pow10 = 1; pow10 < 10_000; pow10 *= 10) { /* randomly generate an int in [pow10, 10 pow10) */ - testAround(parseFloat((r.nextInt(9 * pow10) + pow10) + "e" + e), Z); + testAround(Float.parseFloat((r.nextInt(9 * pow10) + pow10) + "e" + e), Z); } } - private static void testConstants() { addOnFail(P == FloatToDecimal.P, "P"); - addOnFail((int) (float) C_MIN == C_MIN, "C_MIN"); - addOnFail((int) (float) C_MAX == C_MAX, "C_MAX"); - addOnFail(MIN_VALUE == Float.MIN_VALUE, "MIN_VALUE"); - addOnFail(MIN_NORMAL == Float.MIN_NORMAL, "MIN_NORMAL"); - addOnFail(MAX_VALUE == Float.MAX_VALUE, "MAX_VALUE"); + addOnFail(W == FloatToDecimal.W, "W"); addOnFail(Q_MIN == FloatToDecimal.Q_MIN, "Q_MIN"); addOnFail(Q_MAX == FloatToDecimal.Q_MAX, "Q_MAX"); + addOnFail(C_MIN == FloatToDecimal.C_MIN, "C_MIN"); + addOnFail(C_MAX == FloatToDecimal.C_MAX, "C_MAX"); + addOnFail((int) (float) C_MIN == C_MIN, "C_MIN"); + addOnFail((int) (float) C_MAX == C_MAX, "C_MAX"); + addOnFail(E_MIN == FloatToDecimal.E_MIN, "E_MIN"); + addOnFail(E_MAX == FloatToDecimal.E_MAX, "E_MAX"); + addOnFail(E_THR_Z == FloatToDecimal.E_THR_Z, "E_THR_Z"); + addOnFail(E_THR_I == FloatToDecimal.E_THR_I, "E_THR_I"); addOnFail(K_MIN == FloatToDecimal.K_MIN, "K_MIN"); addOnFail(K_MAX == FloatToDecimal.K_MAX, "K_MAX"); - addOnFail(H == FloatToDecimal.H, "H"); - addOnFail(E_MIN == FloatToDecimal.E_MIN, "E_MIN"); - addOnFail(E_MAX == FloatToDecimal.E_MAX, "E_MAX"); addOnFail(C_TINY == FloatToDecimal.C_TINY, "C_TINY"); + addOnFail(H == FloatToDecimal.H, "H"); + + addOnFail(MIN_VALUE.compareTo(new BigDecimal(Float.MIN_VALUE)) == 0, "MIN_VALUE"); + addOnFail(MIN_NORMAL.compareTo(new BigDecimal(Float.MIN_NORMAL)) == 0, "MIN_NORMAL"); + addOnFail(MAX_VALUE.compareTo(new BigDecimal(Float.MAX_VALUE)) == 0, "MAX_VALUE"); } public static void test(int randomCount, Random r) { diff --git a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java index 672a49037f4..1b4cfb82dec 100644 --- a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java +++ b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,447 +23,168 @@ package jdk.internal.math; +import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; -import static java.lang.Double.*; -import static java.lang.Long.numberOfTrailingZeros; -import static java.lang.StrictMath.scalb; import static java.math.BigInteger.*; +import static jdk.internal.math.DoubleToDecimal.*; +import static jdk.internal.math.DoubleToDecimal.Q_MAX; +import static jdk.internal.math.DoubleToDecimal.Q_MIN; import static jdk.internal.math.MathUtils.*; -public class MathUtilsChecker extends BasicChecker { +public final class MathUtilsChecker extends BasicChecker { - private static final BigInteger THREE = valueOf(3); - - // binary constants - private static final int P = - numberOfTrailingZeros(doubleToRawLongBits(3)) + 2; - private static final int W = (SIZE - 1) - (P - 1); - private static final int Q_MIN = (-1 << W - 1) - P + 3; - private static final int Q_MAX = (1 << W - 1) - P; - private static final long C_MIN = 1L << P - 1; - private static final long C_MAX = (1L << P) - 1; + private static final BigDecimal THREE_QUARTER = new BigDecimal("0.75"); // decimal constants - private static final int K_MIN = flog10pow2(Q_MIN); - private static final int K_MAX = flog10pow2(Q_MAX); - private static final int H = flog10pow2(P) + 2; + private static final int N = n(); + private static final int GE_MIN = ge_min(); + private static final int GE_MAX = ge_max(); + + private static final int MARGIN = 10; - private static String gReason(int k) { - return "g(" + k + ") is incorrect"; + private MathUtilsChecker() { } - /* - Let - 10^(-k) = beta 2^r - for the unique integer r and real beta meeting - 2^125 <= beta < 2^126 - Further, let g1 = g1(k), g0 = g0(k) and g = g1 2^63 + g0, - where g1 and g0 are as in MathUtils - Check that: - 2^62 <= g1 < 2^63, - 0 <= g0 < 2^63, - g - 1 <= beta < g, (that is, g = floor(beta) + 1) - The last predicate, after multiplying by 2^r, is equivalent to - (g - 1) 2^r <= 10^(-k) < g 2^r - This is the predicate that will be checked in various forms. - */ - private static void testG(int k) { - long g1 = g1(k); - long g0 = g0(k); - // 2^62 <= g1 < 2^63, 0 <= g0 < 2^63 - addOnFail((g1 >>> (Long.SIZE - 2)) == 0b01 && g0 >= 0, gReason(k)); + static BigDecimal pow2(int q) { + return q >= 0 + ? new BigDecimal(ONE.shiftLeft(q)) + : BigDecimal.ONE.divide(new BigDecimal(ONE.shiftLeft(-q))); + } - BigInteger g = valueOf(g1).shiftLeft(63).or(valueOf(g0)); - // double check that 2^125 <= g < 2^126 - addOnFail(g.signum() > 0 && g.bitLength() == 126, gReason(k)); + static BigDecimal pow10(int e) { + return BigDecimal.valueOf(1L, -e); + } - // see javadoc of MathUtils.g1(int) - int r = flog2pow10(-k) - 125; + static BigInteger floor(BigDecimal v) { + return v.setScale(0, RoundingMode.FLOOR).unscaledValue(); + } - /* - The predicate - (g - 1) 2^r <= 10^(-k) < g 2^r - is equivalent to - g - 1 <= 10^(-k) 2^(-r) < g - When - k <= 0 & r < 0 - all numerical subexpressions are integer-valued. This is the same as - g - 1 = 10^(-k) 2^(-r) - */ - if (k <= 0 && r < 0) { - addOnFail( - g.subtract(ONE).compareTo(TEN.pow(-k).shiftLeft(-r)) == 0, - gReason(k)); - return; - } + static BigInteger ceil(BigDecimal v) { + return v.setScale(0, RoundingMode.CEILING).unscaledValue(); + } + /* floor(log2(v)) */ + static int flog2(BigDecimal v) { /* - The predicate - (g - 1) 2^r <= 10^(-k) < g 2^r - is equivalent to - g 10^k - 10^k <= 2^(-r) < g 10^k - When - k > 0 & r < 0 - all numerical subexpressions are integer-valued. + * Let v = f 10^e. + * Then log2(v) = log2(f) + e / log10(2). + * + * The initial flog2 is an estimate of l = floor(log2(v)), that is, + * 2^l <= v < 2^(l+1). + * Given the initial estimate flog2, search l meeting the above + * inequalities. */ - if (k > 0 && r < 0) { - BigInteger pow5 = TEN.pow(k); - BigInteger mhs = ONE.shiftLeft(-r); - BigInteger rhs = g.multiply(pow5); - addOnFail(rhs.subtract(pow5).compareTo(mhs) <= 0 - && mhs.compareTo(rhs) < 0, - gReason(k)); - return; - } + int flog2 = (v.unscaledValue().bitLength() - 1) + + (int) Math.floor(-v.scale() / Math.log10(2)); + for (; pow2(flog2).compareTo(v) <= 0; ++flog2); // empty body + for (; v.compareTo(pow2(flog2)) < 0; --flog2); // empty body + return flog2; + } - /* - Finally, when - k <= 0 & r >= 0 - the predicate - (g - 1) 2^r <= 10^(-k) < g 2^r - can be used straightforwardly as all numerical subexpressions are - already integer-valued. - */ - if (k <= 0) { - BigInteger mhs = TEN.pow(-k); - addOnFail(g.subtract(ONE).shiftLeft(r).compareTo(mhs) <= 0 && - mhs.compareTo(g.shiftLeft(r)) < 0, - gReason(k)); - return; - } + /* floor(log10(v)) */ + static int flog10(BigDecimal v) { + return v.precision() - v.scale() - 1; + } - /* - For combinatorial reasons, the only remaining case is - k > 0 & r >= 0 - which, however, cannot arise. Indeed, the predicate - (g - 1) 2^r <= 10^(-k) < g 2^r - has a positive integer left-hand side and a middle side < 1, - which cannot hold. - */ - addOnFail(false, "unexpected case for g(" + k + ")"); + /* ceil(log10(v)) */ + static int clog10(BigDecimal v) { + return flog10(v.subtract(v.ulp())) + 1; } - /* - Verifies the soundness of the values returned by g1() and g0(). - */ - private static void testG() { - for (int k = MathUtils.K_MIN; k <= MathUtils.K_MAX; ++k) { - testG(k); - } + /* floor(log10(2^q)) */ + static int flog10pow2(int q) { + return flog10(pow2(q)); } - private static String flog10threeQuartersPow2Reason(int e) { - return "flog10threeQuartersPow2(" + e + ") is incorrect"; + private static int flog10threeQuartersPow2(int q) { + return flog10(THREE_QUARTER.multiply(pow2(q))); } - /* - Let - k = floor(log10(3/4 2^e)) - The method verifies that - k = flog10threeQuartersPow2(e), Q_MIN <= e <= Q_MAX - This range covers all binary exponents of doubles and floats. - - The first equation above is equivalent to - 10^k <= 3 2^(e-2) < 10^(k+1) - Equality never holds. Henceforth, the predicate to check is - 10^k < 3 2^(e-2) < 10^(k+1) - This will be transformed in various ways for checking purposes. - - For integer n > 0, let further - b = len2(n) - denote its length in bits. This means exactly the same as - 2^(b-1) <= n < 2^b - */ - private static void testFlog10threeQuartersPow2() { - // First check the case e = 1 - addOnFail(flog10threeQuartersPow2(1) == 0, - flog10threeQuartersPow2Reason(1)); + private static int flog2pow10(int e) { + return flog2(pow10(e)); + } - /* - Now check the range Q_MIN <= e <= 0. - By rewriting, the predicate to check is equivalent to - 3 10^(-k-1) < 2^(2-e) < 3 10^(-k) - As e <= 0, it follows that 2^(2-e) >= 4 and the right inequality - implies k < 0, so the powers of 10 are integers. - - The left inequality is equivalent to - len2(3 10^(-k-1)) <= 2 - e - and the right inequality to - 2 - e < len2(3 10^(-k)) - The original predicate is therefore equivalent to - len2(3 10^(-k-1)) <= 2 - e < len2(3 10^(-k)) - - Starting with e = 0 and decrementing until the lower bound, the code - keeps track of the two powers of 10 to avoid recomputing them. - This is easy because at each iteration k changes at most by 1. A simple - multiplication by 10 computes the next power of 10 when needed. - */ - int e = 0; - int k0 = flog10threeQuartersPow2(e); - addOnFail(k0 < 0, flog10threeQuartersPow2Reason(e)); - BigInteger l = THREE.multiply(TEN.pow(-k0 - 1)); - BigInteger u = l.multiply(TEN); - for (;;) { - addOnFail(l.bitLength() <= 2 - e & 2 - e < u.bitLength(), - flog10threeQuartersPow2Reason(e)); - --e; - if (e < Q_MIN) { - break; - } - int kp = flog10threeQuartersPow2(e); - addOnFail(kp <= k0, flog10threeQuartersPow2Reason(e)); - if (kp < k0) { - // k changes at most by 1 at each iteration, hence: - addOnFail(k0 - kp == 1, flog10threeQuartersPow2Reason(e)); - k0 = kp; - l = u; - u = u.multiply(TEN); - } - } + private static int n() { + return flog10pow2(Long.SIZE); + } - /* - Finally, check the range 2 <= e <= Q_MAX. - In predicate - 10^k < 3 2^(e-2) < 10^(k+1) - the right inequality shows that k >= 0 as soon as e >= 2. - It is equivalent to - 10^k / 3 < 2^(e-2) < 10^(k+1) / 3 - Both the powers of 10 and the powers of 2 are integers. - The left inequality is therefore equivalent to - floor(10^k / 3) < 2^(e-2) - and thus to - len2(floor(10^k / 3)) <= e - 2 - while the right inequality is equivalent to - 2^(e-2) <= floor(10^(k+1) / 3) - and hence to - e - 2 < len2(floor(10^(k+1) / 3)) - These are summarized as - len2(floor(10^k / 3)) <= e - 2 < len2(floor(10^(k+1) / 3)) - */ - e = 2; - k0 = flog10threeQuartersPow2(e); - addOnFail(k0 >= 0, flog10threeQuartersPow2Reason(e)); - BigInteger l10 = TEN.pow(k0); - BigInteger u10 = l10.multiply(TEN); - l = l10.divide(THREE); - u = u10.divide(THREE); - for (;;) { - addOnFail(l.bitLength() <= e - 2 & e - 2 < u.bitLength(), - flog10threeQuartersPow2Reason(e)); - ++e; - if (e > Q_MAX) { - break; - } - int kp = flog10threeQuartersPow2(e); - addOnFail(kp >= k0, flog10threeQuartersPow2Reason(e)); - if (kp > k0) { - // k changes at most by 1 at each iteration, hence: - addOnFail(kp - k0 == 1, flog10threeQuartersPow2Reason(e)); - k0 = kp; - u10 = u10.multiply(TEN); - l = u; - u = u10.divide(THREE); - } - } + private static int ge_max() { + return Integer.max(-K_MIN, E_THR_I - 2); } - private static String flog10pow2Reason(int e) { - return "flog10pow2(" + e + ") is incorrect"; + private static int ge_min() { + return Integer.min(-K_MAX, E_THR_Z - (N - 1)); } - /* - Let - k = floor(log10(2^e)) - The method verifies that - k = flog10pow2(e), Q_MIN <= e <= Q_MAX - This range covers all binary exponents of doubles and floats. - - The first equation above is equivalent to - 10^k <= 2^e < 10^(k+1) - Equality holds iff e = k = 0. - Henceforth, the predicates to check are equivalent to - k = 0, if e = 0 - 10^k < 2^e < 10^(k+1), otherwise - The latter will be transformed in various ways for checking purposes. - - For integer n > 0, let further - b = len2(n) - denote its length in bits. This means exactly the same as - 2^(b-1) <= n < 2^b - */ - private static void testFlog10pow2() { - // First check the case e = 0 - addOnFail(flog10pow2(0) == 0, flog10pow2Reason(0)); + private static int r(int e) { + return flog2pow10(e) - 125; + } - /* - Now check the range F * Q_MIN <= e < 0. - By inverting all quantities, the predicate to check is equivalent to - 10^(-k-1) < 2^(-e) < 10^(-k) - As e < 0, it follows that 2^(-e) >= 2 and the right inequality - implies k < 0. - The left inequality means exactly the same as - len2(10^(-k-1)) <= -e - Similarly, the right inequality is equivalent to - -e < len2(10^(-k)) - The original predicate is therefore equivalent to - len2(10^(-k-1)) <= -e < len2(10^(-k)) - The powers of 10 are integers because k < 0. - - Starting with e = -1 and decrementing towards the lower bound, the code - keeps track of the two powers of 10 to avoid recomputing them. - This is easy because at each iteration k changes at most by 1. A simple - multiplication by 10 computes the next power of 10 when needed. - */ - int e = -1; - int k = flog10pow2(e); - addOnFail(k < 0, flog10pow2Reason(e)); - BigInteger l = TEN.pow(-k - 1); - BigInteger u = l.multiply(TEN); - for (;;) { - addOnFail(l.bitLength() <= -e & -e < u.bitLength(), - flog10pow2Reason(e)); - --e; - if (e < Q_MIN) { - break; - } - int kp = flog10pow2(e); - addOnFail(kp <= k, flog10pow2Reason(e)); - if (kp < k) { - // k changes at most by 1 at each iteration, hence: - addOnFail(k - kp == 1, flog10pow2Reason(e)); - k = kp; - l = u; - u = u.multiply(TEN); - } - } + private static BigInteger g(int e) { + return floor(pow10(e).multiply(pow2(-r(e)))).add(ONE); + } - /* - Finally, in a similar vein, check the range 0 <= e <= Q_MAX. - In predicate - 10^k < 2^e < 10^(k+1) - the right inequality shows that k >= 0. - The left inequality means the same as - len2(10^k) <= e - and the right inequality holds iff - e < len2(10^(k+1)) - The original predicate is thus equivalent to - len2(10^k) <= e < len2(10^(k+1)) - As k >= 0, the powers of 10 are integers. - */ - e = 1; - k = flog10pow2(e); - addOnFail(k >= 0, flog10pow2Reason(e)); - l = TEN.pow(k); - u = l.multiply(TEN); - for (;;) { - addOnFail(l.bitLength() <= e & e < u.bitLength(), - flog10pow2Reason(e)); - ++e; - if (e > Q_MAX) { - break; - } - int kp = flog10pow2(e); - addOnFail(kp >= k, flog10pow2Reason(e)); - if (kp > k) { - // k changes at most by 1 at each iteration, hence: - addOnFail(kp - k == 1, flog10pow2Reason(e)); - k = kp; - l = u; - u = u.multiply(TEN); - } - } + private static String gReason(int e) { + return "g(" + e + ") is incorrect"; } - private static String flog2pow10Reason(int e) { - return "flog2pow10(" + e + ") is incorrect"; + private static void testG(int e) { + long g1 = g1(e); + long g0 = g0(e); + // 2^62 <= g1 < 2^63, 0 < g0 < 2^63 + addOnFail((g1 >>> -2) == 0b01 && g0 > 0, gReason(e)); + + BigInteger g = valueOf(g1).shiftLeft(63).or(valueOf(g0)); + // double check that 2^125 <= g < 2^126 + addOnFail(g.signum() > 0 && g.bitLength() == 126, gReason(e)); + + addOnFail(g(e).compareTo(g) == 0, gReason(e)); } - /* - Let - k = floor(log2(10^e)) - The method verifies that - k = flog2pow10(e), -K_MAX <= e <= -K_MIN - This range covers all decimal exponents of doubles and floats. - - The first equation above is equivalent to - 2^k <= 10^e < 2^(k+1) - Equality holds iff e = 0, implying k = 0. - Henceforth, the equivalent predicates to check are - k = 0, if e = 0 - 2^k < 10^e < 2^(k+1), otherwise - The latter will be transformed in various ways for checking purposes. - - For integer n > 0, let further - b = len2(n) - denote its length in bits. This means exactly the same as - 2^(b-1) <= n < 2^b - */ - private static void testFlog2pow10() { - // First check the case e = 0 - addOnFail(flog2pow10(0) == 0, flog2pow10Reason(0)); + private static void testG() { + for (int e = GE_MIN; e <= GE_MAX; ++e) { + testG(e); + } + } - /* - Now check the range K_MIN <= e < 0. - By inverting all quantities, the predicate to check is equivalent to - 2^(-k-1) < 10^(-e) < 2^(-k) - As e < 0, this leads to 10^(-e) >= 10 and the right inequality implies - k <= -4. - The above means the same as - len2(10^(-e)) = -k - The powers of 10 are integer values since e < 0. - */ - int e = -1; - int k0 = flog2pow10(e); - addOnFail(k0 <= -4, flog2pow10Reason(e)); - BigInteger l = TEN; - for (;;) { - addOnFail(l.bitLength() == -k0, flog2pow10Reason(e)); - --e; - if (e < -K_MAX) { - break; - } - k0 = flog2pow10(e); - l = l.multiply(TEN); + private static String flog10threeQuartersPow2Reason(int q) { + return "flog10threeQuartersPow2(" + q + ") is incorrect"; + } + + private static void testFlog10threeQuartersPow2() { + for (int q = Q_MIN - MARGIN; q <= Q_MAX + MARGIN; ++q) { + addOnFail(flog10threeQuartersPow2(q) == MathUtils.flog10threeQuartersPow2(q), + flog10threeQuartersPow2Reason(q)); } + } - /* - Finally, check the range 0 < e <= K_MAX. - From the predicate - 2^k < 10^e < 2^(k+1) - as e > 0, it follows that 10^e >= 10 and the right inequality implies - k >= 3. - The above means the same as - len2(10^e) = k + 1 - The powers of 10 are all integer valued, as e > 0. - */ - e = 1; - k0 = flog2pow10(e); - addOnFail(k0 >= 3, flog2pow10Reason(e)); - l = TEN; - for (;;) { - addOnFail(l.bitLength() == k0 + 1, flog2pow10Reason(e)); - ++e; - if (e > -K_MIN) { - break; - } - k0 = flog2pow10(e); - l = l.multiply(TEN); + private static String flog10pow2Reason(int q) { + return "flog10pow2(" + q + ") is incorrect"; + } + + private static void testFlog10pow2() { + for (int q = Q_MIN - MARGIN; q <= Q_MAX + MARGIN; ++q) { + addOnFail(flog10pow2(q) == MathUtils.flog10pow2(q), + flog10pow2Reason(q)); } } - private static void testBinaryConstants() { - addOnFail((long) (double) C_MIN == C_MIN, "C_MIN"); - addOnFail((long) (double) C_MAX == C_MAX, "C_MAX"); - addOnFail(scalb(1.0, Q_MIN) == MIN_VALUE, "MIN_VALUE"); - addOnFail(scalb((double) C_MIN, Q_MIN) == MIN_NORMAL, "MIN_NORMAL"); - addOnFail(scalb((double) C_MAX, Q_MAX) == MAX_VALUE, "MAX_VALUE"); + private static String flog2pow10Reason(int e) { + return "flog2pow10(" + e + ") is incorrect"; + } + + private static void testFlog2pow10() { + for (int e = -K_MAX - MARGIN; e <= -K_MIN + MARGIN; ++e) { + addOnFail(flog2pow10(e) == MathUtils.flog2pow10(e), + flog2pow10Reason(e)); + } } private static void testDecimalConstants() { - addOnFail(K_MIN == MathUtils.K_MIN, "K_MIN"); - addOnFail(K_MAX == MathUtils.K_MAX, "K_MAX"); - addOnFail(H == MathUtils.H, "H"); + addOnFail(GE_MIN == MathUtils.GE_MIN, "GE_MIN"); + addOnFail(GE_MAX == MathUtils.GE_MAX, "GE_MAX"); } private static String pow10Reason(int e) { @@ -471,15 +192,18 @@ private static String pow10Reason(int e) { } private static void testPow10() { - int e = 0; - long pow = 1; - for (; e <= H; e += 1, pow *= 10) { - addOnFail(pow == pow10(e), pow10Reason(e)); + addOnFail(N == MathUtils.N, "N"); + try { + Math.unsignedPowExact(10L, N + 1); // expected to throw + addOnFail(false, "N"); + } catch (RuntimeException _) { + } + for (int e = 0; e <= N; ++e) { + addOnFail(Math.unsignedPowExact(10L, e) == MathUtils.pow10(e), pow10Reason(e)); } } public static void test() { - testBinaryConstants(); testFlog10pow2(); testFlog10threeQuartersPow2(); testDecimalConstants(); diff --git a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java index df019c09de4..52e45cf288d 100644 --- a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java +++ b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -26,9 +26,8 @@ import java.io.IOException; import java.io.StringReader; import java.math.BigDecimal; -import java.math.BigInteger; -import static java.math.BigInteger.*; +import static jdk.internal.math.MathUtilsChecker.*; /* * A checker for the Javadoc specification. @@ -52,32 +51,6 @@ abstract class ToDecimalChecker extends BasicChecker { this.s = s; } - /* - * Returns e be such that 10^(e-1) <= v < 10^e - */ - static int e(double v) { - /* floor(log10(v)) + 1 is a first good approximation of e */ - int e = (int) Math.floor(Math.log10(v)) + 1; - - /* Full precision search for e */ - BigDecimal vp = new BigDecimal(v); - while (new BigDecimal(ONE, -(e - 1)).compareTo(vp) > 0) { - e -= 1; - } - while (vp.compareTo(new BigDecimal(ONE, -e)) >= 0) { - e += 1; - } - return e; - } - - static long cTiny(int qMin, int kMin) { - BigInteger[] qr = ONE.shiftLeft(-qMin) - .divideAndRemainder(TEN.pow(-(kMin + 1))); - BigInteger cTiny = qr[1].signum() > 0 ? qr[0].add(ONE) : qr[0]; - addOnFail(cTiny.bitLength() < Long.SIZE, "C_TINY"); - return cTiny.longValue(); - } - private boolean conversionError(String reason) { return addError("toString(" + hexString() + ")" + " returns incorrect \"" + s + "\" (" + reason + ")"); @@ -254,7 +227,7 @@ boolean check() { } /* The exponent is bounded */ - if (minExp() > q + l || q + l > maxExp()) { + if (eMin() > q + l || q + l > eMax()) { return conversionError("exponent is out-of-range"); } @@ -342,6 +315,91 @@ boolean check() { return false; } + static int size(int p) { + return 1 << -Integer.numberOfLeadingZeros(p); + } + + static int w(int p) { + return (size(p) - 1) - (p - 1); + } + + static int q_min(int p) { + return (-1 << (w(p) - 1)) - p + 3; + } + + static int q_max(int p) { + return (1 << (w(p) - 1)) - p; + } + + static long c_min(int p) { + return 1L << (p - 1); + } + + static long c_max(int p) { + return (1L << p) - 1; + } + + /* max{e : 10^(e-1) <= v */ + static int e(BigDecimal v) { + return flog10(v) + 1; + } + + static int e_min(int p) { + return e(min_value(p)); + } + + static int e_max(int p) { + return e(max_value(p)); + } + + static int e_thr_z(int p) { + BigDecimal THR_Z = pow2(q_min(p) - 1); + return flog10(THR_Z); + } + + static int e_thr_i(int p) { + BigDecimal THR_I = BigDecimal.valueOf(2 * c_max(p) + 1) + .multiply(pow2(q_max(p) - 1)); + return clog10(THR_I) + 1; + } + + static int k_min(int p) { + return flog10pow2(q_min(p)); + } + + static int k_max(int p) { + return flog10pow2(q_max(p)); + } + + /* C_TINY = ceil(2^(-Q_MIN) 10^(K_MIN+1)) */ + static int c_tiny(int p) { + return ceil(pow2(-q_min(p)) + .multiply(pow10(k_min(p) + 1))) + .intValueExact(); + } + + static int h(int p) { + return flog10pow2(p) + 2; + } + + static BigDecimal min_value(int p) { + return pow2(q_min(p)); + } + + static BigDecimal min_normal(int p) { + return BigDecimal.valueOf(c_min(p)) + .multiply(pow2(q_min(p))); + } + + static BigDecimal max_value(int p) { + return BigDecimal.valueOf(c_max(p)) + .multiply(pow2(q_max(p))); + } + + abstract int eMin(); + + abstract int eMax(); + abstract int h(); abstract int maxStringLength(); @@ -354,10 +412,6 @@ boolean check() { abstract String hexString(); - abstract int minExp(); - - abstract int maxExp(); - abstract boolean isNegativeInfinity(); abstract boolean isPositiveInfinity(); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java index e236292de98..9a531d692ed 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java @@ -28,6 +28,7 @@ * @summary Verify that -XshowSettings:system works * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @run main/timeout=360 TestDockerBasic */ diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java index 4d452f20eef..ff039913b8f 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java @@ -35,6 +35,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsCpuTester diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index e8dc616b5e7..7cbab5c3b86 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -33,6 +33,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java index c6b94370807..0587d5a6bfb 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -40,6 +40,7 @@ * @key cgroups * @summary Cgroup v1 subsystem fails to set subsystem path * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 204d7a215d8..8e3d0cacd57 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -27,6 +27,7 @@ * @key cgroups * @bug 8242480 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build GetFreeSwapSpaceSize * @run driver TestGetFreeSwapSpaceSize diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index 1544088f688..31e90e8802a 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build LimitUpdateChecker diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 9fedeb55234..6b19bb475f1 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -28,6 +28,7 @@ * @summary Test JDK Metrics class when running inside a docker container with limited pids * @bug 8266490 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build TestPidsLimit * @run driver TestPidsLimit diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index 93efff64cc4..49ec5663478 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -26,6 +26,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @run main TestSystemMetrics diff --git a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java index 6a96514771c..d8d300401a0 100644 --- a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java +++ b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java @@ -26,6 +26,7 @@ * @test * @summary UseContainerSupport flag should reflect Metrics being available * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build CheckUseContainerSupport diff --git a/test/jdk/jdk/internal/ref/Cleaner/ExitOnThrow.java b/test/jdk/jdk/internal/ref/Cleaner/ExitOnThrow.java deleted file mode 100644 index 7e0ab4685d1..00000000000 --- a/test/jdk/jdk/internal/ref/Cleaner/ExitOnThrow.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003, 2024, 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 - * @bug 4954921 8009259 - * @library /test/lib - * @modules java.base/jdk.internal.ref - * @build jdk.test.lib.Utils - * jdk.test.lib.Asserts - * jdk.test.lib.JDKToolFinder - * jdk.test.lib.JDKToolLauncher - * jdk.test.lib.Platform - * jdk.test.lib.process.* - * @run main ExitOnThrow - * @summary Ensure that if a cleaner throws an exception then the VM exits - */ - -import jdk.internal.ref.Cleaner; - -import jdk.test.lib.process.ProcessTools; - -public class ExitOnThrow { - - public static void main(String[] args) throws Exception { - if (args.length == 0) { - ProcessTools.executeTestJava("--add-exports", "java.base/jdk.internal.ref=ALL-UNNAMED", - "ExitOnThrow", - "-executeCleaner") - .outputTo(System.out) - .errorTo(System.out) - .shouldHaveExitValue(1) - .shouldContain("java.lang.RuntimeException: Foo!"); - } else { - Cleaner.create(new Object(), - () -> { throw new RuntimeException("Foo!"); } ); - while (true) { - System.gc(); - Thread.sleep(100); - } - } - } - -} diff --git a/test/jdk/jdk/internal/vm/Continuation/Basic.java b/test/jdk/jdk/internal/vm/Continuation/Basic.java index e13fa175ad5..393c30a3cc9 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Basic.java +++ b/test/jdk/jdk/internal/vm/Continuation/Basic.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2018, 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 @@ -64,9 +64,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import com.sun.management.HotSpotDiagnosticMXBean; -import java.lang.management.ManagementFactory; - import org.testng.annotations.Test; import org.testng.annotations.DataProvider; import static org.testng.Assert.*; @@ -281,39 +278,6 @@ static String barMany(long b, return "" + r; } - @Test - public void testPinnedMonitor() { - if (!legacyLockingMode()) return; - - // Test pinning due to held monitor - final AtomicReference res = new AtomicReference<>(); - - Continuation cont = new Continuation(FOO, ()-> { - syncFoo(1); - }) { - @Override - protected void onPinned(Continuation.Pinned reason) { - assert Continuation.isPinned(FOO); - res.set(reason); - } - }; - - cont.run(); - assertEquals(res.get(), Continuation.Pinned.MONITOR); - boolean isDone = cont.isDone(); - assertEquals(isDone, true); - } - - static double syncFoo(int a) { - long x = 8; - String s = "yyy"; - String r; - synchronized(FOO) { - r = bar2(a + 1); - } - return Integer.parseInt(r)+1; - } - @Test public void testNotPinnedMonitor() { final AtomicReference res = new AtomicReference<>(); @@ -419,9 +383,4 @@ static int nativeBaz(int b) { static { System.loadLibrary("BasicJNI"); } - - static boolean legacyLockingMode() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - } } diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index 52730c9523b..5959f6ee10f 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2018, 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 @@ -30,6 +30,7 @@ * @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true * @modules java.base java.base/jdk.internal.vm.annotation java.base/jdk.internal.vm * @library /test/lib + * @enablePreview * @build java.base/java.lang.StackWalkerHelper * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox @@ -47,6 +48,7 @@ * @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true * @modules java.base java.base/jdk.internal.vm.annotation java.base/jdk.internal.vm * @library /test/lib + * @enablePreview * @build java.base/java.lang.StackWalkerHelper * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox @@ -83,6 +85,7 @@ public class Fuzz implements Runnable { static final boolean FILE = true; static final boolean RANDOM = true; static final boolean VERBOSE = false; + static final Random RAND = Utils.getRandomInstance(); static float timeoutFactor = Float.parseFloat(System.getProperty("test.timeout.factor", "1.0")); static int COMPILATION_TIMEOUT = (int)(5_000 * timeoutFactor); // ms @@ -110,14 +113,14 @@ public static void main(String[] args) { static void runTests() { if (FILE) testFile("fuzz.dat"); - if (RANDOM) testRandom(System.currentTimeMillis(), 50); + if (RANDOM) testRandom(RAND.nextLong(), 50); } //////////////// enum Op { - CALL_I_INT, CALL_I_DBL, CALL_I_MANY, - CALL_C_INT, CALL_C_DBL, CALL_C_MANY, + CALL_I_INT, CALL_I_DBL, CALL_I_MANY, CALL_I_VAL, + CALL_C_INT, CALL_C_DBL, CALL_C_MANY, CALL_C_VAL, CALL_I_CTCH, CALL_C_CTCH, CALL_I_PIN, CALL_C_PIN, MH_I_INT, MH_C_INT, MH_I_MANY, MH_C_MANY, @@ -280,7 +283,7 @@ int test() { private static int COMPILE_LEVEL; static final int WARMUP_ITERS = 15_000; - static final Op[] WARMUP_TRACE = {Op.MH_C_INT, Op.MH_C_MANY, Op.REF_C_INT, Op.REF_C_MANY, Op.CALL_C_INT}; + static final Op[] WARMUP_TRACE = {Op.MH_C_INT, Op.MH_C_MANY, Op.REF_C_INT, Op.REF_C_MANY, Op.CALL_C_INT, Op.CALL_C_VAL}; static void warmup() { final long start = time(); @@ -473,7 +476,8 @@ void verifyResult(int result) { } boolean shouldPin() { - return traceHas(Op.PIN::contains) && legacyLockingMode(); + // Returns false since we never pin after we removed legacy locking. + return traceHas(Op.PIN::contains) && false; } void verifyPin(boolean yieldResult) { @@ -599,6 +603,118 @@ static String sfToString(Object f) { return f instanceof StackFrame ? StackWalkerHelper.frameToString((StackFrame)f) : Objects.toString(f); } + //// Value Classes + + static abstract value class BaseValue { + public abstract int res(); + }; + + static value class SmallValue extends BaseValue { + int x1; + int x2; + + public SmallValue(int i) { + x1 = i; + x2 = i; + } + + public int res() { + return x1 + x2; + } + }; + + static value class LargeValue extends BaseValue { + int x1; + int x2; + int x3; + int x4; + int x5; + int x6; + int x7; + + public LargeValue(int i) { + x1 = i; + x2 = i; + x3 = i; + x4 = i; + x5 = i; + x6 = i; + x7 = i; + } + + public int res() { + return x1 + x2 + x3 + x4 + x5 + x6 + x7; + } + }; + + static value class OopsValue extends BaseValue { + Object x1; + Object x2; + Object x3; + Object x4; + Object x5; + int x6; + + public OopsValue(int i) { + x1 = new Object(); + x2 = new Object(); + x3 = new Object(); + x4 = new Object(); + x5 = new Object(); + x6 = i; + } + + public int res() { + return x6; + } + }; + + public static value class DoubleValue extends BaseValue { + double d1; + double d2; + double d3; + double d4; + double d5; + double d6; + double d7; + + public DoubleValue(double d) { + d1 = d; + d2 = d + 1; + d3 = d + 2; + d4 = d + 3; + d5 = d + 4; + d6 = d + 4; + d7 = d + 4; + } + + public int res() { + return (int)(d1 + d2 + d3 + d4 + d5 + d6 + d7); + } + }; + + static value class MixedValue extends BaseValue { + byte x1; + short x2; + int x3; + long x4; + double x5; + boolean x6; + + public MixedValue(int i) { + x1 = (byte)i; + x2 = (short)i; + x3 = i; + x4 = i; + x5 = i; + x6 = (i % 2) == 0; + } + + public int res() { + return (int)x1 + (int)x2 + (int)x3 + (int)x4 + (int)x5 + (x6 ? 1 : 0); + } + }; + //// Static Helpers static void rethrow(Throwable t) { @@ -634,6 +750,8 @@ static void time(long startNanos, String message) { static final Class[] run_sig = new Class[]{}; static final Class[] int_sig = new Class[]{int.class, int.class}; static final Class[] dbl_sig = new Class[]{int.class, double.class}; + static final Class[] val_sig = new Class[]{int.class, SmallValue.class, + LargeValue.class, OopsValue.class, DoubleValue.class, MixedValue.class}; static final Class[] mny_sig = new Class[]{int.class, int.class, double.class, long.class, float.class, Object.class, int.class, double.class, long.class, float.class, Object.class, @@ -659,6 +777,8 @@ static void time(long startNanos, String message) { method.put(Op.CALL_C_INT, Fuzz.class.getDeclaredMethod("com_int", int_sig)); method.put(Op.CALL_I_DBL, Fuzz.class.getDeclaredMethod("int_dbl", dbl_sig)); method.put(Op.CALL_C_DBL, Fuzz.class.getDeclaredMethod("com_dbl", dbl_sig)); + method.put(Op.CALL_I_VAL, Fuzz.class.getDeclaredMethod("int_val", val_sig)); + method.put(Op.CALL_C_VAL, Fuzz.class.getDeclaredMethod("com_val", val_sig)); method.put(Op.CALL_I_MANY, Fuzz.class.getDeclaredMethod("int_mny", mny_sig)); method.put(Op.CALL_C_MANY, Fuzz.class.getDeclaredMethod("com_mny", mny_sig)); method.put(Op.CALL_I_PIN, Fuzz.class.getDeclaredMethod("int_pin", int_sig)); @@ -703,6 +823,11 @@ public void run() { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(res); + LargeValue lv = new LargeValue(res); + OopsValue ov = new OopsValue(res); + DoubleValue dv = new DoubleValue((double)res); + MixedValue mv = new MixedValue(res); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -714,6 +839,8 @@ public void run() { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -740,6 +867,11 @@ int int_int(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x); + LargeValue lv = new LargeValue(x); + OopsValue ov = new OopsValue(x); + DoubleValue dv = new DoubleValue((double)x); + MixedValue mv = new MixedValue(x); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -751,6 +883,8 @@ int int_int(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -777,6 +911,11 @@ int com_int(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x); + LargeValue lv = new LargeValue(x); + OopsValue ov = new OopsValue(x); + DoubleValue dv = new DoubleValue((double)x); + MixedValue mv = new MixedValue(x); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -788,6 +927,8 @@ int com_int(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -814,6 +955,11 @@ int com_int(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x1); + LargeValue lv = new LargeValue(x1); + OopsValue ov = new OopsValue(x1); + DoubleValue dv = new DoubleValue((double)x1); + MixedValue mv = new MixedValue(x1); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -825,6 +971,8 @@ int com_int(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -851,6 +999,11 @@ int com_int(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x1); + LargeValue lv = new LargeValue(x1); + OopsValue ov = new OopsValue(x1); + DoubleValue dv = new DoubleValue((double)x1); + MixedValue mv = new MixedValue(x1); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -862,6 +1015,8 @@ int com_int(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -879,6 +1034,110 @@ int com_int(final int depth, int x) { return log(res); } + @DontInline + BaseValue int_val(final int depth, SmallValue x1, LargeValue x2, OopsValue x3, DoubleValue x4, MixedValue x5) { + int res = x1.res(); + + int x11 = (int)res, x12 = (int)res, x13 = (int)res, x14 = (int)res; + double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res; + long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; + float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; + Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(res); + LargeValue lv = new LargeValue(res); + OopsValue ov = new OopsValue(res); + DoubleValue dv = new DoubleValue((double)res); + MixedValue mv = new MixedValue(res); + + for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop + switch (next(c)) { + case THROW -> throwException(); + case LOOP -> { c += 2; index0 = index; } + case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; } + case DONE -> { break; } + case CALL_I_INT -> res += int_int(depth+1, (int)res); + case CALL_C_INT -> res += com_int(depth+1, (int)res); + case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); + case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_I_PIN -> res += int_pin(depth+1, (int)res); + case CALL_C_PIN -> res += com_pin(depth+1, (int)res); + case CALL_I_MANY -> res += int_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); + case CALL_C_MANY -> res += com_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); + case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}} + case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}} + case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }} + case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }} + case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }} + case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }} + default -> throw new AssertionError("Unknown op: " + current()); + } + } + + int positiveRes = (res == Integer.MIN_VALUE) ? Integer.MAX_VALUE : Math.abs(res); + switch (positiveRes % 5) { + case 0 -> { return log(new SmallValue(res)); } + case 1 -> { return log(new LargeValue(res)); } + case 2 -> { return log(new OopsValue(res)); } + case 3 -> { return log(new DoubleValue((double)res)); } + case 4 -> { return log(new MixedValue(res)); } + default -> throw new AssertionError("Invalid case"); + } + } + + @DontInline + BaseValue com_val(final int depth, SmallValue x1, LargeValue x2, OopsValue x3, DoubleValue x4, MixedValue x5) { + int res = x1.res(); + + int x11 = (int)res, x12 = (int)res, x13 = (int)res, x14 = (int)res; + double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res; + long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; + float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; + Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(res); + LargeValue lv = new LargeValue(res); + OopsValue ov = new OopsValue(res); + DoubleValue dv = new DoubleValue((double)res); + MixedValue mv = new MixedValue(res); + + for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop + switch (next(c)) { + case THROW -> throwException(); + case LOOP -> { c += 2; index0 = index; } + case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; } + case DONE -> { break; } + case CALL_I_INT -> res += int_int(depth+1, (int)res); + case CALL_C_INT -> res += com_int(depth+1, (int)res); + case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); + case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_I_PIN -> res += int_pin(depth+1, (int)res); + case CALL_C_PIN -> res += com_pin(depth+1, (int)res); + case CALL_I_MANY -> res += int_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); + case CALL_C_MANY -> res += com_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); + case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}} + case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}} + case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }} + case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }} + case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }} + case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }} + default -> throw new AssertionError("Unknown op: " + current()); + } + } + + int positiveRes = (res == Integer.MIN_VALUE) ? Integer.MAX_VALUE : Math.abs(res); + switch (positiveRes % 5) { + case 0 -> { return log(new SmallValue(res)); } + case 1 -> { return log(new LargeValue(res)); } + case 2 -> { return log(new OopsValue(res)); } + case 3 -> { return log(new DoubleValue((double)res)); } + case 4 -> { return log(new MixedValue(res)); } + default -> throw new AssertionError("Invalid case"); + } + } + @DontInline int int_pin(final int depth, int x) { int res = x; @@ -888,6 +1147,11 @@ int int_pin(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x); + LargeValue lv = new LargeValue(x); + OopsValue ov = new OopsValue(x); + DoubleValue dv = new DoubleValue((double)x); + MixedValue mv = new MixedValue(x); synchronized (this) { @@ -901,6 +1165,8 @@ int int_pin(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -929,6 +1195,11 @@ int com_pin(final int depth, int x) { long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res; float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res; Object o1 = res, o2 = res, o3 = res, o4 = res; + SmallValue sv = new SmallValue(x); + LargeValue lv = new LargeValue(x); + OopsValue ov = new OopsValue(x); + DoubleValue dv = new DoubleValue((double)x); + MixedValue mv = new MixedValue(x); synchronized (this) { @@ -942,6 +1213,8 @@ int com_pin(final int depth, int x) { case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -969,6 +1242,11 @@ int int_mny(int depth, int x4, double d4, long l4, float f4, Object o4) { double res = x1 + d2 + f3 + l4 + (double)(o4 instanceof Double ? (Double)o4 : (Integer)o4); + SmallValue sv = new SmallValue(x1); + LargeValue lv = new LargeValue(x1); + OopsValue ov = new OopsValue(x1); + DoubleValue dv = new DoubleValue((double)x1); + MixedValue mv = new MixedValue(x1); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -980,6 +1258,8 @@ int int_mny(int depth, case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -1005,6 +1285,11 @@ int com_mny(int depth, int x4, double d4, long l4, float f4, Object o4) { double res = x1 + d2 + f3 + l4 + (double)(o4 instanceof Double ? (Double)o4 : (Integer)o4); + SmallValue sv = new SmallValue(x1); + LargeValue lv = new LargeValue(x1); + OopsValue ov = new OopsValue(x1); + DoubleValue dv = new DoubleValue((double)x1); + MixedValue mv = new MixedValue(x1); for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop switch (next(c)) { @@ -1016,6 +1301,8 @@ int com_mny(int depth, case CALL_C_INT -> res += com_int(depth+1, (int)res); case CALL_I_DBL -> res += (int)int_dbl(depth+1, res); case CALL_C_DBL -> res += (int)com_dbl(depth+1, res); + case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res(); + case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res(); case CALL_I_PIN -> res += int_pin(depth+1, (int)res); case CALL_C_PIN -> res += com_pin(depth+1, (int)res); case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); @@ -1032,9 +1319,4 @@ int com_mny(int depth, return log((int)res); } - - static boolean legacyLockingMode() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - } } diff --git a/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java b/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java index da3bd311abb..89aab24b802 100644 --- a/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java +++ b/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java @@ -23,38 +23,25 @@ package jdk.jfr.api.metadata.annotations; -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.io.IOException; import java.lang.reflect.Constructor; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.time.Instant; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import jdk.jfr.AnnotationElement; -import jdk.jfr.Event; -import jdk.jfr.EventType; -import jdk.jfr.MetadataDefinition; -import jdk.jfr.Name; -import jdk.jfr.Threshold; import jdk.jfr.Enabled; +import jdk.jfr.Event; import jdk.jfr.Recording; +import jdk.jfr.SettingControl; import jdk.jfr.SettingDefinition; -import jdk.jfr.SettingDescriptor; +import jdk.jfr.Threshold; import jdk.jfr.Throttle; -import jdk.jfr.ValueDescriptor; import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; import jdk.jfr.consumer.RecordingStream; -import jdk.test.lib.Asserts; -import jdk.test.lib.jfr.Events; -import jdk.jfr.SettingControl; /** * @test @@ -65,6 +52,9 @@ */ public class TestThrottle { + public static class UnthrottledEvent extends Event { + } + @Throttle("off") @Enabled(false) public static class ThrottledDisabledEvent extends Event { @@ -130,7 +120,11 @@ public static class ThrottledReuseEvent extends Event { public int index; } + private static Instant startTime; + public static void main(String[] args) throws Exception { + startTime = determineMinimumTime(); + testUnthrottled(); // To ensure problem is specific to throttled events testThrottleDisabled(); testThrottledOff(); testThottleZeroRate(); @@ -140,6 +134,20 @@ public static void main(String[] args) throws Exception { testThrottleUserdefined(); } + private static void testUnthrottled() throws Exception { + testEvent(UnthrottledEvent.class, true); + } + + private static Instant determineMinimumTime() throws IOException { + try (Recording r = new Recording()) { + r.enable("jdk.JVMInformation"); + r.start(); + Path p = Path.of("start.jfr"); + r.dump(p); + return RecordingFile.readAllEvents(p).get(0).getStartTime(); + } + } + private static void testThrottleDisabled() throws Exception { testEvent(ThrottledDisabledEvent.class, false); } @@ -220,8 +228,6 @@ private static void testThrottleUserdefined(String test, String throttle, boolea if (e5.shouldCommit()) { e5.commit(); } - - r.stop(); assertEvents(r, eventName, emit ? 5 : 0); } } @@ -272,14 +278,31 @@ private static void testEvent(Class eventClass, boolean shouldC private static void assertEvents(Recording r, String name, int expected) throws Exception { int count = 0; - for (RecordedEvent event : Events.fromRecording(r)) { + r.stop(); + Duration d = Duration.between(r.getStartTime(), r.getStopTime()); + Path file = Path.of("dump.jfr"); + r.dump(file); + for (RecordedEvent event : RecordingFile.readAllEvents(file)) { if (event.getEventType().getName().equals(name)) { count++; } + if (event.getDuration().isNegative()) { + System.out.println(event); + throw new Exception("Unexpected negative duration"); + } + if (event.getStartTime().isBefore(startTime)) { + System.out.println(event); + throw new Exception("Unexpected early start time"); + } + if (event.getDuration().toMillis() > 2 * d.toMillis()) { + System.out.println(event); + throw new Exception("Duration exceed twice the length of the recording"); + } } if (count != expected) { throw new Exception("Expected " + expected + " " + name + " events, but found " + count); } + Files.delete(file); } private static void assertShouldCommit(Event e, boolean expected) throws Exception { diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java index eb8d33832b5..d0765c00bd9 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java @@ -38,23 +38,21 @@ */ public class TestCPUTimeAndExecutionSample { - static String sampleEvent = EventNames.CPUTimeSample; - // The period is set to 1100 ms to provoke the 1000 ms // threshold in the JVM for os::naked_short_sleep(). public static void main(String[] args) throws Exception { - run(EventNames.ExecutionSample); - run(EventNames.CPUTimeSample); - run(EventNames.ExecutionSample); - run(EventNames.CPUTimeSample); + run(EventNames.CPUTimeSample, "throttle", "1000/s"); + run(EventNames.ExecutionSample, "period", "1100ms"); + run(EventNames.CPUTimeSample, "throttle", "1100ms"); + run(EventNames.ExecutionSample, "period", "1000ms"); } - private static void run(String eventType) { + private static void run(String eventType, String attribute, String value) { RecurseThread t = new RecurseThread(50); t.setDaemon(true); try (RecordingStream rs = new RecordingStream()) { - rs.enable(sampleEvent).with("throttle", "1000/s"); - rs.onEvent(sampleEvent, e -> { + rs.enable(eventType).with(attribute, value); + rs.onEvent(eventType, e -> { t.quit(); rs.close(); }); diff --git a/test/jdk/jdk/jfr/event/runtime/TestSyncOnValueBasedClassEvent.java b/test/jdk/jdk/jfr/event/runtime/TestSyncOnValueBasedClassEvent.java index 155f9f1e89e..43f4f19271d 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestSyncOnValueBasedClassEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestSyncOnValueBasedClassEvent.java @@ -37,9 +37,9 @@ * @bug 8242263 * @requires vm.hasJFR * @requires vm.flagless + * @enablePreview false * @library /test/lib * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=2 jdk.jfr.event.runtime.TestSyncOnValueBasedClassEvent - * @run main/othervm --enable-preview -XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=2 jdk.jfr.event.runtime.TestSyncOnValueBasedClassEvent */ public class TestSyncOnValueBasedClassEvent { static final String EVENT_NAME = EventNames.SyncOnValueBasedClass; diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Identity32int.java b/test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java similarity index 51% rename from test/micro/org/openjdk/bench/valhalla/array/copy/Identity32int.java rename to test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java index 297aad5cbec..d3e6146bc74 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Identity32int.java +++ b/test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,29 +20,27 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.copy; +package jdk.jfr.event.tracing; -import org.openjdk.bench.valhalla.array.util.StatesR32int; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; +import jdk.internal.misc.Unsafe; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Recording; +/** +* @test +* @summary Tests that PlatformTracer is not initialized if a method filter has not been set. +* @requires vm.flagless +* @requires vm.hasJFR +* @modules java.base/jdk.internal.misc jdk.jfr/jdk.jfr.internal.tracing +* @library /test/lib +* @run main/othervm -XX:StartFlightRecording jdk.jfr.event.tracing.TestLazyPlatformTracer +*/ +public class TestLazyPlatformTracer { -public class Identity32int extends StatesR32int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - R32int[] src = s.arr; - R32int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; + public static void main(String... args) throws Exception { + // Stop recording so end chunk events are emitted + FlightRecorder.getFlightRecorder().getRecordings().getFirst().stop(); + if (!Unsafe.getUnsafe().shouldBeInitialized(jdk.jfr.internal.tracing.PlatformTracer.class)) { + throw new AssertionError("PlatformTracer should not have been initialized"); } } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_arraycopy(Ref_as_Ref s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - } diff --git a/test/jdk/lib/testlibrary/java/lang/UCDFiles.java b/test/jdk/lib/testlibrary/java/lang/UCDFiles.java index 83054c5c0fb..a802a63b556 100644 --- a/test/jdk/lib/testlibrary/java/lang/UCDFiles.java +++ b/test/jdk/lib/testlibrary/java/lang/UCDFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -55,4 +55,6 @@ public class UCDFiles { UCD_DIR.resolve("UnicodeData.txt"); public static Path EMOJI_DATA = UCD_DIR.resolve("emoji").resolve("emoji-data.txt"); + public static Path CASEFOLDING = + UCD_DIR.resolve("CaseFolding.txt"); } diff --git a/test/jdk/sun/awt/image/gif/GifBuilder.java b/test/jdk/sun/awt/image/gif/GifBuilder.java new file mode 100644 index 00000000000..41eed6abeff --- /dev/null +++ b/test/jdk/sun/awt/image/gif/GifBuilder.java @@ -0,0 +1,166 @@ +/* + * 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. + * + * 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 javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.stream.ImageOutputStream; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.File; +import java.io.IOException; +import java.net.URL; + +/** + * This constructs sample gif files used to test different combinations + * of gif frame disposal methods and transparent pixel indices. + */ +public class GifBuilder { + + /** + * Different disposal methods for gif frames. These names exactly + * correspond to the String identifier ImageIO uses. + */ + public enum Disposal {none, doNotDispose, restoreToBackgroundColor, + restoreToPrevious}; + + + /** + * @param disposal the frame disposal method + * @param isFirstTableIndexTransparent if true then the transparent pixel + * is set to 0. If false then the + * transparent pixel is set to the + * last index. + */ + public record FrameDescription(Disposal disposal, boolean + isFirstTableIndexTransparent) {} + + /** + * This creates a sample gif image based on a series of FrameDescriptions, + * and the calls {@link GifComparison#run(URL)} + */ + public static void test(FrameDescription... frameDescriptions) + throws Throwable { + File file = createTestFile(frameDescriptions); + try { + GifComparison.run(file.toURI().toURL()); + } finally { + file.delete(); + } + } + + private static File createTestFile(FrameDescription... frameDescriptions) + throws IOException { + Color[] colors = new Color[] { + Color.red, + Color.yellow, + Color.green, + Color.cyan + }; + File file = File.createTempFile("GifBuilder", ".gif"); + ImageOutputStream ios = ImageIO.createImageOutputStream(file); + ImageWriter gifWriter = ImageIO.getImageWritersByFormatName("GIF"). + next(); + gifWriter.setOutput(ios); + ImageWriteParam wparam = gifWriter.getDefaultWriteParam(); + IIOMetadata streamMetadata = gifWriter. + getDefaultStreamMetadata(wparam); + gifWriter.prepareWriteSequence(streamMetadata); + + IndexColorModel icm = createIndexColorModel(colors, colors.length - 1); + + ImageTypeSpecifier s = ImageTypeSpecifier.createFromBufferedImageType( + BufferedImage.TYPE_BYTE_INDEXED); + IIOMetadata metadata = gifWriter.getDefaultImageMetadata(s, wparam); + String metaFormatName = metadata.getNativeMetadataFormatName(); + + for (FrameDescription frameDescription : frameDescriptions) { + + // prepare the image: + int width = 100 + 50 * (icm.getMapSize() - 2); + BufferedImage bi = new BufferedImage(width, 100, + BufferedImage.TYPE_BYTE_INDEXED, icm); + Graphics2D g = bi.createGraphics(); + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, bi.getWidth(), bi.getHeight()); + g.setComposite(AlphaComposite.SrcOver); + int x = 0; + for (int a = 0; a < icm.getMapSize() - 1; a++) { + if (a != icm.getTransparentPixel()) { + Color color = new Color(icm.getRGB(a)); + g.setColor(color); + g.fillOval(x, 0, 100, 100); + x += 50; + } + } + g.dispose(); + + // wrap attributes for gifWriter: + int transparentPixel = frameDescription.isFirstTableIndexTransparent + ? 0 : icm.getMapSize() - 1; + IIOMetadata frameMetadata = gifWriter.getDefaultImageMetadata( + ImageTypeSpecifier.createFromRenderedImage(bi), wparam); + IIOMetadataNode root = new IIOMetadataNode(metaFormatName); + IIOMetadataNode gce = new IIOMetadataNode( + "GraphicControlExtension"); + gce.setAttribute("disposalMethod", + frameDescription.disposal.name()); + gce.setAttribute("userInputFlag", "FALSE"); + gce.setAttribute("transparentColorFlag", "TRUE"); + gce.setAttribute("delayTime", "0"); + gce.setAttribute("transparentColorIndex", + Integer.toString(transparentPixel)); + root.appendChild(gce); + frameMetadata.mergeTree(metaFormatName, root); + IIOImage img = new IIOImage(bi, null, frameMetadata); + gifWriter.writeToSequence(img, wparam); + } + gifWriter.endWriteSequence(); + ios.flush(); + ios.close(); + + return file; + } + + private static IndexColorModel createIndexColorModel(Color[] colors, + int transparentIndex) { + byte[] r = new byte[colors.length]; + byte[] g = new byte[colors.length]; + byte[] b = new byte[colors.length]; + for (int a = 0; a < colors.length; a++) { + r[a] = (byte) colors[a].getRed(); + g[a] = (byte) colors[a].getGreen(); + b[a] = (byte) colors[a].getBlue(); + } + int bits = (int)(Math.log(colors.length) / Math.log(2) + .5); + return new IndexColorModel(bits, colors.length, r, g, b, + transparentIndex); + } +} diff --git a/test/jdk/sun/awt/image/gif/GifComparison.java b/test/jdk/sun/awt/image/gif/GifComparison.java new file mode 100644 index 00000000000..d0ef3cc128d --- /dev/null +++ b/test/jdk/sun/awt/image/gif/GifComparison.java @@ -0,0 +1,406 @@ +/* + * 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. + * + * 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 org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.IndexColorModel; +import java.net.URL; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This compares the last frame of ImageIO's rendering of a gif with the + * ToolkitImage's rendering. + *

          + * This is intended to serve as a helper class for more specific test cases. + */ +public class GifComparison { + + /** + * This inspects the last frame of a gif and throws an Error / Exception + * if ImageIO and ToolkitImage produce different BufferedImage renderings. + * + * @param srcURL the URL of the image to inspect + * + * @return the last frame encoded as a TYPE_INT_ARGB image. + *

          + * Unit tests may further inspect this image to make sure certain + * conditions are met. + */ + public static BufferedImage run(URL srcURL) throws Throwable { + System.out.println("Comparing ImageIO vs ToolkitImage rendering of " + + srcURL); + ImageIOModel ioModel = new ImageIOModel(srcURL); + AWTModel awtModel = new AWTModel(srcURL); + + BufferedImage lastImage = null; + + int a = ioModel.frames.size() - 1; + BufferedImage ioImg = ioModel.getFrame(a); + BufferedImage awtImage = awtModel.getFrame(a); + + lastImage = awtImage; + + if (!(ioImg.getWidth() == awtImage.getWidth() && + ioImg.getHeight() == awtImage.getHeight())) + throw new Error("These images are not the same size: " + + ioImg.getWidth() + "x" + ioImg.getHeight() + " vs " + + awtImage.getWidth() + "x" + awtImage.getHeight()); + + for (int y = 0; y < ioImg.getHeight(); y++) { + for (int x = 0; x < ioImg.getWidth(); x++) { + int argb1 = ioImg.getRGB(x, y); + int argb2 = awtImage.getRGB(x, y); + + int alpha1 = (argb1 & 0xff000000) >> 24; + int alpha2 = (argb2 & 0xff000000) >> 24; + if (alpha1 == 0 && alpha2 == 0) { + continue; + } else if (alpha1 == 0 || alpha2 == 0) { + throw new Error("pixels at (" + x + ", " + y + + ") have different opacities: " + + Integer.toUnsignedString(argb1, 16) + " vs " + + Integer.toUnsignedString(argb2, 16)); + } + int rgb1 = argb1 & 0xffffff; + int rgb2 = argb2 & 0xffffff; + if (rgb1 != rgb2) { + throw new Error("pixels at (" + x + ", " + y + + ") have different opaque RGB values: " + + Integer.toUnsignedString(rgb1, 16) + " vs " + + Integer.toUnsignedString(rgb2, 16)); + } + } + } + System.out.println("Passed"); + return lastImage; + } +} + +/** + * This identifies frames of a GIF image using ImageIO classes. + */ +class ImageIOModel { + + record Frame(int x, int y, int w, int h, String disposalMethod, + int transparentColorIndex) {} + + private final URL url; + private int width, height; + + final List frames = new LinkedList<>(); + private Color backgroundColor; + + ImageIOModel(URL url) throws Exception { + this.url = url; + + ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); + try { + initialize(reader); + } finally { + reader.dispose(); + } + } + + private void initialize(ImageReader reader) throws Exception { + reader.setInput(ImageIO.createImageInputStream(url.openStream())); + IIOMetadata metadata = reader.getStreamMetadata(); + IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree( + metadata.getNativeMetadataFormatName()); + + NodeList globalScreenDescriptor = globalRoot.getElementsByTagName( + "LogicalScreenDescriptor"); + if (globalScreenDescriptor.getLength() > 0) { + IIOMetadataNode screenDescriptor = (IIOMetadataNode) + globalScreenDescriptor.item(0); + + if (screenDescriptor != null) { + width = Integer.parseInt( + screenDescriptor.getAttribute("logicalScreenWidth")); + height = Integer.parseInt( + screenDescriptor.getAttribute("logicalScreenHeight")); + } + } + + NodeList globalColorTable = globalRoot.getElementsByTagName( + "GlobalColorTable"); + if (globalColorTable.getLength() > 0) { + IIOMetadataNode colorTable = (IIOMetadataNode) + globalColorTable.item(0); + + if (colorTable != null) { + String bgIndex = colorTable.getAttribute( + "backgroundColorIndex"); + IIOMetadataNode colorEntry = (IIOMetadataNode) + colorTable.getFirstChild(); + while (colorEntry != null) { + if (colorEntry.getAttribute("index").equals(bgIndex)) { + int red = Integer.parseInt(colorEntry.getAttribute( + "red")); + int green = Integer.parseInt(colorEntry.getAttribute( + "green")); + int blue = Integer.parseInt(colorEntry.getAttribute( + "blue")); + + backgroundColor = new Color(red, green, blue); + break; + } + + colorEntry = (IIOMetadataNode) colorEntry.getNextSibling(); + } + } + } + + int frameCount = reader.getNumImages(true); + + for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { + IIOMetadataNode root = (IIOMetadataNode) reader. + getImageMetadata(frameIndex). + getAsTree("javax_imageio_gif_image_1.0"); + IIOMetadataNode gce = (IIOMetadataNode) root. + getElementsByTagName("GraphicControlExtension").item(0); + NodeList children = root.getChildNodes(); + int transparentColorIndex = -1; + if ("TRUE".equalsIgnoreCase(gce.getAttribute( + "transparentColorFlag"))) { + transparentColorIndex = Integer.parseInt(gce.getAttribute( + "transparentColorIndex")); + } + + String disposalMethodStr = gce.getAttribute("disposalMethod"); + + int frameX = 0; + int frameY = 0; + int frameWidth = width; + int frameHeight = height; + + for (int nodeIndex = 0; nodeIndex < children.getLength(); + nodeIndex++) { + Node nodeItem = children.item(nodeIndex); + + if (nodeItem.getNodeName().equals("ImageDescriptor")) { + NamedNodeMap map = nodeItem.getAttributes(); + + frameX = Integer.parseInt(map.getNamedItem( + "imageLeftPosition").getNodeValue()); + frameY = Integer.parseInt(map.getNamedItem( + "imageTopPosition").getNodeValue()); + frameWidth = Integer.parseInt(map.getNamedItem( + "imageWidth").getNodeValue()); + frameHeight = Integer.parseInt(map.getNamedItem( + "imageHeight").getNodeValue()); + width = Math.max(width, frameX + frameWidth); + height = Math.max(height, frameY + frameHeight); + } + } + + frames.add(new Frame(frameX, frameY, frameWidth, frameHeight, + disposalMethodStr, transparentColorIndex)); + } + } + + public BufferedImage getFrame(int frameIndex) throws Exception { + ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); + reader.setInput(ImageIO.createImageInputStream(url.openStream())); + try { + BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + BufferedImage previousImage = null; + + for (int a = 0; a <= frameIndex; a++) { + Frame f = frames.get(a); + if (Objects.equals(f.disposalMethod, "restoreToPrevious")) { + if (previousImage == null) { + previousImage = new BufferedImage(image.getWidth(), + image.getHeight(), + BufferedImage.TYPE_INT_ARGB); + } + } + + if (previousImage != null) { + Graphics2D g = previousImage.createGraphics(); + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, image.getWidth(), image.getHeight()); + g.setComposite(AlphaComposite.SrcOver); + g.drawImage(image, 0, 0, null); + g.dispose(); + } + + BufferedImage frame = reader.read(a); + Graphics2D g = image.createGraphics(); + g.drawImage(frame, f.x, f.y, null); + g.dispose(); + IndexColorModel icm = (IndexColorModel) frame.getColorModel(); + + if (a != frameIndex) { + switch (f.disposalMethod) { + case "restoreToBackgroundColor" -> { + g = image.createGraphics(); + int t = icm.getTransparentPixel(); + if (t >= 0 && t == f.transparentColorIndex) { + g.setComposite(AlphaComposite.Clear); + g.fillRect(f.x, f.y, f.w, f.h); + } else { + g.setColor(backgroundColor); + g.fillRect(f.x, f.y, f.w, f.h); + } + g.dispose(); + } + case "restoreToPrevious" -> { + g = image.createGraphics(); + g.setComposite(AlphaComposite.Clear); + g.fillRect(f.x, f.y, f.w, f.h); + g.setComposite(AlphaComposite.SrcOver); + g.drawImage(previousImage, f.x, f.y, + f.x + f.w, f.y + f.h, + f.x, f.y, + f.x + f.w, f.y + f.h, null); + g.dispose(); + } + } + } + } + + return image; + } finally { + reader.dispose(); + } + } +} + + +/** + * This identifies frames of a GIF image using ToolkitImage / ImageProducer. + */ +class AWTModel { + private final URL url; + + AWTModel(URL url) { + this.url = url; + } + + public BufferedImage getFrame(int frameIndex) { + // Unfortunately the AWT gif decoder calls Thread.sleep if the frame + // delay is non-zero. So this method may take a long time to render a + // frame simply because the decoder is calling Thread.sleep constantly. + + Image image = Toolkit.getDefaultToolkit().createImage(url); + + AtomicReference returnValue = new AtomicReference<>(); + Semaphore semaphore = new Semaphore(1); + semaphore.acquireUninterruptibly(); + image.getSource().startProduction(new ImageConsumer() { + BufferedImage bi; + int frameCtr = 0; + + @Override + public void setDimensions(int width, int height) { + bi = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + } + + @Override + public void setProperties(Hashtable props) {} + + @Override + public void setColorModel(ColorModel model) {} + + @Override + public void setHints(int hintflags) {} + + @Override + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int off, + int scansize) { + try { + final int yMax = y + h; + final int xMax = x + w; + + IndexColorModel icm = (IndexColorModel) model; + int[] colorModelRGBs = new int[icm.getMapSize()]; + icm.getRGBs(colorModelRGBs); + int[] argbRow = new int[bi.getWidth()]; + + for (int y_ = y; y_ < yMax; y_++) { + int i = y_ * scansize + off; + for (int x_ = x; x_ < xMax; x_++, i++) { + int pixel = pixels[i] & 0xff; + argbRow[x_ - x] = colorModelRGBs[pixel]; + } + bi.getRaster().setDataElements(x, y_, w, 1, argbRow); + } + } catch (RuntimeException e) { + // we don't expect this to happen, but if something goes + // wrong nobody else will print our stacktrace for us: + e.printStackTrace(); + throw e; + } + } + + @Override + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int off, + int scansize) {} + + @Override + public void imageComplete(int status) { + try { + frameCtr++; + if (frameCtr == frameIndex + 1) { + returnValue.set(bi); + semaphore.release(); + // if we don't detach this consumer the producer will + // loop forever + image.getSource().removeConsumer(this); + image.flush(); + } + } catch(Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + }); + + semaphore.acquireUninterruptibly(); + + return returnValue.get(); + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive32int.java b/test/jdk/sun/awt/image/gif/GifEmptyBackgroundTest.java similarity index 58% rename from test/micro/org/openjdk/bench/valhalla/array/read/Primitive32int.java rename to test/jdk/sun/awt/image/gif/GifEmptyBackgroundTest.java index 3f185b86d05..3adc2faa387 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive32int.java +++ b/test/jdk/sun/awt/image/gif/GifEmptyBackgroundTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,25 +20,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.read; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive32int extends PrimitiveStates { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void consume_int(int v) { - } +/* + * @test + * @bug 8356137 + * @summary This test verifies a non-zero transparent pixel in gifs works when + * the disposal method changes from 2 to 1 + */ - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p32int_read(Primitive32int st) { - int[] values = st.arr; - for (int i = 0; i < values.length; i++) { - consume_int(values[i]); - } +public class GifEmptyBackgroundTest { + public static void main(String[] args) throws Throwable { + GifBuilder.test( + new GifBuilder.FrameDescription( + GifBuilder.Disposal.restoreToBackgroundColor, false), + new GifBuilder.FrameDescription( + GifBuilder.Disposal.doNotDispose, false), + new GifBuilder.FrameDescription( + GifBuilder.Disposal.doNotDispose, false) ); } - } diff --git a/test/jdk/tools/jimage/ImageReaderDuplicateChildNodesTest.java b/test/jdk/tools/jimage/ImageReaderDuplicateChildNodesTest.java index bec32bee0f8..bf0855f273f 100644 --- a/test/jdk/tools/jimage/ImageReaderDuplicateChildNodesTest.java +++ b/test/jdk/tools/jimage/ImageReaderDuplicateChildNodesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -54,7 +54,7 @@ public static void main(final String[] args) throws Exception { System.out.println("Running test against image " + imagePath); final String integersParentResource = "/modules/java.base/java/lang"; final String integerResource = integersParentResource + "/Integer.class"; - try (final ImageReader reader = ImageReader.open(imagePath)) { + try (final ImageReader reader = ImageReader.open(imagePath, /* previewMode */ false)) { // find the child node/resource first final ImageReader.Node integerNode = reader.findNode(integerResource); if (integerNode == null) { @@ -68,17 +68,17 @@ public static void main(final String[] args) throws Exception { + " in " + imagePath); } // now verify that the parent node which is a directory, doesn't have duplicate children - final List children = parent.getChildren(); - if (children == null || children.isEmpty()) { + final List childNames = parent.getChildNames().toList(); + if (childNames.isEmpty()) { throw new RuntimeException("ImageReader did not return any child resources under " + integersParentResource + " in " + imagePath); } final Set uniqueChildren = new HashSet<>(); - for (final ImageReader.Node child : children) { - final boolean unique = uniqueChildren.add(child); + for (final String childName : childNames) { + final boolean unique = uniqueChildren.add(reader.findNode(childName)); if (!unique) { throw new RuntimeException("ImageReader returned duplicate child resource " - + child + " under " + parent + " from image " + imagePath); + + childName + " under " + parent + " from image " + imagePath); } } } diff --git a/test/micro/org/openjdk/bench/valhalla/types/ByInt.java b/test/jdk/tools/jlink/whitebox/ImageResourcesTreeTestDriver.java similarity index 72% rename from test/micro/org/openjdk/bench/valhalla/types/ByInt.java rename to test/jdk/tools/jlink/whitebox/ImageResourcesTreeTestDriver.java index 57f398c0c53..6c1d18d6d46 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/ByInt.java +++ b/test/jdk/tools/jlink/whitebox/ImageResourcesTreeTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,10 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; -public interface ByInt { - - public int intSum(); - -} +/* + * @test + * @summary Whitebox tests for ImageResourcesTree. + * @modules jdk.jlink/jdk.tools.jlink.internal + * @build jdk.jlink/jdk.tools.jlink.internal.ImageResourcesTreeTest + * @run junit/othervm jdk.jlink/jdk.tools.jlink.internal.ImageResourcesTreeTest + */ +public class ImageResourcesTreeTestDriver {} diff --git a/test/jdk/tools/jlink/whitebox/TEST.properties b/test/jdk/tools/jlink/whitebox/TEST.properties new file mode 100644 index 00000000000..35196da49bf --- /dev/null +++ b/test/jdk/tools/jlink/whitebox/TEST.properties @@ -0,0 +1,3 @@ +modules = \ + jdk.jlink/jdk.tools.jlink.internal +bootclasspath.dirs=. diff --git a/test/jdk/tools/jlink/whitebox/jdk.jlink/jdk/tools/jlink/internal/ImageResourcesTreeTest.java b/test/jdk/tools/jlink/whitebox/jdk.jlink/jdk/tools/jlink/internal/ImageResourcesTreeTest.java new file mode 100644 index 00000000000..bb38c93749c --- /dev/null +++ b/test/jdk/tools/jlink/whitebox/jdk.jlink/jdk/tools/jlink/internal/ImageResourcesTreeTest.java @@ -0,0 +1,275 @@ +/* + * 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. + * + * 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. + */ + +package jdk.tools.jlink.internal; + +import jdk.tools.jlink.internal.ImageResourcesTree.Node; +import jdk.tools.jlink.internal.ImageResourcesTree.PackageNode; +import jdk.tools.jlink.internal.ImageResourcesTree.PackageNode.PackageReference; +import jdk.tools.jlink.internal.ImageResourcesTree.ResourceNode; +import jdk.tools.jlink.internal.ImageResourcesTree.Tree; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ImageResourcesTreeTest { + + private static final String MODULES_PREFIX = "/modules/"; + private static final String PACKAGES_PREFIX = "/packages/"; + + // Package entry flags copied from ImageResourcesTree. + private static final int PKG_FLAG_HAS_NORMAL_CONTENT = 0x1; + private static final int PKG_FLAG_HAS_PREVIEW_CONTENT = 0x2; + private static final int PKG_FLAG_IS_PREVIEW_ONLY = 0x4; + + @Test + public void directoryNodes() { + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.base/java/util/SomeOtherClass.class", + "/java.base/java/util/resource.txt", + "/java.logging/java/util/logging/LoggingClass.class", + "/java.logging/java/util/logging/OtherLoggingClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + + // All paths from the root (but not the root itself). + assertTrue(nodes.containsKey("/modules")); + assertTrue(nodes.containsKey("/modules/java.base")); + assertTrue(nodes.containsKey("/modules/java.base/java")); + assertTrue(nodes.containsKey("/modules/java.base/java/util")); + assertFalse(nodes.containsKey("/")); + + // Check for mismatched modules. + assertTrue(nodes.containsKey("/modules/java.logging/java/util/logging")); + assertFalse(nodes.containsKey("/modules/java.base/java/util/logging")); + + Set dirPaths = nodes.keySet().stream() + .filter(p -> p.startsWith(MODULES_PREFIX)) + .collect(Collectors.toSet()); + for (String path : dirPaths) { + Node dir = nodes.get(path); + assertFalse(dir instanceof ResourceNode, "Unexpected resource: " + dir); + assertEquals(path, dir.getPath()); + assertTrue(path.endsWith("/" + dir.getName()), "Unexpected directory name: " + dir); + } + } + + @Test + public void resourceNodes() { + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.base/java/util/SomeOtherClass.class", + "/java.base/java/util/resource.txt", + "/java.logging/java/util/logging/LoggingClass.class", + "/java.logging/java/util/logging/OtherLoggingClass.class"); + + Tree tree = new Tree(paths); + // This map *does not* contain the resources, only the "directory" nodes. + Map nodes = tree.getMap(); + + assertContainsResources( + nodes.get("/modules/java.base/java/util"), + "SomeClass.class", "SomeOtherClass.class", "resource.txt"); + + assertContainsResources( + nodes.get("/modules/java.logging/java/util/logging"), + "LoggingClass.class", "OtherLoggingClass.class"); + } + + @Test + public void expectedPackages() { + // Paths are only to resources. Packages are inferred. + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.logging/java/util/logging/SomeClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + Node packages = nodes.get("/packages"); + List pkgNames = nodes.keySet().stream() + .filter(p -> p.startsWith(PACKAGES_PREFIX)) + .map(p -> p.substring(PACKAGES_PREFIX.length())) + .sorted() + .toList(); + + assertEquals(List.of("java", "java.util", "java.util.logging"), pkgNames); + for (String pkgName : pkgNames) { + PackageNode pkgNode = assertInstanceOf(PackageNode.class, packages.getChildren(pkgName)); + assertSame(nodes.get(PACKAGES_PREFIX + pkgNode.getName()), pkgNode); + } + } + + @Test + public void expectedPackageEntries() { + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.logging/java/util/logging/SomeClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + PackageNode pkgUtil = getPackageNode(nodes, "java.util"); + assertEquals(2, pkgUtil.moduleCount()); + List modRefs = pkgUtil.modules().toList(); + + List modNames = modRefs.stream().map(PackageReference::name).toList(); + assertEquals(List.of("java.base", "java.logging"), modNames); + + PackageReference baseRef = modRefs.get(0); + assertNonEmptyRef(baseRef, "java.base"); + assertEquals(PKG_FLAG_HAS_NORMAL_CONTENT, baseRef.flags()); + + PackageReference loggingRef = modRefs.get(1); + assertEmptyRef(loggingRef, "java.logging"); + assertEquals(0, loggingRef.flags()); + } + + @Test + public void expectedPackageEntries_withPreviewResources() { + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.base/java/util/OtherClass.class", + "/java.base/META-INF/preview/java/util/OtherClass.class", + "/java.logging/java/util/logging/SomeClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + PackageNode pkgUtil = getPackageNode(nodes, "java.util"); + List modRefs = pkgUtil.modules().toList(); + + PackageReference baseRef = modRefs.get(0); + assertNonEmptyRef(baseRef, "java.base"); + assertEquals(PKG_FLAG_HAS_NORMAL_CONTENT | PKG_FLAG_HAS_PREVIEW_CONTENT, baseRef.flags()); + } + + @Test + public void expectedPackageEntries_withPreviewOnlyPackages() { + List paths = List.of( + "/java.base/java/util/SomeClass.class", + "/java.base/META-INF/preview/java/util/preview/only/PreviewClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + + // Preview only package (with content). + PackageNode nonEmptyPkg = getPackageNode(nodes, "java.util.preview.only"); + PackageReference nonEmptyRef = nonEmptyPkg.modules().findFirst().orElseThrow(); + assertNonEmptyPreviewOnlyRef(nonEmptyRef, "java.base"); + assertEquals(PKG_FLAG_IS_PREVIEW_ONLY | PKG_FLAG_HAS_PREVIEW_CONTENT, nonEmptyRef.flags()); + + // Preview only packages can be empty. + PackageNode emptyPkg = getPackageNode(nodes, "java.util.preview"); + PackageReference emptyRef = emptyPkg.modules().findFirst().orElseThrow(); + assertEmptyPreviewOnlyRef(emptyRef, "java.base"); + assertEquals(PKG_FLAG_IS_PREVIEW_ONLY, emptyRef.flags()); + } + + @Test + public void expectedPackageEntries_sharedPackage() { + // Resource in many modules define the same package (java.shared). + // However, the package "java.shared" only has content in one module. + // Order of test data is shuffled to show reordering in entry list. + // "java.preview" would sort before after "java.resource" if it were + // only sorted by name, but the preview flag has precedence. + // Expect: content -> resource{1..6} -> preview{7..8} + List paths = List.of( + "/java.resource1/java/shared/one/SomeClass.class", + "/java.preview7/META-INF/preview/java/shared/foo/SomeClass.class", + "/java.resource3/java/shared/three/SomeClass.class", + "/java.resource6/java/shared/six/SomeClass.class", + "/java.preview8/META-INF/preview/java/shared/bar/SomeClass.class", + "/java.resource5/java/shared/five/SomeClass.class", + "/java.content/java/shared/MainPackageClass.class", + "/java.resource2/java/shared/two/SomeClass.class", + "/java.resource4/java/shared/four/SomeClass.class"); + + Tree tree = new Tree(paths); + Map nodes = tree.getMap(); + + // Preview only package (with content). + PackageNode sharedPkg = getPackageNode(nodes, "java.shared"); + assertEquals(9, sharedPkg.moduleCount()); + + List refs = sharedPkg.modules().toList(); + assertNonEmptyRef(refs.getFirst(), "java.content"); + assertEquals(PKG_FLAG_HAS_NORMAL_CONTENT, refs.getFirst().flags()); + + // Empty non-preview refs after non-empty ref. + int idx = 1; + for (PackageReference emptyRef : refs.subList(1, 7)) { + assertEmptyRef(emptyRef, "java.resource" + idx++); + assertEquals(0, emptyRef.flags()); + } + // Empty preview-only refs last. + for (PackageReference emptyRef : refs.subList(7, 9)) { + assertEmptyPreviewOnlyRef(emptyRef, "java.preview" + idx++); + assertEquals(PKG_FLAG_IS_PREVIEW_ONLY, emptyRef.flags()); + } + } + + static PackageNode getPackageNode(Map nodes, String pkgName) { + return assertInstanceOf(PackageNode.class, nodes.get(PACKAGES_PREFIX + pkgName)); + } + + static void assertContainsResources(Node dirNode, String... resourceNames) { + for (String name : resourceNames) { + Node node = assertInstanceOf(ResourceNode.class, dirNode.getChildren(name)); + assertEquals(name, node.getName()); + assertEquals(dirNode.getPath() + "/" + name, node.getPath()); + } + } + + static void assertNonEmptyRef(PackageReference ref, String modName) { + assertEquals(modName, ref.name(), "Unexpected module name: " + ref); + assertFalse(ref.isEmpty(), "Expected non-empty reference: " + ref); + assertFalse(ref.isPreviewOnly(), "Expected not preview-only: " + ref); + } + + static void assertEmptyRef(PackageReference ref, String modName) { + assertEquals(modName, ref.name(), "Unexpected module name: " + ref); + assertTrue(ref.isEmpty(), "Expected empty reference: " + ref); + assertFalse(ref.isPreviewOnly(), "Expected not preview-only: " + ref); + } + + static void assertNonEmptyPreviewOnlyRef(PackageReference ref, String modName) { + assertEquals(modName, ref.name(), "Unexpected module name: " + ref); + assertFalse(ref.isEmpty(), "Expected empty reference: " + ref); + assertTrue(ref.isPreviewOnly(), "Expected preview-only: " + ref); + } + + static void assertEmptyPreviewOnlyRef(PackageReference ref, String modName) { + assertEquals(modName, ref.name(), "Unexpected module name: " + ref); + assertTrue(ref.isEmpty(), "Expected empty reference: " + ref); + assertTrue(ref.isPreviewOnly(), "Expected preview-only: " + ref); + } +} diff --git a/test/jdk/tools/jpackage/macosx/MacSignTest.java b/test/jdk/tools/jpackage/macosx/MacSignTest.java index 7b2e06dc7ca..b6f3f91ff58 100644 --- a/test/jdk/tools/jpackage/macosx/MacSignTest.java +++ b/test/jdk/tools/jpackage/macosx/MacSignTest.java @@ -133,14 +133,20 @@ public static void testExpiredCertificate(PackageType type, SignOption... option } @Test - @Parameter({"IMAGE", "GOOD_SIGNING_KEY_USER_NAME"}) - @Parameter({"MAC_DMG", "GOOD_SIGNING_KEY_USER_NAME"}) - @Parameter({"MAC_PKG", "GOOD_SIGNING_KEY_USER_NAME_PKG", "GOOD_SIGNING_KEY_USER_NAME"}) - - @Parameter({"IMAGE", "GOOD_CODESIGN_SIGN_IDENTITY"}) - @Parameter({"MAC_PKG", "GOOD_CODESIGN_SIGN_IDENTITY", "GOOD_PKG_SIGN_IDENTITY"}) - @Parameter({"MAC_PKG", "GOOD_PKG_SIGN_IDENTITY"}) - public static void testMultipleCertificates(PackageType type, SignOption... options) { + // Case "--mac-signing-key-user-name": jpackage selects first certificate + // found with warning message. Certificate hash is pass to "codesign" in this + // case. + @Parameter({"IMAGE", "0", "GOOD_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_DMG", "0", "GOOD_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_PKG", "0", "GOOD_SIGNING_KEY_USER_NAME_PKG", "GOOD_SIGNING_KEY_USER_NAME"}) + + // Case "--mac-app-image-sign-identity": sign identity will be pass to + // "codesign" and "codesign" should fail due to multiple certificates with + // same common name found. + @Parameter({"IMAGE", "1", "GOOD_CODESIGN_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "1", "GOOD_CODESIGN_SIGN_IDENTITY", "GOOD_PKG_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "1", "GOOD_PKG_SIGN_IDENTITY"}) + public static void testMultipleCertificates(PackageType type, int jpackageExitCode, SignOption... options) { final var keychain = SigningBase.StandardKeychain.DUPLICATE.spec().keychain(); @@ -154,7 +160,7 @@ public static void testMultipleCertificates(PackageType type, SignOption... opti SignOption.configureOutputValidation(cmd, List.of(options), opt -> { return JPackageStringBundle.MAIN.cannedFormattedString("error.multiple.certs.found", opt.identityName(), keychain.name()); - }).execute(1); + }).execute(jpackageExitCode); }); } diff --git a/test/micro/org/openjdk/bench/valhalla/types/Complex.java b/test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java similarity index 80% rename from test/micro/org/openjdk/bench/valhalla/types/Complex.java rename to test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java index 013c5a1868c..364bc8bd3f2 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/Complex.java +++ b/test/jdk/tools/sincechecker/modules/jdk.editpad/JdkEditpadCheckSince.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,16 +20,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; -public interface Complex { - - double re(); - - double im(); - - Complex add(Complex that); - - Complex mul(Complex that); - -} +/* + * @test + * @bug 8346884 + * @summary Test for `@since` in jdk.editpad module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.editpad + */ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index d8782ee0029..e8b53568357 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -118,10 +118,9 @@ public Map call() { map.put("vm.jvmti", this::vmHasJVMTI); map.put("vm.cpu.features", this::cpuFeatures); map.put("vm.pageSize", this::vmPageSize); - map.put("vm.rtm.cpu", this::vmRTMCPU); - map.put("vm.rtm.compiler", this::vmRTMCompiler); // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", this::vmCDS); + map.put("vm.cds.default.archive.available", this::vmCDSDefaultArchiveAvailable); map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders); map.put("vm.cds.supports.aot.class.linking", this::vmCDSSupportsAOTClassLinking); map.put("vm.cds.supports.aot.code.caching", this::vmCDSSupportsAOTCodeCaching); @@ -418,28 +417,6 @@ protected String vmHasDTrace() { return "" + WB.isDTraceIncluded(); } - /** - * @return "true" if compiler in use supports RTM and "false" otherwise. - * Note: Lightweight locking does not support RTM (for now). - */ - protected String vmRTMCompiler() { - boolean isRTMCompiler = false; - - if (Compiler.isC2Enabled() && - (Platform.isX86() || Platform.isX64() || Platform.isPPC()) && - is_LM_LIGHTWEIGHT().equals("false")) { - isRTMCompiler = true; - } - return "" + isRTMCompiler; - } - - /** - * @return true if VM runs RTM supported CPU and false otherwise. - */ - protected String vmRTMCPU() { - return "" + CPUInfo.hasFeature("rtm"); - } - /** * Check for CDS support. * @@ -449,6 +426,16 @@ protected String vmCDS() { return "" + WB.isCDSIncluded(); } + /** + * Check for CDS default archive existence. + * + * @return true if CDS default archive classes.jsa exists in the JDK to be tested. + */ + protected String vmCDSDefaultArchiveAvailable() { + Path archive = Paths.get(System.getProperty("java.home"), "lib", "server", "classes.jsa"); + return "" + ("true".equals(vmCDS()) && Files.exists(archive)); + } + /** * Check for CDS support for custom loaders. * @@ -533,34 +520,6 @@ protected String vmPageSize() { return "" + WB.getVMPageSize(); } - /** - * @return LockingMode. - */ - protected String vmLockingMode() { - return "" + WB.getIntVMFlag("LockingMode"); - } - - /** - * @return "true" if LockingMode == 0 (LM_MONITOR) - */ - protected String is_LM_MONITOR() { - return "" + vmLockingMode().equals("0"); - } - - /** - * @return "true" if LockingMode == 1 (LM_LEGACY) - */ - protected String is_LM_LEGACY() { - return "" + vmLockingMode().equals("1"); - } - - /** - * @return "true" if LockingMode == 2 (LM_LIGHTWEIGHT) - */ - protected String is_LM_LIGHTWEIGHT() { - return "" + vmLockingMode().equals("2"); - } - /** * Check if Graal is used as JIT compiler. * diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index da7149cf6a9..8b2eb6122b5 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -62,6 +62,10 @@ tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java tools/javac/warnings/suppress/TypeAnnotations.java 8057683 generic-all improve ordering of errors with type annotations tools/javac/modules/SourceInSymlinkTest.java 8180263 windows-all fails when run on a subst drive +tools/javac/flags/ExtendedStandardFlagsOverlayFlagsConflict.java 8368078 generic-all +tools/javac/ObjectEarlyContext/T8361481.java 8368076 generic-all +tools/javac/processing/model/element/TestValueClasses.java 8368081 generic-all + ########################################################################### # # javap diff --git a/test/langtools/jdk/javadoc/doclet/testDuplicateMethodsWarn/TestDuplicateMethods.java b/test/langtools/jdk/javadoc/doclet/testDuplicateMethodsWarn/TestDuplicateMethods.java new file mode 100644 index 00000000000..7e191290f8a --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testDuplicateMethodsWarn/TestDuplicateMethods.java @@ -0,0 +1,220 @@ +/* + * 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. + * + * 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 + * @bug 8177100 + * @summary Test to check for duplicate methods across different inheritance patterns + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestDuplicateMethods + */ + +import java.io.IOException; +import java.nio.file.Path; + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +public class TestDuplicateMethods extends JavadocTester { + + public static void main(String... args) throws Exception { + var tester = new TestDuplicateMethods(); + tester.runTests(); + } + + ToolBox tb = new ToolBox(); + Path src = Path.of("src"); + + + TestDuplicateMethods() throws IOException { + // Diamond class inheritance + tb.writeJavaFiles(src, """ + package p; + interface A { + /** + * JavaDoc for method in interface A. + */ + abstract void testA( ); + }""", """ + package p; + interface B extends A { + /** + * JavaDoc for method in interface B. + */ + abstract void testB( ); + }""", """ + package p; + abstract class C implements A { + /** + * Inherited JavaDoc for method in class C. + */ + public final void testA( ) { + // Do nothing. + } + }""",""" + package p; + public final class D extends C implements B { + /** + * Inherited JavaDoc. + */ + public final void testB() { + // Do nothing. + } + } + """); + + // Mirrors the implementation of StringBuilder + tb.writeJavaFiles(src, + """ + package sb; + public interface I { + /** + * JavaDoc for method in public interface I. + */ + void testI(); + } + """, """ + package sb; + abstract class P implements I { + /** + * Inherited JavaDoc for method in class P. + */ + public final void testI() { + // Do nothing. + } + } + """, """ + package sb; + public class U extends P implements I { + // No overrides + } + """ + ); + + // Mirrors the implementation of HashMap + tb.writeJavaFiles(src, + """ + package hm; + public interface J { + /** + * JavaDoc for method in public interface J. + */ + void testJ(); + } + """, + """ + package hm; + public abstract class PubJ implements J { + /** + * Inherited JavaDoc for method in public abstract class PubJ. + */ + public final void testJ() { + // Do nothing. + } + } + """, + """ + package hm; + public class V extends PubJ implements J { + // No override + } + """ + ); + } + + @Test + public void testDiamondInheritance(Path base) { + javadoc("-d", base.resolve("out").toString(), + "-sourcepath", src.toString(), + "p"); + checkExit(Exit.OK); + checkOutput("p/D.html", true, + """ +

          Inherited JavaDoc for method in class C.
          + """, """ +
          public final void testA()
          +
          Inherited JavaDoc for method in class C.
          + """ + ); + + checkOutput("p/D.html", false, """ +
          JavaDoc for method in Interface A.
          """, """ +
          void testA()
          +
          JavaDoc for method in Interface A.
          """); + + + checkOutput("p/D.html", false, + """ +
          JavaDoc for method in interface A.
          + """); + } + + @Test + public void testStringBuilderInheritance(Path base) { + javadoc("-d", base.resolve("out").toString(), + "-sourcepath", src.toString(), + "sb"); + checkExit(Exit.OK); + + checkOutput("sb/U.html", false, + """ +
          +

          Methods inherited from interface I

          + testI
          + """); + + checkOutput("sb/U.html", true, + """ +

          testI

          +
          +
          public final void testI()
          +
          Inherited JavaDoc for method in class P.
          +
          +
          Specified by:
          +
          testI in interface I
          +
          """); + } + + @Test + public void testHashMapInheritance(Path base) { + javadoc("-d", base.resolve("out").toString(), + "-sourcepath", src.toString(), + "hm"); + checkExit(Exit.OK); + + checkOutput("hm/V.html", false, + """ +
          +

          Methods inherited from interface J

          + testJ
          """); + + checkOutput("hm/V.html", true, + """ +
          +

          Methods inherited from class PubJ

          + testJ
          + """); + } +} diff --git a/test/langtools/jdk/jshell/InputUITest.java b/test/langtools/jdk/jshell/InputUITest.java index d46c88aa797..9df0597390c 100644 --- a/test/langtools/jdk/jshell/InputUITest.java +++ b/test/langtools/jdk/jshell/InputUITest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8356165 + * @bug 8356165 8358552 * @summary Check user input works properly * @modules * jdk.compiler/com.sun.tools.javac.api @@ -38,6 +38,7 @@ * @run testng/othervm -Dstderr.encoding=UTF-8 -Dstdin.encoding=UTF-8 -Dstdout.encoding=UTF-8 InputUITest */ +import java.util.Map; import java.util.function.Function; import org.testng.annotations.Test; @@ -67,4 +68,33 @@ public void testUserInputWithSurrogates() throws Exception { }, false); } + public void testCloseInputSinkWhileReadingUserInputSimulatingCtrlD() throws Exception { + var snippets = Map.of( + "System.in.read()", " ==> -1", + "System.console().reader().read()", " ==> -1", + "System.console().readLine()", " ==> null", + "System.console().readPassword()", " ==> null", + "IO.readln()", " ==> null", + "System.in.readAllBytes()", " ==> byte[0] { }" + ); + for (var snippet : snippets.entrySet()) { + doRunTest((inputSink, out) -> { + inputSink.write(snippet.getKey() + "\n" + CTRL_D); + waitOutput(out, patternQuote(snippet.getValue()), patternQuote("EndOfFileException")); + }, false); + } + } + + public void testUserInputWithCtrlDAndMultipleSnippets() throws Exception { + doRunTest((inputSink, out) -> { + inputSink.write("IO.readln()\n" + CTRL_D); + waitOutput(out, patternQuote("==> null")); + inputSink.write("IO.readln()\nAB\n"); + waitOutput(out, patternQuote("==> \"AB\"")); + inputSink.write("System.in.read()\n" + CTRL_D); + waitOutput(out, patternQuote("==> -1")); + inputSink.write("System.in.read()\nA\n"); + waitOutput(out, patternQuote("==> 65")); + }, false); + } } \ No newline at end of file diff --git a/test/langtools/jdk/jshell/UITesting.java b/test/langtools/jdk/jshell/UITesting.java index 70a1b12a943..cc821b1874b 100644 --- a/test/langtools/jdk/jshell/UITesting.java +++ b/test/langtools/jdk/jshell/UITesting.java @@ -52,6 +52,7 @@ public class UITesting { protected static final String REDRAW_PROMPT = "\n\r?" + PROMPT; protected static final String UP = "\033[A"; protected static final String DOWN = "\033[B"; + protected static final String CTRL_D = "\u0004"; private final boolean laxLineEndings; public UITesting() { @@ -106,11 +107,19 @@ protected void doRunTest(Test test, boolean setUserInput) throws Exception { }); Writer inputSink = new OutputStreamWriter(input.createOutput(), StandardCharsets.UTF_8) { + boolean closed = false; @Override public void write(String str) throws IOException { + if (closed) return; // prevents exception thrown due to closed writer super.write(str); flush(); } + + @Override + public void close() throws IOException { + super.close(); + closed = true; + } }; runner.start(); diff --git a/test/langtools/tools/javac/NoTypeIntersectionASTAfterTransTypesTest.java b/test/langtools/tools/javac/NoTypeIntersectionASTAfterTransTypesTest.java new file mode 100644 index 00000000000..d7f2b7325c5 --- /dev/null +++ b/test/langtools/tools/javac/NoTypeIntersectionASTAfterTransTypesTest.java @@ -0,0 +1,94 @@ +/* + * 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. + * + * 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 + * @bug 8361499 + * @summary intersection type cast causes javac crash with -Xjcov + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask NoTypeIntersectionASTAfterTransTypesTest + * @run main NoTypeIntersectionASTAfterTransTypesTest + */ + +import java.util.List; +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.TransTypes; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCTypeIntersection; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; + +import toolbox.ToolBox; + +public class NoTypeIntersectionASTAfterTransTypesTest { + public static void main(String... args) { + new NoTypeIntersectionASTAfterTransTypesTest().run(); + } + + void run() { + String code = + """ + class Test { + interface I {} + void test() { + Runnable r1 = (Runnable & I)() -> {}; + Runnable r2 = (I & Runnable)() -> {}; + } + } + """; + Context ctx = new Context(); + MyTransTypes.preRegister(ctx); + JavacTask task = JavacTool.create().getTask(null, null, null, null, null, List.of(new ToolBox.JavaSource(code)), ctx); + if (!task.call()) { + throw new AssertionError("test failed due to a compilation error"); + } + } + + static class MyTransTypes extends TransTypes { + public static void preRegister(Context ctx) { + ctx.put(transTypesKey, new Factory() { + @Override + public TransTypes make(Context c) { + return new MyTransTypes(c); + } + }); + } + public MyTransTypes(Context context) { + super(context); + } + @Override + public void visitTypeIntersection(JCTypeIntersection tree) { + super.visitTypeIntersection(tree); + // after the invocation to the method in the super class the JCTypeIntersection should have been lowered + if (result instanceof JCTypeIntersection) { + throw new AssertionError("there are unexpected type intersection ASTs"); + } + } + } +} diff --git a/test/langtools/tools/javac/ObjectEarlyContext/T8361481.java b/test/langtools/tools/javac/ObjectEarlyContext/T8361481.java new file mode 100644 index 00000000000..16eb11ee449 --- /dev/null +++ b/test/langtools/tools/javac/ObjectEarlyContext/T8361481.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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 + * @bug 8361481 + * @modules jdk.compiler + * @summary Flexible Constructor Bodies generates a compilation error when compiling a user supplied java.lang.Object class + */ + +import java.io.*; +import java.util.*; + +public class T8361481 { + static String testSrc = System.getProperty("test.src", "."); + + public static void main(String... args) throws Exception { + new T8361481().run(); + } + + public void run() throws Exception { + // compile modified Object.java, using patch-module to avoid errors + File x = new File(testSrc, "x"); + String[] jcArgs = { "-d", ".", "--patch-module", "java.base=" + x.getAbsolutePath(), + new File(new File(new File(x, "java"), "lang"), "Object.java").getPath()}; + compile(jcArgs); + } + + void compile(String... args) { + int rc = com.sun.tools.javac.Main.compile(args); + if (rc != 0) + throw new Error("javac failed: " + Arrays.asList(args) + ": " + rc); + } +} + diff --git a/test/micro/org/openjdk/bench/valhalla/types/ByLong.java b/test/langtools/tools/javac/ObjectEarlyContext/x/java/lang/Object.java similarity index 82% rename from test/micro/org/openjdk/bench/valhalla/types/ByLong.java rename to test/langtools/tools/javac/ObjectEarlyContext/x/java/lang/Object.java index f69bd23be10..0a68e1cccb6 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/ByLong.java +++ b/test/langtools/tools/javac/ObjectEarlyContext/x/java/lang/Object.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,10 +20,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; -public interface ByLong { +package java.lang; - public long longSum(); +public class Object { + public Object() { + foo(); // valid, not in early constructor context + } + void foo() { } } diff --git a/test/langtools/tools/javac/SuperInit/SuperInitFails.java b/test/langtools/tools/javac/SuperInit/SuperInitFails.java index 320514b2b66..6ba6f8edf89 100644 --- a/test/langtools/tools/javac/SuperInit/SuperInitFails.java +++ b/test/langtools/tools/javac/SuperInit/SuperInitFails.java @@ -192,9 +192,9 @@ public SuperInitFails(double[][] x) { SuperInitFails(short[][] ignore) { int i = new SuperInitFails(){ void foo() { - System.err.println(xx); // this should fail + System.err.println(xx); // this one is OK, reading field `xx` in the anonymous class } - }.xx; // this one is OK though + }.xx; // this one is OK too, field of a fully constructed class super(null); } diff --git a/test/langtools/tools/javac/SuperInit/SuperInitFails.out b/test/langtools/tools/javac/SuperInit/SuperInitFails.out index c01e2f1b2cd..f93d5592854 100644 --- a/test/langtools/tools/javac/SuperInit/SuperInitFails.out +++ b/test/langtools/tools/javac/SuperInit/SuperInitFails.out @@ -18,7 +18,6 @@ SuperInitFails.java:172:17: compiler.err.cant.ref.before.ctor.called: x SuperInitFails.java:176:24: compiler.err.cant.ref.before.ctor.called: x SuperInitFails.java:180:18: compiler.err.cant.ref.before.ctor.called: x SuperInitFails.java:186:32: compiler.err.cant.ref.before.ctor.called: x -SuperInitFails.java:195:36: compiler.err.cant.ref.before.ctor.called: xx SuperInitFails.java:206:25: compiler.err.return.before.superclass.initialized SuperInitFails.java:211:33: compiler.err.ctor.calls.not.allowed.here SuperInitFails.java:216:29: compiler.err.redundant.superclass.init @@ -34,4 +33,4 @@ SuperInitFails.java:53:32: compiler.err.call.must.only.appear.in.ctor SuperInitFails.java:83:18: compiler.err.ctor.calls.not.allowed.here SuperInitFails.java:89:13: compiler.err.return.before.superclass.initialized SuperInitFails.java:150:18: compiler.err.call.must.only.appear.in.ctor -36 errors +35 errors diff --git a/test/langtools/tools/javac/SuperInit/SuperInitGood.java b/test/langtools/tools/javac/SuperInit/SuperInitGood.java index 5952ecc6615..9898adf9cb5 100644 --- a/test/langtools/tools/javac/SuperInit/SuperInitGood.java +++ b/test/langtools/tools/javac/SuperInit/SuperInitGood.java @@ -512,6 +512,20 @@ class Sub extends Test24 { } } + public static class Test25 { + public Test25(Object o) {} + + class Sub extends Test25 { + public Sub() { + super(new Object() { + void foo() { + getClass(); + } + }); + } + } + } + public static void main(String[] args) { new Test0(); new Test1(); @@ -559,5 +573,6 @@ public static void main(String[] args) { new Test22('x'); new Test23(); new Test24(); + new Test25(null); } } diff --git a/test/micro/org/openjdk/bench/valhalla/types/R64long.java b/test/langtools/tools/javac/T8357472.java similarity index 66% rename from test/micro/org/openjdk/bench/valhalla/types/R64long.java rename to test/langtools/tools/javac/T8357472.java index adcad6f8df9..5a2486ba29f 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/R64long.java +++ b/test/langtools/tools/javac/T8357472.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,28 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.types; -public class R64long extends A64long { - - public final long v0; - - public R64long(long v0) { - this.v0 = v0; - } - - @Override - public long longValue() { - return v0; - } +/* + * @test + * @bug 8357472 + * @summary NPE in Types.containsType for type variable used as a qualifier + * @compile T8357472.java + */ - @Override - public int intValue() { - return (int) v0; - } +class T8357472 { + class A { + protected class B {} - @Override - public long longSum() { - return v0; + public static > void f(Object g) { + @SuppressWarnings("unchecked") + M.B mapping = (M.B) g; + M.B[] mapping2 = new M.B[1]; + mapping2[0] = mapping; + } } } diff --git a/test/langtools/tools/javac/T8357653.java b/test/langtools/tools/javac/T8357653.java new file mode 100644 index 00000000000..d74ffdb21f5 --- /dev/null +++ b/test/langtools/tools/javac/T8357653.java @@ -0,0 +1,281 @@ +/* + * 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. + * + * 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 + * @bug 8357653 + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * @summary Inner classes of type parameters emitted as raw types in signatures + * @build toolbox.ToolBox toolbox.JavapTask + * @run main T8357653 + */ +import toolbox.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Gatherers; +import java.util.stream.Stream; + +public class T8357653 extends TestRunner { + private ToolBox tb; + + public static void main(String... args) throws Exception { + new T8357653().runTests(); + } + + T8357653() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testCompilation(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + public class Test { + static abstract class Getters { + abstract class Getter { + abstract X get(); + } + } + + static class Usage1> { + public T test(G.Getter getter) { + return getter.get(); + } + } + + static class Usage2, G extends U> { + public T test(G.Getter getter) { + return getter.get(); + } + } + + static class Usage3> { + public T test(G.Getter getter) { + return getter.get(); + } + } + + class G2 extends Getters {} + static class Usage4> { + M test(L.Getter getter) { + return getter.get(); + } + } + } + """); + + Files.createDirectories(classes); + + { + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + } + } + + @Test + public void testCompilationArray(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + public class Test { + static abstract class Getters { + abstract class Getter { + abstract X get(); + } + } + + static class Usage1> { + public T test(G.Getter[] getter) { + return getter[0].get(); + } + } + + static class Usage2, G extends U> { + public T test(G.Getter[] getter) { + return getter[0].get(); + } + } + + static class Usage3> { + public T test(G.Getter[] getter) { + return getter[0].get(); + } + } + + class G2 extends Getters {} + static class Usage4> { + M test(L.Getter[] getter) { + return getter[0].get(); + } + } + } + """); + + Files.createDirectories(classes); + + { + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + } + } + + @Test + public void testErasureViaJavap(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + public class Test { + static abstract class Getters { + abstract class Getter { + abstract X get(); + } + } + + static class Usage1> { + public T test(G.Getter getter) { + return getter.get(); + } + } + } + """); + + Files.createDirectories(classes); + + { + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + String javapOut = new JavapTask(tb) + .options("-v") + .classpath(classes.toString()) + .classes("test.Test$Usage1") + .run() + .getOutput(Task.OutputKind.DIRECT); + + if (!javapOut.contains("Signature: #21 // ;>Ljava/lang/Object;")) + throw new AssertionError("Wrongly erased generated signature:\n" + javapOut); + } + } + + @Test + public void testGenericsViaReflection(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import java.lang.reflect.*; + import java.util.Arrays; + + public class Test { + public static void main(String[] args) throws Throwable { + new test.Test().test(); + } + + public void test() throws Throwable { + var m = getClass().getDeclaredMethod("getOwner", Test.Base.Handler.class); + System.out.println(m); + System.out.println(Arrays.toString(m.getGenericParameterTypes())); + System.out.println(m.getGenericReturnType()); + } + + > S getOwner(S.Handler handler) { + return handler.owner(); + } + + abstract class Base> { + class Handler { + @SuppressWarnings("unchecked") + S owner() { + return (S) Base.this; + } + } + } + } + """); + + Files.createDirectories(classes); + + { + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + var out = new JavaTask(tb) + .classpath(classes.toString()) + .className("test.Test") + .run() + .writeAll() + .getOutput(Task.OutputKind.STDOUT); + + var expectedOut = """ + test.Test$Base test.Test.getOwner(test.Test$Base$Handler) + [test.Test$Base$Handler] + S + """; + + containsOrdered(out, expectedOut, "Wrongly erased generated signature:\n"); + } + } + + private static void containsOrdered(String expected, String actual, String message) { + List expectedLines = expected.lines().map(s -> s.strip()).toList(); + Stream actualLines = actual.lines().map(s -> s.strip()); + + if (!actualLines.gather(Gatherers.windowSliding(expectedLines.size())).anyMatch(window -> window.equals(expectedLines))) + throw new AssertionError(message + actual); + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Primitive32.java b/test/langtools/tools/javac/T8357653b.java similarity index 64% rename from test/micro/org/openjdk/bench/valhalla/array/set/Primitive32.java rename to test/langtools/tools/javac/T8357653b.java index cfa5d46f132..527c09ca0bd 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Primitive32.java +++ b/test/langtools/tools/javac/T8357653b.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,21 +20,30 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.set; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive32 extends PrimitiveStates { +/* + * @test + * @bug 8357653 + * @summary Inner classes of type parameters emitted as raw types in signatures + * @compile T8357653b.java + */ - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void set(Primitive32int st) { - int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; +class T8357653b { + class A { + class B { + public T rett() { return null; } } } + class C extends A { + static class D { + { + B b = null; + String s = b.rett(); + + B[] b2 = new B[1]; + String s2 = b2[0].rett(); + } + } + } } diff --git a/test/langtools/tools/javac/flags/ExtendedStandardFlagsOverlayFlagsConflict.java b/test/langtools/tools/javac/flags/ExtendedStandardFlagsOverlayFlagsConflict.java new file mode 100644 index 00000000000..88eeb6165e4 --- /dev/null +++ b/test/langtools/tools/javac/flags/ExtendedStandardFlagsOverlayFlagsConflict.java @@ -0,0 +1,82 @@ +/* + * 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. + * + * 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 + * @bug 8361570 + * @summary Verify no flags in ExtendedStandardFlags have overlays for different + * Symbol kinds. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.code + * @compile ExtendedStandardFlagsOverlayFlagsConflict.java + * @run main ExtendedStandardFlagsOverlayFlagsConflict + */ + +import com.sun.tools.javac.code.Flags; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* Flags in ExtendedStandardFlags are checked using masks, and if they have + * Symbol-kind specific meaning, they can lead to confusing errors. Hence, + * Flags in ExtendedStandardFlags should have the same meaning for all Symbols. + */ +public class ExtendedStandardFlagsOverlayFlagsConflict { + + public static void main(String... args) throws Exception { + ExtendedStandardFlagsOverlayFlagsConflict t = + new ExtendedStandardFlagsOverlayFlagsConflict(); + t.run(); + } + + public void run() throws Exception { + Map> value2FlagFields = new HashMap<>(); + + for (Field f : Flags.class.getFields()) { + if (!Modifier.isStatic(f.getModifiers())) { + continue; + } + if (f.getName().startsWith("ACC_")) { + continue; + } + long flag = ((Number) f.get(null)).longValue(); + value2FlagFields.computeIfAbsent(flag, _ -> new ArrayList<>()) + .add(f); + } + + long pendingFlags2Check = Flags.ExtendedStandardFlags; + + while (pendingFlags2Check != 0) { + long flag = Long.highestOneBit(pendingFlags2Check); + List flagFields = value2FlagFields.get(flag); + if (flagFields.size() != 1) { + throw new AssertionError("Flag: " + flag + + " has more than one flag field: " + flagFields); + } + pendingFlags2Check &= ~flag; + } + } +} diff --git a/test/langtools/tools/javac/flags/NoFalseSealedError.java b/test/langtools/tools/javac/flags/NoFalseSealedError.java new file mode 100644 index 00000000000..d7832576ea9 --- /dev/null +++ b/test/langtools/tools/javac/flags/NoFalseSealedError.java @@ -0,0 +1,21 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8361570 + * @summary Verify there's no fake sealed not allowed here error when sealed + * and requires-identity Flags clash + * @modules java.base/jdk.internal + * @compile NoFalseSealedError.java + */ + +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +void main(String[] args) { + new RequiresIdentity(null) {}; + new WeakReference<>(null) {}; + new WeakHashMap<>() {}; +} + +static class RequiresIdentity { + RequiresIdentity(@jdk.internal.RequiresIdentity Object o) {} +} diff --git a/test/jdk/java/awt/applet/Applet/HeadlessApplet.java b/test/langtools/tools/javac/generics/diamond/AnonymousLabeledAsAbstractTest.java similarity index 57% rename from test/jdk/java/awt/applet/Applet/HeadlessApplet.java rename to test/langtools/tools/javac/generics/diamond/AnonymousLabeledAsAbstractTest.java index c258e080a22..54c464cc464 100644 --- a/test/jdk/java/awt/applet/Applet/HeadlessApplet.java +++ b/test/langtools/tools/javac/generics/diamond/AnonymousLabeledAsAbstractTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,29 +21,24 @@ * questions. */ -import java.applet.Applet; -import java.awt.HeadlessException; - /* * @test - * @summary Check HeadlessException occurrence when trying to create Applet - * in headless mode - * @run main/othervm -Djava.awt.headless=true HeadlessApplet + * @bug 8361214 + * @summary An anonymous class is erroneously being classify as an abstract class + * @compile AnonymousLabeledAsAbstractTest.java */ -public class HeadlessApplet { - - public static void main(String args[]) { - boolean noExceptions = true; - - try { - Applet a = new Applet(); - } catch (HeadlessException e) { - noExceptions = false; - } - - if (noExceptions) { - throw new RuntimeException("No HeadlessException occured when creating Applet in headless mode"); - } +class AnonymousLabeledAsAbstractTest { + abstract class Base {} + abstract class Derived1 extends Base {} + abstract class Derived2 extends Base { + Derived2(Derived1 obj){} + } + abstract class Derived3 extends Base { + Derived3(Derived2 obj){} } + + Base obj = new Derived2<>(new Derived1<>(){}){}; + Base obj2 = new Derived3(new Derived2<>(new Derived1<>(){}){}){}; + Base obj3 = new Derived3<>(new Derived2<>(new Derived1<>(){}){}){}; } diff --git a/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java b/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java index b905dedf327..0f5a117b509 100644 --- a/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java +++ b/test/langtools/tools/javac/jvm/ClassRefDupInConstantPoolTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -25,7 +25,7 @@ * @test * @bug 8015927 * @summary Class reference duplicates in constant pool - * @clean ClassRefDupInConstantPoolTest$Duplicates + * @clean ClassRefDupInConstantPoolTest ClassRefDupInConstantPoolTest$Duplicates * @run main ClassRefDupInConstantPoolTest */ diff --git a/src/java.desktop/share/classes/java/applet/package-info.java b/test/langtools/tools/javac/lint/LintOptions.java similarity index 52% rename from src/java.desktop/share/classes/java/applet/package-info.java rename to test/langtools/tools/javac/lint/LintOptions.java index 492edbcff08..10def72a31a 100644 --- a/src/java.desktop/share/classes/java/applet/package-info.java +++ b/test/langtools/tools/javac/lint/LintOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,25 +23,16 @@ * questions. */ -/** - * Provides the classes necessary to create an applet and the classes an applet - * uses to communicate with its applet context. - *

          - * The applet framework involves two entities: the applet and the - * applet context. An applet is an embeddable window (see the Panel - * class) with a few extra methods that the applet context can use to - * initialize, start, and stop the applet. - *

          - * The applet context is an application that is responsible for loading and - * running applets. For example, the applet context could be a Web browser or an - * applet development environment. - *

          - * This package has been deprecated and may be removed in - * a future version of the Java Platform. There is no replacement. - * All of the classes and interfaces in this package have been terminally - * deprecated. - * Users are advised to migrate their applications to other technologies. - * - * @since 1.0 +/* + * @test + * @bug 8359596 + * @summary Verify behavior when both "-Xlint:options" and "-Xlint:-options" are given + * @compile/fail/ref=LintOptions.out -Werror -XDrawDiagnostics -source 21 -target 21 LintOptions.java + * @compile/fail/ref=LintOptions.out -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:-options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options -Xlint:-options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:none LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options -Xlint:none LintOptions.java */ -package java.applet; +class LintOptions { +} diff --git a/test/langtools/tools/javac/lint/LintOptions.out b/test/langtools/tools/javac/lint/LintOptions.out new file mode 100644 index 00000000000..020c626ee5c --- /dev/null +++ b/test/langtools/tools/javac/lint/LintOptions.out @@ -0,0 +1,4 @@ +- compiler.warn.source.no.system.modules.path: 21, (compiler.misc.source.no.system.modules.path.with.target: 21, 21) +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/test/langtools/tools/javac/options/system/SystemSunProprietary.java b/test/langtools/tools/javac/options/system/SystemSunProprietary.java index a057972d73d..fbc3fbb5ff3 100644 --- a/test/langtools/tools/javac/options/system/SystemSunProprietary.java +++ b/test/langtools/tools/javac/options/system/SystemSunProprietary.java @@ -41,6 +41,10 @@ import toolbox.TestRunner; import toolbox.ToolBox; +import javax.tools.Diagnostic; +import javax.tools.Diagnostic.Kind; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -48,6 +52,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; public class SystemSunProprietary extends TestRunner { @@ -110,28 +115,34 @@ private void expectNoSunapi(boolean ignoreSymbolFile, String... options) throws private void expectSunapi(boolean expectDiagnostic, boolean ignoreSymbolFile, String... options) throws IOException { - List expected = - expectDiagnostic - ? List.of( - "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe", - "1 warning") - : List.of(""); List allOptions = new ArrayList<>(); allOptions.add("-XDrawDiagnostics"); Collections.addAll(allOptions, options); JavacFileManager fm = new JavacFileManager(new Context(), false, null); fm.setSymbolFileEnabled(!ignoreSymbolFile); - List log = - new JavacTask(tb) - .fileManager(fm) - .options(allOptions) - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Expect.SUCCESS) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - if (!log.equals(expected)) { - throw new AssertionError("expected: " + expected + "\nactual: " + log + "\n"); + new JavacTask(tb) + .fileManager(fm) + .options(allOptions) + .diagnosticListener(d -> sunAPIWarningChecker(d, expectDiagnostic)) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Expect.SUCCESS) + .writeAll(); + } + + void sunAPIWarningChecker(Diagnostic diag, boolean expectDiagnostic) { + if (!expectDiagnostic) { + throw new AssertionError("Unexpected diagnostic: " + diag.getMessage(Locale.getDefault())); + } else { + if (diag.getKind() != Kind.WARNING) { + throw new AssertionError("Bad diagnostic kind. Expected " + Kind.WARNING + ", found: " + diag.getKind() + "\n"); + } + if (!diag.getCode().equals("compiler.warn.sun.proprietary")) { + throw new AssertionError("Bad diagnostic code. Expected \"compiler.warn.sun.proprietary\", found: " + diag.getCode() + "\n"); + } + if (diag.getLineNumber() != 1 || diag.getColumnNumber() != 43) { + throw new AssertionError("Bad diagnostic position. Expected 1:43, found: " + diag.getLineNumber() + ":" + diag.getColumnNumber() + "\n"); + } } } diff --git a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfBytecodeTest.java b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfBytecodeTest.java new file mode 100644 index 00000000000..ba9cb1aa533 --- /dev/null +++ b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfBytecodeTest.java @@ -0,0 +1,83 @@ +/* + * 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. + * + * 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.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.instruction.LoadInstruction; +import java.lang.classfile.instruction.StoreInstruction; +import java.util.BitSet; +import java.util.Map; + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/* + * @test + * @bug 8357185 + * @enablePreview + * @summary No unused local variable in unconditionally exact primitive patterns + * @library /test/lib + * @run junit PrimitiveInstanceOfBytecodeTest + */ +public class PrimitiveInstanceOfBytecodeTest { + + private static final String SOURCE = """ + public class Test { + public record A(int i) {} + public Integer get(A a) { + if (a instanceof A(int i)) { + return i; + } + return null; + } + } + """; + + @Test + public void testNoUnusedVarInRecordPattern() { + var testBytes = InMemoryJavaCompiler.compile(Map.of("Test", SOURCE)).get("Test"); + var code = ClassFile.of().parse(testBytes).methods().stream() + .filter(m -> m.methodName().equalsString("get")).findFirst() + .orElseThrow().findAttribute(Attributes.code()).orElseThrow(); + BitSet stores = new BitSet(code.maxLocals()); + BitSet loads = new BitSet(code.maxLocals()); + code.forEach(ce -> { + switch (ce) { + case StoreInstruction store -> stores.set(store.slot()); + case LoadInstruction load -> loads.set(load.slot()); + default -> {} + } + }); + // [this, a] are built-in locals that may be unused + loads.clear(0, 2); + stores.clear(0, 2); + if (!loads.equals(stores)) { + System.err.println("Loads: " + loads); + System.err.println("Stores: " + stores); + System.err.println(code.toDebugString()); + fail("Store and load mismatch, see stderr"); + } + } +} diff --git a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java index 5c6d3e6361d..1b6c3af5520 100644 --- a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java +++ b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8304487 8325257 8327683 8330387 + * @bug 8304487 8325257 8327683 8330387 8357185 * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview) * @enablePreview * @compile PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java @@ -52,6 +52,7 @@ public static void main(String[] args) { assertEquals(true, narrowingAndUnboxing()); assertEquals(true, patternExtractRecordComponent()); assertEquals(true, exprMethod()); + assertEquals(true, exprMethodSideEffect()); assertEquals(true, exprStaticallyQualified()); } @@ -173,6 +174,13 @@ public static boolean exprMethod() { return meth() instanceof int ii; } + static int sideEffect; + public static Integer methSideEffect() { sideEffect++; return 42;} + public static boolean exprMethodSideEffect() { + sideEffect = 5; + return methSideEffect() instanceof int ii && sideEffect == 6; + } + public class A1 { public static int i = 42; } diff --git a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java index 47686c98a42..afd0f77e7bf 100644 --- a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java +++ b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8304487 8325257 8327683 8330387 + * @bug 8304487 8325257 8327683 8330387 8357185 * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview) * @enablePreview * @compile PrimitiveInstanceOfTypeComparisonOp.java @@ -52,6 +52,7 @@ public static void main(String[] args) { assertEquals(true, narrowingAndUnboxing()); assertEquals(true, patternExtractRecordComponent()); assertEquals(true, exprMethod()); + assertEquals(true, exprMethodSideEffect()); assertEquals(true, exprStaticallyQualified()); } @@ -173,6 +174,13 @@ public static boolean exprMethod() { return meth() instanceof int; } + static int sideEffect; + public static Integer methSideEffect() { sideEffect++; return 42;} + public static boolean exprMethodSideEffect() { + sideEffect = 5; + return methSideEffect() instanceof int && sideEffect == 6; + } + public class A1 { public static int i = 42; } diff --git a/test/langtools/tools/javac/patterns/T8358801.java b/test/langtools/tools/javac/patterns/T8358801.java new file mode 100644 index 00000000000..11d51452aa1 --- /dev/null +++ b/test/langtools/tools/javac/patterns/T8358801.java @@ -0,0 +1,132 @@ +/* + * 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. + * + * 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 + * @bug 8358801 + * @summary Verify variables introduced by let expressions are correctly undefined + * @library /tools/lib + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import java.lang.classfile.ClassFile; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.tools.JavaCompiler; + +import toolbox.JavaTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class T8358801 extends TestRunner { + private ToolBox tb; + + public static void main(String... args) throws Exception { + new T8358801().runTests(); + } + + T8358801() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testPatternsInJava(Path base) throws Exception { + Path classes = base.resolve("classes"); + + List files = new ArrayList<>(); + files.add(new ToolBox.JavaSource( + """ + public class Main { + private boolean test(String s, int i) { + if (s.subSequence(0, 1) instanceof Runnable r) { + return true; + } + + switch (i) { + case 0: + String clashing1 = null; + String clashing2 = null; + String clashing3 = null; + String clashing4 = null; + return true; + default: + System.out.println("correct"); + return true; + } + } + + public static void main(String[] args) { + new Main().test("hello", 1); + } + } + """ + )); + + if (Files.exists(classes)) { + tb.cleanDirectory(classes); + } else { + Files.createDirectories(classes); + } + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + Iterable options = Arrays.asList("-d", classes.toString()); + JavacTask task = (JavacTask) compiler.getTask(null, null, null, options, null, files); + + task.generate(); + + List errors = ClassFile.of().verify(classes.resolve("Main.class")); + + if (!errors.isEmpty()) { + throw new AssertionError("verify errors found: " + errors); + } + + List log = + new JavaTask(tb).classpath(classes.toString()) + .className("Main") + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + List expected = List.of("correct"); + + if (!Objects.equals(log, expected)) { + throw new AssertionError("Incorrect result, expected: " + expected + + ", got: " + log); + } + } + +} diff --git a/test/langtools/tools/javac/platform/RequiresIdentityTest.java b/test/langtools/tools/javac/platform/RequiresIdentityTest.java index f10d6e8054c..8f246a95d4f 100644 --- a/test/langtools/tools/javac/platform/RequiresIdentityTest.java +++ b/test/langtools/tools/javac/platform/RequiresIdentityTest.java @@ -132,7 +132,7 @@ public void testModel(Path base) throws Exception { List expected = List.of( "public class WeakHashMap<@jdk.internal.RequiresIdentity K, V> extends java.util.AbstractMap implements java.util.Map {", - " public V put(@jdk.internal.RequiresIdentity sealed K key," + " public V put(@jdk.internal.RequiresIdentity K key," ); if (!expected.equals(printed)) { throw new AssertionError("Expected: " + expected + @@ -154,7 +154,7 @@ public void testModel(Path base) throws Exception { List expected = List.of( "public class WeakHashMap extends java.util.AbstractMap implements java.util.Map {", - " public V put(sealed K arg0," + " public V put(K arg0," ); if (!expected.equals(printed)) { throw new AssertionError("Expected: " + expected + diff --git a/test/langtools/tools/javac/recovery/AnnotationRecovery.java b/test/langtools/tools/javac/recovery/AnnotationRecovery.java index 89c436912e9..e5e52b82159 100644 --- a/test/langtools/tools/javac/recovery/AnnotationRecovery.java +++ b/test/langtools/tools/javac/recovery/AnnotationRecovery.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8270139 + * @bug 8270139 8361445 * @summary Verify error recovery w.r.t. annotations * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -33,8 +33,10 @@ */ import java.nio.file.Path; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import toolbox.JavacTask; import toolbox.Task.Expect; @@ -110,4 +112,116 @@ public void testRepeatableAnnotationWrongAttribute() throws Exception { } } + @Test //JDK-8361445 + public void testSuppressWarningsErroneousAttribute1() throws Exception { + String code = """ + @SuppressWarnings(CONST) + public class Test { + public static final String CONST = ""; + } + """; + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code) + .outdir(curPath) + .run(Expect.FAIL) + .getOutputLines(OutputKind.DIRECT); + + List expected = List.of( + "Test.java:1:19: compiler.err.cant.resolve: kindname.variable, CONST, , ", + "1 error" + ); + + if (!Objects.equals(actual, expected)) { + error("Expected: " + expected + ", but got: " + actual); + } + } + + @Test //JDK-8361445 + public void testSuppressWarningsErroneousAttribute2() throws Exception { + String code = """ + @SuppressWarnings(0) + public class Test { + } + """; + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code) + .outdir(curPath) + .run(Expect.FAIL) + .getOutputLines(OutputKind.DIRECT); + + List expected = List.of( + "Test.java:1:19: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.String)", + "1 error" + ); + + if (!Objects.equals(actual, expected)) { + error("Expected: " + expected + ", but got: " + actual); + } + } + + @Test //JDK-8361445 + public void testSuppressWarningsErroneousAttribute3() throws Exception { + String[] attributeValues = { + "Test.BOOLEAN", + "Test.BYTE", + "Test.SHORT", + "Test.INT", + "Test.LONG", + "Test.FLOAT", + "Test.DOUBLE", + "Test.CHAR", + "Test.class", + "@Deprecated", + "E.A", + }; + Set variants = new HashSet<>(); + + for (String attributeValue : attributeValues) { + variants.add(attributeValue); + variants.add("{" + attributeValue + "}"); + } + + for (String attributeValue1 : attributeValues) { + for (String attributeValue2 : attributeValues) { + variants.add("{" + attributeValue1 + ", " + attributeValue2 + "}"); + } + } + + String code = """ + @SuppressWarnings($ATTRIBUTE_VALUE) + public class Test { + public static final boolean BOOLEAN = false; + public static final byte BYTE = 0; + public static final short SHORT = 0; + public static final int INT = 0; + public static final long LONG = 0l; + public static final float FLOAT = 0.0; + public static final double DOUBLE = 0.0; + public static final char CHAR = '\0'; + } + enum E { + A + } + """; + + for (String variant : variants) { + System.out.println("current variant: " + variant); + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code.replace("$ATTRIBUTE_VALUE", variant)) + .outdir(curPath) + .run(Expect.FAIL) + .getOutputLines(OutputKind.DIRECT); + + if (actual.isEmpty() || !actual.get(actual.size() - 1).contains("error")) { + error("Incorrect actual errors: " + actual + " for variant: " + variant); + } + } + } + } diff --git a/test/langtools/tools/lib/toolbox/JavacTask.java b/test/langtools/tools/lib/toolbox/JavacTask.java index 49d14de2d1e..c067764c9d3 100644 --- a/test/langtools/tools/lib/toolbox/JavacTask.java +++ b/test/langtools/tools/lib/toolbox/JavacTask.java @@ -37,6 +37,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.processing.Processor; +import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; @@ -62,6 +63,7 @@ public class JavacTask extends AbstractTask { private JavaFileManager fileManager; private Consumer callback; private List procs; + private DiagnosticListener diagnosticListener; private JavaCompiler compiler; private StandardJavaFileManager internalFileManager; @@ -285,6 +287,14 @@ public JavacTask processors(Processor... procs) { return this; } + /** + * Sets the diagnostic listener to be used. + */ + public JavacTask diagnosticListener(DiagnosticListener diagnosticListener) { + this.diagnosticListener = diagnosticListener; + return this; + } + /** * Sets the file manager to be used by this task. * @param fileManager the file manager @@ -406,7 +416,7 @@ private int runAPI(PrintWriter pw) throws IOException { Iterable allFiles = joinFiles(files, fileObjects); JavaCompiler.CompilationTask task = compiler.getTask(pw, fileManager, - null, // diagnostic listener; should optionally collect diags + diagnosticListener, // diagnostic listener; should optionally collect diags allOpts, classes, allFiles); diff --git a/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java b/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java new file mode 100644 index 00000000000..3cee24b4684 --- /dev/null +++ b/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java @@ -0,0 +1,128 @@ +/* + * 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. + * + * 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. + */ + +package jdk.test.lib.jittester; + +import java.lang.reflect.Executable; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/* + * @test + * @summary Unit tests for JITTester string method templates + * + * @library /test/lib + * /test/hotspot/jtreg/testlibrary/jittester/src + * + * @run testng jdk.test.lib.jittester.MethodTemplateTest + */ +public class MethodTemplateTest { + + @Test + public void testMatchingPatterns() throws NoSuchMethodException { + Tester.forMethod(System.class, "getenv", String.class) + .assertMatches("java/lang/System::getenv(Ljava/lang/String;)") + .assertMatches("*::getenv(Ljava/lang/String;)") + .assertMatches("java/lang/*::getenv(Ljava/lang/String;)") + .assertMatches("java/lang/System::*env*(Ljava/lang/String;)") + .assertMatches("java/lang/System::getenv") + .assertMatches("java/lang/System::getenv(*)"); + + Tester.forCtor(RuntimeException.class, Throwable.class) + .assertMatches("java/lang/RuntimeException::RuntimeException(Ljava/lang/Throwable;)"); + + Tester.forMethod(String.class, "regionMatches", int.class, String.class, int.class, int.class) + .assertMatches("java/lang/String::regionMatches(ILjava/lang/String;II)"); + } + + @Test + public void testNonMatchingPatterns() throws NoSuchMethodException { + Tester.forMethod(String.class, "regionMatches", int.class, String.class, int.class, int.class) + .assertDoesNotMatch("java/lang/String::regionMatches(IIILjava/lang/String;)"); + + Tester.forMethod(String.class, "endsWith", String.class) + .assertDoesNotMatch("java/lang/String::startsWith(Ljava/lang/String;)"); + } + + @Test + public void testWildcardStrings() { + assertTrue(new MethodTemplate.WildcardString("Torment") + .matches("Torment")); + + assertTrue(new MethodTemplate.WildcardString("Torm*") + .matches("Torment")); + + assertTrue(new MethodTemplate.WildcardString("*ent") + .matches("Torment")); + + assertTrue(new MethodTemplate.WildcardString("*") + .matches("Something")); + + assertTrue(new MethodTemplate.WildcardString("**") + .matches("Something")); + + assertTrue(new MethodTemplate.WildcardString("*Middle*") + .matches("OnlyMiddleMatches")); + + assertFalse(new MethodTemplate.WildcardString("Wrong") + .matches("Correct")); + assertFalse(new MethodTemplate.WildcardString("Joy") + .matches("Joyfull")); + assertFalse(new MethodTemplate.WildcardString("*Torm*") + .matches("Sorrow")); + } + + static final class Tester { + private final Executable executable; + + private Tester(Executable executable) { + this.executable = executable; + } + + public Tester assertMatches(String stringTemplate) { + MethodTemplate template = MethodTemplate.parse(stringTemplate); + assertTrue(template.matches(executable), + "Method '" + executable + "' does not match template '" + stringTemplate + "'"); + return this; + } + + public Tester assertDoesNotMatch(String stringTemplate) { + MethodTemplate template = MethodTemplate.parse(stringTemplate); + assertFalse(template.matches(executable), + "Method '" + executable + "' erroneously matches template '" + stringTemplate + "'"); + return this; + } + + public static Tester forMethod(Class klass, String name, Class... arguments) + throws NoSuchMethodException { + return new Tester(klass.getDeclaredMethod(name, arguments)); + } + + public static Tester forCtor(Class klass, Class... arguments) + throws NoSuchMethodException { + return new Tester(klass.getConstructor(arguments)); + } + } + +} diff --git a/test/lib/RedefineClassHelper.java b/test/lib/RedefineClassHelper.java index 88f31f8ba8f..ce27fb33f44 100644 --- a/test/lib/RedefineClassHelper.java +++ b/test/lib/RedefineClassHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -21,8 +21,14 @@ * questions. */ -import java.lang.instrument.Instrumentation; +import java.io.InputStream; +import java.lang.classfile.ClassElement; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.constant.ClassDesc; + import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.helpers.ClassFileInstaller; @@ -33,6 +39,7 @@ * * See sample test in test/testlibrary_tests/RedefineClassTest.java */ + public class RedefineClassHelper { public static Instrumentation instrumentation; @@ -61,6 +68,41 @@ public static void redefineClass(Class clazz, byte[] bytecode) throws Excepti instrumentation.redefineClasses(new ClassDefinition(clazz, bytecode)); } + private static byte[] getBytecodes(ClassLoader loader, String name) throws Exception { + try (InputStream is = loader.getResourceAsStream(name + ".class")) { + byte[] buf = is.readAllBytes(); + System.out.println("sizeof(" + name + ".class) == " + buf.length); + return buf; + } + } + + /* + * Copy the class defined by `bytes`, replacing the name of the class with `newClassName`, + * so that both old and new classes can be compiled by jtreg for the test. + * + * @param bytes read from the original class file. + * @param newClassName new class name for the returned class representation + * @return a copy of the class represented by `bytes` but with the name `newClassName` + */ + public static byte[] replaceClassName(byte[] bytes, String newClassName) throws Exception { + ClassModel classModel = ClassFile.of().parse(bytes); + return ClassFile.of().build(ClassDesc.of(newClassName), classModel::forEach); + } + + /* + * Replace class name in bytecodes to the class we're trying to redefine, so that both + * old and new classes can be compiled with jtreg for the test. + * + * @param loader ClassLoader to find the bytes for the old class. + * @param oldClassName old class name. + * @param newClassName new class name to replace with old class name. + * @return a copy of the class represented by `bytes` but with the name `newClassName` + */ + public static byte[] replaceClassName(ClassLoader loader, String oldClassName, String newClassName) throws Exception { + byte[] buf = getBytecodes(loader, oldClassName); + return replaceClassName(buf, newClassName); + } + /** * Main method to be invoked before test to create the redefineagent.jar */ diff --git a/test/lib/jdk/test/lib/cds/CDSAppTester.java b/test/lib/jdk/test/lib/cds/CDSAppTester.java index 7e98b57cb83..cfe17a0be14 100644 --- a/test/lib/jdk/test/lib/cds/CDSAppTester.java +++ b/test/lib/jdk/test/lib/cds/CDSAppTester.java @@ -262,7 +262,7 @@ private OutputAnalyzer recordAOTConfiguration() throws Exception { "class+load=debug", "aot=debug", "cds=debug", - "cds+class=debug")); + "aot+class=debug")); cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, aotConfigurationFile, aotConfigurationFileLog); @@ -275,8 +275,9 @@ private OutputAnalyzer createAOTCacheOneStep() throws Exception { "-XX:AOTCacheOutput=" + aotCacheFile, logToFile(aotCacheFileLog, "class+load=debug", - "cds=debug", - "cds+class=debug")); + "aot=debug", + "aot+class=debug", + "cds=debug")); cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); OutputAnalyzer out = executeAndCheck(cmdLine, runMode, aotCacheFile, aotCacheFileLog); @@ -310,7 +311,7 @@ private OutputAnalyzer dumpStaticArchive() throws Exception { "cds=debug", "cds+class=debug", "aot+heap=warning", - "cds+resolve=debug")); + "aot+resolve=debug")); cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, staticArchiveFile, staticArchiveFileLog); @@ -326,11 +327,11 @@ private OutputAnalyzer createAOTCache() throws Exception { "-XX:AOTConfiguration=" + aotConfigurationFile, "-XX:AOTCache=" + aotCacheFile, logToFile(aotCacheFileLog, - "aot=debug", "cds=debug", - "cds+class=debug", + "aot=debug", + "aot+class=debug", "aot+heap=warning", - "cds+resolve=debug")); + "aot+resolve=debug")); cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, aotCacheFile, aotCacheFileLog); @@ -377,7 +378,7 @@ private OutputAnalyzer dumpDynamicArchive() throws Exception { "aot=debug", "cds=debug", "cds+class=debug", - "cds+resolve=debug", + "aot+resolve=debug", "class+load=debug")); cmdLine = addCommonVMArgs(runMode, cmdLine); } diff --git a/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java b/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java index 57779b7d9fa..8e28ea08365 100644 --- a/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java +++ b/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java @@ -122,8 +122,8 @@ public static void verifyJVMStartup(String expectedMessages[], outputAnalyzer.shouldHaveExitValue(exitCode.value); } catch (RuntimeException e) { String errorMessage = String.format( - "JVM process should have exit value '%d'.%n%s", - exitCode.value, exitErrorMessage); + "JVM process should have exit value '%d', but has '%d'.%n%s", + exitCode.value, outputAnalyzer.getExitValue(), exitErrorMessage); throw new AssertionError(errorMessage, e); } @@ -302,9 +302,12 @@ public static void verifyOptionValue(String optionName, CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, optionName, expectedValue)); } catch (RuntimeException e) { + String observedValue = outputAnalyzer.firstMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionName, "\\S")); String errorMessage = String.format( - "Option '%s' is expected to have '%s' value%n%s", - optionName, expectedValue, + "Option '%s' is expected to have '%s' value, but is '%s'.%n%s", + optionName, expectedValue, observedValue, optionErrorString); throw new AssertionError(errorMessage, e); } diff --git a/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java index 88538e7e780..0d1c3a358ab 100644 --- a/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java @@ -79,12 +79,21 @@ public static ContainerRuntimeVersionTestUtils fromVersionString(String version) try { // Example 'docker version 20.10.0 or podman version 4.9.4-rhel' String versNums = version.split("\\s+", 3)[2]; + // On some docker implementations e.g. RHEL8 ppc64le we have the following version output: + // Docker version v25.0.3, build 4debf41 + // Trim potentially leading 'v' and trailing ',' + if (versNums.startsWith("v")) { + versNums = versNums.substring(1); + } + int cidx = versNums.indexOf(','); + versNums = (cidx != -1) ? versNums.substring(0, cidx) : versNums; + String[] numbers = versNums.split("-")[0].split("\\.", 3); return new ContainerRuntimeVersionTestUtils(Integer.parseInt(numbers[0]), Integer.parseInt(numbers[1]), Integer.parseInt(numbers[2])); } catch (Exception e) { - throw new RuntimeException("Failed to parse container runtime version: " + version); + throw new RuntimeException("Failed to parse container runtime version: " + version, e); } } @@ -104,4 +113,4 @@ public static String getContainerRuntimeVersionStr() { public static ContainerRuntimeVersionTestUtils getContainerRuntimeVersion() { return ContainerRuntimeVersionTestUtils.fromVersionString(getContainerRuntimeVersionStr()); } -} \ No newline at end of file +} diff --git a/test/micro/org/openjdk/bench/java/io/ReaderReadAllLines.java b/test/micro/org/openjdk/bench/java/io/ReaderReadAllLines.java new file mode 100644 index 00000000000..a3663e083ec --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/ReaderReadAllLines.java @@ -0,0 +1,66 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.java.io; + +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import java.util.Random; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +@State(Scope.Benchmark) +public class ReaderReadAllLines { + + private char[] chars = null; + + @Setup + public void setup() throws IOException { + final int len = 128_000; + chars = new char[len]; + Random rnd = new Random(System.nanoTime()); + int off = 0; + while (off < len) { + int lineLen = 40 + rnd.nextInt(8192); + if (lineLen > len - off) { + off = len; + } else { + chars[off + lineLen] = '\n'; + off += lineLen; + } + } + } + + @Benchmark + public List readAllLines() throws IOException { + List lines; + try (Reader reader = new CharArrayReader(chars)) { + lines = reader.readAllLines(); + } + return lines; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/ScopedValues.java b/test/micro/org/openjdk/bench/java/lang/ScopedValues.java index 70c97d57551..6f88bbcc6b1 100644 --- a/test/micro/org/openjdk/bench/java/lang/ScopedValues.java +++ b/test/micro/org/openjdk/bench/java/lang/ScopedValues.java @@ -80,6 +80,16 @@ public int thousandIsBoundQueries(Blackhole bh) throws Exception { return result; } + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int thousandUnboundQueries(Blackhole bh) throws Exception { + var result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.unbound.isBound() ? 1 : 0; + } + return result; + } + @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public int thousandMaybeGets(Blackhole bh) throws Exception { @@ -213,4 +223,11 @@ public void counter_ThreadLocal() { var ctr = tl_atomicInt.get(); ctr.setPlain(ctr.getPlain() + 1); } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Object newInstance() { + ScopedValue val = ScopedValue.newInstance(); + return val; + } } diff --git a/test/micro/org/openjdk/bench/java/lang/ScopedValuesData.java b/test/micro/org/openjdk/bench/java/lang/ScopedValuesData.java index 693594fbaee..70f89f79074 100644 --- a/test/micro/org/openjdk/bench/java/lang/ScopedValuesData.java +++ b/test/micro/org/openjdk/bench/java/lang/ScopedValuesData.java @@ -57,11 +57,13 @@ public class ScopedValuesData { public static void run(Runnable action) { try { tl1.set(42); tl2.set(2); tl3.set(3); tl4.set(4); tl5.set(5); tl6.set(6); - tl1.get(); // Create the ScopedValue cache as a side effect tl_atomicInt.set(new AtomicInteger()); VALUES.where(sl_atomicInt, new AtomicInteger()) .where(sl_atomicRef, new AtomicReference<>()) - .run(action); + .run(() -> { + sl1.get(); // Create the ScopedValue cache as a side effect + action.run(); + }); } finally { tl1.remove(); tl2.remove(); tl3.remove(); tl4.remove(); tl5.remove(); tl6.remove(); tl_atomicInt.remove(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferChurn.java similarity index 55% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java rename to test/micro/org/openjdk/bench/java/nio/DirectByteBufferChurn.java index 2046fd075ad..73a6a6744cb 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java +++ b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferChurn.java @@ -19,42 +19,30 @@ * 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. - * */ +package org.openjdk.bench.java.nio; + +import java.nio.ByteBuffer; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3, jvmArgs = {"-Xmx256m", "-Xms256m", "-XX:+AlwaysPreTouch"}) +public class DirectByteBufferChurn { + + @Param({"128", "256", "512", "1024", "2048"}) + int recipFreq; + + @Benchmark + public Object test() { + boolean direct = ThreadLocalRandom.current().nextInt(recipFreq) == 0; + return direct ? ByteBuffer.allocateDirect(1) : ByteBuffer.allocate(1); + } -package sun.jvm.hotspot.runtime; - -import sun.jvm.hotspot.types.TypeDataBase; - - -/** Encapsulates the LockingMode enum in globalDefinitions.hpp in - the VM. */ - -public class LockingMode { - private static int monitor; - private static int legacy; - private static int lightweight; - - static { - VM.registerVMInitializedObserver( - (o, d) -> initialize(VM.getVM().getTypeDataBase())); - } - - private static synchronized void initialize(TypeDataBase db) { - monitor = db.lookupIntConstant("LM_MONITOR").intValue(); - legacy = db.lookupIntConstant("LM_LEGACY").intValue(); - lightweight = db.lookupIntConstant("LM_LIGHTWEIGHT").intValue(); - } - - public static int getMonitor() { - return monitor; - } - - public static int getLegacy() { - return legacy; - } - - public static int getLightweight() { - return lightweight; - } } diff --git a/test/micro/org/openjdk/bench/java/nio/DirectByteBufferGC.java b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferGC.java new file mode 100644 index 00000000000..bef9d2d9805 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferGC.java @@ -0,0 +1,64 @@ +/* + * Copyright Amazon.com Inc. 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. + */ +package org.openjdk.bench.java.nio; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3, jvmArgs = {"-Xmx1g", "-Xms1g", "-XX:+AlwaysPreTouch"}) +public class DirectByteBufferGC { + + @Param({"16384", "65536", "262144", "1048576", "4194304"}) + int count; + + // Make sure all buffers are reachable and available for GC. Buffers + // directly reference their Cleanables, so we do not want to provide + // excess GC parallelism opportunities here, this is why reference + // buffers from a linked list. + // + // This exposes the potential GC parallelism problem in Cleaner lists. + LinkedList buffers; + + @Setup + public void setup() { + buffers = new LinkedList<>(); + for (int c = 0; c < count; c++) { + buffers.add(ByteBuffer.allocateDirect(1)); + } + } + + @Benchmark + public void test() { + System.gc(); + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/internal/jrtfs/ImageReaderBenchmark.java b/test/micro/org/openjdk/bench/jdk/internal/jrtfs/ImageReaderBenchmark.java new file mode 100644 index 00000000000..f2e30bea2a1 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/internal/jrtfs/ImageReaderBenchmark.java @@ -0,0 +1,1202 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.jdk.internal.jrtfs; + +import jdk.internal.jimage.ImageReader; +import jdk.internal.jimage.ImageReader.Node; +import jdk.internal.jimage.PreviewMode; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toList; + +/// Benchmarks for ImageReader. See individual benchmarks for details on what they +/// measure, and their potential applicability for real world conclusions. +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, timeUnit = TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 1, jvmArgs = {"--add-exports", "java.base/jdk.internal.jimage=ALL-UNNAMED"}) +public class ImageReaderBenchmark { + + private static final Path SYSTEM_IMAGE_FILE = Path.of(System.getProperty("java.home"), "lib", "modules"); + static { + if (!Files.exists(SYSTEM_IMAGE_FILE)) { + throw new IllegalStateException("Cannot locate jimage file for benchmark: " + SYSTEM_IMAGE_FILE); + } + } + + /// NOT annotated with `@State` since it needs to potentially be used as a + /// per-trial or a per-iteration state object. The subclasses provide + /// any lifetime annotations that are needed. + static class BaseState { + protected Path copiedImageFile; + long count = 0; + + public void setUp() throws IOException { + copiedImageFile = Files.createTempFile("copied_jimage", ""); + Files.copy(SYSTEM_IMAGE_FILE, copiedImageFile, REPLACE_EXISTING); + } + + public void tearDown() throws IOException { + Files.deleteIfExists(copiedImageFile); + System.err.println("Result: " + count); + } + } + + /// A {@link Level#Trial per-trial} state which provides an image reader, + /// suitable for {@link Mode#AverageTime average time} benchmarks. + @State(Scope.Benchmark) + public static class WarmStart extends BaseState { + @Param({"DISABLED", "ENABLED"}) + PreviewMode previewMode; + ImageReader reader; + + @Setup(Level.Trial) + public void setUp() throws IOException { + super.setUp(); + reader = ImageReader.open(copiedImageFile, previewMode); + } + + @TearDown(Level.Trial) + public void tearDown() throws IOException { + super.tearDown(); + } + } + + @State(Scope.Benchmark) + public static class WarmStartWithCachedNodes extends WarmStart { + @Setup(Level.Trial) + public void setUp() throws IOException { + super.setUp(); + countAllNodes(reader, reader.findNode("/")); + } + } + + /// A {@link Level#Iteration per-iteration} state suitable for + /// {@link Mode#SingleShotTime single shot} benchmarks. Unlike + /// {@link WarmStart}, this state does not provide a reader instance. + @State(Scope.Benchmark) + public static class ColdStart extends BaseState { + @Param({"DISABLED", "ENABLED"}) + PreviewMode previewMode; + + @Setup(Level.Iteration) + public void setUp() throws IOException { + super.setUp(); + } + + @TearDown(Level.Iteration) + public void tearDown() throws IOException { + super.tearDown(); + } + } + + @State(Scope.Benchmark) + public static class ColdStartWithImageReader extends ColdStart { + ImageReader reader; + + @Setup(Level.Iteration) + public void setup() throws IOException { + super.setUp(); + reader = ImageReader.open(copiedImageFile, previewMode); + } + + @TearDown(Level.Iteration) + public void tearDown() throws IOException { + reader.close(); + super.tearDown(); + } + } + + /// Benchmarks counting of all nodes in the system image *after* they have all + /// been visited at least once. Image nodes should be cached after first use, + /// so this benchmark should be fast and very stable. + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public void warmStart_CountAllNodes(WarmStartWithCachedNodes state) throws IOException { + state.count = countAllNodes(state.reader, state.reader.findNode("/")); + } + + /// Benchmarks {@link ImageReader#containsResource(String, String)} when no + /// nodes have been cached in the {@link ImageReader}. In non-preview mode, + /// this should be identical to the case where nodes are cached (because the + /// cache isn't used) but in preview mode, the cache will be tested for + /// preview resources, and thus differ depending on whether nodes are present. + /// + /// This doesn't need to be a cold start because it never modifies the nodes + /// cache. + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public void warmStart_ContainsResource_emptyNodeCache(WarmStart state) throws IOException { + state.count = countContainsResource(state.reader, ClassList.pathMap()); + } + + /// As above, but the nodes cache has been filled, giving preview mode a + /// different code path. + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public void warmStart_ContainsResource_fullNodeCache(WarmStartWithCachedNodes state) throws IOException { + state.count = countContainsResource(state.reader, ClassList.pathMap()); + } + + /// As {@link #warmStart_ContainsResource_emptyNodeCache}, but tests + /// {@link ImageReader#findResourceNode(String, String)}. + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public void warmStart_FindResourceNode_emptyNodeCache(WarmStart state) throws IOException { + state.count = countFindResourceNode(state.reader, ClassList.pathMap()); + } + + /// As {@link #warmStart_ContainsResource_fullNodeCache}, but tests + /// {@link ImageReader#findResourceNode(String, String)}. + @Benchmark + @BenchmarkMode(Mode.AverageTime) + public void warmStart_FindResourceNode_fullNodeCache(WarmStartWithCachedNodes state) throws IOException { + state.count = countFindResourceNode(state.reader, ClassList.pathMap()); + } + + + /// Benchmarks counting of all nodes in the system image from a "cold start". This + /// visits all nodes in depth-first order and counts them. + /// + /// This benchmark is not representative of any typical usage pattern, but can be + /// used for comparisons between versions of `ImageReader`. + @Benchmark + @BenchmarkMode(Mode.SingleShotTime) + public void coldStart_InitAndCount(ColdStart state) throws IOException { + try (var reader = ImageReader.open(state.copiedImageFile, state.previewMode)) { + state.count = countAllNodes(reader, reader.findNode("/")); + } + } + + /// As above, but excludes the time to initialize the `ImageReader`. + @Benchmark + @BenchmarkMode(Mode.SingleShotTime) + public void coldStart_CountOnly(ColdStartWithImageReader state) throws IOException { + state.count = countAllNodes(state.reader, state.reader.findNode("/")); + } + + /// Benchmarks the time taken to load the byte array contents of classes + /// representative of those loaded by javac to for the simplest `HelloWorld` + /// program. + /// + /// This benchmark is somewhat representative of the cost of class loading + /// during javac startup. It is useful for comparisons between versions of + /// `ImageReader`, but also to estimate a lower bound for any reduction or + /// increase in the real-world startup time of javac. + @Benchmark + @BenchmarkMode(Mode.SingleShotTime) + public void coldStart_LoadJavacInitClasses(Blackhole bh, ColdStart state) throws IOException { + int errors = 0; + try (var reader = ImageReader.open(state.copiedImageFile, state.previewMode)) { + for (String path : ClassList.names()) { + // Path determination isn't perfect so there can be a few "misses" in here. + // Report the count of bad paths as the "result", which should be < 20 or so. + Node node = reader.findNode(path); + if (node != null) { + bh.consume(reader.getResource(node)); + } else { + errors += 1; + } + } + } + state.count = ClassList.count(); + // Allow up to 2% missing classes before complaining. + if ((100 * errors) / ClassList.count() >= 2) { + reportMissingClassesAndFail(state, errors); + } + } + + static long countAllNodes(ImageReader reader, Node node) { + long count = 1; + if (node.isDirectory()) { + count += node.getChildNames().mapToLong(n -> { + try { + return countAllNodes(reader, reader.findNode(n)); + } catch (IOException e) { + throw new RuntimeException(e); + } + }).sum(); + } + return count; + } + + static long countContainsResource(ImageReader reader, Map> modToPaths) + throws IOException { + long count = 0; + for (Map.Entry> e : modToPaths.entrySet()) { + String mod = e.getKey(); + for (String path : e.getValue()) { + if (reader.containsResource(mod, path)) { + count++; + } + } + } + return count; + } + + static long countFindResourceNode(ImageReader reader, Map> modToPaths) throws IOException { + long count = 0; + for (Map.Entry> e : modToPaths.entrySet()) { + String mod = e.getKey(); + for (String path : e.getValue()) { + if (reader.findResourceNode(mod, path) != null) { + count++; + } + } + } + return count; + } + + // Run if the INIT_CLASSES list below is sufficiently out-of-date. + // DO NOT run this before the benchmark, as it will cache all the nodes! + private static void reportMissingClassesAndFail(ColdStart state, int errors) throws IOException { + List missing = new ArrayList<>(errors); + try (var reader = ImageReader.open(state.copiedImageFile, state.previewMode)) { + for (String path : ClassList.names()) { + if (reader.findNode(path) == null) { + missing.add(path); + } + } + } + throw new IllegalStateException( + String.format( + "Too many missing classes (%d of %d) in the hardcoded benchmark list.\n" + + "Please regenerate it according to instructions in the source code.\n" + + "Missing classes:\n\t%s", + errors, ClassList.count(), String.join("\n\t", missing))); + } + + /// Note: This list is inherently a little fragile and may end up being more + /// trouble than it's worth to maintain. If it turns out that it needs to be + /// regenerated often when this benchmark is run, then a new approach should + /// be considered, such as: + /// * Limit the list of classes to non-internal ones. + /// * Calculate the list dynamically based on the running JVM. + /// * Build a custom jimage file similar to ImageReaderTest + private static final class ClassList { + /// Returns the names of resource nodes expected to be present in the + /// reader, excluding preview mode paths (i.e. "/META-INF/preview/"). + private static Set names() { + return INIT_CLASSES; + } + + /// Returns the number of resources present. + private static int count() { + return INIT_CLASSES.size(); + } + + /// Returns the resource nodes represented as a map from module name to + /// resource path. This is suitable for testing functions like + /// {@link ImageReader#containsResource(String, String)} without the + /// overhead of splitting resource names during the trial. + private static Map> pathMap() { + return MODULE_TO_PATHS; + } + + // Created by running "java -verbose:class", throwing away anonymous inner + // classes and anything without a reliable name, and grouping by the stated + // source. It's not perfect, but it's representative. + // + // /bin/java -verbose:class HelloWorld 2>&1 \ + // | fgrep '[class,load]' | cut -d' ' -f2 \ + // | tr '.' '/' \ + // | egrep -v '\$[0-9$]' \ + // | fgrep -v 'HelloWorld' \ + // | fgrep -v '/META-INF/preview/' \ + // | while read f ; do echo "${f}.class" ; done \ + // > initclasses.txt + // + // Output: + // java/lang/Object.class + // java/io/Serializable.class + // ... + // + // jimage list /images/jdk/lib/modules \ + // | awk '/^Module: */ { MOD=$2 }; /^ */ { print "/modules/"MOD"/"$1 }' \ + // > fullpaths.txt + // + // Output: + // ... + // /modules/java.base/java/lang/Object.class + // /modules/java.base/java/lang/OutOfMemoryError.class + // ... + // + // while read c ; do grep "/$c" fullpaths.txt ; done < initclasses.txt \ + // | while read c ; do printf ' "%s",\n' "$c" ; done \ + // > initpaths.txt + // + // Output: + private static final Set INIT_CLASSES = Set.of( + "/modules/java.base/java/lang/Object.class", + "/modules/java.base/java/io/Serializable.class", + "/modules/java.base/java/lang/Comparable.class", + "/modules/java.base/java/lang/CharSequence.class", + "/modules/java.base/java/lang/constant/Constable.class", + "/modules/java.base/java/lang/constant/ConstantDesc.class", + "/modules/java.base/java/lang/String.class", + "/modules/java.base/java/lang/reflect/AnnotatedElement.class", + "/modules/java.base/java/lang/reflect/GenericDeclaration.class", + "/modules/java.base/java/lang/reflect/Type.class", + "/modules/java.base/java/lang/invoke/TypeDescriptor.class", + "/modules/java.base/java/lang/invoke/TypeDescriptor$OfField.class", + "/modules/java.base/java/lang/Class.class", + "/modules/java.base/java/lang/Cloneable.class", + "/modules/java.base/java/lang/ClassLoader.class", + "/modules/java.base/java/lang/System.class", + "/modules/java.base/java/lang/Throwable.class", + "/modules/java.base/java/lang/Error.class", + "/modules/java.base/java/lang/Exception.class", + "/modules/java.base/java/lang/RuntimeException.class", + "/modules/java.base/java/security/ProtectionDomain.class", + "/modules/java.base/java/security/SecureClassLoader.class", + "/modules/java.base/java/lang/ReflectiveOperationException.class", + "/modules/java.base/java/lang/ClassNotFoundException.class", + "/modules/java.base/java/lang/Record.class", + "/modules/java.base/java/lang/LinkageError.class", + "/modules/java.base/java/lang/NoClassDefFoundError.class", + "/modules/java.base/java/lang/ClassCastException.class", + "/modules/java.base/java/lang/ArrayStoreException.class", + "/modules/java.base/java/lang/VirtualMachineError.class", + "/modules/java.base/java/lang/InternalError.class", + "/modules/java.base/java/lang/OutOfMemoryError.class", + "/modules/java.base/java/lang/StackOverflowError.class", + "/modules/java.base/java/lang/IllegalMonitorStateException.class", + "/modules/java.base/java/lang/ref/Reference.class", + "/modules/java.base/java/lang/IllegalCallerException.class", + "/modules/java.base/java/lang/ref/SoftReference.class", + "/modules/java.base/java/lang/ref/WeakReference.class", + "/modules/java.base/java/lang/ref/FinalReference.class", + "/modules/java.base/java/lang/ref/PhantomReference.class", + "/modules/java.base/java/lang/ref/Finalizer.class", + "/modules/java.base/java/lang/Runnable.class", + "/modules/java.base/java/lang/Thread.class", + "/modules/java.base/java/lang/Thread$FieldHolder.class", + "/modules/java.base/java/lang/Thread$Constants.class", + "/modules/java.base/java/lang/Thread$UncaughtExceptionHandler.class", + "/modules/java.base/java/lang/ThreadGroup.class", + "/modules/java.base/java/lang/BaseVirtualThread.class", + "/modules/java.base/java/lang/VirtualThread.class", + "/modules/java.base/java/lang/ThreadBuilders$BoundVirtualThread.class", + "/modules/java.base/java/util/Map.class", + "/modules/java.base/java/util/Dictionary.class", + "/modules/java.base/java/util/Hashtable.class", + "/modules/java.base/java/util/Properties.class", + "/modules/java.base/java/lang/Module.class", + "/modules/java.base/java/lang/reflect/AccessibleObject.class", + "/modules/java.base/java/lang/reflect/Member.class", + "/modules/java.base/java/lang/reflect/Field.class", + "/modules/java.base/java/lang/reflect/Parameter.class", + "/modules/java.base/java/lang/reflect/Executable.class", + "/modules/java.base/java/lang/reflect/Method.class", + "/modules/java.base/java/lang/reflect/Constructor.class", + "/modules/java.base/jdk/internal/vm/ContinuationScope.class", + "/modules/java.base/jdk/internal/vm/Continuation.class", + "/modules/java.base/jdk/internal/vm/StackChunk.class", + "/modules/java.base/jdk/internal/reflect/MethodAccessor.class", + "/modules/java.base/jdk/internal/reflect/MethodAccessorImpl.class", + "/modules/java.base/jdk/internal/reflect/ConstantPool.class", + "/modules/java.base/java/lang/annotation/Annotation.class", + "/modules/java.base/jdk/internal/reflect/CallerSensitive.class", + "/modules/java.base/jdk/internal/reflect/ConstructorAccessor.class", + "/modules/java.base/jdk/internal/reflect/ConstructorAccessorImpl.class", + "/modules/java.base/jdk/internal/reflect/DirectConstructorHandleAccessor$NativeAccessor.class", + "/modules/java.base/java/lang/invoke/MethodHandle.class", + "/modules/java.base/java/lang/invoke/DirectMethodHandle.class", + "/modules/java.base/java/lang/invoke/VarHandle.class", + "/modules/java.base/java/lang/invoke/MemberName.class", + "/modules/java.base/java/lang/invoke/ResolvedMethodName.class", + "/modules/java.base/java/lang/invoke/MethodHandleNatives.class", + "/modules/java.base/java/lang/invoke/LambdaForm.class", + "/modules/java.base/java/lang/invoke/TypeDescriptor$OfMethod.class", + "/modules/java.base/java/lang/invoke/MethodType.class", + "/modules/java.base/java/lang/BootstrapMethodError.class", + "/modules/java.base/java/lang/invoke/CallSite.class", + "/modules/java.base/jdk/internal/foreign/abi/NativeEntryPoint.class", + "/modules/java.base/jdk/internal/foreign/abi/ABIDescriptor.class", + "/modules/java.base/jdk/internal/foreign/abi/VMStorage.class", + "/modules/java.base/jdk/internal/foreign/abi/UpcallLinker$CallRegs.class", + "/modules/java.base/java/lang/invoke/ConstantCallSite.class", + "/modules/java.base/java/lang/invoke/MutableCallSite.class", + "/modules/java.base/java/lang/invoke/VolatileCallSite.class", + "/modules/java.base/java/lang/AssertionStatusDirectives.class", + "/modules/java.base/java/lang/Appendable.class", + "/modules/java.base/java/lang/AbstractStringBuilder.class", + "/modules/java.base/java/lang/StringBuffer.class", + "/modules/java.base/java/lang/StringBuilder.class", + "/modules/java.base/jdk/internal/misc/UnsafeConstants.class", + "/modules/java.base/jdk/internal/misc/Unsafe.class", + "/modules/java.base/jdk/internal/module/Modules.class", + "/modules/java.base/java/lang/AutoCloseable.class", + "/modules/java.base/java/io/Closeable.class", + "/modules/java.base/java/io/InputStream.class", + "/modules/java.base/java/io/ByteArrayInputStream.class", + "/modules/java.base/java/net/URL.class", + "/modules/java.base/java/lang/Enum.class", + "/modules/java.base/java/util/jar/Manifest.class", + "/modules/java.base/jdk/internal/loader/BuiltinClassLoader.class", + "/modules/java.base/jdk/internal/loader/ClassLoaders.class", + "/modules/java.base/jdk/internal/loader/ClassLoaders$AppClassLoader.class", + "/modules/java.base/jdk/internal/loader/ClassLoaders$PlatformClassLoader.class", + "/modules/java.base/java/security/CodeSource.class", + "/modules/java.base/java/util/concurrent/ConcurrentMap.class", + "/modules/java.base/java/util/AbstractMap.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap.class", + "/modules/java.base/java/lang/Iterable.class", + "/modules/java.base/java/util/Collection.class", + "/modules/java.base/java/util/SequencedCollection.class", + "/modules/java.base/java/util/List.class", + "/modules/java.base/java/util/RandomAccess.class", + "/modules/java.base/java/util/AbstractCollection.class", + "/modules/java.base/java/util/AbstractList.class", + "/modules/java.base/java/util/ArrayList.class", + "/modules/java.base/java/lang/StackTraceElement.class", + "/modules/java.base/java/nio/Buffer.class", + "/modules/java.base/java/lang/StackWalker.class", + "/modules/java.base/java/lang/StackStreamFactory$AbstractStackWalker.class", + "/modules/java.base/java/lang/StackWalker$StackFrame.class", + "/modules/java.base/java/lang/ClassFrameInfo.class", + "/modules/java.base/java/lang/StackFrameInfo.class", + "/modules/java.base/java/lang/LiveStackFrame.class", + "/modules/java.base/java/lang/LiveStackFrameInfo.class", + "/modules/java.base/java/util/concurrent/locks/AbstractOwnableSynchronizer.class", + "/modules/java.base/java/lang/Boolean.class", + "/modules/java.base/java/lang/Character.class", + "/modules/java.base/java/lang/Number.class", + "/modules/java.base/java/lang/Float.class", + "/modules/java.base/java/lang/Double.class", + "/modules/java.base/java/lang/Byte.class", + "/modules/java.base/java/lang/Short.class", + "/modules/java.base/java/lang/Integer.class", + "/modules/java.base/java/lang/Long.class", + "/modules/java.base/java/lang/Void.class", + "/modules/java.base/java/util/Iterator.class", + "/modules/java.base/java/lang/reflect/RecordComponent.class", + "/modules/java.base/jdk/internal/vm/vector/VectorSupport.class", + "/modules/java.base/jdk/internal/vm/vector/VectorSupport$VectorPayload.class", + "/modules/java.base/jdk/internal/vm/vector/VectorSupport$Vector.class", + "/modules/java.base/jdk/internal/vm/vector/VectorSupport$VectorMask.class", + "/modules/java.base/jdk/internal/vm/vector/VectorSupport$VectorShuffle.class", + "/modules/java.base/jdk/internal/vm/FillerObject.class", + "/modules/java.base/java/lang/NullPointerException.class", + "/modules/java.base/java/lang/ArithmeticException.class", + "/modules/java.base/java/lang/IndexOutOfBoundsException.class", + "/modules/java.base/java/lang/ArrayIndexOutOfBoundsException.class", + "/modules/java.base/java/io/ObjectStreamField.class", + "/modules/java.base/java/util/Comparator.class", + "/modules/java.base/java/lang/String$CaseInsensitiveComparator.class", + "/modules/java.base/jdk/internal/misc/VM.class", + "/modules/java.base/java/lang/Module$ArchivedData.class", + "/modules/java.base/jdk/internal/misc/CDS.class", + "/modules/java.base/java/util/Set.class", + "/modules/java.base/java/util/ImmutableCollections$AbstractImmutableCollection.class", + "/modules/java.base/java/util/ImmutableCollections$AbstractImmutableSet.class", + "/modules/java.base/java/util/ImmutableCollections$Set12.class", + "/modules/java.base/java/util/Objects.class", + "/modules/java.base/java/util/ImmutableCollections.class", + "/modules/java.base/java/util/ImmutableCollections$AbstractImmutableList.class", + "/modules/java.base/java/util/ImmutableCollections$ListN.class", + "/modules/java.base/java/util/ImmutableCollections$SetN.class", + "/modules/java.base/java/util/ImmutableCollections$AbstractImmutableMap.class", + "/modules/java.base/java/util/ImmutableCollections$MapN.class", + "/modules/java.base/jdk/internal/access/JavaLangReflectAccess.class", + "/modules/java.base/java/lang/reflect/ReflectAccess.class", + "/modules/java.base/jdk/internal/access/SharedSecrets.class", + "/modules/java.base/jdk/internal/reflect/ReflectionFactory.class", + "/modules/java.base/java/io/ObjectStreamClass.class", + "/modules/java.base/java/lang/Math.class", + "/modules/java.base/jdk/internal/reflect/ReflectionFactory$Config.class", + "/modules/java.base/jdk/internal/access/JavaLangRefAccess.class", + "/modules/java.base/java/lang/ref/ReferenceQueue.class", + "/modules/java.base/java/lang/ref/ReferenceQueue$Null.class", + "/modules/java.base/java/lang/ref/ReferenceQueue$Lock.class", + "/modules/java.base/jdk/internal/access/JavaLangAccess.class", + "/modules/java.base/jdk/internal/util/SystemProps.class", + "/modules/java.base/jdk/internal/util/SystemProps$Raw.class", + "/modules/java.base/java/nio/charset/Charset.class", + "/modules/java.base/java/nio/charset/spi/CharsetProvider.class", + "/modules/java.base/sun/nio/cs/StandardCharsets.class", + "/modules/java.base/java/lang/StringLatin1.class", + "/modules/java.base/sun/nio/cs/HistoricallyNamedCharset.class", + "/modules/java.base/sun/nio/cs/Unicode.class", + "/modules/java.base/sun/nio/cs/UTF_8.class", + "/modules/java.base/java/util/HashMap.class", + "/modules/java.base/java/lang/StrictMath.class", + "/modules/java.base/jdk/internal/util/ArraysSupport.class", + "/modules/java.base/java/util/Map$Entry.class", + "/modules/java.base/java/util/HashMap$Node.class", + "/modules/java.base/java/util/LinkedHashMap$Entry.class", + "/modules/java.base/java/util/HashMap$TreeNode.class", + "/modules/java.base/java/lang/StringConcatHelper.class", + "/modules/java.base/java/lang/VersionProps.class", + "/modules/java.base/java/lang/Runtime.class", + "/modules/java.base/java/util/concurrent/locks/Lock.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantLock.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$Segment.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$CounterCell.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$Node.class", + "/modules/java.base/java/util/concurrent/locks/LockSupport.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$ReservationNode.class", + "/modules/java.base/java/util/AbstractSet.class", + "/modules/java.base/java/util/HashMap$EntrySet.class", + "/modules/java.base/java/util/HashMap$HashIterator.class", + "/modules/java.base/java/util/HashMap$EntryIterator.class", + "/modules/java.base/jdk/internal/util/StaticProperty.class", + "/modules/java.base/java/io/FileInputStream.class", + "/modules/java.base/java/lang/System$In.class", + "/modules/java.base/java/io/FileDescriptor.class", + "/modules/java.base/jdk/internal/access/JavaIOFileDescriptorAccess.class", + "/modules/java.base/java/io/Flushable.class", + "/modules/java.base/java/io/OutputStream.class", + "/modules/java.base/java/io/FileOutputStream.class", + "/modules/java.base/java/lang/System$Out.class", + "/modules/java.base/java/io/FilterInputStream.class", + "/modules/java.base/java/io/BufferedInputStream.class", + "/modules/java.base/java/io/FilterOutputStream.class", + "/modules/java.base/java/io/PrintStream.class", + "/modules/java.base/java/io/BufferedOutputStream.class", + "/modules/java.base/java/io/Writer.class", + "/modules/java.base/java/io/OutputStreamWriter.class", + "/modules/java.base/sun/nio/cs/StreamEncoder.class", + "/modules/java.base/java/nio/charset/CharsetEncoder.class", + "/modules/java.base/sun/nio/cs/UTF_8$Encoder.class", + "/modules/java.base/java/nio/charset/CodingErrorAction.class", + "/modules/java.base/java/util/Arrays.class", + "/modules/java.base/java/nio/ByteBuffer.class", + "/modules/java.base/jdk/internal/misc/ScopedMemoryAccess.class", + "/modules/java.base/java/util/function/Function.class", + "/modules/java.base/jdk/internal/util/Preconditions.class", + "/modules/java.base/java/util/function/BiFunction.class", + "/modules/java.base/jdk/internal/access/JavaNioAccess.class", + "/modules/java.base/java/nio/HeapByteBuffer.class", + "/modules/java.base/java/nio/ByteOrder.class", + "/modules/java.base/java/io/BufferedWriter.class", + "/modules/java.base/java/lang/Terminator.class", + "/modules/java.base/jdk/internal/misc/Signal$Handler.class", + "/modules/java.base/jdk/internal/misc/Signal.class", + "/modules/java.base/java/util/Hashtable$Entry.class", + "/modules/java.base/jdk/internal/misc/Signal$NativeHandler.class", + "/modules/java.base/java/lang/Integer$IntegerCache.class", + "/modules/java.base/jdk/internal/misc/OSEnvironment.class", + "/modules/java.base/java/lang/Thread$State.class", + "/modules/java.base/java/lang/ref/Reference$ReferenceHandler.class", + "/modules/java.base/java/lang/Thread$ThreadIdentifiers.class", + "/modules/java.base/java/lang/ref/Finalizer$FinalizerThread.class", + "/modules/java.base/jdk/internal/ref/Cleaner.class", + "/modules/java.base/java/util/Collections.class", + "/modules/java.base/java/util/Collections$EmptySet.class", + "/modules/java.base/java/util/Collections$EmptyList.class", + "/modules/java.base/java/util/Collections$EmptyMap.class", + "/modules/java.base/java/lang/IllegalArgumentException.class", + "/modules/java.base/java/lang/invoke/MethodHandleStatics.class", + "/modules/java.base/java/lang/reflect/ClassFileFormatVersion.class", + "/modules/java.base/java/lang/CharacterData.class", + "/modules/java.base/java/lang/CharacterDataLatin1.class", + "/modules/java.base/jdk/internal/util/ClassFileDumper.class", + "/modules/java.base/java/util/HexFormat.class", + "/modules/java.base/java/lang/Character$CharacterCache.class", + "/modules/java.base/java/util/concurrent/atomic/AtomicInteger.class", + "/modules/java.base/jdk/internal/module/ModuleBootstrap.class", + "/modules/java.base/java/lang/module/ModuleDescriptor.class", + "/modules/java.base/java/lang/invoke/MethodHandles.class", + "/modules/java.base/java/lang/invoke/MemberName$Factory.class", + "/modules/java.base/jdk/internal/reflect/Reflection.class", + "/modules/java.base/java/lang/invoke/MethodHandles$Lookup.class", + "/modules/java.base/java/util/ImmutableCollections$MapN$MapNIterator.class", + "/modules/java.base/java/util/KeyValueHolder.class", + "/modules/java.base/sun/invoke/util/VerifyAccess.class", + "/modules/java.base/java/lang/reflect/Modifier.class", + "/modules/java.base/jdk/internal/access/JavaLangModuleAccess.class", + "/modules/java.base/java/io/File.class", + "/modules/java.base/java/io/DefaultFileSystem.class", + "/modules/java.base/java/io/FileSystem.class", + "/modules/java.base/java/io/UnixFileSystem.class", + "/modules/java.base/jdk/internal/util/DecimalDigits.class", + "/modules/java.base/jdk/internal/module/ModulePatcher.class", + "/modules/java.base/jdk/internal/module/ModuleBootstrap$IllegalNativeAccess.class", + "/modules/java.base/java/util/HashSet.class", + "/modules/java.base/jdk/internal/module/ModuleLoaderMap.class", + "/modules/java.base/jdk/internal/module/ModuleLoaderMap$Modules.class", + "/modules/java.base/jdk/internal/module/ModuleBootstrap$Counters.class", + "/modules/java.base/jdk/internal/module/ArchivedBootLayer.class", + "/modules/java.base/jdk/internal/module/ArchivedModuleGraph.class", + "/modules/java.base/jdk/internal/module/SystemModuleFinders.class", + "/modules/java.base/java/net/URI.class", + "/modules/java.base/jdk/internal/access/JavaNetUriAccess.class", + "/modules/java.base/jdk/internal/module/SystemModulesMap.class", + "/modules/java.base/jdk/internal/module/SystemModules.class", + "/modules/java.base/jdk/internal/module/ExplodedSystemModules.class", + "/modules/java.base/java/nio/file/Watchable.class", + "/modules/java.base/java/nio/file/Path.class", + "/modules/java.base/java/nio/file/FileSystems.class", + "/modules/java.base/sun/nio/fs/DefaultFileSystemProvider.class", + "/modules/java.base/java/nio/file/spi/FileSystemProvider.class", + "/modules/java.base/sun/nio/fs/AbstractFileSystemProvider.class", + "/modules/java.base/sun/nio/fs/UnixFileSystemProvider.class", + "/modules/java.base/sun/nio/fs/LinuxFileSystemProvider.class", + "/modules/java.base/java/nio/file/OpenOption.class", + "/modules/java.base/java/nio/file/StandardOpenOption.class", + "/modules/java.base/java/nio/file/FileSystem.class", + "/modules/java.base/sun/nio/fs/UnixFileSystem.class", + "/modules/java.base/sun/nio/fs/LinuxFileSystem.class", + "/modules/java.base/sun/nio/fs/UnixPath.class", + "/modules/java.base/sun/nio/fs/Util.class", + "/modules/java.base/java/lang/StringCoding.class", + "/modules/java.base/sun/nio/fs/UnixNativeDispatcher.class", + "/modules/java.base/jdk/internal/loader/BootLoader.class", + "/modules/java.base/java/lang/Module$EnableNativeAccess.class", + "/modules/java.base/jdk/internal/loader/NativeLibraries.class", + "/modules/java.base/jdk/internal/loader/ClassLoaderHelper.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$CollectionView.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$KeySetView.class", + "/modules/java.base/jdk/internal/loader/NativeLibraries$LibraryPaths.class", + "/modules/java.base/java/io/File$PathStatus.class", + "/modules/java.base/jdk/internal/loader/NativeLibraries$CountedLock.class", + "/modules/java.base/java/util/concurrent/locks/AbstractQueuedSynchronizer.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantLock$Sync.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantLock$NonfairSync.class", + "/modules/java.base/jdk/internal/loader/NativeLibraries$NativeLibraryContext.class", + "/modules/java.base/java/util/Queue.class", + "/modules/java.base/java/util/Deque.class", + "/modules/java.base/java/util/ArrayDeque.class", + "/modules/java.base/java/util/ArrayDeque$DeqIterator.class", + "/modules/java.base/jdk/internal/loader/NativeLibrary.class", + "/modules/java.base/jdk/internal/loader/NativeLibraries$NativeLibraryImpl.class", + "/modules/java.base/java/security/cert/Certificate.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$ValuesView.class", + "/modules/java.base/java/util/Enumeration.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$Traverser.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$BaseIterator.class", + "/modules/java.base/java/util/concurrent/ConcurrentHashMap$ValueIterator.class", + "/modules/java.base/java/nio/file/attribute/BasicFileAttributes.class", + "/modules/java.base/java/nio/file/attribute/PosixFileAttributes.class", + "/modules/java.base/sun/nio/fs/UnixFileAttributes.class", + "/modules/java.base/sun/nio/fs/UnixFileStoreAttributes.class", + "/modules/java.base/sun/nio/fs/UnixMountEntry.class", + "/modules/java.base/java/nio/file/CopyOption.class", + "/modules/java.base/java/nio/file/LinkOption.class", + "/modules/java.base/java/nio/file/Files.class", + "/modules/java.base/sun/nio/fs/NativeBuffers.class", + "/modules/java.base/java/lang/ThreadLocal.class", + "/modules/java.base/jdk/internal/misc/CarrierThreadLocal.class", + "/modules/java.base/jdk/internal/misc/TerminatingThreadLocal.class", + "/modules/java.base/java/lang/ThreadLocal$ThreadLocalMap.class", + "/modules/java.base/java/lang/ThreadLocal$ThreadLocalMap$Entry.class", + "/modules/java.base/java/util/IdentityHashMap.class", + "/modules/java.base/java/util/Collections$SetFromMap.class", + "/modules/java.base/java/util/IdentityHashMap$KeySet.class", + "/modules/java.base/sun/nio/fs/NativeBuffer.class", + "/modules/java.base/jdk/internal/ref/CleanerFactory.class", + "/modules/java.base/java/util/concurrent/ThreadFactory.class", + "/modules/java.base/java/lang/ref/Cleaner.class", + "/modules/java.base/jdk/internal/ref/CleanerImpl.class", + "/modules/java.base/jdk/internal/ref/CleanerImpl$CleanableList.class", + "/modules/java.base/jdk/internal/ref/CleanerImpl$CleanableList$Node.class", + "/modules/java.base/java/lang/ref/Cleaner$Cleanable.class", + "/modules/java.base/jdk/internal/ref/PhantomCleanable.class", + "/modules/java.base/jdk/internal/ref/CleanerImpl$CleanerCleanable.class", + "/modules/java.base/jdk/internal/misc/InnocuousThread.class", + "/modules/java.base/sun/nio/fs/NativeBuffer$Deallocator.class", + "/modules/java.base/jdk/internal/ref/CleanerImpl$PhantomCleanableRef.class", + "/modules/java.base/java/lang/module/ModuleFinder.class", + "/modules/java.base/jdk/internal/module/ModulePath.class", + "/modules/java.base/java/util/jar/Attributes$Name.class", + "/modules/java.base/java/lang/reflect/Array.class", + "/modules/java.base/jdk/internal/perf/PerfCounter.class", + "/modules/java.base/jdk/internal/perf/Perf.class", + "/modules/java.base/sun/nio/ch/DirectBuffer.class", + "/modules/java.base/java/nio/MappedByteBuffer.class", + "/modules/java.base/java/nio/DirectByteBuffer.class", + "/modules/java.base/java/nio/Bits.class", + "/modules/java.base/java/util/concurrent/atomic/AtomicLong.class", + "/modules/java.base/jdk/internal/misc/VM$BufferPool.class", + "/modules/java.base/java/nio/LongBuffer.class", + "/modules/java.base/java/nio/DirectLongBufferU.class", + "/modules/java.base/java/util/zip/ZipConstants.class", + "/modules/java.base/java/util/zip/ZipFile.class", + "/modules/java.base/java/util/jar/JarFile.class", + "/modules/java.base/java/util/BitSet.class", + "/modules/java.base/jdk/internal/access/JavaUtilZipFileAccess.class", + "/modules/java.base/jdk/internal/access/JavaUtilJarAccess.class", + "/modules/java.base/java/util/jar/JavaUtilJarAccessImpl.class", + "/modules/java.base/java/lang/Runtime$Version.class", + "/modules/java.base/java/util/ImmutableCollections$List12.class", + "/modules/java.base/java/util/Optional.class", + "/modules/java.base/java/nio/file/attribute/DosFileAttributes.class", + "/modules/java.base/java/nio/file/attribute/AttributeView.class", + "/modules/java.base/java/nio/file/attribute/FileAttributeView.class", + "/modules/java.base/java/nio/file/attribute/BasicFileAttributeView.class", + "/modules/java.base/java/nio/file/attribute/DosFileAttributeView.class", + "/modules/java.base/java/nio/file/attribute/UserDefinedFileAttributeView.class", + "/modules/java.base/sun/nio/fs/UnixFileAttributeViews.class", + "/modules/java.base/sun/nio/fs/DynamicFileAttributeView.class", + "/modules/java.base/sun/nio/fs/AbstractBasicFileAttributeView.class", + "/modules/java.base/sun/nio/fs/UnixFileAttributeViews$Basic.class", + "/modules/java.base/sun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes.class", + "/modules/java.base/java/nio/file/DirectoryStream$Filter.class", + "/modules/java.base/java/nio/file/Files$AcceptAllFilter.class", + "/modules/java.base/java/nio/file/DirectoryStream.class", + "/modules/java.base/java/nio/file/SecureDirectoryStream.class", + "/modules/java.base/sun/nio/fs/UnixSecureDirectoryStream.class", + "/modules/java.base/sun/nio/fs/UnixDirectoryStream.class", + "/modules/java.base/java/util/concurrent/locks/ReadWriteLock.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.class", + "/modules/java.base/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock$Sync.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock$FairSync.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock.class", + "/modules/java.base/java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock.class", + "/modules/java.base/sun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator.class", + "/modules/java.base/java/nio/file/attribute/FileAttribute.class", + "/modules/java.base/sun/nio/fs/UnixFileModeAttribute.class", + "/modules/java.base/sun/nio/fs/UnixChannelFactory.class", + "/modules/java.base/sun/nio/fs/UnixChannelFactory$Flags.class", + "/modules/java.base/java/util/Collections$EmptyIterator.class", + "/modules/java.base/java/nio/channels/Channel.class", + "/modules/java.base/java/nio/channels/ReadableByteChannel.class", + "/modules/java.base/java/nio/channels/WritableByteChannel.class", + "/modules/java.base/java/nio/channels/ByteChannel.class", + "/modules/java.base/java/nio/channels/SeekableByteChannel.class", + "/modules/java.base/java/nio/channels/GatheringByteChannel.class", + "/modules/java.base/java/nio/channels/ScatteringByteChannel.class", + "/modules/java.base/java/nio/channels/InterruptibleChannel.class", + "/modules/java.base/java/nio/channels/spi/AbstractInterruptibleChannel.class", + "/modules/java.base/java/nio/channels/FileChannel.class", + "/modules/java.base/sun/nio/ch/FileChannelImpl.class", + "/modules/java.base/sun/nio/ch/NativeDispatcher.class", + "/modules/java.base/sun/nio/ch/FileDispatcher.class", + "/modules/java.base/sun/nio/ch/UnixFileDispatcherImpl.class", + "/modules/java.base/sun/nio/ch/FileDispatcherImpl.class", + "/modules/java.base/sun/nio/ch/IOUtil.class", + "/modules/java.base/sun/nio/ch/Interruptible.class", + "/modules/java.base/sun/nio/ch/NativeThreadSet.class", + "/modules/java.base/sun/nio/ch/FileChannelImpl$Closer.class", + "/modules/java.base/java/nio/channels/Channels.class", + "/modules/java.base/sun/nio/ch/Streams.class", + "/modules/java.base/sun/nio/ch/SelChImpl.class", + "/modules/java.base/java/nio/channels/NetworkChannel.class", + "/modules/java.base/java/nio/channels/SelectableChannel.class", + "/modules/java.base/java/nio/channels/spi/AbstractSelectableChannel.class", + "/modules/java.base/java/nio/channels/SocketChannel.class", + "/modules/java.base/sun/nio/ch/SocketChannelImpl.class", + "/modules/java.base/sun/nio/ch/ChannelInputStream.class", + "/modules/java.base/java/lang/invoke/LambdaMetafactory.class", + "/modules/java.base/java/util/function/Supplier.class", + "/modules/java.base/jdk/internal/util/ReferencedKeySet.class", + "/modules/java.base/jdk/internal/util/ReferencedKeyMap.class", + "/modules/java.base/jdk/internal/util/ReferenceKey.class", + "/modules/java.base/jdk/internal/util/StrongReferenceKey.class", + "/modules/java.base/java/lang/invoke/MethodTypeForm.class", + "/modules/java.base/jdk/internal/util/WeakReferenceKey.class", + "/modules/java.base/sun/invoke/util/Wrapper.class", + "/modules/java.base/sun/invoke/util/Wrapper$Format.class", + "/modules/java.base/java/lang/constant/ConstantDescs.class", + "/modules/java.base/java/lang/constant/ClassDesc.class", + "/modules/java.base/jdk/internal/constant/ClassOrInterfaceDescImpl.class", + "/modules/java.base/jdk/internal/constant/ArrayClassDescImpl.class", + "/modules/java.base/jdk/internal/constant/ConstantUtils.class", + "/modules/java.base/java/lang/constant/DirectMethodHandleDesc$Kind.class", + "/modules/java.base/java/lang/constant/MethodTypeDesc.class", + "/modules/java.base/jdk/internal/constant/MethodTypeDescImpl.class", + "/modules/java.base/java/lang/constant/MethodHandleDesc.class", + "/modules/java.base/java/lang/constant/DirectMethodHandleDesc.class", + "/modules/java.base/jdk/internal/constant/DirectMethodHandleDescImpl.class", + "/modules/java.base/java/lang/constant/DynamicConstantDesc.class", + "/modules/java.base/jdk/internal/constant/PrimitiveClassDescImpl.class", + "/modules/java.base/java/lang/constant/DynamicConstantDesc$AnonymousDynamicConstantDesc.class", + "/modules/java.base/java/lang/invoke/LambdaForm$NamedFunction.class", + "/modules/java.base/java/lang/invoke/DirectMethodHandle$Holder.class", + "/modules/java.base/sun/invoke/util/ValueConversions.class", + "/modules/java.base/java/lang/invoke/MethodHandleImpl.class", + "/modules/java.base/java/lang/invoke/Invokers.class", + "/modules/java.base/java/lang/invoke/LambdaForm$Kind.class", + "/modules/java.base/java/lang/NoSuchMethodException.class", + "/modules/java.base/java/lang/invoke/LambdaForm$BasicType.class", + "/modules/java.base/java/lang/classfile/TypeKind.class", + "/modules/java.base/java/lang/invoke/LambdaForm$Name.class", + "/modules/java.base/java/lang/invoke/LambdaForm$Holder.class", + "/modules/java.base/java/lang/invoke/InvokerBytecodeGenerator.class", + "/modules/java.base/java/lang/classfile/AnnotationElement.class", + "/modules/java.base/java/lang/classfile/Annotation.class", + "/modules/java.base/java/lang/classfile/constantpool/ConstantPool.class", + "/modules/java.base/java/lang/classfile/constantpool/ConstantPoolBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/TemporaryConstantPool.class", + "/modules/java.base/java/lang/classfile/constantpool/PoolEntry.class", + "/modules/java.base/java/lang/classfile/constantpool/AnnotationConstantValueEntry.class", + "/modules/java.base/java/lang/classfile/constantpool/Utf8Entry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$Utf8EntryImpl.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$Utf8EntryImpl$State.class", + "/modules/java.base/jdk/internal/classfile/impl/AnnotationImpl.class", + "/modules/java.base/java/lang/classfile/ClassFileElement.class", + "/modules/java.base/java/lang/classfile/Attribute.class", + "/modules/java.base/java/lang/classfile/ClassElement.class", + "/modules/java.base/java/lang/classfile/MethodElement.class", + "/modules/java.base/java/lang/classfile/FieldElement.class", + "/modules/java.base/java/lang/classfile/attribute/RuntimeVisibleAnnotationsAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/Util$Writable.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractElement.class", + "/modules/java.base/jdk/internal/classfile/impl/UnboundAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleAnnotationsAttribute.class", + "/modules/java.base/java/lang/classfile/Attributes.class", + "/modules/java.base/java/lang/classfile/AttributeMapper.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractAttributeMapper.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractAttributeMapper$RuntimeVisibleAnnotationsMapper.class", + "/modules/java.base/java/lang/classfile/AttributeMapper$AttributeStability.class", + "/modules/java.base/java/lang/invoke/MethodHandleImpl$Intrinsic.class", + "/modules/java.base/jdk/internal/classfile/impl/SplitConstantPool.class", + "/modules/java.base/java/lang/classfile/BootstrapMethodEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/BootstrapMethodEntryImpl.class", + "/modules/java.base/jdk/internal/classfile/impl/EntryMap.class", + "/modules/java.base/jdk/internal/classfile/impl/Util.class", + "/modules/java.base/java/lang/classfile/constantpool/LoadableConstantEntry.class", + "/modules/java.base/java/lang/classfile/constantpool/ClassEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$AbstractRefEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$AbstractNamedEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$ClassEntryImpl.class", + "/modules/java.base/java/util/function/Consumer.class", + "/modules/java.base/java/lang/classfile/ClassFile.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassFileImpl.class", + "/modules/java.base/java/lang/classfile/ClassFileBuilder.class", + "/modules/java.base/java/lang/classfile/ClassBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractDirectBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/DirectClassBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/AttributeHolder.class", + "/modules/java.base/java/lang/classfile/Superclass.class", + "/modules/java.base/jdk/internal/classfile/impl/SuperclassImpl.class", + "/modules/java.base/java/lang/classfile/attribute/SourceFileAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceFileAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractAttributeMapper$SourceFileMapper.class", + "/modules/java.base/jdk/internal/classfile/impl/BoundAttribute.class", + "/modules/java.base/java/lang/classfile/MethodBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/MethodInfo.class", + "/modules/java.base/jdk/internal/classfile/impl/TerminalMethodBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/DirectMethodBuilder.class", + "/modules/java.base/java/lang/classfile/constantpool/NameAndTypeEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$AbstractRefsEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$NameAndTypeEntryImpl.class", + "/modules/java.base/java/lang/classfile/constantpool/MemberRefEntry.class", + "/modules/java.base/java/lang/classfile/constantpool/FieldRefEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$AbstractMemberRefEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$FieldRefEntryImpl.class", + "/modules/java.base/java/lang/invoke/InvokerBytecodeGenerator$ClassData.class", + "/modules/java.base/java/lang/classfile/CodeBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/LabelContext.class", + "/modules/java.base/jdk/internal/classfile/impl/TerminalCodeBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/DirectCodeBuilder.class", + "/modules/java.base/java/lang/classfile/CodeElement.class", + "/modules/java.base/java/lang/classfile/PseudoInstruction.class", + "/modules/java.base/java/lang/classfile/instruction/CharacterRange.class", + "/modules/java.base/java/lang/classfile/instruction/LocalVariable.class", + "/modules/java.base/java/lang/classfile/instruction/LocalVariableType.class", + "/modules/java.base/jdk/internal/classfile/impl/DirectCodeBuilder$DeferredLabel.class", + "/modules/java.base/java/lang/classfile/BufWriter.class", + "/modules/java.base/jdk/internal/classfile/impl/BufWriterImpl.class", + "/modules/java.base/java/lang/classfile/Label.class", + "/modules/java.base/java/lang/classfile/instruction/LabelTarget.class", + "/modules/java.base/jdk/internal/classfile/impl/LabelImpl.class", + "/modules/java.base/sun/invoke/util/VerifyType.class", + "/modules/java.base/java/lang/classfile/Opcode.class", + "/modules/java.base/java/lang/classfile/Opcode$Kind.class", + "/modules/java.base/java/lang/classfile/constantpool/MethodRefEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$MethodRefEntryImpl.class", + "/modules/java.base/sun/invoke/empty/Empty.class", + "/modules/java.base/jdk/internal/classfile/impl/BytecodeHelpers.class", + "/modules/java.base/jdk/internal/classfile/impl/UnboundAttribute$AdHocAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractAttributeMapper$CodeMapper.class", + "/modules/java.base/java/lang/classfile/FieldBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/TerminalFieldBuilder.class", + "/modules/java.base/jdk/internal/classfile/impl/DirectFieldBuilder.class", + "/modules/java.base/java/lang/classfile/CustomAttribute.class", + "/modules/java.base/jdk/internal/classfile/impl/AnnotationReader.class", + "/modules/java.base/java/util/ListIterator.class", + "/modules/java.base/java/util/ImmutableCollections$ListItr.class", + "/modules/java.base/jdk/internal/classfile/impl/StackMapGenerator.class", + "/modules/java.base/jdk/internal/classfile/impl/StackMapGenerator$Frame.class", + "/modules/java.base/jdk/internal/classfile/impl/StackMapGenerator$Type.class", + "/modules/java.base/jdk/internal/classfile/impl/RawBytecodeHelper.class", + "/modules/java.base/jdk/internal/classfile/impl/RawBytecodeHelper$CodeRange.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassHierarchyImpl.class", + "/modules/java.base/java/lang/classfile/ClassHierarchyResolver.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassHierarchyImpl$ClassLoadingClassHierarchyResolver.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassHierarchyImpl$CachedClassHierarchyResolver.class", + "/modules/java.base/java/lang/classfile/ClassHierarchyResolver$ClassHierarchyInfo.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassHierarchyImpl$ClassHierarchyInfoImpl.class", + "/modules/java.base/java/lang/classfile/ClassReader.class", + "/modules/java.base/jdk/internal/classfile/impl/ClassReaderImpl.class", + "/modules/java.base/jdk/internal/util/ModifiedUtf.class", + "/modules/java.base/java/lang/invoke/MethodHandles$Lookup$ClassDefiner.class", + "/modules/java.base/java/lang/IncompatibleClassChangeError.class", + "/modules/java.base/java/lang/NoSuchMethodError.class", + "/modules/java.base/java/lang/invoke/BootstrapMethodInvoker.class", + "/modules/java.base/java/lang/invoke/AbstractValidatingLambdaMetafactory.class", + "/modules/java.base/java/lang/invoke/InnerClassLambdaMetafactory.class", + "/modules/java.base/java/lang/invoke/MethodHandleInfo.class", + "/modules/java.base/java/lang/invoke/InfoFromMemberName.class", + "/modules/java.base/java/util/ImmutableCollections$Access.class", + "/modules/java.base/jdk/internal/access/JavaUtilCollectionAccess.class", + "/modules/java.base/java/lang/classfile/Interfaces.class", + "/modules/java.base/jdk/internal/classfile/impl/InterfacesImpl.class", + "/modules/java.base/java/lang/invoke/TypeConvertingMethodAdapter.class", + "/modules/java.base/java/lang/invoke/DirectMethodHandle$Constructor.class", + "/modules/java.base/jdk/internal/access/JavaLangInvokeAccess.class", + "/modules/java.base/java/lang/invoke/VarHandle$AccessMode.class", + "/modules/java.base/java/lang/invoke/VarHandle$AccessType.class", + "/modules/java.base/java/lang/invoke/Invokers$Holder.class", + "/modules/java.base/jdk/internal/module/ModuleInfo.class", + "/modules/java.base/java/io/DataInput.class", + "/modules/java.base/java/io/DataInputStream.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$CountingDataInput.class", + "/modules/java.base/sun/nio/ch/NativeThread.class", + "/modules/java.base/jdk/internal/misc/Blocker.class", + "/modules/java.base/sun/nio/ch/Util.class", + "/modules/java.base/sun/nio/ch/Util$BufferCache.class", + "/modules/java.base/sun/nio/ch/IOStatus.class", + "/modules/java.base/jdk/internal/util/ByteArray.class", + "/modules/java.base/java/lang/invoke/VarHandles.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsShorts$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsShorts$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleGuards.class", + "/modules/java.base/java/lang/invoke/VarForm.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsChars$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsChars$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsInts$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsInts$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsFloats$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsFloats$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsLongs$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsLongs$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsDoubles$ByteArrayViewVarHandle.class", + "/modules/java.base/java/lang/invoke/VarHandleByteArrayAsDoubles$ArrayHandle.class", + "/modules/java.base/java/lang/invoke/VarHandle$AccessDescriptor.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$ConstantPool.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$ConstantPool$Entry.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$ConstantPool$IndexEntry.class", + "/modules/java.base/java/nio/charset/StandardCharsets.class", + "/modules/java.base/sun/nio/cs/US_ASCII.class", + "/modules/java.base/sun/nio/cs/ISO_8859_1.class", + "/modules/java.base/sun/nio/cs/UTF_16BE.class", + "/modules/java.base/sun/nio/cs/UTF_16LE.class", + "/modules/java.base/sun/nio/cs/UTF_16.class", + "/modules/java.base/sun/nio/cs/UTF_32BE.class", + "/modules/java.base/sun/nio/cs/UTF_32LE.class", + "/modules/java.base/sun/nio/cs/UTF_32.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$ConstantPool$ValueEntry.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Builder.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Modifier.class", + "/modules/java.base/java/lang/reflect/AccessFlag.class", + "/modules/java.base/java/lang/reflect/AccessFlag$Location.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Requires$Modifier.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Requires.class", + "/modules/java.base/java/util/HashMap$KeySet.class", + "/modules/java.base/java/util/HashMap$KeyIterator.class", + "/modules/java.base/jdk/internal/module/Checks.class", + "/modules/java.base/java/util/ArrayList$Itr.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Provides.class", + "/modules/java.base/java/util/Collections$UnmodifiableCollection.class", + "/modules/java.base/java/util/Collections$UnmodifiableSet.class", + "/modules/java.base/java/util/HashMap$Values.class", + "/modules/java.base/java/util/HashMap$ValueIterator.class", + "/modules/java.base/java/util/ImmutableCollections$SetN$SetNIterator.class", + "/modules/java.base/jdk/internal/module/ModuleInfo$Attributes.class", + "/modules/java.base/jdk/internal/module/ModuleReferences.class", + "/modules/java.base/java/lang/module/ModuleReader.class", + "/modules/java.base/sun/nio/fs/UnixUriUtils.class", + "/modules/java.base/java/net/URI$Parser.class", + "/modules/java.base/java/lang/module/ModuleReference.class", + "/modules/java.base/jdk/internal/module/ModuleReferenceImpl.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Exports.class", + "/modules/java.base/java/lang/module/ModuleDescriptor$Opens.class", + "/modules/java.base/sun/nio/fs/UnixException.class", + "/modules/java.base/java/io/IOException.class", + "/modules/java.base/jdk/internal/loader/ArchivedClassLoaders.class", + "/modules/java.base/jdk/internal/loader/ClassLoaders$BootClassLoader.class", + "/modules/java.base/java/lang/ClassLoader$ParallelLoaders.class", + "/modules/java.base/java/util/WeakHashMap.class", + "/modules/java.base/java/util/WeakHashMap$Entry.class", + "/modules/java.base/java/util/WeakHashMap$KeySet.class", + "/modules/java.base/java/security/Principal.class", + "/modules/java.base/jdk/internal/loader/URLClassPath.class", + "/modules/java.base/java/net/URLStreamHandlerFactory.class", + "/modules/java.base/java/net/URL$DefaultFactory.class", + "/modules/java.base/jdk/internal/access/JavaNetURLAccess.class", + "/modules/java.base/sun/net/www/ParseUtil.class", + "/modules/java.base/java/net/URLStreamHandler.class", + "/modules/java.base/sun/net/www/protocol/file/Handler.class", + "/modules/java.base/sun/net/util/IPAddressUtil.class", + "/modules/java.base/sun/net/util/IPAddressUtil$MASKS.class", + "/modules/java.base/sun/net/www/protocol/jar/Handler.class", + "/modules/java.base/jdk/internal/module/ServicesCatalog.class", + "/modules/java.base/jdk/internal/loader/AbstractClassLoaderValue.class", + "/modules/java.base/jdk/internal/loader/ClassLoaderValue.class", + "/modules/java.base/jdk/internal/loader/BuiltinClassLoader$LoadedModule.class", + "/modules/java.base/jdk/internal/module/DefaultRoots.class", + "/modules/java.base/java/util/Spliterator.class", + "/modules/java.base/java/util/HashMap$HashMapSpliterator.class", + "/modules/java.base/java/util/HashMap$ValueSpliterator.class", + "/modules/java.base/java/util/stream/StreamSupport.class", + "/modules/java.base/java/util/stream/BaseStream.class", + "/modules/java.base/java/util/stream/Stream.class", + "/modules/java.base/java/util/stream/PipelineHelper.class", + "/modules/java.base/java/util/stream/AbstractPipeline.class", + "/modules/java.base/java/util/stream/ReferencePipeline.class", + "/modules/java.base/java/util/stream/ReferencePipeline$Head.class", + "/modules/java.base/java/util/stream/StreamOpFlag.class", + "/modules/java.base/java/util/stream/StreamOpFlag$Type.class", + "/modules/java.base/java/util/stream/StreamOpFlag$MaskBuilder.class", + "/modules/java.base/java/util/EnumMap.class", + "/modules/java.base/java/lang/Class$ReflectionData.class", + "/modules/java.base/java/lang/Class$Atomic.class", + "/modules/java.base/java/lang/PublicMethods$MethodList.class", + "/modules/java.base/java/lang/PublicMethods$Key.class", + "/modules/java.base/sun/reflect/annotation/AnnotationParser.class", + "/modules/java.base/jdk/internal/reflect/MethodHandleAccessorFactory.class", + "/modules/java.base/jdk/internal/reflect/MethodHandleAccessorFactory$LazyStaticHolder.class", + "/modules/java.base/java/lang/invoke/BoundMethodHandle.class", + "/modules/java.base/java/lang/invoke/ClassSpecializer.class", + "/modules/java.base/java/lang/invoke/BoundMethodHandle$Specializer.class", + "/modules/java.base/jdk/internal/vm/annotation/Stable.class", + "/modules/java.base/java/lang/invoke/ClassSpecializer$SpeciesData.class", + "/modules/java.base/java/lang/invoke/BoundMethodHandle$SpeciesData.class", + "/modules/java.base/java/lang/invoke/ClassSpecializer$Factory.class", + "/modules/java.base/java/lang/invoke/BoundMethodHandle$Specializer$Factory.class", + "/modules/java.base/java/lang/invoke/SimpleMethodHandle.class", + "/modules/java.base/java/lang/NoSuchFieldException.class", + "/modules/java.base/java/lang/invoke/BoundMethodHandle$Species_L.class", + "/modules/java.base/java/lang/invoke/DirectMethodHandle$Accessor.class", + "/modules/java.base/java/lang/invoke/DelegatingMethodHandle.class", + "/modules/java.base/java/lang/invoke/DelegatingMethodHandle$Holder.class", + "/modules/java.base/java/lang/invoke/LambdaFormEditor.class", + "/modules/java.base/java/lang/invoke/LambdaFormEditor$TransformKey.class", + "/modules/java.base/java/lang/invoke/LambdaFormBuffer.class", + "/modules/java.base/java/lang/invoke/LambdaFormEditor$Transform.class", + "/modules/java.base/jdk/internal/reflect/DirectMethodHandleAccessor.class", + "/modules/java.base/java/util/stream/Collectors.class", + "/modules/java.base/java/util/stream/Collector$Characteristics.class", + "/modules/java.base/java/util/EnumSet.class", + "/modules/java.base/java/util/RegularEnumSet.class", + "/modules/java.base/java/util/stream/Collector.class", + "/modules/java.base/java/util/stream/Collectors$CollectorImpl.class", + "/modules/java.base/java/util/function/BiConsumer.class", + "/modules/java.base/java/lang/invoke/DirectMethodHandle$Interface.class", + "/modules/java.base/java/lang/classfile/constantpool/InterfaceMethodRefEntry.class", + "/modules/java.base/jdk/internal/classfile/impl/AbstractPoolEntry$InterfaceMethodRefEntryImpl.class", + "/modules/java.base/java/util/function/BinaryOperator.class", + "/modules/java.base/java/util/stream/ReduceOps.class", + "/modules/java.base/java/util/stream/TerminalOp.class", + "/modules/java.base/java/util/stream/ReduceOps$ReduceOp.class", + "/modules/java.base/java/util/stream/StreamShape.class", + "/modules/java.base/java/util/stream/Sink.class", + "/modules/java.base/java/util/stream/TerminalSink.class", + "/modules/java.base/java/util/stream/ReduceOps$AccumulatingSink.class", + "/modules/java.base/java/util/stream/ReduceOps$Box.class", + "/modules/java.base/java/util/HashMap$KeySpliterator.class", + "/modules/java.base/java/util/function/Predicate.class", + "/modules/java.base/java/util/stream/ReferencePipeline$StatelessOp.class", + "/modules/java.base/java/util/stream/Sink$ChainedReference.class", + "/modules/java.base/jdk/internal/module/ModuleResolution.class", + "/modules/java.base/java/util/stream/FindOps.class", + "/modules/java.base/java/util/stream/FindOps$FindSink.class", + "/modules/java.base/java/util/stream/FindOps$FindSink$OfRef.class", + "/modules/java.base/java/util/stream/FindOps$FindOp.class", + "/modules/java.base/java/util/Spliterators.class", + "/modules/java.base/java/util/Spliterators$IteratorSpliterator.class", + "/modules/java.base/java/lang/module/Configuration.class", + "/modules/java.base/java/lang/module/Resolver.class", + "/modules/java.base/java/lang/ModuleLayer.class", + "/modules/java.base/java/util/SequencedSet.class", + "/modules/java.base/java/util/LinkedHashSet.class", + "/modules/java.base/java/util/SequencedMap.class", + "/modules/java.base/java/util/LinkedHashMap.class", + "/modules/java.base/java/lang/module/ResolvedModule.class", + "/modules/java.base/jdk/internal/module/ModuleLoaderMap$Mapper.class", + "/modules/java.base/jdk/internal/loader/AbstractClassLoaderValue$Memoizer.class", + "/modules/java.base/jdk/internal/module/ServicesCatalog$ServiceProvider.class", + "/modules/java.base/java/util/concurrent/CopyOnWriteArrayList.class", + "/modules/java.base/java/lang/ModuleLayer$Controller.class", + "/modules/java.base/jdk/internal/module/ModuleBootstrap$SafeModuleFinder.class", + "/modules/java.base/jdk/internal/vm/ContinuationSupport.class", + "/modules/java.base/jdk/internal/vm/Continuation$Pinned.class", + "/modules/java.base/sun/launcher/LauncherHelper.class", + "/modules/java.base/sun/net/util/URLUtil.class", + "/modules/java.base/jdk/internal/loader/URLClassPath$Loader.class", + "/modules/java.base/jdk/internal/loader/URLClassPath$FileLoader.class", + "/modules/java.base/jdk/internal/loader/Resource.class", + "/modules/java.base/java/io/FileCleanable.class", + "/modules/java.base/sun/nio/ByteBuffered.class", + "/modules/java.base/java/security/SecureClassLoader$CodeSourceKey.class", + "/modules/java.base/java/security/PermissionCollection.class", + "/modules/java.base/java/security/Permissions.class", + "/modules/java.base/java/lang/NamedPackage.class", + "/modules/java.base/jdk/internal/misc/MethodFinder.class", + "/modules/java.base/java/lang/Readable.class", + "/modules/java.base/java/nio/CharBuffer.class", + "/modules/java.base/java/nio/HeapCharBuffer.class", + "/modules/java.base/java/nio/charset/CoderResult.class", + "/modules/java.base/java/util/IdentityHashMap$IdentityHashMapIterator.class", + "/modules/java.base/java/util/IdentityHashMap$KeyIterator.class", + "/modules/java.base/java/lang/Shutdown.class", + "/modules/java.base/java/lang/Shutdown$Lock.class"); + + private static final Pattern SPLIT_MODULE_AND_PATH = Pattern.compile("/modules/([^/]+)/(.*)"); + + private static final Map> MODULE_TO_PATHS = INIT_CLASSES.stream() + .map(name -> { + Matcher m = SPLIT_MODULE_AND_PATH.matcher(name); + if (!m.matches()) { + throw new IllegalArgumentException("Bad resource name: " + name); + } + return m.toMatchResult(); + }) + .collect(groupingBy(m -> m.group(1), mapping(m -> m.group(2), toList()))); + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/AckermannBase.java b/test/micro/org/openjdk/bench/valhalla/ackermann/AckermannBase.java index d2e4cbb09f7..55e44dd8a33 100644 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/AckermannBase.java +++ b/test/micro/org/openjdk/bench/valhalla/ackermann/AckermannBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -41,7 +41,7 @@ @State(Scope.Thread) public abstract class AckermannBase { - // ackermann(1,1748)+ ackermann(2,1897)+ ackermann(3,8); == 9999999 calls + // ackermann(1,1748) + ackermann(2,1897) + ackermann(3,8) == 9999999 invocations // max depth - 3798 public static final int X1 = 1; public static final int Y1 = 1748; diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/IdentityLong.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Identity.java similarity index 50% rename from test/micro/org/openjdk/bench/valhalla/ackermann/IdentityLong.java rename to test/micro/org/openjdk/bench/valhalla/ackermann/Identity.java index b26c0da6365..0ad0836fc23 100644 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/IdentityLong.java +++ b/test/micro/org/openjdk/bench/valhalla/ackermann/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,22 +25,40 @@ import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.OperationsPerInvocation; -public class IdentityLong extends AckermannBase { +public class Identity extends AckermannBase { - private static Long ack_Long(Long x, Long y) { - return x == 0 ? - y + 1 : - (y == 0 ? - ack_Long(x - 1, 1L) : - ack_Long(x - 1, ack_Long(x, y - 1))); + private static IdentityLong ack_identity(IdentityLong x, IdentityLong y) { + return x.value() == 0 ? + IdentityLong.valueOf(y.value() + 1) : + (y.value() == 0 ? + ack_identity(IdentityLong.valueOf(x.value() - 1), IdentityLong.valueOf(1)) : + ack_identity(IdentityLong.valueOf(x.value() - 1), ack_identity(x, IdentityLong.valueOf(y.value() - 1)))); } @Benchmark @OperationsPerInvocation(OPI) - public long ref_Long() { - return ack_Long(Long.valueOf(X1), Long.valueOf(Y1)) - + ack_Long(Long.valueOf(X2), Long.valueOf(Y2)) - + ack_Long(Long.valueOf(X3), Long.valueOf(Y3)); + public long ackermann() { + return ack_identity(IdentityLong.valueOf(X1), IdentityLong.valueOf(Y1)).value() + + ack_identity(IdentityLong.valueOf(X2), IdentityLong.valueOf(Y2)).value() + + ack_identity(IdentityLong.valueOf(X3), IdentityLong.valueOf(Y3)).value(); + } + + public static class IdentityLong { + + public final long v0; + + public IdentityLong(long v0) { + this.v0 = v0; + } + + public long value() { + return v0; + } + + public static IdentityLong valueOf(long value) { + return new IdentityLong(value); + } + } } diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64byte.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64byte.java deleted file mode 100644 index bb085fb0c44..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64byte.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Identity64byte extends AckermannBase { - - private static R64byte ack_ref(R64byte x, R64byte y) { - return x.longValue() == 0 ? - new R64byte(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new R64byte(x.longValue()-1) , new R64byte(1)) : - ack_ref(new R64byte(x.longValue()-1), ack_ref(x, new R64byte(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new R64byte(X1), new R64byte(Y1)).longValue() - + ack_ref(new R64byte(X2), new R64byte(Y2)).longValue() - + ack_ref(new R64byte(X3), new R64byte(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new R64byte(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new R64byte(x.longValue()-1) , new R64byte(1)) : - ack_inter(new R64byte(x.longValue()-1), ack_inter(x, new R64byte(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new R64byte(X1), new R64byte(Y1)).longValue() - + ack_inter(new R64byte(X2), new R64byte(Y2)).longValue() - + ack_inter(new R64byte(X3), new R64byte(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64int.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64int.java deleted file mode 100644 index 8462cc3f20a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64int.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Identity64int extends AckermannBase { - - private static R64int ack_ref(R64int x, R64int y) { - return x.longValue() == 0 ? - new R64int(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new R64int(x.longValue()-1) , new R64int(1)) : - ack_ref(new R64int(x.longValue()-1), ack_ref(x, new R64int(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new R64int(X1), new R64int(Y1)).longValue() - + ack_ref(new R64int(X2), new R64int(Y2)).longValue() - + ack_ref(new R64int(X3), new R64int(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new R64int(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new R64int(x.longValue()-1) , new R64int(1)) : - ack_inter(new R64int(x.longValue()-1), ack_inter(x, new R64int(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new R64int(X1), new R64int(Y1)).longValue() - + ack_inter(new R64int(X2), new R64int(Y2)).longValue() - + ack_inter(new R64int(X3), new R64int(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64long.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64long.java deleted file mode 100644 index a3eaad57f75..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Identity64long.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Identity64long extends AckermannBase { - - private static R64long ack_ref(R64long x, R64long y) { - return x.longValue() == 0 ? - new R64long(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new R64long(x.longValue()-1) , new R64long(1)) : - ack_ref(new R64long(x.longValue()-1), ack_ref(x, new R64long(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new R64long(X1), new R64long(Y1)).longValue() - + ack_ref(new R64long(X2), new R64long(Y2)).longValue() - + ack_ref(new R64long(X3), new R64long(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new R64long(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new R64long(x.longValue()-1) , new R64long(1)) : - ack_inter(new R64long(x.longValue()-1), ack_inter(x, new R64long(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new R64long(X1), new R64long(Y1)).longValue() - + ack_inter(new R64long(X2), new R64long(Y2)).longValue() - + ack_inter(new R64long(X3), new R64long(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64byte.java deleted file mode 100644 index 7d25d7a9dde..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64byte.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Inline64byte extends AckermannBase { - - private static Q64byte ack_value(Q64byte x, Q64byte y) { - return x.longValue() == 0 ? - new Q64byte(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_value(new Q64byte(x.longValue()-1) , new Q64byte(1)) : - ack_value(new Q64byte(x.longValue()-1), ack_value(x, new Q64byte(y.longValue()-1)))); - } - -// @Benchmark -// @OperationsPerInvocation(OPI) -// TODO fix StackOverflowException - public long ack_Val() { - return ack_value(new Q64byte(X1), new Q64byte(Y1)).longValue() - + ack_value(new Q64byte(X2), new Q64byte(Y2)).longValue() - + ack_value(new Q64byte(X3), new Q64byte(Y3)).longValue(); - } - - private static Q64byte ack_ref(Q64byte x, Q64byte y) { - return x.longValue() == 0 ? - new Q64byte(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new Q64byte(x.longValue()-1) , new Q64byte(1)) : - ack_ref(new Q64byte(x.longValue()-1), ack_ref(x, new Q64byte(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new Q64byte(X1), new Q64byte(Y1)).longValue() - + ack_ref(new Q64byte(X2), new Q64byte(Y2)).longValue() - + ack_ref(new Q64byte(X3), new Q64byte(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new Q64byte(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new Q64byte(x.longValue()-1) , new Q64byte(1)) : - ack_inter(new Q64byte(x.longValue()-1), ack_inter(x, new Q64byte(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new Q64byte(X1), new Q64byte(Y1)).longValue() - + ack_inter(new Q64byte(X2), new Q64byte(Y2)).longValue() - + ack_inter(new Q64byte(X3), new Q64byte(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64int.java deleted file mode 100644 index 6a542813de6..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64int.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Inline64int extends AckermannBase { - - private static Q64int ack_value(Q64int x, Q64int y) { - return x.longValue() == 0 ? - new Q64int(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_value(new Q64int(x.longValue()-1) , new Q64int(1)) : - ack_value(new Q64int(x.longValue()-1), ack_value(x, new Q64int(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Val() { - return ack_value(new Q64int(X1), new Q64int(Y1)).longValue() - + ack_value(new Q64int(X2), new Q64int(Y2)).longValue() - + ack_value(new Q64int(X3), new Q64int(Y3)).longValue(); - } - - private static Q64int ack_ref(Q64int x, Q64int y) { - return x.longValue() == 0 ? - new Q64int(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new Q64int(x.longValue()-1) , new Q64int(1)) : - ack_ref(new Q64int(x.longValue()-1), ack_ref(x, new Q64int(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new Q64int(X1), new Q64int(Y1)).longValue() - + ack_ref(new Q64int(X2), new Q64int(Y2)).longValue() - + ack_ref(new Q64int(X3), new Q64int(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new Q64int(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new Q64int(x.longValue()-1) , new Q64int(1)) : - ack_inter(new Q64int(x.longValue()-1), ack_inter(x, new Q64int(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new Q64int(X1), new Q64int(Y1)).longValue() - + ack_inter(new Q64int(X2), new Q64int(Y2)).longValue() - + ack_inter(new Q64int(X3), new Q64int(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java deleted file mode 100644 index b075e928747..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.ackermann; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; - -public class Inline64long extends AckermannBase { - - private static Q64long ack_value(Q64long x, Q64long y) { - return x.longValue() == 0 ? - new Q64long(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_value(new Q64long(x.longValue()-1) , new Q64long(1)) : - ack_value(new Q64long(x.longValue()-1), ack_value(x, new Q64long(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Val() { - return ack_value(new Q64long(X1), new Q64long(Y1)).longValue() - + ack_value(new Q64long(X2), new Q64long(Y2)).longValue() - + ack_value(new Q64long(X3), new Q64long(Y3)).longValue(); - } - - private static Q64long ack_ref(Q64long x, Q64long y) { - return x.longValue() == 0 ? - new Q64long(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_ref(new Q64long(x.longValue()-1) , new Q64long(1)) : - ack_ref(new Q64long(x.longValue()-1), ack_ref(x, new Q64long(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Ref() { - return ack_ref(new Q64long(X1), new Q64long(Y1)).longValue() - + ack_ref(new Q64long(X2), new Q64long(Y2)).longValue() - + ack_ref(new Q64long(X3), new Q64long(Y3)).longValue(); - } - - private static Int64 ack_inter(Int64 x, Int64 y) { - return x.longValue() == 0 ? - new Q64long(y.longValue() + 1) : - (y.longValue() == 0 ? - ack_inter(new Q64long(x.longValue()-1) , new Q64long(1)) : - ack_inter(new Q64long(x.longValue()-1), ack_inter(x, new Q64long(y.longValue()-1)))); - } - - @Benchmark - @OperationsPerInvocation(OPI) - public long ack_Int() { - return ack_inter(new Q64long(X1), new Q64long(Y1)).longValue() - + ack_inter(new Q64long(X2), new Q64long(Y2)).longValue() - + ack_inter(new Q64long(X3), new Q64long(Y3)).longValue(); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Primitive64.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Primitive.java similarity index 91% rename from test/micro/org/openjdk/bench/valhalla/ackermann/Primitive64.java rename to test/micro/org/openjdk/bench/valhalla/ackermann/Primitive.java index c8a6b115c82..85f0e326a3f 100644 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Primitive64.java +++ b/test/micro/org/openjdk/bench/valhalla/ackermann/Primitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,7 +25,7 @@ import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.OperationsPerInvocation; -public class Primitive64 extends AckermannBase { +public class Primitive extends AckermannBase { private static long ack_primitive(long x, long y) { return x == 0 ? @@ -37,7 +37,7 @@ private static long ack_primitive(long x, long y) { @Benchmark @OperationsPerInvocation(OPI) - public long primitive() { + public long ackermann() { return ack_primitive(X1, Y1) + ack_primitive(X2, Y2) + ack_primitive(X3, Y3); diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Value.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Value.java new file mode 100644 index 00000000000..384bd1b2e72 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/ackermann/Value.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.ackermann; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.OperationsPerInvocation; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value extends AckermannBase { + + private static ValueLong ack_value(ValueLong x, ValueLong y) { + return x.value() == 0 ? + ValueLong.valueOf(y.value() + 1) : + (y.value() == 0 ? + ack_value(ValueLong.valueOf(x.value() - 1), ValueLong.valueOf(1)) : + ack_value(ValueLong.valueOf(x.value() - 1), ack_value(x, ValueLong.valueOf(y.value() - 1)))); + } + + @Benchmark + @OperationsPerInvocation(OPI) + public long ackermann_value() { + return ack_value(ValueLong.valueOf(X1), ValueLong.valueOf(Y1)).value() + + ack_value(ValueLong.valueOf(X2), ValueLong.valueOf(Y2)).value() + + ack_value(ValueLong.valueOf(X3), ValueLong.valueOf(Y3)).value(); + } + + private static InterfaceLong ack_value_as_Int(InterfaceLong x, InterfaceLong y) { + return x.value() == 0 ? + ValueLong.valueOf(y.value() + 1) : + (y.value() == 0 ? + ack_value_as_Int(ValueLong.valueOf(x.value() - 1), ValueLong.valueOf(1)) : + ack_value_as_Int(ValueLong.valueOf(x.value() - 1), ack_value_as_Int(x, ValueLong.valueOf(y.value() - 1)))); + } + + @Benchmark + @OperationsPerInvocation(OPI) + public long ackermann_interface() { + return ack_value_as_Int(ValueLong.valueOf(X1), ValueLong.valueOf(Y1)).value() + + ack_value_as_Int(ValueLong.valueOf(X2), ValueLong.valueOf(Y2)).value() + + ack_value_as_Int(ValueLong.valueOf(X3), ValueLong.valueOf(Y3)).value(); + } + + public static interface InterfaceLong { + public long value(); + } + + public static value class ValueLong implements InterfaceLong { + + public final long v0; + + public ValueLong(long v0) { + this.v0 = v0; + } + + public long value() { + return v0; + } + + public static ValueLong valueOf(long value) { + return new ValueLong(value); + } + + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Identity.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Identity.java new file mode 100644 index 00000000000..1ced050a126 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Identity.java @@ -0,0 +1,398 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Identity -wmb "org.openjdk.bench.valhalla.acmp.array.Identity.*050" + */ + +@Fork(3) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Identity { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(Object[] objects1, Object[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_ref(IdentityInt[] objects1, IdentityInt[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_ref(IdentityInt[] objects1, IdentityInt[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(Object[] objects1, Object[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals000(RefState00 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals025(RefState25 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals050(RefState50 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals075(RefState75 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals100(RefState100 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals000(RefState00 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals025(RefState25 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals050(RefState50 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals075(RefState75 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals100(RefState100 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + public static class IdentityInt { + + public final int v0; + + public IdentityInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = null; + arr2[0] = new IdentityInt(1); + arr1[1] = new IdentityInt(2); + arr2[1] = null; + for (int i = 2; i < SIZE; i++) { + arr1[i] = new IdentityInt(2 * i); + arr2[i] = new IdentityInt(2 * i + 1); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = null; + for (int i = 1; i < SIZE; i++) { + arr2[i] = arr1[i] = new IdentityInt(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = arr1[i] = null; + samenulls = false; + } else { + arr2[i] = arr1[i] = new IdentityInt(i); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = null; + arr2[i] = new IdentityInt(2 * i + 1); + distinctnulls = 1; + break; + case 1: + arr1[i] = new IdentityInt(2 * i); + arr2[i] = null; + distinctnulls = 2; + break; + default: + arr1[i] = new IdentityInt(2 * i); + arr2[i] = new IdentityInt(2 * i + 1); + break; + } + } + } + + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + Object[] arr1, arr2; + + public void setup(int eq) { + arr1 = new Object[SIZE]; + arr2 = new Object[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class RefState { + IdentityInt[] arr1, arr2; + + public void setup(int eq) { + arr1 = new IdentityInt[SIZE]; + arr2 = new IdentityInt[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class RefState00 extends RefState { + @Setup + public void setup() { + setup(0); + } + } + + public static class RefState25 extends RefState { + @Setup + public void setup() { + setup(25); + } + } + + public static class RefState50 extends RefState { + @Setup + public void setup() { + setup(50); + } + } + + public static class RefState75 extends RefState { + @Setup + public void setup() { + setup(75); + } + } + + public static class RefState100 extends RefState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpBranch.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpBranch.java deleted file mode 100644 index bff11fbdc69..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpBranch.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -/* - * For proper results it should be executed: - * java -jar target/benchmarks.jar IdentityIsCmpBranch -wmb IdentityIsCmpBranch.equals050 - */ - -@Fork(3) -@Warmup(iterations = 3, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class IdentityIsCmpBranch extends StatesR64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Obj(Object[] objects1, Object[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Ref(R64long[] objects1, R64long[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals000(RefState00 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals025(RefState25 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals050(RefState50 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals075(RefState75 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals100(RefState100 st) { - return cmp_Ref(st.arr1, st.arr2); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64byte.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64byte.java deleted file mode 100644 index 8852292a536..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64byte.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 3, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineIsCmpBranch64byte extends StatesQ64byte { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Obj(Object[] objects1, Object[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Int(Int64[] objects1, Int64[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Ref(Q64byte[] objects1, Q64byte[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Val(Q64byte[] objects1, Q64byte[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals000(IntState00 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals025(IntState25 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals050(IntState50 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals075(IntState75 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals100(IntState100 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals000(RefState00 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals025(RefState25 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals050(RefState50 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals075(RefState75 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals100(RefState100 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals000(ValState00 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals025(ValState25 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals050(ValState50 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals075(ValState75 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals100(ValState100 st) { - return cmp_Val(st.arr1, st.arr2); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64long.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64long.java deleted file mode 100644 index a3c5e57c159..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/InlineIsCmpBranch64long.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 3, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineIsCmpBranch64long extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Obj(Object[] objects1, Object[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Int(Int64[] objects1, Int64[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Ref(Q64long[] objects1, Q64long[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Val(Q64long[] objects1, Q64long[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] == objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals000(IntState00 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals025(IntState25 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals050(IntState50 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals075(IntState75 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals100(IntState100 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals000(RefState00 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals025(RefState25 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals050(RefState50 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals075(RefState75 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals100(RefState100 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals000(ValState00 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals025(ValState25 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals050(ValState50 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals075(ValState75 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals100(ValState100 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Ref_equals000(ValState00 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Ref_equals025(ValState25 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Ref_equals050(ValState50 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Ref_equals075(ValState75 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Ref_equals100(ValState100 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Int_equals000(ValState00 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Int_equals025(ValState25 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Int_equals050(ValState50 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Int_equals075(ValState75 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Int_equals100(ValState100 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Obj_equals000(ValState00 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Obj_equals025(ValState25 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Obj_equals050(ValState50 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Obj_equals075(ValState75 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_as_Obj_equals100(ValState100 st) { - return cmp_Obj(st.arr1, st.arr2); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64byte.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64byte.java deleted file mode 100644 index b04e52e831a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64byte.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import java.util.BitSet; -import java.util.Random; - -public class StatesQ64byte { - - public static final int SIZE = 100; - - private static BitSet indices(Random rnd, int bound, int size) { - return rnd.ints(0, bound) - .distinct() - .limit(size) - .collect(BitSet::new, BitSet::set, BitSet::or); - } - - private static void populate(Object[] arr1, Object[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new Q64byte(i); - } else { - arr1[i] = new Q64byte(2 * i); - arr2[i] = new Q64byte(2 * i + 1); - } - } - } - - @State(Scope.Thread) - public abstract static class ObjState { - Object[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class IntState { - Int64[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class RefState { - Q64byte[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class ValState { - Q64byte[] arr1, arr2; - } - - public static class ObjState00 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 0); - } - - } - - public static class ObjState25 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 25); - } - - } - - public static class ObjState50 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 50); - } - - } - - public static class ObjState75 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 75); - } - - } - - public static class ObjState100 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class IntState00 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class IntState25 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class IntState50 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class IntState75 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class IntState100 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class RefState00 extends RefState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class RefState25 extends RefState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class RefState50 extends RefState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class RefState75 extends RefState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class RefState100 extends RefState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class ValState00 extends ValState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class ValState25 extends ValState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class ValState50 extends ValState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class ValState75 extends ValState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class ValState100 extends ValState { - @Setup - public void setup() { - arr1 = new Q64byte[SIZE]; - arr2 = new Q64byte[SIZE]; - populate(arr1, arr2, 100); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64long.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64long.java deleted file mode 100644 index bc0b273720a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesQ64long.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import java.util.BitSet; -import java.util.Random; - -public class StatesQ64long { - - public static final int SIZE = 100; - - private static BitSet indices(Random rnd, int bound, int size) { - return rnd.ints(0, bound) - .distinct() - .limit(size) - .collect(BitSet::new, BitSet::set, BitSet::or); - } - - private static void populate(Object[] arr1, Object[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new Q64long(i); - } else { - arr1[i] = new Q64long(2 * i); - arr2[i] = new Q64long(2 * i + 1); - } - } - } - - @State(Scope.Thread) - public abstract static class ObjState { - Object[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class IntState { - Int64[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class RefState { - Q64long[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class ValState { - Q64long[] arr1, arr2; - } - - public static class ObjState00 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 0); - } - - } - - public static class ObjState25 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 25); - } - - } - - public static class ObjState50 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 50); - } - - } - - public static class ObjState75 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 75); - } - - } - - public static class ObjState100 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class IntState00 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class IntState25 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class IntState50 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class IntState75 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class IntState100 extends IntState { - @Setup - public void setup() { - arr1 = new Int64[SIZE]; - arr2 = new Int64[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class RefState00 extends RefState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class RefState25 extends RefState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class RefState50 extends RefState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class RefState75 extends RefState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class RefState100 extends RefState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class ValState00 extends ValState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class ValState25 extends ValState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class ValState50 extends ValState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class ValState75 extends ValState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class ValState100 extends ValState { - @Setup - public void setup() { - arr1 = new Q64long[SIZE]; - arr2 = new Q64long[SIZE]; - populate(arr1, arr2, 100); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesR64long.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesR64long.java deleted file mode 100644 index e53e0b5b4e1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/StatesR64long.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.acmp.array; - -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import java.util.BitSet; -import java.util.Random; - -public class StatesR64long { - - public static final int SIZE = 100; - - private static BitSet indices(Random rnd, int bound, int size) { - return rnd.ints(0, bound) - .distinct() - .limit(size) - .collect(BitSet::new, BitSet::set, BitSet::or); - } - - private static void populate(Object[] arr1, Object[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - int samenulls = 0; - int distinctnulls = 0; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - if (samenulls > 0) { - arr2[i] = arr1[i] = new R64long(i); - } else { - arr2[i] = arr1[i] = null; - samenulls++; - } - } else { - if (distinctnulls > 1) { - arr1[i] = new R64long(2 * i); - arr2[i] = new R64long(2 * i + 1); - } else { - if (distinctnulls == 0) { - arr1[i] = null; - arr2[i] = new R64long(2 * i + 1); - } else { - arr1[i] = new R64long(2 * i); - arr2[i] = null; - } - distinctnulls++; - } - } - } - } - - @State(Scope.Thread) - public abstract static class ObjState { - Object[] arr1, arr2; - } - - @State(Scope.Thread) - public abstract static class RefState { - R64long[] arr1, arr2; - } - - public static class ObjState00 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 0); - } - - } - - public static class ObjState25 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 25); - } - - } - - public static class ObjState50 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 50); - } - - } - - public static class ObjState75 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 75); - } - - } - - public static class ObjState100 extends ObjState { - @Setup - public void setup() { - arr1 = new Object[SIZE]; - arr2 = new Object[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class RefState00 extends RefState { - @Setup - public void setup() { - arr1 = new R64long[SIZE]; - arr2 = new R64long[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class RefState25 extends RefState { - @Setup - public void setup() { - arr1 = new R64long[SIZE]; - arr2 = new R64long[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class RefState50 extends RefState { - @Setup - public void setup() { - arr1 = new R64long[SIZE]; - arr2 = new R64long[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class RefState75 extends RefState { - @Setup - public void setup() { - arr1 = new R64long[SIZE]; - arr2 = new R64long[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class RefState100 extends RefState { - @Setup - public void setup() { - arr1 = new R64long[SIZE]; - arr2 = new R64long[SIZE]; - populate(arr1, arr2, 100); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032.java new file mode 100644 index 00000000000..b76b5184c91 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032.java @@ -0,0 +1,398 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032 { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(Object[] objects1, Object[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt[] objects1, ValueInt[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt[] objects1, ValueInt[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(Object[] objects1, Object[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = null; + arr2[0] = new ValueInt(1); + arr1[1] = new ValueInt(2); + arr2[1] = null; + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = null; + for (int i = 1; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = arr1[i] = null; + samenulls = false; + } else { + arr2[i] = arr1[i] = new ValueInt(i); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = null; + arr2[i] = new ValueInt(2 * i + 1); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ValueInt(2 * i); + arr2[i] = null; + distinctnulls = 2; + break; + default: + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + break; + } + } + } + + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + Object[] arr1, arr2; + + public void setup(int eq) { + arr1 = new Object[SIZE]; + arr2 = new Object[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValueInt[SIZE]; + arr2 = new ValueInt[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFree.java new file mode 100644 index 00000000000..eeb66b6eeef --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFree.java @@ -0,0 +1,233 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032NullFree { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt[] objects1, ValueInt[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt[] objects1, ValueInt[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + arr2[i] = arr1[i] = new ValueInt(i); + } else { + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + } + } + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt[] arr1, arr2; + + public void setup(int eq) { + arr1 = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, SIZE, new ValueInt(0)); + arr2 = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, SIZE, new ValueInt(0)); + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..cee0b51d527 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value032NullFreeNonAtomic.java @@ -0,0 +1,235 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032NullFreeNonAtomic { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt[] objects1, ValueInt[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt[] objects1, ValueInt[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @LooselyConsistentValue + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + arr2[i] = arr1[i] = new ValueInt(i); + } else { + arr1[i] = new ValueInt(2 * i); + arr2[i] = new ValueInt(2 * i + 1); + } + } + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt[] arr1, arr2; + + public void setup(int eq) { + arr1 = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, SIZE, new ValueInt(0)); + arr2 = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, SIZE, new ValueInt(0)); + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128.java new file mode 100644 index 00000000000..82a77606007 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128.java @@ -0,0 +1,400 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128 { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(Object[] objects1, Object[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt4[] objects1, ValueInt4[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt4[] objects1, ValueInt4[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(Object[] objects1, Object[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = null; + arr2[0] = new ValueInt4(1); + arr1[1] = new ValueInt4(2); + arr2[1] = null; + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = null; + for (int i = 1; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt4(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = arr1[i] = null; + samenulls = false; + } else { + arr2[i] = arr1[i] = new ValueInt4(i); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = null; + arr2[i] = new ValueInt4(2 * i + 1); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ValueInt4(2 * i); + arr2[i] = null; + distinctnulls = 2; + break; + default: + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + break; + } + } + } + + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + Object[] arr1, arr2; + + public void setup(int eq) { + arr1 = new Object[SIZE]; + arr2 = new Object[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt4[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValueInt4[SIZE]; + arr2 = new ValueInt4[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFree.java new file mode 100644 index 00000000000..6e2c0ad0af7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFree.java @@ -0,0 +1,235 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128NullFree { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt4[] objects1, ValueInt4[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt4[] objects1, ValueInt4[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt4(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + arr2[i] = arr1[i] = new ValueInt4(i); + } else { + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + } + } + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt4[] arr1, arr2; + + public void setup(int eq) { + arr1 = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, SIZE, new ValueInt4(0)); + arr2 = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, SIZE, new ValueInt4(0)); + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..6fee2a97ca2 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/array/Value128NullFreeNonAtomic.java @@ -0,0 +1,237 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.array; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128NullFreeNonAtomic { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValueInt4[] objects1, ValueInt4[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i] == objects2[i]) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValueInt4[] objects1, ValueInt4[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i] == objects2[i]; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @LooselyConsistentValue + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(Object[] arr1, Object[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + arr2[i] = arr1[i] = new ValueInt4(i); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + arr2[i] = arr1[i] = new ValueInt4(i); + } else { + arr1[i] = new ValueInt4(2 * i); + arr2[i] = new ValueInt4(2 * i + 1); + } + } + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValueInt4[] arr1, arr2; + + public void setup(int eq) { + arr1 = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, SIZE, new ValueInt4(0)); + arr2 = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, SIZE, new ValueInt4(0)); + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Identity.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Identity.java new file mode 100644 index 00000000000..d35f716c0e7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Identity.java @@ -0,0 +1,473 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Identity -wmb "org.openjdk.bench.valhalla.acmp.field.Identity.*050" + */ + +@Fork(3) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Identity { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_ref(RefWrapper[] objects1, RefWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_ref(RefWrapper[] objects1, RefWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals000(RefState00 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals025(RefState25 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals050(RefState50 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals075(RefState75 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_ref_equals100(RefState100 st) { + return cmp_branch_ref(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals000(RefState00 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals025(RefState25 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals050(RefState50 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals075(RefState75 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_ref_equals100(RefState100 st) { + return cmp_result_ref(st.arr1, st.arr2); + } + + public static class IdentityInt { + + public final int v0; + + public IdentityInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(ObjWrapper[] arr1, ObjWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new ObjWrapper(null); + arr2[0] = new ObjWrapper(new IdentityInt(1)); + arr1[1] = new ObjWrapper(new IdentityInt(2)); + arr2[1] = new ObjWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ObjWrapper(new IdentityInt(2 * i)); + arr2[i] = new ObjWrapper(new IdentityInt(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new ObjWrapper(null); + for (int i = 1; i < SIZE; i++) { + IdentityInt x = new IdentityInt(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new ObjWrapper(null); + arr1[i] = new ObjWrapper(null); + samenulls = false; + } else { + IdentityInt x = new IdentityInt(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new ObjWrapper(null); + arr2[i] = new ObjWrapper(new IdentityInt(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ObjWrapper(new IdentityInt(2 * i)); + arr2[i] = new ObjWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new ObjWrapper(new IdentityInt(2 * i)); + arr2[i] = new ObjWrapper(new IdentityInt(2 * i + 1)); + break; + } + } + } + } + } + + + private static void populate(RefWrapper[] arr1, RefWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new RefWrapper(null); + arr2[0] = new RefWrapper(new IdentityInt(1)); + arr1[1] = new RefWrapper(new IdentityInt(2)); + arr2[1] = new RefWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new RefWrapper(new IdentityInt(2 * i)); + arr2[i] = new RefWrapper(new IdentityInt(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new RefWrapper(null); + for (int i = 1; i < SIZE; i++) { + IdentityInt x = new IdentityInt(i); + arr2[i] = new RefWrapper(x); + arr1[i] = new RefWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new RefWrapper(null); + arr1[i] = new RefWrapper(null); + samenulls = false; + } else { + IdentityInt x = new IdentityInt(i); + arr2[i] = new RefWrapper(x); + arr1[i] = new RefWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new RefWrapper(null); + arr2[i] = new RefWrapper(new IdentityInt(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new RefWrapper(new IdentityInt(2 * i)); + arr2[i] = new RefWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new RefWrapper(new IdentityInt(2 * i)); + arr2[i] = new RefWrapper(new IdentityInt(2 * i + 1)); + break; + } + } + } + } + } + + public static class ObjWrapper { + public final Object f; + + public ObjWrapper(Object f) { + this.f = f; + } + } + + public static class RefWrapper { + public final IdentityInt f; + + public RefWrapper(IdentityInt f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + ObjWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ObjWrapper[SIZE]; + arr2 = new ObjWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class RefState { + RefWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new RefWrapper[SIZE]; + arr2 = new RefWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class RefState00 extends RefState { + @Setup + public void setup() { + setup(0); + } + } + + public static class RefState25 extends RefState { + @Setup + public void setup() { + setup(25); + } + } + + public static class RefState50 extends RefState { + @Setup + public void setup() { + setup(50); + } + } + + public static class RefState75 extends RefState { + @Setup + public void setup() { + setup(75); + } + } + + public static class RefState100 extends RefState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/InlineIsCmpBranch64long.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/InlineIsCmpBranch64long.java deleted file mode 100644 index fd93d3b8bfe..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/field/InlineIsCmpBranch64long.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.acmp.field; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -/* - * For proper results it should be executed: - * java -jar target/benchmarks.jar baseline.acmp.IsCmpBranch -wmb baseline.acmp.IsCmpBranch.equals050 - */ - -@Fork(3) -@Warmup(iterations = 3, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineIsCmpBranch64long extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i].f == objects2[i].f) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Int(IntWrapper[] objects1, IntWrapper[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i].f == objects2[i].f) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Ref(RefWrapper[] objects1, RefWrapper[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i].f == objects2[i].f) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Val(ValWrapper[] objects1, ValWrapper[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i].f == objects2[i].f) { - s += 1; - } else { - s -= 1; - } - } - return s; - } - - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals000(IntState00 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals025(IntState25 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals050(IntState50 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals075(IntState75 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Int_equals100(IntState100 st) { - return cmp_Int(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals000(RefState00 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals025(RefState25 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals050(RefState50 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals075(RefState75 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Ref_equals100(RefState100 st) { - return cmp_Ref(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals000(ValState00 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals025(ValState25 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals050(ValState50 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals075(ValState75 st) { - return cmp_Val(st.arr1, st.arr2); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Val_equals100(ValState100 st) { - return cmp_Val(st.arr1, st.arr2); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/StatesQ64long.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/StatesQ64long.java deleted file mode 100644 index 147e736203f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/acmp/field/StatesQ64long.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.acmp.field; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import java.util.BitSet; -import java.util.Random; - -public class StatesQ64long { - - public static final int SIZE = 100; - - private static BitSet indices(Random rnd, int bound, int size) { - return rnd.ints(0, bound) - .distinct() - .limit(size) - .collect(BitSet::new, BitSet::set, BitSet::or); - } - - private static void populate(ObjWrapper[] arr1, ObjWrapper[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new ObjWrapper(new Q64long(i)); - } else { - arr1[i] = new ObjWrapper(new Q64long(2 * i)); - arr2[i] = new ObjWrapper(new Q64long(2 * i + 1)); - } - } - } - - private static void populate(IntWrapper[] arr1, IntWrapper[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new IntWrapper(new Q64long(i)); - } else { - arr1[i] = new IntWrapper(new Q64long(2 * i)); - arr2[i] = new IntWrapper(new Q64long(2 * i + 1)); - } - } - } - - private static void populate(RefWrapper[] arr1, RefWrapper[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new RefWrapper(new Q64long(i)); - } else { - arr1[i] = new RefWrapper(new Q64long(2 * i)); - arr2[i] = new RefWrapper(new Q64long(2 * i + 1)); - } - } - } - - private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { - BitSet eqset = (eq > 0 && eq < 100) ? indices(new Random(42), SIZE, (eq * SIZE) / 100) : null; - for (int i = 0; i < SIZE; i++) { - if (eq > 0 && (eq >= 100 || eqset.get(i))) { - arr2[i] = arr1[i] = new ValWrapper(new Q64long(i)); - } else { - arr1[i] = new ValWrapper(new Q64long(2 * i)); - arr2[i] = new ValWrapper(new Q64long(2 * i + 1)); - } - } - } - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - - @State(Scope.Thread) - public abstract static class ObjState { - ObjWrapper[] arr1, arr2; - } - - public static class IntWrapper { - public Int64 f; - - public IntWrapper(Int64 f) { - this.f = f; - } - } - - @State(Scope.Thread) - public abstract static class IntState { - IntWrapper[] arr1, arr2; - } - - public static class RefWrapper { - public Q64long f; - - public RefWrapper(Q64long f) { - this.f = f; - } - } - - - @State(Scope.Thread) - public abstract static class RefState { - RefWrapper[] arr1, arr2; - } - - public static class ValWrapper { - public Q64long f; - - public ValWrapper(Q64long f) { - this.f = f; - } - } - - - @State(Scope.Thread) - public abstract static class ValState { - ValWrapper[] arr1, arr2; - } - - public static class ObjState00 extends ObjState { - @Setup - public void setup() { - arr1 = new ObjWrapper[SIZE]; - arr2 = new ObjWrapper[SIZE]; - populate(arr1, arr2, 0); - } - - } - - public static class ObjState25 extends ObjState { - @Setup - public void setup() { - arr1 = new ObjWrapper[SIZE]; - arr2 = new ObjWrapper[SIZE]; - populate(arr1, arr2, 25); - } - - } - - public static class ObjState50 extends ObjState { - @Setup - public void setup() { - arr1 = new ObjWrapper[SIZE]; - arr2 = new ObjWrapper[SIZE]; - populate(arr1, arr2, 50); - } - - } - - public static class ObjState75 extends ObjState { - @Setup - public void setup() { - arr1 = new ObjWrapper[SIZE]; - arr2 = new ObjWrapper[SIZE]; - populate(arr1, arr2, 75); - } - - } - - public static class ObjState100 extends ObjState { - @Setup - public void setup() { - arr1 = new ObjWrapper[SIZE]; - arr2 = new ObjWrapper[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class IntState00 extends IntState { - @Setup - public void setup() { - arr1 = new IntWrapper[SIZE]; - arr2 = new IntWrapper[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class IntState25 extends IntState { - @Setup - public void setup() { - arr1 = new IntWrapper[SIZE]; - arr2 = new IntWrapper[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class IntState50 extends IntState { - @Setup - public void setup() { - arr1 = new IntWrapper[SIZE]; - arr2 = new IntWrapper[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class IntState75 extends IntState { - @Setup - public void setup() { - arr1 = new IntWrapper[SIZE]; - arr2 = new IntWrapper[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class IntState100 extends IntState { - @Setup - public void setup() { - arr1 = new IntWrapper[SIZE]; - arr2 = new IntWrapper[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class RefState00 extends RefState { - @Setup - public void setup() { - arr1 = new RefWrapper[SIZE]; - arr2 = new RefWrapper[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class RefState25 extends RefState { - @Setup - public void setup() { - arr1 = new RefWrapper[SIZE]; - arr2 = new RefWrapper[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class RefState50 extends RefState { - @Setup - public void setup() { - arr1 = new RefWrapper[SIZE]; - arr2 = new RefWrapper[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class RefState75 extends RefState { - @Setup - public void setup() { - arr1 = new RefWrapper[SIZE]; - arr2 = new RefWrapper[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class RefState100 extends RefState { - @Setup - public void setup() { - arr1 = new RefWrapper[SIZE]; - arr2 = new RefWrapper[SIZE]; - populate(arr1, arr2, 100); - } - } - - public static class ValState00 extends ValState { - @Setup - public void setup() { - arr1 = new ValWrapper[SIZE]; - arr2 = new ValWrapper[SIZE]; - populate(arr1, arr2, 0); - } - } - - public static class ValState25 extends ValState { - @Setup - public void setup() { - arr1 = new ValWrapper[SIZE]; - arr2 = new ValWrapper[SIZE]; - populate(arr1, arr2, 25); - } - } - - public static class ValState50 extends ValState { - @Setup - public void setup() { - arr1 = new ValWrapper[SIZE]; - arr2 = new ValWrapper[SIZE]; - populate(arr1, arr2, 50); - } - } - - public static class ValState75 extends ValState { - @Setup - public void setup() { - arr1 = new ValWrapper[SIZE]; - arr2 = new ValWrapper[SIZE]; - populate(arr1, arr2, 75); - } - } - - public static class ValState100 extends ValState { - @Setup - public void setup() { - arr1 = new ValWrapper[SIZE]; - arr2 = new ValWrapper[SIZE]; - populate(arr1, arr2, 100); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032.java new file mode 100644 index 00000000000..e413d5bb7e7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032.java @@ -0,0 +1,473 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032 { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(ObjWrapper[] arr1, ObjWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new ObjWrapper(null); + arr2[0] = new ObjWrapper(new ValueInt(1)); + arr1[1] = new ObjWrapper(new ValueInt(2)); + arr2[1] = new ObjWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ObjWrapper(new ValueInt(2 * i)); + arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new ObjWrapper(null); + for (int i = 1; i < SIZE; i++) { + ValueInt x = new ValueInt(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new ObjWrapper(null); + arr1[i] = new ObjWrapper(null); + samenulls = false; + } else { + ValueInt x = new ValueInt(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new ObjWrapper(null); + arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ObjWrapper(new ValueInt(2 * i)); + arr2[i] = new ObjWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new ObjWrapper(new ValueInt(2 * i)); + arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); + break; + } + } + } + } + } + + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new ValWrapper(null); + arr2[0] = new ValWrapper(new ValueInt(1)); + arr1[1] = new ValWrapper(new ValueInt(2)); + arr2[1] = new ValWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new ValWrapper(null); + for (int i = 1; i < SIZE; i++) { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new ValWrapper(null); + arr1[i] = new ValWrapper(null); + samenulls = false; + } else { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new ValWrapper(null); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + break; + } + } + } + } + } + + public static class ObjWrapper { + public Object f; + + public ObjWrapper(Object f) { + this.f = f; + } + } + + public static class ValWrapper { + public ValueInt f; + + public ValWrapper(ValueInt f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + ObjWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ObjWrapper[SIZE]; + arr2 = new ObjWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFree.java new file mode 100644 index 00000000000..bae5a039316 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFree.java @@ -0,0 +1,249 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + * */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032NullFree { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } else { + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + } + } + } + } + + public static class ValWrapper { + + @Strict + @NullRestricted + public final ValueInt f; + + public ValWrapper(ValueInt f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..634cfe6b517 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value032NullFreeNonAtomic.java @@ -0,0 +1,251 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value032NullFreeNonAtomic { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @LooselyConsistentValue + public static value class ValueInt { + + public final int v0; + + public ValueInt(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + } + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + ValueInt x = new ValueInt(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } else { + arr1[i] = new ValWrapper(new ValueInt(2 * i)); + arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); + } + } + } + } + + public static class ValWrapper { + + @Strict + @NullRestricted + public final ValueInt f; + + public ValWrapper(ValueInt f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128.java new file mode 100644 index 00000000000..3559dd3caed --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128.java @@ -0,0 +1,475 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128 { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals000(ObjState00 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals025(ObjState25 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals050(ObjState50 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals075(ObjState75 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_obj_equals100(ObjState100 st) { + return cmp_branch_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals000(ObjState00 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals025(ObjState25 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals050(ObjState50 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals075(ObjState75 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_obj_equals100(ObjState100 st) { + return cmp_result_obj(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(ObjWrapper[] arr1, ObjWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new ObjWrapper(null); + arr2[0] = new ObjWrapper(new ValueInt4(1)); + arr1[1] = new ObjWrapper(new ValueInt4(2)); + arr2[1] = new ObjWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ObjWrapper(new ValueInt4(2 * i)); + arr2[i] = new ObjWrapper(new ValueInt4(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new ObjWrapper(null); + for (int i = 1; i < SIZE; i++) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new ObjWrapper(null); + arr1[i] = new ObjWrapper(null); + samenulls = false; + } else { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ObjWrapper(x); + arr1[i] = new ObjWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new ObjWrapper(null); + arr2[i] = new ObjWrapper(new ValueInt4(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ObjWrapper(new ValueInt4(2 * i)); + arr2[i] = new ObjWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new ObjWrapper(new ValueInt4(2 * i)); + arr2[i] = new ObjWrapper(new ValueInt4(2 * i + 1)); + break; + } + } + } + } + } + + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + arr1[0] = new ValWrapper(null); + arr2[0] = new ValWrapper(new ValueInt4(1)); + arr1[1] = new ValWrapper(new ValueInt4(2)); + arr2[1] = new ValWrapper(null); + for (int i = 2; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + } + } else if (eq >= 100) { + arr2[0] = arr1[0] = new ValWrapper(null); + for (int i = 1; i < SIZE; i++) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + boolean samenulls = true; + int distinctnulls = 0; + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + if(samenulls) { + arr2[i] = new ValWrapper(null); + arr1[i] = new ValWrapper(null); + samenulls = false; + } else { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + switch (distinctnulls) { + case 0: + arr1[i] = new ValWrapper(null); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + distinctnulls = 1; + break; + case 1: + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(null); + distinctnulls = 2; + break; + default: + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + break; + } + } + } + } + } + + public static class ObjWrapper { + public Object f; + + public ObjWrapper(Object f) { + this.f = f; + } + } + + public static class ValWrapper { + public ValueInt4 f; + + public ValWrapper(ValueInt4 f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ObjState { + ObjWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ObjWrapper[SIZE]; + arr2 = new ObjWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ObjState00 extends ObjState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ObjState25 extends ObjState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ObjState50 extends ObjState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ObjState75 extends ObjState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ObjState100 extends ObjState { + @Setup + public void setup() { + setup(100); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFree.java new file mode 100644 index 00000000000..b334ab2d778 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFree.java @@ -0,0 +1,253 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128NullFree { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } else { + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + } + } + } + } + + public static class ValWrapper { + + @Strict + @NullRestricted + public final ValueInt4 f; + + public ValWrapper(ValueInt4 f) { + this.f = f; + } + } + + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..7a9530a004c --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/acmp/field/Value128NullFreeNonAtomic.java @@ -0,0 +1,253 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.acmp.field; + +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.BitSet; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/* + * For proper results it should be executed: + * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.Value.*050" + */ + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value128NullFreeNonAtomic { + + public static final int SIZE = 100; + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int cmp_branch_val(ValWrapper[] objects1, ValWrapper[] objects2) { + int s = 0; + for (int i = 0; i < SIZE; i++) { + if (objects1[i].f == objects2[i].f) { + s += 1; + } else { + s -= 1; + } + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean cmp_result_val(ValWrapper[] objects1, ValWrapper[] objects2) { + boolean s = false; + for (int i = 0; i < SIZE; i++) { + s ^= objects1[i].f == objects2[i].f; + } + return s; + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals000(ValState00 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals025(ValState25 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals050(ValState50 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals075(ValState75 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public int branch_val_equals100(ValState100 st) { + return cmp_branch_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals000(ValState00 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals025(ValState25 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals050(ValState50 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals075(ValState75 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean result_val_equals100(ValState100 st) { + return cmp_result_val(st.arr1, st.arr2); + } + + @LooselyConsistentValue + public static value class ValueInt4 { + + public final int v0; + public final int v1; + public final int v2; + public final int v3; + + public ValueInt4(int v) { + this.v0 = v; + this.v1 = v + 1; + this.v2 = v + 2; + this.v3 = v + 3; + } + + } + + private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { + if (eq <= 0) { + for (int i = 0; i < SIZE; i++) { + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + } + } else if (eq >= 100) { + for (int i = 0; i < SIZE; i++) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } + } else { + BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); + for (int i = 0; i < SIZE; i++) { + if (eqset.get(i)) { + ValueInt4 x = new ValueInt4(i); + arr2[i] = new ValWrapper(x); + arr1[i] = new ValWrapper(x); + } else { + arr1[i] = new ValWrapper(new ValueInt4(2 * i)); + arr2[i] = new ValWrapper(new ValueInt4(2 * i + 1)); + } + } + } + } + + public static class ValWrapper { + + @Strict + @NullRestricted + public final ValueInt4 f; + + public ValWrapper(ValueInt4 f) { + this.f = f; + } + } + + @State(Scope.Thread) + public abstract static class ValState { + ValWrapper[] arr1, arr2; + + public void setup(int eq) { + arr1 = new ValWrapper[SIZE]; + arr2 = new ValWrapper[SIZE]; + populate(arr1, arr2, eq); + } + } + + public static class ValState00 extends ValState { + @Setup + public void setup() { + setup(0); + } + } + + public static class ValState25 extends ValState { + @Setup + public void setup() { + setup(25); + } + } + + public static class ValState50 extends ValState { + @Setup + public void setup() { + setup(50); + } + } + + public static class ValState75 extends ValState { + @Setup + public void setup() { + setup(75); + } + } + + public static class ValState100 extends ValState { + @Setup + public void setup() { + setup(100); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialEquals.java b/test/micro/org/openjdk/bench/valhalla/acmp/trivial/Identity.java similarity index 86% rename from test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialEquals.java rename to test/micro/org/openjdk/bench/valhalla/acmp/trivial/Identity.java index 5ed70e9ea90..b690cfd84b1 100644 --- a/test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialEquals.java +++ b/test/micro/org/openjdk/bench/valhalla/acmp/trivial/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,6 @@ */ package org.openjdk.bench.valhalla.acmp.trivial; -import org.openjdk.bench.valhalla.types.R64long; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -47,10 +46,10 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityTrivialEquals { +public class Identity { - Object o1 = new R64long(1); - Object o2 = new R64long(2); + Object o1 = new IdentityLong(1); + Object o2 = new IdentityLong(2); @CompilerControl(CompilerControl.Mode.DONT_INLINE) private static boolean cmpEquals(Object a, Object b) { @@ -81,4 +80,18 @@ public boolean isCmp_o1_o2() { return cmpEquals(o1, o2); } + public static class IdentityLong { + + public final long v0; + + public IdentityLong(long v0) { + this.v0 = v0; + } + + public long value() { + return v0; + } + + } + } diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialNotEquals.java b/test/micro/org/openjdk/bench/valhalla/acmp/trivial/Value.java similarity index 68% rename from test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialNotEquals.java rename to test/micro/org/openjdk/bench/valhalla/acmp/trivial/Value.java index 66728d26fe7..0e3b15a58fd 100644 --- a/test/micro/org/openjdk/bench/valhalla/acmp/trivial/IdentityTrivialNotEquals.java +++ b/test/micro/org/openjdk/bench/valhalla/acmp/trivial/Value.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,13 +22,13 @@ */ package org.openjdk.bench.valhalla.acmp.trivial; -import org.openjdk.bench.valhalla.types.R64long; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; @@ -41,46 +41,58 @@ * -wm INDI * -wm BULK */ - -@Fork(1) +@Fork(value = 1, jvmArgsAppend = {"--enable-preview"}) @Warmup(iterations = 3, time = 1) @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityTrivialNotEquals { +public class Value { - Object o1 = new R64long(1); - Object o2 = new R64long(2); + Object o1 = new ValueLong(1); + Object o2 = new ValueLong(2); @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static boolean cmpNotEquals(Object a, Object b) { - return a != b; // new acmp - } + private static boolean cmpEquals(Object a, Object b) { + return a == b; } @Benchmark - public boolean isNotCmp_null_null() { - return cmpNotEquals(null, null); + public boolean isCmp_null_null() { + return cmpEquals(null, null); } @Benchmark - public boolean isNotCmp_o1_null() { - return cmpNotEquals(o1, null); + public boolean isCmp_o1_null() { + return cmpEquals(o1, null); } @Benchmark - public boolean isNotCmp_null_o1() { - return cmpNotEquals(null, o1); + public boolean isCmp_null_o1() { + return cmpEquals(null, o1); } @Benchmark - public boolean isNotCmp_o1_o1() { - return cmpNotEquals(o1, o1); + public boolean isCmp_o1_o1() { + return cmpEquals(o1, o1); } @Benchmark - public boolean isNotCmp_o1_o2() { - return cmpNotEquals(o1, o2); + public boolean isCmp_o1_o2() { + return cmpEquals(o1, o2); + } + + public static value class ValueLong { + + public final long v0; + + public ValueLong(long v0) { + this.v0 = v0; + } + + public long value() { + return v0; + } + } } diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/CopyBase.java b/test/micro/org/openjdk/bench/valhalla/array/copy/CopyBase.java new file mode 100644 index 00000000000..8ba6e27c84d --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/CopyBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class CopyBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Identity.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Identity.java new file mode 100644 index 00000000000..8e298df4a6d --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Identity.java @@ -0,0 +1,104 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; + +public class Identity extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt implements InterfaceInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + + public static class RefState extends SizeState { + public IdentityInt[] arr; + + @Setup + public void setup() { + arr = new IdentityInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_ref(IdentityInt[] dst, IdentityInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_ref(IdentityInt[] dst, IdentityInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_ref_as_ref(RefState st1, RefState st2) { + copy_ref(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_ref_as_ref(RefState st1, RefState st2) { + arraycopy_ref(st1.arr, st2.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Inline128int.java deleted file mode 100644 index cdf6944437f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline128int.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.StatesQ128int; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline128int extends StatesQ128int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q128int[] src = s.arr; - Q128int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_arraycopy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q128int[] src = s.arr; - Q128int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_arraycopy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q128int[] src = s.arr; - Q128int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_arraycopy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Inline32int.java deleted file mode 100644 index fe83f58efb1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline32int.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.StatesQ32int; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline32int extends StatesQ32int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q32int[] src = s.arr; - Q32int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_arraycopy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q32int[] src = s.arr; - Q32int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_arraycopy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q32int[] src = s.arr; - Q32int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_arraycopy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64byte.java deleted file mode 100644 index 753e4a63596..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64byte.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.StatesQ64byte; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64byte extends StatesQ64byte { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q64byte[] src = s.arr; - Q64byte[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_arraycopy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q64byte[] src = s.arr; - Q64byte[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_arraycopy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q64byte[] src = s.arr; - Q64byte[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_arraycopy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64int.java deleted file mode 100644 index 7f73e470752..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Inline64int.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.StatesQ64int; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64int extends StatesQ64int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q64int[] src = s.arr; - Q64int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_arraycopy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q64int[] src = s.arr; - Q64int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_arraycopy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q64int[] src = s.arr; - Q64int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_arraycopy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/InlineOpt.java b/test/micro/org/openjdk/bench/valhalla/array/copy/InlineOpt.java deleted file mode 100644 index 63698ebc180..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/InlineOpt.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.StatesQOpt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.QOpt; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineOpt extends StatesQOpt { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - QOpt[] src = s.arr; - QOpt[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_arraycopy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - QOpt[] src = s.arr; - QOpt[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_arraycopy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - QOpt[] src = s.arr; - QOpt[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_arraycopy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive32.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive032.java similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/array/copy/Primitive32.java rename to test/micro/org/openjdk/bench/valhalla/array/copy/Primitive032.java index 4ec435a9654..9c1eafe274e 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive32.java +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,26 +22,44 @@ */ package org.openjdk.bench.valhalla.array.copy; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; -public class Primitive32 extends PrimitiveStates { +public class Primitive032 extends CopyBase { + + public static class PrimitiveState extends SizeState { + public int[] arr; + + @Setup + public void setup() { + arr = new int[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p32int_copy(Primitive32int s, Primitive32int d) { - int[] src = s.arr; - int[] dst = d.arr; + private static void copy_primitive(int[] dst, int[] src) { for (int i = 0; i < src.length; i++) { dst[i] = src[i]; } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p32int_arraycopy(Primitive32int s, Primitive32int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); + private static void arraycopy_primitive(int[] dst, int[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy(PrimitiveState st1, PrimitiveState st2) { + copy_primitive(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy(PrimitiveState st1, PrimitiveState st2) { + arraycopy_primitive(st1.arr, st2.arr); } } diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive128.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive128.java deleted file mode 100644 index ae4e4e33fc5..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive128.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive128 extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p128int_copy(Primitive128int s, Primitive128int d) { - int[] src = s.arr; - int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p128int_arraycopy(Primitive128int s, Primitive128int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive64.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive64.java deleted file mode 100644 index 57de8b15d76..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/copy/Primitive64.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.copy; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive64 extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64byte_copy(Primitive64byte s, Primitive64byte d) { - byte[] src = s.arr; - byte[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64byte_arraycopy(Primitive64byte s, Primitive64byte d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64int_copy(Primitive64int s, Primitive64int d) { - int[] src = s.arr; - int[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64int_arraycopy(Primitive64int s, Primitive64int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64long_copy(Primitive64long s, Primitive64long d) { - long[] src = s.arr; - long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64long_arraycopy(Primitive64long s, Primitive64long d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value032.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032.java new file mode 100644 index 00000000000..fad494e0ece --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032.java @@ -0,0 +1,120 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value032 extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = new ValueInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt[] dst, ValueInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt[] dst, ValueInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFree.java new file mode 100644 index 00000000000..d5310f60744 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFree.java @@ -0,0 +1,122 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFree extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt[] dst, ValueInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt[] dst, ValueInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..dace774868a --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value032NullFreeNonAtomic.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFreeNonAtomic extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt[] dst, ValueInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt[] dst, ValueInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128.java new file mode 100644 index 00000000000..aeb828e9a97 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128.java @@ -0,0 +1,128 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt4[] dst, ValueInt4[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt4[] dst, ValueInt4[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFree.java new file mode 100644 index 00000000000..0d771be401e --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFree.java @@ -0,0 +1,129 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt4[] dst, ValueInt4[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt4[] dst, ValueInt4[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..3a9d10519d6 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/Value128NullFreeNonAtomic.java @@ -0,0 +1,131 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends CopyBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueInt4[] dst, ValueInt4[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceInt[] dst, InterfaceInt[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueInt4[] dst, ValueInt4[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceInt[] dst, InterfaceInt[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOop.java b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOop.java new file mode 100644 index 00000000000..b6751aee438 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOop.java @@ -0,0 +1,131 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class ValueOop extends CopyBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = new ValueRef[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueRef[] dst, ValueRef[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceOop[] dst, InterfaceOop[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueRef[] dst, ValueRef[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceOop[] dst, InterfaceOop[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFree.java b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFree.java new file mode 100644 index 00000000000..5cb271c86c4 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFree.java @@ -0,0 +1,132 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFree extends CopyBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueRef[] dst, ValueRef[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceOop[] dst, InterfaceOop[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueRef[] dst, ValueRef[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceOop[] dst, InterfaceOop[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFreeNonAtomic.java new file mode 100644 index 00000000000..9dfb57c1d3f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/copy/ValueOopNullFreeNonAtomic.java @@ -0,0 +1,134 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.copy; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFreeNonAtomic extends CopyBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + @LooselyConsistentValue + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_val(ValueRef[] dst, ValueRef[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_int(InterfaceOop[] dst, InterfaceOop[] src) { + for (int i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_val(ValueRef[] dst, ValueRef[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arraycopy_int(InterfaceOop[] dst, InterfaceOop[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + @Benchmark + public void copy_val_as_val(ValState st1, ValState st2) { + copy_val(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_val_as_val(ValState st1, ValState st2) { + arraycopy_val(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_as_int(IntState st1, IntState st2) { + copy_int(st1.arr, st2.arr); + } + + @Benchmark + public void arraycopy_int_as_int(IntState st1, IntState st2) { + arraycopy_int(st1.arr, st2.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/FillBase.java b/test/micro/org/openjdk/bench/valhalla/array/fill/FillBase.java new file mode 100644 index 00000000000..e70ee86d601 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/FillBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class FillBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Identity.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Identity.java new file mode 100644 index 00000000000..971733cfc36 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Identity.java @@ -0,0 +1,165 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +public class Identity extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt implements InterfaceInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + + public static class RefState extends SizeState { + public IdentityInt[] arr; + + @Setup + public void setup() { + arr = new IdentityInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + public static class StaticHolder { + public static IdentityInt VALUE = new IdentityInt(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + public IdentityInt VALUE = new IdentityInt(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public IdentityInt get_ref(int i) { + return new IdentityInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_ref(IdentityInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new IdentityInt(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_ref(IdentityInt[] dst) { + Arrays.fill(dst, new IdentityInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_ref(IdentityInt[] dst) { + IdentityInt local = get_ref(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_ref(IdentityInt[] dst) { + Arrays.fill(dst, get_ref(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_ref(IdentityInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_ref(IdentityInt[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_ref(IdentityInt[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_ref(IdentityInt[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(RefState st1) { + fill_new_ref(st1.arr); + } + + @Benchmark + public void arrayfill_new(RefState st1) { + arrayfill_new_ref(st1.arr); + } + + @Benchmark + public void fill_local(RefState st1) { + fill_local_ref(st1.arr); + } + + @Benchmark + public void arrayfill_local(RefState st1) { + arrayfill_local_ref(st1.arr); + } + + @Benchmark + public void fill_static(RefState st1) { + fill_static_ref(st1.arr); + } + + @Benchmark + public void arrayfill_static(RefState st1) { + arrayfill_static_ref(st1.arr); + } + + @Benchmark + public void fill_instance(RefState st1, InstanceHolder ih) { + fill_instance_ref(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(RefState st1, InstanceHolder ih) { + arrayfill_instance_ref(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Identity32int.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Identity32int.java deleted file mode 100644 index d6c54684512..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Identity32int.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesR32int; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Identity32int extends StatesR32int { - - public static class RefStaticField { - static R32int f = new R32int(42); - } - - @State(Scope.Thread) - public static class RefInstanceField { - R32int f = new R32int(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - R32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new R32int(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - R32int[] arr = st.arr; - R32int v = new R32int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fill_fillstat(Ref_as_Ref st) { - R32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - R32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new R32int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new R32int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/IdentityOpt.java b/test/micro/org/openjdk/bench/valhalla/array/fill/IdentityOpt.java deleted file mode 100644 index 26a2539815f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/IdentityOpt.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesROpt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.ROpt; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class IdentityOpt extends StatesROpt { - - public static class RefStaticField { - static ROpt f = ROpt.of(new R32int(42)); - } - - @State(Scope.Thread) - public static class RefInstanceField { - ROpt f = ROpt.of(new R32int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - ROpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ROpt.of(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - ROpt[] arr = st.arr; - ROpt v = ROpt.of(new R32int(42)); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fill_fillstat(Ref_as_Ref st) { - ROpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - ROpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, ROpt.of() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, ROpt.of(new R32int(42))); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Inline128int.java deleted file mode 100644 index 319277f0b30..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline128int.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesQ128int; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline128int extends StatesQ128int { - - public static class RefStaticField { - static Q128int f = new Q128int(42); - } - - public static class ValStaticField { - static Q128int f = new Q128int(42); - } - - @State(Scope.Thread) - public static class RefInstanceField { - Q128int f = new Q128int(42); - } - - @State(Scope.Thread) - public static class ValInstanceField { - Q128int f = new Q128int(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill(Val_as_Val st) { - Q128int[] arr = st.arr; - Q128int v = new Q128int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst(Val_as_Val st, RefInstanceField f) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst(Val_as_Val st, ValInstanceField f) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q128int[] arr = st.arr; - Q128int v = new Q128int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst(Ref_as_Ref st, ValInstanceField f) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q128int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q128int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q128int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q128int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Inline32int.java deleted file mode 100644 index ce9d5a687d1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline32int.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesQ32int; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline32int extends StatesQ32int { - - public static class RefStaticField { - static Q32int f = new Q32int(42); - } - - public static class ValStaticField { - static Q32int f = new Q32int(42); - } - - @State(Scope.Thread) - public static class RefInstanceField { - Q32int f = new Q32int(42); - } - - @State(Scope.Thread) - public static class ValInstanceField { - Q32int f = new Q32int(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill(Val_as_Val st) { - Q32int[] arr = st.arr; - Q32int v = new Q32int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst(Val_as_Val st, RefInstanceField f) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst(Val_as_Val st, ValInstanceField f) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q32int[] arr = st.arr; - Q32int v = new Q32int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst(Ref_as_Ref st, ValInstanceField f) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q32int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q32int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q32int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q32int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64byte.java deleted file mode 100644 index 75b1d74443b..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64byte.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesQ64byte; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64byte extends StatesQ64byte { - - public static class RefStaticField { - static Q64byte f = new Q64byte(42); - } - - public static class ValStaticField { - static Q64byte f = new Q64byte(42); - } - - @State(Scope.Thread) - public static class RefInstanceField { - Q64byte f = new Q64byte(42); - } - - @State(Scope.Thread) - public static class ValInstanceField { - Q64byte f = new Q64byte(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill(Val_as_Val st) { - Q64byte[] arr = st.arr; - Q64byte v = new Q64byte(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst(Val_as_Val st, RefInstanceField f) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst(Val_as_Val st, ValInstanceField f) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - Q64byte v = new Q64byte(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst(Ref_as_Ref st, ValInstanceField f) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64byte() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64byte(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64byte() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64byte(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64int.java deleted file mode 100644 index 4d687dc56b7..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Inline64int.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesQ64int; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64int extends StatesQ64int { - - public static class RefStaticField { - static Q64int f = new Q64int(42); - } - - public static class ValStaticField { - static Q64int f = new Q64int(42); - } - - @State(Scope.Thread) - public static class RefInstanceField { - Q64int f = new Q64int(42); - } - - @State(Scope.Thread) - public static class ValInstanceField { - Q64int f = new Q64int(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill(Val_as_Val st) { - Q64int[] arr = st.arr; - Q64int v = new Q64int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst(Val_as_Val st, RefInstanceField f) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst(Val_as_Val st, ValInstanceField f) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - Q64int[] arr = st.arr; - Q64int v = new Q64int(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst(Ref_as_Ref st, ValInstanceField f) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64int() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/InlineOpt.java b/test/micro/org/openjdk/bench/valhalla/array/fill/InlineOpt.java deleted file mode 100644 index 100ded53d98..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/InlineOpt.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.fill; - -import org.openjdk.bench.valhalla.array.util.StatesQOpt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.QOpt; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class InlineOpt extends StatesQOpt { - - public static class RefStaticField { - static QOpt f = QOpt.of(new R32int(42)); - } - - public static class ValStaticField { - static QOpt f = QOpt.of(new R32int(42)); - } - - @State(Scope.Thread) - public static class RefInstanceField { - QOpt f = QOpt.of(new R32int(42)); - } - - @State(Scope.Thread) - public static class ValInstanceField { - QOpt f = QOpt.of(new R32int(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill(Val_as_Val st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill(Val_as_Val st) { - QOpt[] arr = st.arr; - QOpt v = QOpt.of(new R32int(42)); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat(Val_as_Val st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat(Val_as_Val st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst(Val_as_Val st, RefInstanceField f) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst(Val_as_Val st, ValInstanceField f) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill(Ref_as_Ref st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill(Ref_as_Ref st) { - QOpt[] arr = st.arr; - QOpt v = QOpt.of(new R32int(42)); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = RefStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat(Ref_as_Ref st) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = ValStaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst(Ref_as_Ref st, RefInstanceField f) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst(Ref_as_Ref st, ValInstanceField f) { - QOpt[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, QOpt.of() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, QOpt.of(new R32int(42))); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, QOpt.of() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, QOpt.of(new R32int(42))); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, RefStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, ValStaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, RefInstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, ValInstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64long.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Primitive032.java similarity index 59% rename from test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64long.java rename to test/micro/org/openjdk/bench/valhalla/array/fill/Primitive032.java index eb3a6d4d99e..81da99335bb 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64long.java +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Primitive032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,34 +20,49 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.sum; +package org.openjdk.bench.valhalla.array.fill; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; -public class Primitive64long extends PrimitiveStates { +import java.util.Arrays; - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long sum0(Primitive64long st) { - long s = 0; - long[] values = st.arr; - for (int i = 0; i < values.length; i++) { - s += values[i]; +public class Primitive032 extends FillBase { + + public static class PrimitiveState extends SizeState { + public int[] arr; + + @Setup + public void setup() { + arr = new int[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } } - return s; } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long sum1(Primitive64long st) { - long s = 0; - int len = st.arr.length; - for (int i = 0; i < len; i++) { - s += st.arr[i]; + private static void fill_primitive(int[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = 42; } - return s; } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void arrayfill_primitive(int[] dst) { + Arrays.fill(dst, 42); + } + + @Benchmark + public void fill(PrimitiveState st1) { + fill_primitive(st1.arr); + } + + @Benchmark + public void arrayfill(PrimitiveState st1) { + arrayfill_primitive(st1.arr); + } + + } diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value032.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032.java new file mode 100644 index 00000000000..8fda3d3d59f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032.java @@ -0,0 +1,170 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value032 extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = new ValueInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class StaticHolder { + public static ValueInt VALUE = new ValueInt(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + public ValueInt VALUE = new ValueInt(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt[] dst) { + Arrays.fill(dst, new ValueInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt[] dst) { + ValueInt local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFree.java new file mode 100644 index 00000000000..08b04d987ec --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFree.java @@ -0,0 +1,177 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFree extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueInt VALUE = new ValueInt(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueInt VALUE = new ValueInt(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt[] dst) { + Arrays.fill(dst, new ValueInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt[] dst) { + ValueInt local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..2a888ad26ed --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value032NullFreeNonAtomic.java @@ -0,0 +1,179 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFreeNonAtomic extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueInt VALUE = new ValueInt(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueInt VALUE = new ValueInt(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt[] dst) { + Arrays.fill(dst, new ValueInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt[] dst) { + ValueInt local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128.java new file mode 100644 index 00000000000..ca043c7abef --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128.java @@ -0,0 +1,177 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class StaticHolder { + public static ValueInt4 VALUE = new ValueInt4(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + public ValueInt4 VALUE = new ValueInt4(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt4[] dst) { + Arrays.fill(dst, new ValueInt4(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt4[] dst) { + ValueInt4 local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt4[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt4[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFree.java new file mode 100644 index 00000000000..98c396b21ac --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFree.java @@ -0,0 +1,184 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueInt4 VALUE = new ValueInt4(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueInt4 VALUE = new ValueInt4(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt4[] dst) { + Arrays.fill(dst, new ValueInt4(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt4[] dst) { + ValueInt4 local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt4[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt4[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..ef57a63bbf9 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/Value128NullFreeNonAtomic.java @@ -0,0 +1,186 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends FillBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueInt4 VALUE = new ValueInt4(42); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueInt4 VALUE = new ValueInt4(42); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(42); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueInt4[] dst) { + Arrays.fill(dst, new ValueInt4(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueInt4[] dst) { + ValueInt4 local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueInt4[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueInt4[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueInt4[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOop.java b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOop.java new file mode 100644 index 00000000000..8ecc5b4cf9e --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOop.java @@ -0,0 +1,180 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class ValueOop extends FillBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = new ValueRef[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class StaticHolder { + public static ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @State(Scope.Thread) + public static class InstanceHolder { + public ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(42)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueRef[] dst) { + Arrays.fill(dst, new ValueRef(new IdentityInt(42))); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueRef[] dst) { + ValueRef local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueRef[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueRef[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueRef[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueRef[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFree.java b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFree.java new file mode 100644 index 00000000000..3218a1d21dc --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFree.java @@ -0,0 +1,187 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFree extends FillBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(42)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueRef[] dst) { + Arrays.fill(dst, new ValueRef(new IdentityInt(42))); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueRef[] dst) { + ValueRef local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueRef[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueRef[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueRef[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueRef[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFreeNonAtomic.java new file mode 100644 index 00000000000..69a8daf4709 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/fill/ValueOopNullFreeNonAtomic.java @@ -0,0 +1,189 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.fill; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFreeNonAtomic extends FillBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + @LooselyConsistentValue + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class StaticHolder { + @Strict + @NullRestricted + public static ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @State(Scope.Thread) + public static class InstanceHolder { + @Strict + @NullRestricted + public ValueRef VALUE = new ValueRef(new IdentityInt(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(42)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_new_val(ValueRef[] dst) { + Arrays.fill(dst, new ValueRef(new IdentityInt(42))); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_local_val(ValueRef[] dst) { + ValueRef local = get_val(42); + for (int i = 0; i < dst.length; i++) { + dst[i] = local; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_local_val(ValueRef[] dst) { + Arrays.fill(dst, get_val(42)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_static_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = StaticHolder.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_static_val(ValueRef[] dst) { + Arrays.fill(dst, StaticHolder.VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void fill_instance_val(ValueRef[] dst, InstanceHolder ih) { + for (int i = 0; i < dst.length; i++) { + dst[i] = ih.VALUE; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void arrayfill_instance_val(ValueRef[] dst, InstanceHolder ih) { + Arrays.fill(dst, ih.VALUE); + } + + @Benchmark + public void fill_new(ValState st1) { + fill_new_val(st1.arr); + } + + @Benchmark + public void arrayfill_new(ValState st1) { + arrayfill_new_val(st1.arr); + } + + @Benchmark + public void fill_local(ValState st1) { + fill_local_val(st1.arr); + } + + @Benchmark + public void arrayfill_local(ValState st1) { + arrayfill_local_val(st1.arr); + } + + @Benchmark + public void fill_static(ValState st1) { + fill_static_val(st1.arr); + } + + @Benchmark + public void arrayfill_static(ValState st1) { + arrayfill_static_val(st1.arr); + } + + @Benchmark + public void fill_instance(ValState st1, InstanceHolder ih) { + fill_instance_val(st1.arr, ih); + } + + @Benchmark + public void arrayfill_instance(ValState st1, InstanceHolder ih) { + arrayfill_instance_val(st1.arr, ih); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/read/Identity.java similarity index 55% rename from test/micro/org/openjdk/bench/valhalla/field/copy/Inline64byte.java rename to test/micro/org/openjdk/bench/valhalla/array/read/Identity.java index 5db20fa33cf..c5cd3261339 100644 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64byte.java +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,44 +20,53 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.field.copy; +package org.openjdk.bench.valhalla.array.read; -import org.openjdk.bench.valhalla.field.util.StatesQ64byte; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; -public class Inline64byte extends StatesQ64byte { +public class Identity extends ReadBase { - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(RefState s, ValState d) { - RefWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt implements InterfaceInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; } } - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(ValState s, RefState d) { - ValWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + public static class RefState extends SizeState { + public IdentityInt[] arr; + + @Setup + public void setup() { + arr = new IdentityInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(ValState s, ValState d) { - ValWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; + public void read_ref(IdentityInt[] src, Blackhole bh) { for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + bh.consume(src[i]); } } + @Benchmark + public void read(RefState st1, Blackhole bh) { + read_ref(st1.arr, bh); + } + } diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Inline128int.java deleted file mode 100644 index 53319304710..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Inline128int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.StatesQ128int; -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline128int extends StatesQ128int { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void val_consume(Q128int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_consume(Q128int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void int_consume(Int128 v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Val_read(Val_as_Val st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Ref_read(Val_as_Val st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Int_read(Val_as_Val st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Val_read(Val_as_Ref st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Ref_read(Val_as_Ref st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Int_read(Val_as_Ref st) { - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Int_read(Val_as_Int st) { - Int128[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Inline32int.java deleted file mode 100644 index d561b15e99f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Inline32int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.StatesQ32int; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline32int extends StatesQ32int { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void val_consume(Q32int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_consume(Q32int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void int_consume(Int32 v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Val_read(Val_as_Val st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Ref_read(Val_as_Val st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Int_read(Val_as_Val st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Val_read(Val_as_Ref st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Ref_read(Val_as_Ref st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Int_read(Val_as_Ref st) { - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Int_read(Val_as_Int st) { - Int32[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/read/Inline64byte.java deleted file mode 100644 index 2f18a1cc301..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Inline64byte.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.StatesQ64byte; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64byte extends StatesQ64byte { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void val_consume(Q64byte v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_consume(Q64byte v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void int_consume(Int64 v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Val_read(Val_as_Val st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Ref_read(Val_as_Val st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Int_read(Val_as_Val st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Val_read(Val_as_Ref st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Ref_read(Val_as_Ref st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Int_read(Val_as_Ref st) { - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Int_read(Val_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Inline64int.java deleted file mode 100644 index e05e0faf680..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Inline64int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.StatesQ64int; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64int extends StatesQ64int { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void val_consume(Q64int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_consume(Q64int v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void int_consume(Int64 v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Val_read(Val_as_Val st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Ref_read(Val_as_Val st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Int_read(Val_as_Val st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Val_read(Val_as_Ref st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Ref_read(Val_as_Ref st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Int_read(Val_as_Ref st) { - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Int_read(Val_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Primitive64.java b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive032.java similarity index 64% rename from test/micro/org/openjdk/bench/valhalla/traversal/Primitive64.java rename to test/micro/org/openjdk/bench/valhalla/array/read/Primitive032.java index 9de6b6219ae..1d78186d8ce 100644 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Primitive64.java +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,38 +20,37 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.traversal; +package org.openjdk.bench.valhalla.array.read; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.util.Utils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; -public class Primitive64 extends SizeBase { +public class Primitive032 extends ReadBase { - public static class LongState extends SizeState { - public long[] arr; + public static class PrimitiveState extends SizeState { + public int[] arr; @Setup public void setup() { - int[] a = Utils.makeRandomRing(size); - arr = new long[a.length]; - for (int i = 0; i < a.length; i++) { - arr[i] = a[i]; + arr = new int[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; } } + } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void read_primitive(int[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } } @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int walk(LongState s) { - int steps = 0; - long[] values = s.arr; - for (int i = (int) values[0]; i != 0; i = (int) values[i]) steps++; - return steps; + public void read(PrimitiveState st1, Blackhole bh) { + read_primitive(st1.arr, bh); } } - diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive128int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive128int.java deleted file mode 100644 index 78cc5b72f38..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive128int.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive128int extends PrimitiveStates { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void consume_int(int v0, int v1, int v2, int v3) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p128int_read(Primitive128int st) { - int[] values = st.arr; - for (int i = 0; i < values.length; i+=4) { - consume_int(values[i], values[i+1], values[i+2], values[i+3]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64byte.java b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64byte.java deleted file mode 100644 index 1fb70f8d638..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64byte.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive64byte extends PrimitiveStates { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void consume_byte(byte v0, byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64byte_read(Primitive64byte st) { - byte[] values = st.arr; - for (int i = 0; i < values.length; i+=8) { - consume_byte(values[i], values[i+1], values[i+2], values[i+3], values[i+4], values[i+5], values[i+6], values[i+7]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64int.java deleted file mode 100644 index b9900aebf85..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64int.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive64int extends PrimitiveStates { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void consume_int(int v0, int v1) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void read(Primitive64int st) { - int[] values = st.arr; - for (int i = 0; i < values.length; i+=2) { - consume_int(values[i], values[i+1]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64long.java b/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64long.java deleted file mode 100644 index 791275450ab..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/read/Primitive64long.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.read; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive64long extends PrimitiveStates { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void consume_long(long v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p64long_read(Primitive64long st) { - long[] values = st.arr; - for (int i = 0; i < values.length; i++) { - consume_long(values[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/ReadBase.java b/test/micro/org/openjdk/bench/valhalla/array/read/ReadBase.java new file mode 100644 index 00000000000..b8bae66cffd --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/ReadBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class ReadBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value032.java similarity index 53% rename from test/micro/org/openjdk/bench/valhalla/field/copy/Inline64int.java rename to test/micro/org/openjdk/bench/valhalla/array/read/Value032.java index af61dcc5e6c..d3a8f19e1c8 100644 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64int.java +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,44 +20,57 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.field.copy; +package org.openjdk.bench.valhalla.array.read; -import org.openjdk.bench.valhalla.field.util.StatesQ64int; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; -public class Inline64int extends StatesQ64int { +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value032 extends ReadBase { - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(RefState s, ValState d) { - RefWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; } + } + public static class ValState extends SizeState { + public ValueInt[] arr; - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(ValState s, RefState d) { - ValWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + @Setup + public void setup() { + arr = new ValueInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(ValState s, ValState d) { - ValWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; + public void read_val(ValueInt[] src, Blackhole bh) { for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + bh.consume(src[i]); } } + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } } diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFree.java new file mode 100644 index 00000000000..698df68f1fb --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFree.java @@ -0,0 +1,77 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFree extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..e9ce85ab804 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value032NullFreeNonAtomic.java @@ -0,0 +1,79 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFreeNonAtomic extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value128.java new file mode 100644 index 00000000000..071297109c3 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value128.java @@ -0,0 +1,83 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFree.java new file mode 100644 index 00000000000..bfe4f0bd12b --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFree.java @@ -0,0 +1,84 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..e01c311a6a2 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/Value128NullFreeNonAtomic.java @@ -0,0 +1,86 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/ValueOop.java b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOop.java new file mode 100644 index 00000000000..105de0b13b1 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOop.java @@ -0,0 +1,86 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class ValueOop extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = new ValueRef[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFree.java b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFree.java new file mode 100644 index 00000000000..6e66f180410 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFree.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFree extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFreeNonAtomic.java new file mode 100644 index 00000000000..7d4015fc20f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/read/ValueOopNullFreeNonAtomic.java @@ -0,0 +1,89 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.read; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFreeNonAtomic extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + @LooselyConsistentValue + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/Identity.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Identity.java new file mode 100644 index 00000000000..1b7bfa196f9 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Identity.java @@ -0,0 +1,77 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +public class Identity extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt4 implements InterfaceInt { + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + public final int value; + public IdentityInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + public int value() { + return value; + } + } + + + public static class RefState extends SizeState { + public IdentityInt4[] arr; + + @Setup + public void setup() { + arr = new IdentityInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_ref(IdentityInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(RefState st1, Blackhole bh) { + read_ref(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/fill/Primitive64.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Primitive128.java similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/array/fill/Primitive64.java rename to test/micro/org/openjdk/bench/valhalla/array/readpartial/Primitive128.java index d37e32aafc1..de95bac7f7a 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/fill/Primitive64.java +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Primitive128.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,39 +20,37 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.fill1; +package org.openjdk.bench.valhalla.array.readpartial; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; -import java.util.Arrays; +public class Primitive128 extends ReadBase { -public class Primitive64 extends PrimitiveStates { + public static class PrimitiveState extends SizeState { + public int[] arr; - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void fill0(Primitive64long st) { - long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = 42; + @Setup + public void setup() { + arr = new int[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void fill1(Primitive64long st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = 42; + private static void read_primitive(int[] src, Blackhole bh) { + for (int i = 0; i < src.length; i += 4) { + bh.consume(src[i + 3]); } } @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void arrayfill(Primitive64long st) { - Arrays.fill(st.arr, 42); + public void read(PrimitiveState st1, Blackhole bh) { + read_primitive(st1.arr, bh); } } diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/ReadBase.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ReadBase.java new file mode 100644 index 00000000000..e8818239ed7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ReadBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class ReadBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128.java new file mode 100644 index 00000000000..f7eaf45bdd5 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128.java @@ -0,0 +1,83 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFree.java new file mode 100644 index 00000000000..f6d912167e1 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFree.java @@ -0,0 +1,84 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..b8b450dc52e --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/Value128NullFreeNonAtomic.java @@ -0,0 +1,93 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends ReadBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueInt4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i]); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_int(InterfaceInt[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value()); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOop.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOop.java new file mode 100644 index 00000000000..f2241674aea --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOop.java @@ -0,0 +1,91 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class ValueOop extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef4 implements InterfaceOop { + public final IdentityInt prevalue0; + public final IdentityInt prevalue1; + public final IdentityInt prevalue2; + public final IdentityInt value; + + public ValueRef4(IdentityInt value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef4[] arr; + + @Setup + public void setup() { + arr = new ValueRef4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef4(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFree.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFree.java new file mode 100644 index 00000000000..f62d517e910 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFree.java @@ -0,0 +1,94 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFree extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef4 implements InterfaceOop { + public final IdentityInt prevalue0; + public final IdentityInt prevalue1; + public final IdentityInt prevalue2; + public final IdentityInt value; + + public ValueRef4(IdentityInt value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + + public static class ValState extends SizeState { + public ValueRef4[] arr; + + @Setup + public void setup() { + arr = (ValueRef4[]) ValueClass.newNullRestrictedAtomicArray(ValueRef4.class, size, new ValueRef4(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef4(new IdentityInt(i)); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFreeNonAtomic.java new file mode 100644 index 00000000000..fd0fe34eb15 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/readpartial/ValueOopNullFreeNonAtomic.java @@ -0,0 +1,94 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.readpartial; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.infra.Blackhole; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFreeNonAtomic extends ReadBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + @LooselyConsistentValue + public static value class ValueRef4 implements InterfaceOop { + public final IdentityInt prevalue0; + public final IdentityInt prevalue1; + public final IdentityInt prevalue2; + public final IdentityInt value; + + public ValueRef4(IdentityInt value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef4[] arr; + + @Setup + public void setup() { + arr = (ValueRef4[]) ValueClass.newNullRestrictedAtomicArray(ValueRef4.class, size, new ValueRef4(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef4(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void read_val(ValueRef4[] src, Blackhole bh) { + for (int i = 0; i < src.length; i++) { + bh.consume(src[i].value); + } + } + + @Benchmark + public void read(ValState st1, Blackhole bh) { + read_val(st1.arr, bh); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Identity.java b/test/micro/org/openjdk/bench/valhalla/array/set/Identity.java new file mode 100644 index 00000000000..2a341776f52 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Identity.java @@ -0,0 +1,128 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; + +public class Identity extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt implements InterfaceInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + + public static class RefState extends SizeState { + public IdentityInt[] arr; + + @Setup + public void setup() { + arr = new IdentityInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public IdentityInt get_ref(int i) { + return new IdentityInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new IdentityInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_ref(IdentityInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new IdentityInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new IdentityInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_ref(IdentityInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_ref(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_ref_as_ref(RefState st1) { + set_new_ref(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_ref_as_ref(RefState st1) { + set_call_ref(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/array/set/Inline128int.java deleted file mode 100644 index 97a2c65f2f0..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Inline128int.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.set; - -import org.openjdk.bench.valhalla.array.util.StatesQ128int; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline128int extends StatesQ128int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q128int getRef(int i) { - return new Q128int(i); - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q128int getVal(int i) { - return new Q128int(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set(Val_as_Val st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q128int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/set/Inline32int.java deleted file mode 100644 index 37267ebe4bd..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Inline32int.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.set; - -import org.openjdk.bench.valhalla.array.util.StatesQ32int; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline32int extends StatesQ32int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q32int getRef(int i) { - return new Q32int(i); - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q32int getVal(int i) { - return new Q32int(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set(Val_as_Val st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q32int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/set/Inline64byte.java deleted file mode 100644 index b4b1168915e..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Inline64byte.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.set; - -import org.openjdk.bench.valhalla.array.util.StatesQ64byte; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64byte extends StatesQ64byte { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64byte getRef(int i) { - return new Q64byte(i); - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64byte getVal(int i) { - return new Q64byte(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set(Val_as_Val st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64byte[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/set/Inline64int.java deleted file mode 100644 index 0e18f335468..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Inline64int.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.set; - -import org.openjdk.bench.valhalla.array.util.StatesQ64int; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64int extends StatesQ64int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64int getRef(int i) { - return new Q64int(i); - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64int getVal(int i) { - return new Q64int(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getRef(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set(Val_as_Val st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set(Ref_as_Ref st) { - Q64int[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = getVal(i); - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/set/Primitive032.java similarity index 58% rename from test/micro/org/openjdk/bench/valhalla/field/copy/Inline32int.java rename to test/micro/org/openjdk/bench/valhalla/array/set/Primitive032.java index d0b7aa3c845..805f686d5cb 100644 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline32int.java +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Primitive032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,44 +20,54 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.field.copy; +package org.openjdk.bench.valhalla.array.set; -import org.openjdk.bench.valhalla.field.util.StatesQ32int; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; -public class Inline32int extends StatesQ32int { +public class Primitive032 extends SetBase { - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(RefState s, ValState d) { - RefWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + public static class PrimitiveState extends SizeState { + public int[] arr; + + @Setup + public void setup() { + arr = new int[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(ValState s, RefState d) { - ValWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + private static int get_primitive(int i) { + return i; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void set_primitive(int[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = i; } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(ValState s, ValState d) { - ValWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; + private static void set_call_primitive(int[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_primitive(i); } } + @Benchmark + public void set(PrimitiveState st1) { + set_primitive(st1.arr); + } + + @Benchmark + public void set_call(PrimitiveState st1) { + set_call_primitive(st1.arr); + } } diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/SetBase.java b/test/micro/org/openjdk/bench/valhalla/array/set/SetBase.java new file mode 100644 index 00000000000..274452493f0 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/SetBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class SetBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value032.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value032.java new file mode 100644 index 00000000000..a8376a9af3f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value032.java @@ -0,0 +1,134 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value032 extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = new ValueInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFree.java new file mode 100644 index 00000000000..33152c1c306 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFree.java @@ -0,0 +1,135 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFree extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..84508db7b73 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value032NullFreeNonAtomic.java @@ -0,0 +1,137 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFreeNonAtomic extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size, new ValueInt(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt get_val(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value128.java new file mode 100644 index 00000000000..e0b7ea9262b --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value128.java @@ -0,0 +1,141 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFree.java new file mode 100644 index 00000000000..6c69c36c05f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFree.java @@ -0,0 +1,142 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..1d9840c8250 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/Value128NullFreeNonAtomic.java @@ -0,0 +1,144 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends SetBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueInt4(i); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueInt4 get_val(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceInt get_int(int i) { + return new ValueInt4(i); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueInt4(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueInt4[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceInt[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/ValueOop.java b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOop.java new file mode 100644 index 00000000000..213b1517ce8 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOop.java @@ -0,0 +1,144 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class ValueOop extends SetBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = new ValueRef[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceOop get_int(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFree.java b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFree.java new file mode 100644 index 00000000000..2c29fb250f6 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFree.java @@ -0,0 +1,145 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFree extends SetBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceOop get_int(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFreeNonAtomic.java new file mode 100644 index 00000000000..ce038ef46aa --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/set/ValueOopNullFreeNonAtomic.java @@ -0,0 +1,147 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.set; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueOopNullFreeNonAtomic extends SetBase { + + public static class IdentityInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + public interface InterfaceOop { + public IdentityInt value(); + } + + @LooselyConsistentValue + public static value class ValueRef implements InterfaceOop { + + public final IdentityInt value; + + public ValueRef(IdentityInt value) { + this.value = value; + } + + public IdentityInt value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueRef[] arr; + + @Setup + public void setup() { + arr = (ValueRef[]) ValueClass.newNullRestrictedAtomicArray(ValueRef.class, size, new ValueRef(new IdentityInt(0))); + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public InterfaceOop[] arr; + + @Setup + public void setup() { + arr = new InterfaceOop[size]; + for (int i = 0; i < size; i++) { + arr[i] = new ValueRef(new IdentityInt(i)); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueRef get_val(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public InterfaceOop get_int(int i) { + return new ValueRef(new IdentityInt(i)); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_new_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = new ValueRef(new IdentityInt(i)); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_val(ValueRef[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_val(i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void set_call_int(InterfaceOop[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = get_int(i); + } + } + + @Benchmark + public void set_new_val_as_val(ValState st1) { + set_new_val(st1.arr); + } + + @Benchmark + public void set_new_int_as_int(IntState st1) { + set_new_int(st1.arr); + } + + @Benchmark + public void set_call_val_as_val(ValState st1) { + set_call_val(st1.arr); + } + + @Benchmark + public void set_call_int_as_int(IntState st1) { + set_call_int(st1.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/IdentityOpt.java b/test/micro/org/openjdk/bench/valhalla/array/sum/IdentityOpt.java deleted file mode 100644 index a9fb5a0e14c..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/IdentityOpt.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesROpt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Opt; -import org.openjdk.bench.valhalla.types.ROpt; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityOpt extends StatesROpt { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_fields(Ref_as_Ref st) { - int s = 0; - ROpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].value.intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_sum(Ref_as_Ref st) { - int s = 0; - ROpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(Int_as_Int st) { - int s = 0; - Opt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Inline128int.java deleted file mode 100644 index c858a4c5505..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline128int.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesQ128int; -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline128int extends StatesQ128int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_fields(Val_as_Val st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0.v0; - s += arr[i].v0.v1.v0; - s += arr[i].v1.v0.v0; - s += arr[i].v1.v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_fields(Val_as_Ref st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0.v0; - s += arr[i].v0.v1.v0; - s += arr[i].v1.v0.v0; - s += arr[i].v1.v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_fields(Ref_as_Ref st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0.v0; - s += arr[i].v0.v1.v0; - s += arr[i].v1.v0.v0; - s += arr[i].v1.v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_sum(Val_as_Val st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_sum(Val_as_Ref st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_sum(Ref_as_Ref st) { - int s = 0; - Q128int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_sum(Val_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Int_sum(Ref_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(By_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline32int.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Inline32int.java deleted file mode 100644 index 2c36679a020..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline32int.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesQ32int; -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline32int extends StatesQ32int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_fields(Val_as_Val st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_fields(Val_as_Ref st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_fields(Ref_as_Ref st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_sum(Val_as_Val st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_sum(Val_as_Ref st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_sum(Ref_as_Ref st) { - int s = 0; - Q32int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_sum(Val_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(By_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64byte.java deleted file mode 100644 index 07e4a56f354..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64byte.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesQ64byte; -import org.openjdk.bench.valhalla.types.ByByte; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64byte extends StatesQ64byte { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Val_as_Val_fields(Val_as_Val st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v0.v1; - s += arr[i].v0.v2; - s += arr[i].v0.v3; - s += arr[i].v1.v0; - s += arr[i].v1.v1; - s += arr[i].v1.v2; - s += arr[i].v1.v3; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Val_as_Ref_fields(Val_as_Ref st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v0.v1; - s += arr[i].v0.v2; - s += arr[i].v0.v3; - s += arr[i].v1.v0; - s += arr[i].v1.v1; - s += arr[i].v1.v2; - s += arr[i].v1.v3; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Ref_as_Ref_fields(Ref_as_Ref st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v0.v1; - s += arr[i].v0.v2; - s += arr[i].v0.v3; - s += arr[i].v1.v0; - s += arr[i].v1.v1; - s += arr[i].v1.v2; - s += arr[i].v1.v3; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Val_as_Val_sum(Val_as_Val st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].byteSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Val_as_Ref_sum(Val_as_Ref st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].byteSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte Ref_as_Ref_sum(Ref_as_Ref st) { - byte s = 0; - Q64byte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].byteSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_sum(Val_as_By st) { - int s = 0; - ByByte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].byteSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(By_as_By st) { - int s = 0; - ByByte[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].byteSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64int.java deleted file mode 100644 index 4446d2347be..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Inline64int.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesQ64int; -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64int extends StatesQ64int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_fields(Val_as_Val st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_fields(Val_as_Ref st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_fields(Ref_as_Ref st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0.v0; - s += arr[i].v1.v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_sum(Val_as_Val st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_sum(Val_as_Ref st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_sum(Ref_as_Ref st) { - int s = 0; - Q64int[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_sum(Val_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Int_sum(Ref_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(By_as_By st) { - int s = 0; - ByInt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].intSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/InlineOpt.java b/test/micro/org/openjdk/bench/valhalla/array/sum/InlineOpt.java deleted file mode 100644 index 09905bce0b0..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/InlineOpt.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.StatesQOpt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Opt; -import org.openjdk.bench.valhalla.types.QOpt; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineOpt extends StatesQOpt { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_fields(Val_as_Val st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].value.intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_fields(Val_as_Ref st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].value.intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_fields(Ref_as_Ref st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].value.intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_sum(Val_as_Val st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_sum(Val_as_Ref st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_sum(Ref_as_Ref st) { - int s = 0; - QOpt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_sum(Val_as_Int st) { - int s = 0; - Opt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_sum(Int_as_Int st) { - int s = 0; - Opt[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].get().intValue(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive32int.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive32int.java deleted file mode 100644 index d45a91d1a24..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive32int.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive32int extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int sum(Primitive32int st) { - int s = 0; - int[] values = st.arr; - for (int i = 0; i < values.length; i++) { - s += values[i]; - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64byte.java b/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64byte.java deleted file mode 100644 index 86c96a45c53..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64byte.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.sum; - -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive64byte extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte sum(Primitive64byte st) { - byte s = 0; - byte[] values = st.arr; - for (int i = 0; i < values.length; i++) { - s += values[i]; - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/PrimitiveStates.java b/test/micro/org/openjdk/bench/valhalla/array/util/PrimitiveStates.java deleted file mode 100644 index 448d0948749..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/PrimitiveStates.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class PrimitiveStates extends SizeBase { - - public static abstract class ByteState extends SizeState { - public byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = (byte) i; - } - } - } - - public static abstract class IntState extends SizeState { - public int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - } - } - - public static abstract class LongState extends SizeState { - public long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - } - } - - public static class Primitive32int extends IntState { - @Setup - public void setup() { - arr = new int[size]; - fill(); - } - } - - public static class Primitive64byte extends ByteState { - @Setup - public void setup() { - arr = new byte[size * 8]; - fill(); - } - } - - public static class Primitive64int extends IntState { - @Setup - public void setup() { - arr = new int[size * 2]; - fill(); - } - } - - public static class Primitive64long extends LongState { - @Setup - public void setup() { - arr = new long[size]; - fill(); - } - } - - public static class Primitive128int extends IntState { - @Setup - public void setup() { - arr = new int[size * 4]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128byte.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128byte.java deleted file mode 100644 index ab1773e5292..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128byte.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.Q128byte; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ128byte extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128byte(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int128[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128byte(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q128byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128byte(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q128byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128byte(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q128byte[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128int.java deleted file mode 100644 index d12af907832..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128int.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ128int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int128[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q128int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q128int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByInt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128int(i); - } - } - } - - public static class Val_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class Ref_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new Q128int[size]; - fill(); - } - } - - public static class By_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new ByInt[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128long.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128long.java deleted file mode 100644 index e0778dfbda1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ128long.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.Q128long; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ128long extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128long(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int128[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128long(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q128long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128long(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q128long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q128long(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q128long[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ32int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ32int.java deleted file mode 100644 index 2fa6dbde753..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ32int.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ32int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int32[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q32int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q32int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int32[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int32[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByInt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q32int(i); - } - } - } - - public static class Val_as_By extends ByState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Ref_as_By extends ByState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class By_as_By extends ByState { - @Setup - public void setup() { - arr = new ByInt[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64byte.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64byte.java deleted file mode 100644 index 41471482b70..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64byte.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.ByByte; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64byte extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q64byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q64byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByByte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64byte(i); - } - } - } - - public static class Val_as_By extends ByState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class Ref_as_By extends ByState { - @Setup - public void setup() { - arr = new Q64byte[size]; - fill(); - } - } - - public static class By_as_By extends ByState { - @Setup - public void setup() { - arr = new ByByte[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64int.java deleted file mode 100644 index 012f0ede0ce..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQ64int.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.ByInt; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q64int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q64int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByInt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64int(i); - } - } - } - - public static class Val_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class Ref_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new Q64int[size]; - fill(); - } - } - - public static class By_as_By extends StatesQ32int.ByState { - @Setup - public void setup() { - arr = new ByInt[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQOpt.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesQOpt.java deleted file mode 100644 index 553e72715c1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesQOpt.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Opt; -import org.openjdk.bench.valhalla.types.QOpt; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQOpt extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(new R32int(i)); - } - } - } - - public static abstract class IntState extends SizeState { - public Opt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(new R32int(i)); - } - } - } - - public static abstract class RefState extends SizeState { - public QOpt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(new R32int(i)); - } - } - } - - public static abstract class ValState extends SizeState { - public QOpt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = QOpt.of(new R32int(i)); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Opt[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Opt[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new QOpt[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR128int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesR128int.java deleted file mode 100644 index baba0abe13d..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR128int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.R128int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesR128int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R128int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int128[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R128int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public R128int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R128int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new R128int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int128[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R128int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R128int[size]; - fill(); - } - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR32int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesR32int.java deleted file mode 100644 index f9609390751..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR32int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesR32int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R32int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int32[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R32int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public R32int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R32int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int32[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new R32int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int32[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R32int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R32int[size]; - fill(); - } - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64byte.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64byte.java deleted file mode 100644 index b3f58236495..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64byte.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64byte; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesR64byte extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64byte(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64byte(i); - } - } - } - - public static abstract class RefState extends SizeState { - public R64byte[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64byte(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new R64byte[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R64byte[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R64byte[size]; - fill(); - } - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64int.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64int.java deleted file mode 100644 index c31f0f36a80..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesR64int.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesR64int extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64int(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64int(i); - } - } - } - - public static abstract class RefState extends SizeState { - public R64int[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64int(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new R64int[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R64int[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R64int[size]; - fill(); - } - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/array/util/StatesROpt.java b/test/micro/org/openjdk/bench/valhalla/array/util/StatesROpt.java deleted file mode 100644 index a200338dadd..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/array/util/StatesROpt.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.array.util; - -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Opt; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.bench.valhalla.types.ROpt; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesROpt extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = ROpt.of(new R32int(i)); - } - } - } - - public static abstract class IntState extends SizeState { - public Opt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = ROpt.of(new R32int(i)); - } - } - } - - public static abstract class RefState extends SizeState { - public ROpt[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = ROpt.of(new R32int(i)); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Opt[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new ROpt[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Opt[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new ROpt[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new ROpt[size]; - fill(); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Identity32.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Identity.java similarity index 55% rename from test/micro/org/openjdk/bench/valhalla/traversal/Identity32.java rename to test/micro/org/openjdk/bench/valhalla/array/walk/Identity.java index f1d9fe9bc59..9ece262c815 100644 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Identity32.java +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,70 +20,81 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.traversal; +package org.openjdk.bench.valhalla.array.walk; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.R32int; -import org.openjdk.bench.valhalla.util.Utils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Setup; -public class Identity32 extends SizeBase { +public class Identity extends WalkBase { - public static abstract class IntState extends SizeState { - public Int32[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new R32int(a[i]); - } - } + public interface InterfaceInt { + public int value(); } - public static abstract class RefState extends SizeState { - public R32int[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new R32int(a[i]); - } + public static class IdentityInt implements InterfaceInt { + + public final int value; + + public IdentityInt(int value) { + this.value = value; } + + public int value() { + return value; + } + } - public static class Int_as_Int extends IntState { + + public static class RefState extends SizeState { + public IdentityInt[] arr; + @Setup public void setup() { - arr = new Int32[size]; - fill(); + arr = new IdentityInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new IdentityInt(a[i]); + } } } - public static class Ref_as_Ref extends RefState { + public static class IntState extends SizeState { + public InterfaceInt[] arr; + @Setup public void setup() { - arr = new R32int[size]; - fill(); + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new IdentityInt(a[i]); + } } } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_walk(Int_as_Int s) { + private static int walk_ref(IdentityInt[] values) { int steps = 0; - Int32[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; return steps; } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_walk(Ref_as_Ref s) { + private static int walk_int(InterfaceInt[] values) { int steps = 0; - R32int[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; return steps; } + @Benchmark + public int walk_ref_as_ref(RefState st) { + return walk_ref(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + } diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Primitive32.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Primitive.java similarity index 74% rename from test/micro/org/openjdk/bench/valhalla/traversal/Primitive32.java rename to test/micro/org/openjdk/bench/valhalla/array/walk/Primitive.java index ddea918920c..098f45f134e 100644 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Primitive32.java +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Primitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,31 +20,27 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.traversal; +package org.openjdk.bench.valhalla.array.walk; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.util.Utils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Setup; -public class Primitive32 extends SizeBase { +public class Primitive extends WalkBase { - public static class IntState extends SizeState { + public static class PrimState extends SizeState { public int[] arr; @Setup public void setup() { - int[] a = Utils.makeRandomRing(size); - arr = new int[a.length]; - System.arraycopy(a, 0, arr, 0, a.length); + arr = makeRandomRing(size); } } @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int walk(IntState s) { + public int walk(PrimState s) { int steps = 0; int[] values = s.arr; for (int i = values[0]; i != 0; i = values[i]) steps++; diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value032.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032.java new file mode 100644 index 00000000000..f02e19fddb8 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032.java @@ -0,0 +1,102 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value032 extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = new ValueInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFree.java new file mode 100644 index 00000000000..96dee5bea6d --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFree.java @@ -0,0 +1,102 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFree extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size, new ValueInt(0)); + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFreeNonAtomic.java new file mode 100644 index 00000000000..33aa7f80d18 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value032NullFreeNonAtomic.java @@ -0,0 +1,104 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value032NullFreeNonAtomic extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceInt { + + public final int value; + + public ValueInt(int value) { + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt[] arr; + + @Setup + public void setup() { + arr = (ValueInt[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size, new ValueInt(0)); + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt(a[i]); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value128.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128.java new file mode 100644 index 00000000000..f336ef9aa06 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128.java @@ -0,0 +1,108 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value128 extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = new ValueInt4[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt4[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFree.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFree.java new file mode 100644 index 00000000000..f42633ce3eb --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFree.java @@ -0,0 +1,108 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFree extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt4[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFreeNonAtomic.java new file mode 100644 index 00000000000..4a90370ce93 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/Value128NullFreeNonAtomic.java @@ -0,0 +1,110 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.array.walk; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class Value128NullFreeNonAtomic extends WalkBase { + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt4 implements InterfaceInt { + + public final int prevalue0; + public final int prevalue1; + public final int prevalue2; + public final int value; + + public ValueInt4(int value) { + this.prevalue0 = value; + this.prevalue1 = value; + this.prevalue2 = value; + this.value = value; + } + + public int value() { + return value; + } + + } + + public static class ValState extends SizeState { + public ValueInt4[] arr; + + @Setup + public void setup() { + arr = (ValueInt4[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt4.class, size, new ValueInt4(0)); + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + public static class IntState extends SizeState { + public InterfaceInt[] arr; + + @Setup + public void setup() { + arr = new InterfaceInt[size]; + int[] a = makeRandomRing(arr.length); + for (int i = 0; i < a.length; i++) { + arr[i] = new ValueInt4(a[i]); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_val(ValueInt4[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int walk_int(InterfaceInt[] values) { + int steps = 0; + for (int i = values[0].value(); i != 0; i = values[i].value()) steps++; + return steps; + } + + @Benchmark + public int walk_val_as_val(ValState st) { + return walk_val(st.arr); + } + + @Benchmark + public int walk_int_as_int(IntState st) { + return walk_int(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/util/Utils.java b/test/micro/org/openjdk/bench/valhalla/array/walk/WalkBase.java similarity index 61% rename from test/micro/org/openjdk/bench/valhalla/util/Utils.java rename to test/micro/org/openjdk/bench/valhalla/array/walk/WalkBase.java index e2247744771..0ad521a7481 100644 --- a/test/micro/org/openjdk/bench/valhalla/util/Utils.java +++ b/test/micro/org/openjdk/bench/valhalla/array/walk/WalkBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,11 +20,38 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.util; +package org.openjdk.bench.valhalla.array.walk; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.Random; +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class WalkBase { -public class Utils { + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } public static void shuffle(int[] a, Random rnd) { for (int i = a.length; i > 1; i--) { @@ -50,4 +77,5 @@ public static int[] makeRandomRing(int size) { a[x] = 0; return a; } + } diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityArrayCopy.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityArrayCopy.java deleted file mode 100644 index 5441654300f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityArrayCopy.java +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityArrayCopy extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Obj_copy(Obj_as_Obj s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Int_copy(Obj_as_Obj s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Abs_copy(Obj_as_Obj s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Abs_copy(Obj_as_Obj s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Obj_copy(Int_as_Obj s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Int_copy(Int_as_Obj s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Abs_copy(Int_as_Obj s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Abs_copy(Int_as_Obj s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Obj_to_Obj_copy(Abs_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Obj_copy(Abs_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Obj_copy(Abs_as_Obj s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Obj_copy(Abs_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Int_copy(Abs_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Int_copy(Abs_as_Obj s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Int_copy(Abs_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Abs_copy(Abs_as_Obj s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Abs_copy(Abs_as_Obj s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Ref_copy(Abs_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Obj_copy(Ref_as_Obj s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Int_copy(Ref_as_Obj s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Abs_copy(Ref_as_Obj s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Abs_copy(Ref_as_Obj s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Obj_copy(Int_as_Int s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Int_copy(Int_as_Int s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Abs_copy(Int_as_Int s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Abs_copy(Int_as_Int s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Int_to_Obj_copy(Abs_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Obj_copy(Abs_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Obj_copy(Abs_as_Int s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Obj_copy(Abs_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Int_copy(Abs_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Int_copy(Abs_as_Int s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Int_copy(Abs_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Abs_copy(Abs_as_Int s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Abs_copy(Abs_as_Int s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Ref_copy(Abs_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Obj_copy(Ref_as_Int s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Int_copy(Ref_as_Int s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Abs_copy(Ref_as_Int s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Abs_copy(Ref_as_Int s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Abs_to_Obj_copy(Abs_as_Abs s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Obj_copy(Abs_as_Abs s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Obj_copy(Abs_as_Abs s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Obj_copy(Abs_as_Abs s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Int_copy(Abs_as_Abs s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Int_copy(Abs_as_Abs s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Int_copy(Abs_as_Abs s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Abs_copy(Abs_as_Abs s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Abs_copy(Abs_as_Abs s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Ref_copy(Abs_as_Abs s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Abs_to_Obj_copy(Ref_as_Abs s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Obj_copy(Ref_as_Abs s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Obj_copy(Ref_as_Abs s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Obj_copy(Ref_as_Abs s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Int_copy(Ref_as_Abs s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Int_copy(Ref_as_Abs s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Int_copy(Ref_as_Abs s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Abs_copy(Ref_as_Abs s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Abs_copy(Ref_as_Abs s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Ref_copy(Ref_as_Abs s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Obj_copy(Ref_as_Ref s, Abs_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Int_copy(Ref_as_Ref s, Abs_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Abs_copy(Ref_as_Ref s, Abs_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Abs_copy(Ref_as_Ref s, Ref_as_Abs d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy0.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy0.java deleted file mode 100644 index acb3e1d3bac..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy0.java +++ /dev/null @@ -1,1034 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityCopy0 extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Obj_copy(Obj_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Int_copy(Obj_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Abs_copy(Obj_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Abs_copy(Obj_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Obj_copy(Int_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Int_copy(Int_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Abs_copy(Int_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Abs_copy(Int_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Obj_to_Obj_copy(Abs_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Obj_copy(Abs_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Obj_copy(Abs_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Obj_copy(Abs_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Int_copy(Abs_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Int_copy(Abs_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Int_copy(Abs_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Abs_copy(Abs_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Abs_copy(Abs_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Ref_copy(Abs_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Obj_copy(Ref_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Int_copy(Ref_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Abs_copy(Ref_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Abs_copy(Ref_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Obj_copy(Int_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Int_copy(Int_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Abs_copy(Int_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Abs_copy(Int_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Int_to_Obj_copy(Abs_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Obj_copy(Abs_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Obj_copy(Abs_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Obj_copy(Abs_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Int_copy(Abs_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Int_copy(Abs_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Int_copy(Abs_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Abs_copy(Abs_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Abs_copy(Abs_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Ref_copy(Abs_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Obj_copy(Ref_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Int_copy(Ref_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Abs_copy(Ref_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Abs_copy(Ref_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Abs_to_Obj_copy(Abs_as_Abs s, Obj_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Obj_copy(Abs_as_Abs s, Int_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Obj_copy(Abs_as_Abs s, Abs_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Obj_copy(Abs_as_Abs s, Ref_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Int_copy(Abs_as_Abs s, Int_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Int_copy(Abs_as_Abs s, Abs_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Int_copy(Abs_as_Abs s, Ref_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Abs_copy(Abs_as_Abs s, Abs_as_Abs d) { - A64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Abs_copy(Abs_as_Abs s, Ref_as_Abs d) { - A64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Ref_copy(Abs_as_Abs s, Ref_as_Ref d) { - A64long[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Abs_to_Obj_copy(Ref_as_Abs s, Obj_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Obj_copy(Ref_as_Abs s, Int_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Obj_copy(Ref_as_Abs s, Abs_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Obj_copy(Ref_as_Abs s, Ref_as_Obj d) { - A64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Int_copy(Ref_as_Abs s, Int_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Int_copy(Ref_as_Abs s, Abs_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Int_copy(Ref_as_Abs s, Ref_as_Int d) { - A64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Abs_copy(Ref_as_Abs s, Abs_as_Abs d) { - A64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Abs_copy(Ref_as_Abs s, Ref_as_Abs d) { - A64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Ref_copy(Ref_as_Abs s, Ref_as_Ref d) { - A64long[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - R64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - R64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Obj_copy(Ref_as_Ref s, Abs_as_Obj d) { - R64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - R64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - R64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Int_copy(Ref_as_Ref s, Abs_as_Int d) { - R64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - R64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Abs_copy(Ref_as_Ref s, Abs_as_Abs d) { - R64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Abs_copy(Ref_as_Ref s, Ref_as_Abs d) { - R64long[] src = s.arr; - A64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - R64long[] src = s.arr; - R64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy1.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy1.java deleted file mode 100644 index 57efe0a717e..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy1.java +++ /dev/null @@ -1,934 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityCopy1 extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Obj_copy(Obj_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Int_copy(Obj_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Abs_copy(Obj_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Abs_copy(Obj_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Obj_copy(Int_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Int_copy(Int_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Abs_copy(Int_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Abs_copy(Int_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Obj_to_Obj_copy(Abs_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Obj_copy(Abs_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Obj_copy(Abs_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Obj_copy(Abs_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Int_copy(Abs_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Int_copy(Abs_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Int_copy(Abs_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Abs_copy(Abs_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Abs_copy(Abs_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Ref_copy(Abs_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Obj_copy(Ref_as_Obj s, Abs_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Int_copy(Ref_as_Obj s, Abs_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Abs_copy(Ref_as_Obj s, Abs_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Abs_copy(Ref_as_Obj s, Ref_as_Abs d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Obj_copy(Int_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Int_copy(Int_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Abs_copy(Int_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Abs_copy(Int_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Int_to_Obj_copy(Abs_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Obj_copy(Abs_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Obj_copy(Abs_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Obj_copy(Abs_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Int_copy(Abs_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Int_copy(Abs_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Int_copy(Abs_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Abs_copy(Abs_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Abs_copy(Abs_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Ref_copy(Abs_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Obj_copy(Ref_as_Int s, Abs_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Int_copy(Ref_as_Int s, Abs_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Abs_copy(Ref_as_Int s, Abs_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Abs_copy(Ref_as_Int s, Ref_as_Abs d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (A64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Abs_to_Obj_copy(Abs_as_Abs s, Obj_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Obj_copy(Abs_as_Abs s, Int_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Obj_copy(Abs_as_Abs s, Abs_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Obj_copy(Abs_as_Abs s, Ref_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Int_copy(Abs_as_Abs s, Int_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Int_copy(Abs_as_Abs s, Abs_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Int_copy(Abs_as_Abs s, Ref_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Abs_copy(Abs_as_Abs s, Abs_as_Abs d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Abs_copy(Abs_as_Abs s, Ref_as_Abs d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Ref_copy(Abs_as_Abs s, Ref_as_Ref d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Abs_to_Obj_copy(Ref_as_Abs s, Obj_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Obj_copy(Ref_as_Abs s, Int_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Obj_copy(Ref_as_Abs s, Abs_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Obj_copy(Ref_as_Abs s, Ref_as_Obj d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Int_copy(Ref_as_Abs s, Int_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Int_copy(Ref_as_Abs s, Abs_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Int_copy(Ref_as_Abs s, Ref_as_Int d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Abs_copy(Ref_as_Abs s, Abs_as_Abs d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Abs_copy(Ref_as_Abs s, Ref_as_Abs d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Ref_copy(Ref_as_Abs s, Ref_as_Ref d) { - A64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (R64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Obj_copy(Ref_as_Ref s, Abs_as_Obj d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Int_copy(Ref_as_Ref s, Abs_as_Int d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Abs_copy(Ref_as_Ref s, Abs_as_Abs d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Abs_copy(Ref_as_Ref s, Ref_as_Abs d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - R64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy2.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy2.java deleted file mode 100644 index a38079fa650..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy2.java +++ /dev/null @@ -1,1034 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityCopy2 extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Obj_copy(Obj_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Int_copy(Obj_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Abs_copy(Obj_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Abs_copy(Obj_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Obj_copy(Int_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Int_copy(Int_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Abs_copy(Int_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Abs_copy(Int_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Obj_to_Obj_copy(Abs_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Obj_copy(Abs_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Obj_copy(Abs_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Obj_copy(Abs_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Int_copy(Abs_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Int_copy(Abs_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Int_copy(Abs_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Abs_copy(Abs_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Abs_copy(Abs_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Ref_copy(Abs_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Obj_copy(Ref_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Int_copy(Ref_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Abs_copy(Ref_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Abs_copy(Ref_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Obj_copy(Int_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Int_copy(Int_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Abs_copy(Int_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Abs_copy(Int_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Int_to_Obj_copy(Abs_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Obj_copy(Abs_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Obj_copy(Abs_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Obj_copy(Abs_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Int_copy(Abs_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Int_copy(Abs_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Int_copy(Abs_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Abs_copy(Abs_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Abs_copy(Abs_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Ref_copy(Abs_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Obj_copy(Ref_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Int_copy(Ref_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Abs_copy(Ref_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Abs_copy(Ref_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Abs_to_Obj_copy(Abs_as_Abs s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Obj_copy(Abs_as_Abs s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Obj_copy(Abs_as_Abs s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Obj_copy(Abs_as_Abs s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Int_copy(Abs_as_Abs s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Int_copy(Abs_as_Abs s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Int_copy(Abs_as_Abs s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Abs_copy(Abs_as_Abs s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Abs_copy(Abs_as_Abs s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Ref_copy(Abs_as_Abs s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Abs_to_Obj_copy(Ref_as_Abs s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Obj_copy(Ref_as_Abs s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Obj_copy(Ref_as_Abs s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Obj_copy(Ref_as_Abs s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Int_copy(Ref_as_Abs s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Int_copy(Ref_as_Abs s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Int_copy(Ref_as_Abs s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Abs_copy(Ref_as_Abs s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Abs_copy(Ref_as_Abs s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Ref_copy(Ref_as_Abs s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Obj_copy(Ref_as_Ref s, Abs_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Int_copy(Ref_as_Ref s, Abs_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Abs_copy(Ref_as_Ref s, Abs_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Abs_copy(Ref_as_Ref s, Ref_as_Abs d) { - int len = s.arr.length; - A64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - R64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy3.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy3.java deleted file mode 100644 index 7d047fc8778..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/IdentityCopy3.java +++ /dev/null @@ -1,934 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class IdentityCopy3 extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Obj_copy(Obj_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Int_copy(Obj_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Abs_as_Obj_to_Abs_copy(Obj_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Abs_copy(Obj_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Obj_copy(Int_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Int_copy(Int_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Obj_to_Abs_copy(Int_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Abs_copy(Int_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Obj_to_Obj_copy(Abs_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Obj_copy(Abs_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Obj_copy(Abs_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Obj_copy(Abs_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Obj_to_Int_copy(Abs_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Int_copy(Abs_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Int_copy(Abs_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Obj_to_Abs_copy(Abs_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Abs_copy(Abs_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Obj_to_Ref_copy(Abs_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Obj_copy(Ref_as_Obj s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Int_copy(Ref_as_Obj s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Obj_to_Abs_copy(Ref_as_Obj s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Abs_copy(Ref_as_Obj s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Obj_copy(Int_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Int_copy(Int_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Abs_as_Int_to_Abs_copy(Int_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Abs_copy(Int_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Int_to_Obj_copy(Abs_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Obj_copy(Abs_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Obj_copy(Abs_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Obj_copy(Abs_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Int_to_Int_copy(Abs_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Int_copy(Abs_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Int_copy(Abs_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Int_to_Abs_copy(Abs_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Abs_copy(Abs_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Int_to_Ref_copy(Abs_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Obj_copy(Ref_as_Int s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Int_copy(Ref_as_Int s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Int_to_Abs_copy(Ref_as_Int s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Abs_copy(Ref_as_Int s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (A64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Obj_as_Abs_to_Obj_copy(Abs_as_Abs s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Obj_copy(Abs_as_Abs s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Obj_copy(Abs_as_Abs s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Obj_copy(Abs_as_Abs s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Int_as_Abs_to_Int_copy(Abs_as_Abs s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Int_copy(Abs_as_Abs s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Int_copy(Abs_as_Abs s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Abs_as_Abs_to_Abs_copy(Abs_as_Abs s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Abs_copy(Abs_as_Abs s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Abs_to_Ref_as_Abs_to_Ref_copy(Abs_as_Abs s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Abs_to_Obj_copy(Ref_as_Abs s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Obj_copy(Ref_as_Abs s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Obj_copy(Ref_as_Abs s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Obj_copy(Ref_as_Abs s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Abs_to_Int_copy(Ref_as_Abs s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Int_copy(Ref_as_Abs s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Int_copy(Ref_as_Abs s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Abs_to_Abs_copy(Ref_as_Abs s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Abs_copy(Ref_as_Abs s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Abs_to_Ref_copy(Ref_as_Abs s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (R64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Obj_copy(Ref_as_Ref s, Abs_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Int_copy(Ref_as_Ref s, Abs_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Abs_as_Ref_to_Abs_copy(Ref_as_Ref s, Abs_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Abs_copy(Ref_as_Ref s, Ref_as_Abs d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineArrayCopy.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineArrayCopy.java deleted file mode 100644 index b8675321402..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineArrayCopy.java +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineArrayCopy extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Obj_copy(Obj_as_Obj s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Int_copy(Obj_as_Obj s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Ref_copy(Obj_as_Obj s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Val_copy(Obj_as_Obj s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Obj_copy(Int_as_Obj s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Int_copy(Int_as_Obj s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Ref_copy(Int_as_Obj s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Val_copy(Int_as_Obj s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Obj_copy(Ref_as_Obj s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Int_copy(Ref_as_Obj s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Ref_copy(Ref_as_Obj s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Val_copy(Ref_as_Obj s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_to_Obj_copy(Val_as_Obj s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Obj_copy(Val_as_Obj s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Obj_copy(Val_as_Obj s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Obj_copy(Val_as_Obj s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Int_copy(Val_as_Obj s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Int_copy(Val_as_Obj s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Int_copy(Val_as_Obj s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Ref_copy(Val_as_Obj s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Ref_copy(Val_as_Obj s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Val_copy(Val_as_Obj s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Obj_copy(Int_as_Int s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Int_copy(Int_as_Int s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Ref_copy(Int_as_Int s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Val_copy(Int_as_Int s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Obj_copy(Ref_as_Int s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Int_copy(Ref_as_Int s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Ref_copy(Ref_as_Int s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Val_copy(Ref_as_Int s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Int_to_Obj_copy(Val_as_Int s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Obj_copy(Val_as_Int s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Obj_copy(Val_as_Int s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Obj_copy(Val_as_Int s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Int_copy(Val_as_Int s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Int_copy(Val_as_Int s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Int_copy(Val_as_Int s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Ref_copy(Val_as_Int s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Ref_copy(Val_as_Int s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Val_copy(Val_as_Int s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Obj_copy(Ref_as_Ref s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Int_copy(Ref_as_Ref s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Ref_copy(Ref_as_Ref s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Ref_to_Obj_copy(Val_as_Ref s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Obj_copy(Val_as_Ref s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Obj_copy(Val_as_Ref s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Obj_copy(Val_as_Ref s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Int_copy(Val_as_Ref s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Int_copy(Val_as_Ref s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Int_copy(Val_as_Ref s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Ref_copy(Val_as_Ref s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Ref_copy(Val_as_Ref s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Val_copy(Val_as_Ref s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Val_to_Obj_copy(Val_as_Val s, Obj_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Obj_copy(Val_as_Val s, Int_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Obj_copy(Val_as_Val s, Ref_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Obj_copy(Val_as_Val s, Val_as_Obj d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Int_copy(Val_as_Val s, Int_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Int_copy(Val_as_Val s, Ref_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Int_copy(Val_as_Val s, Val_as_Int d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Ref_copy(Val_as_Val s, Val_as_Ref d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - System.arraycopy(s.arr, 0, d.arr, 0, s.arr.length); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy0.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy0.java deleted file mode 100644 index baaf48a56d5..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy0.java +++ /dev/null @@ -1,1034 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineCopy0 extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Obj_copy(Obj_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Int_copy(Obj_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Ref_copy(Obj_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Val_copy(Obj_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Obj_copy(Int_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Int_copy(Int_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Ref_copy(Int_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Val_copy(Int_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Obj_copy(Ref_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Int_copy(Ref_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Ref_copy(Ref_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Val_copy(Ref_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_to_Obj_copy(Val_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Obj_copy(Val_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Obj_copy(Val_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Obj_copy(Val_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Int_copy(Val_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Int_copy(Val_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Int_copy(Val_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Ref_copy(Val_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Ref_copy(Val_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Val_copy(Val_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Obj_copy(Int_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Int_copy(Int_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Ref_copy(Int_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Val_copy(Int_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Obj_copy(Ref_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Int_copy(Ref_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Ref_copy(Ref_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Val_copy(Ref_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Int_to_Obj_copy(Val_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Obj_copy(Val_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Obj_copy(Val_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Obj_copy(Val_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Int_copy(Val_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Int_copy(Val_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Int_copy(Val_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Ref_copy(Val_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Ref_copy(Val_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Val_copy(Val_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Obj_copy(Ref_as_Ref s, Val_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Int_copy(Ref_as_Ref s, Val_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Ref_copy(Ref_as_Ref s, Val_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Ref_to_Obj_copy(Val_as_Ref s, Obj_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Obj_copy(Val_as_Ref s, Int_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Obj_copy(Val_as_Ref s, Ref_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Obj_copy(Val_as_Ref s, Val_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Int_copy(Val_as_Ref s, Int_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Int_copy(Val_as_Ref s, Ref_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Int_copy(Val_as_Ref s, Val_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Ref_copy(Val_as_Ref s, Ref_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Ref_copy(Val_as_Ref s, Val_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Val_copy(Val_as_Ref s, Val_as_Val d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Val_to_Obj_copy(Val_as_Val s, Obj_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Obj_copy(Val_as_Val s, Int_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Obj_copy(Val_as_Val s, Ref_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Obj_copy(Val_as_Val s, Val_as_Obj d) { - Q64long[] src = s.arr; - Object[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Int_copy(Val_as_Val s, Int_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Int_copy(Val_as_Val s, Ref_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Int_copy(Val_as_Val s, Val_as_Int d) { - Q64long[] src = s.arr; - Int64[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Ref_copy(Val_as_Val s, Val_as_Ref d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q64long[] src = s.arr; - Q64long[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i] = src[i]; - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy1.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy1.java deleted file mode 100644 index 0ca77d7f35c..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy1.java +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineCopy1 extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Obj_copy(Obj_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Int_copy(Obj_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Ref_copy(Obj_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Val_copy(Obj_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Obj_copy(Int_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Int_copy(Int_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Ref_copy(Int_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Val_copy(Int_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Obj_copy(Ref_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Int_copy(Ref_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Ref_copy(Ref_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Val_copy(Ref_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_to_Obj_copy(Val_as_Obj s, Obj_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Obj_copy(Val_as_Obj s, Int_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Obj_copy(Val_as_Obj s, Ref_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Obj_copy(Val_as_Obj s, Val_as_Obj d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Int_copy(Val_as_Obj s, Int_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Int_copy(Val_as_Obj s, Ref_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Int_copy(Val_as_Obj s, Val_as_Int d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Int64)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Ref_copy(Val_as_Obj s, Ref_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Ref_copy(Val_as_Obj s, Val_as_Ref d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Val_copy(Val_as_Obj s, Val_as_Val d) { - Object[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Obj_copy(Int_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Int_copy(Int_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Ref_copy(Int_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Val_copy(Int_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Obj_copy(Ref_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Int_copy(Ref_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Ref_copy(Ref_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Val_copy(Ref_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Int_to_Obj_copy(Val_as_Int s, Obj_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Obj_copy(Val_as_Int s, Int_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Obj_copy(Val_as_Int s, Ref_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Obj_copy(Val_as_Int s, Val_as_Obj d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Int_copy(Val_as_Int s, Int_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Int_copy(Val_as_Int s, Ref_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Int_copy(Val_as_Int s, Val_as_Int d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Ref_copy(Val_as_Int s, Ref_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Ref_copy(Val_as_Int s, Val_as_Ref d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Val_copy(Val_as_Int s, Val_as_Val d) { - Int64[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = (Q64long)src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Obj_copy(Ref_as_Ref s, Val_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Int_copy(Ref_as_Ref s, Val_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Ref_copy(Ref_as_Ref s, Val_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Ref_to_Obj_copy(Val_as_Ref s, Obj_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Obj_copy(Val_as_Ref s, Int_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Obj_copy(Val_as_Ref s, Ref_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Obj_copy(Val_as_Ref s, Val_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Int_copy(Val_as_Ref s, Int_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Int_copy(Val_as_Ref s, Ref_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Int_copy(Val_as_Ref s, Val_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Ref_copy(Val_as_Ref s, Ref_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Ref_copy(Val_as_Ref s, Val_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Val_copy(Val_as_Ref s, Val_as_Val d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Val_to_Obj_copy(Val_as_Val s, Obj_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Obj_copy(Val_as_Val s, Int_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Obj_copy(Val_as_Val s, Ref_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Obj_copy(Val_as_Val s, Val_as_Obj d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Int_copy(Val_as_Val s, Int_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Int_copy(Val_as_Val s, Ref_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Int_copy(Val_as_Val s, Val_as_Int d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Ref_copy(Val_as_Val s, Val_as_Ref d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - Q64long[] src = s.arr; - for (int i = 0; i < src.length; i++) { - d.arr[i] = src[i]; - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy2.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy2.java deleted file mode 100644 index 2cd9f3bef49..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy2.java +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineCopy2 extends StatesQ64long { - - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Obj_copy(Obj_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Int_copy(Obj_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Ref_copy(Obj_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Val_copy(Obj_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Obj_copy(Int_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Int_copy(Int_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Ref_copy(Int_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Val_copy(Int_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Obj_copy(Ref_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Int_copy(Ref_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Ref_copy(Ref_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Val_copy(Ref_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_to_Obj_copy(Val_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Obj_copy(Val_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Obj_copy(Val_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Obj_copy(Val_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Int_copy(Val_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Int_copy(Val_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Int_copy(Val_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Ref_copy(Val_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Ref_copy(Val_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Val_copy(Val_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Obj_copy(Int_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Int_copy(Int_as_Int s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Ref_copy(Int_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Val_copy(Int_as_Int s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Obj_copy(Ref_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Int_copy(Ref_as_Int s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Ref_copy(Ref_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Val_copy(Ref_as_Int s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Int_to_Obj_copy(Val_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Obj_copy(Val_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Obj_copy(Val_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Obj_copy(Val_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Int_copy(Val_as_Int s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Int_copy(Val_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Int_copy(Val_as_Int s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Ref_copy(Val_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Ref_copy(Val_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Val_copy(Val_as_Int s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Obj_copy(Ref_as_Ref s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Int_copy(Ref_as_Ref s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Ref_copy(Ref_as_Ref s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Ref_to_Obj_copy(Val_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Obj_copy(Val_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Obj_copy(Val_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Obj_copy(Val_as_Ref s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Int_copy(Val_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Int_copy(Val_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Int_copy(Val_as_Ref s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Ref_copy(Val_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Ref_copy(Val_as_Ref s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Val_copy(Val_as_Ref s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Val_to_Obj_copy(Val_as_Val s, Obj_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Obj_copy(Val_as_Val s, Int_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Obj_copy(Val_as_Val s, Ref_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Obj_copy(Val_as_Val s, Val_as_Obj d) { - int len = s.arr.length; - Object[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Int_copy(Val_as_Val s, Int_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Int_copy(Val_as_Val s, Ref_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Int_copy(Val_as_Val s, Val_as_Int d) { - int len = s.arr.length; - Int64[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Ref_copy(Val_as_Val s, Val_as_Ref d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - int len = s.arr.length; - Q64long[] dst = d.arr; - for (int i = 0; i < len; i++) { - dst[i] = s.arr[i]; - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy3.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy3.java deleted file mode 100644 index dbee68e06eb..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/copy/InlineCopy3.java +++ /dev/null @@ -1,935 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.copy; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class InlineCopy3 extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_to_Obj_copy(Obj_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Obj_copy(Obj_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Obj_copy(Obj_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Obj_copy(Obj_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_to_Int_copy(Obj_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Int_copy(Obj_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Int_copy(Obj_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_to_Ref_copy(Obj_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Ref_copy(Obj_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_to_Val_copy(Obj_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_to_Obj_copy(Int_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Obj_copy(Int_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Obj_copy(Int_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Obj_copy(Int_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_to_Int_copy(Int_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Int_copy(Int_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Int_copy(Int_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_to_Ref_copy(Int_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Ref_copy(Int_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_to_Val_copy(Int_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_to_Obj_copy(Ref_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Obj_copy(Ref_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Obj_copy(Ref_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Obj_copy(Ref_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_to_Int_copy(Ref_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Int_copy(Ref_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Int_copy(Ref_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_to_Ref_copy(Ref_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Ref_copy(Ref_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_to_Val_copy(Ref_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_to_Obj_copy(Val_as_Obj s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Obj_copy(Val_as_Obj s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Obj_copy(Val_as_Obj s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Obj_copy(Val_as_Obj s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_to_Int_copy(Val_as_Obj s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Int_copy(Val_as_Obj s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Int_copy(Val_as_Obj s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Int64)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_to_Ref_copy(Val_as_Obj s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Ref_copy(Val_as_Obj s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_to_Val_copy(Val_as_Obj s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Int_to_Obj_copy(Int_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Obj_copy(Int_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Obj_copy(Int_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Obj_copy(Int_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_to_Int_copy(Int_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Int_copy(Int_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Int_copy(Int_as_Int s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_to_Ref_copy(Int_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Ref_copy(Int_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_to_Val_copy(Int_as_Int s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Int_to_Obj_copy(Ref_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Obj_copy(Ref_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Obj_copy(Ref_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Obj_copy(Ref_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_to_Int_copy(Ref_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Int_copy(Ref_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Int_copy(Ref_as_Int s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_to_Ref_copy(Ref_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Ref_copy(Ref_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_to_Val_copy(Ref_as_Int s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Int_to_Obj_copy(Val_as_Int s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Obj_copy(Val_as_Int s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Obj_copy(Val_as_Int s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Obj_copy(Val_as_Int s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_to_Int_copy(Val_as_Int s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Int_copy(Val_as_Int s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Int_copy(Val_as_Int s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_to_Ref_copy(Val_as_Int s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Ref_copy(Val_as_Int s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_to_Val_copy(Val_as_Int s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = (Q64long)s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Ref_to_Obj_copy(Ref_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Obj_copy(Ref_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Obj_copy(Ref_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Obj_copy(Ref_as_Ref s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Ref_to_Int_copy(Ref_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Int_copy(Ref_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Int_copy(Ref_as_Ref s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_to_Ref_copy(Ref_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Ref_copy(Ref_as_Ref s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_to_Val_copy(Ref_as_Ref s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Ref_to_Obj_copy(Val_as_Ref s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Obj_copy(Val_as_Ref s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Obj_copy(Val_as_Ref s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Obj_copy(Val_as_Ref s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Ref_to_Int_copy(Val_as_Ref s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Int_copy(Val_as_Ref s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Int_copy(Val_as_Ref s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_to_Ref_copy(Val_as_Ref s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Ref_copy(Val_as_Ref s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_to_Val_copy(Val_as_Ref s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Val_to_Obj_copy(Val_as_Val s, Obj_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Obj_copy(Val_as_Val s, Int_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Obj_copy(Val_as_Val s, Ref_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Obj_copy(Val_as_Val s, Val_as_Obj d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Val_to_Int_copy(Val_as_Val s, Int_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Int_copy(Val_as_Val s, Ref_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Int_copy(Val_as_Val s, Val_as_Int d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Val_to_Ref_copy(Val_as_Val s, Ref_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Ref_copy(Val_as_Val s, Val_as_Ref d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_to_Val_copy(Val_as_Val s, Val_as_Val d) { - int len = s.arr.length; - for (int i = 0; i < len; i++) { - d.arr[i] = s.arr[i]; - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillDef.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillDef.java deleted file mode 100644 index 3576686c644..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillDef.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import java.util.Arrays; - -public class Inline64longFillDef extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long() ; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, new Q64long() ); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Def_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, new Q64long() ); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstInt.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstInt.java deleted file mode 100644 index 7348fa48d92..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstInt.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64longFillInstInt extends StatesQ64long { - - - @State(Scope.Thread) - public static class InstanceField { - Q64long f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fillinst0( Val_as_Val st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fillinst1( Val_as_Val st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fillinst0( Val_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fillinst1( Val_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fillinst0( Ref_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fillinst1( Ref_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fillinst0( Val_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fillinst1( Val_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fillinst0( Ref_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fillinst1( Ref_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fillinst0( Int_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fillinst1( Int_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fillinst0( Val_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fillinst1( Val_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fillinst0( Ref_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fillinst1( Ref_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fillinst0( Int_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fillinst1( Int_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fillinst0( Obj_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fillinst1( Obj_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_arrayfill_arrayfillinst(Val_as_Val st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_arrayfillinst(Val_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_arrayfillinst(Val_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_arrayfillinst(Ref_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_arrayfillinst(Int_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_arrayfillinst(Val_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_arrayfillinst(Ref_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_arrayfillinst(Int_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_arrayfillinst(Obj_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstObj.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstObj.java deleted file mode 100644 index 1a1d252567e..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstObj.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64longFillInstObj extends StatesQ64long { - - - @State(Scope.Thread) - public static class InstanceField { - Object f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fillinst0(Val_as_Val st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fillinst1(Val_as_Val st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fillinst0(Val_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fillinst1(Val_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fillinst0(Ref_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fillinst1(Ref_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fillinst0(Val_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fillinst1(Val_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fillinst0(Ref_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fillinst1(Ref_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fillinst0(Int_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fillinst1(Int_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fillinst0(Val_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fillinst1(Val_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fillinst0(Ref_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fillinst1(Ref_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fillinst0(Int_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fillinst1(Int_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fillinst0(Obj_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fillinst1(Obj_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_arrayfillinst(Val_as_Val st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_arrayfillinst(Val_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_arrayfillinst(Val_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_arrayfillinst(Ref_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_arrayfillinst(Int_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_arrayfillinst(Val_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_arrayfillinst(Ref_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_arrayfillinst(Int_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_arrayfillinst(Obj_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstRef.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstRef.java deleted file mode 100644 index d0b8cb8d71f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstRef.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64longFillInstRef extends StatesQ64long { - - - @State(Scope.Thread) - public static class InstanceField { - Q64long f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst0(Val_as_Val st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillinst1(Val_as_Val st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fillinst0(Val_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fillinst1(Val_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst0(Ref_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillinst1(Ref_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fillinst0(Val_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fillinst1(Val_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fillinst0(Ref_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fillinst1(Ref_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fillinst0(Int_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fillinst1(Int_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fillinst0(Val_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fillinst1(Val_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fillinst0(Ref_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fillinst1(Ref_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fillinst0(Int_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fillinst1(Int_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fillinst0(Obj_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fillinst1(Obj_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillinst(Val_as_Val st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_arrayfillinst(Val_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_arrayfillinst(Val_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_arrayfillinst(Ref_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_arrayfillinst(Int_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_arrayfillinst(Val_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_arrayfillinst(Ref_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_arrayfillinst(Int_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_arrayfillinst(Obj_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstVal.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstVal.java deleted file mode 100644 index 0617955687d..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInstVal.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import java.util.Arrays; - -public class Inline64longFillInstVal extends StatesQ64long { - - - @State(Scope.Thread) - public static class InstanceField { - Q64long f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst0(Val_as_Val st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillinst1(Val_as_Val st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fillinst0(Val_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fillinst1(Val_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst0(Ref_as_Ref st, InstanceField f) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillinst1(Ref_as_Ref st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fillinst0(Val_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fillinst1(Val_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fillinst0(Ref_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fillinst1(Ref_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fillinst0(Int_as_Int st, InstanceField f) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fillinst1(Int_as_Int st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fillinst0(Val_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fillinst1(Val_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fillinst0(Ref_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fillinst1(Ref_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fillinst0(Int_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fillinst1(Int_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fillinst0(Obj_as_Obj st, InstanceField f) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fillinst1(Obj_as_Obj st, InstanceField f) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = f.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillinst(Val_as_Val st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_arrayfillinst(Val_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillinst(Ref_as_Ref st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_arrayfillinst(Val_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_arrayfillinst(Ref_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_arrayfillinst(Int_as_Int st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_arrayfillinst(Val_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_arrayfillinst(Ref_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_arrayfillinst(Int_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_arrayfillinst(Obj_as_Obj st, InstanceField f) { - Arrays.fill(st.arr, f.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInt.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInt.java deleted file mode 100644 index e0becf0a8b8..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillInt.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillInt extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Int64 get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - Int64 v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - Int64 v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillNew.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillNew.java deleted file mode 100644 index b8f36771170..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillNew.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillNew extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - Q64long v = new Q64long(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - Q64long v = new Q64long(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, new Q64long(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, new Q64long(42)); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillObj.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillObj.java deleted file mode 100644 index 182dcf752b4..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillObj.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillObj extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Object get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - Object v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - Object v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillRef.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillRef.java deleted file mode 100644 index 0a0e52de3b1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillRef.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillRef extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64long get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatInt.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatInt.java deleted file mode 100644 index 0e4fbe4fb08..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatInt.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillStatInt extends StatesQ64long { - - public static class StaticField { - static Int64 f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fillstat0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_fillstat1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fillstat0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_fillstat1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fillstat0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_fillstat1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fillstat0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_fillstat1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fillstat0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_fillstat1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fillstat0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_fillstat1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fillstat0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_fillstat1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fillstat0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_fillstat1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fillstat0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_fillstat1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fillstat0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_fillstat1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_arrayfillstat(Val_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_arrayfillstat(Val_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_arrayfillstat(Ref_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_arrayfillstat(Int_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_arrayfillstat(Val_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_arrayfillstat(Ref_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_arrayfillstat(Int_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_arrayfillstat(Obj_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatObj.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatObj.java deleted file mode 100644 index 04f2e36b72b..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatObj.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillStatObj extends StatesQ64long { - - public static class StaticField { - static Object f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fillstat0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_fillstat1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fillstat0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_fillstat1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fillstat0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_fillstat1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fillstat0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_fillstat1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fillstat0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_fillstat1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fillstat0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_fillstat1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64) StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fillstat0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_fillstat1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fillstat0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_fillstat1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fillstat0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_fillstat1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fillstat0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_fillstat1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_arrayfillstat(Val_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_arrayfillstat(Val_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_arrayfillstat(Ref_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_arrayfillstat(Int_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_arrayfillstat(Val_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_arrayfillstat(Ref_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_arrayfillstat(Int_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_arrayfillstat(Obj_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatRef.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatRef.java deleted file mode 100644 index 35223ffb54c..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatRef.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillStatRef extends StatesQ64long { - - public static class StaticField { - static Q64long f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_fillstat1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fillstat0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_fillstat1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_fillstat1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fillstat0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_fillstat1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fillstat0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_fillstat1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fillstat0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_fillstat1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fillstat0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_fillstat1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fillstat0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_fillstat1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fillstat0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_fillstat1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fillstat0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_fillstat1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_arrayfillstat(Val_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_arrayfillstat(Val_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_arrayfillstat(Ref_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_arrayfillstat(Int_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_arrayfillstat(Val_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_arrayfillstat(Ref_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_arrayfillstat(Int_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_arrayfillstat(Obj_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatVal.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatVal.java deleted file mode 100644 index 50042b51ba5..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillStatVal.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillStatVal extends StatesQ64long { - - public static class StaticField { - static Q64long f = new Q64long(42); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fillstat1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fillstat0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fillstat1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fillstat1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fillstat0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fillstat1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fillstat0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fillstat1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fillstat0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fillstat1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fillstat0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fillstat1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fillstat0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fillstat1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fillstat0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fillstat1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fillstat0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fillstat1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = StaticField.f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfillstat(Val_as_Val st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_arrayfillstat(Val_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfillstat(Ref_as_Ref st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_arrayfillstat(Val_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_arrayfillstat(Ref_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_arrayfillstat(Int_as_Int st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_arrayfillstat(Val_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_arrayfillstat(Ref_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_arrayfillstat(Int_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_arrayfillstat(Obj_as_Obj st) { - Arrays.fill(st.arr, StaticField.f); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillVal.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillVal.java deleted file mode 100644 index cc3e762a993..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/fill/Inline64longFillVal.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.fill; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -import java.util.Arrays; - -public class Inline64longFillVal extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64long get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fill0(Val_as_Val st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_fill1(Val_as_Val st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fill0(Val_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_fill1(Val_as_Ref st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fill0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_fill1(Ref_as_Ref st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fill0(Val_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_fill1(Val_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fill0(Ref_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_fill1(Ref_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fill0(Int_as_Int st) { - Int64[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_fill1(Int_as_Int st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fill0(Val_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_fill1(Val_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fill0(Ref_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_fill1(Ref_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fill0(Int_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_fill1(Int_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fill0(Obj_as_Obj st) { - Object[] arr = st.arr; - Q64long v = get(42); - for (int i = 0; i < arr.length; i++) { - arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_fill1(Obj_as_Obj st) { - int len = st.arr.length; - Q64long v = get(42); - for (int i = 0; i < len; i++) { - st.arr[i] = v; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_arrayfill(Val_as_Val st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_arrayfill(Val_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_arrayfill(Ref_as_Ref st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_arrayfill(Val_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_arrayfill(Ref_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_arrayfill(Int_as_Int st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_arrayfill(Val_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_arrayfill(Ref_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_arrayfill(Int_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_arrayfill(Obj_as_Obj st) { - Arrays.fill(st.arr, get(42)); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/read/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/read/Inline64long.java deleted file mode 100644 index ec9efc4b4ff..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/read/Inline64long.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.read; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64long extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void val_consume(Q64long v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void ref_consume(Q64long v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void int_consume(Int64 v) { - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void obj_consume(Object v) { - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Val_read(Val_as_Val st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Ref_read(Val_as_Val st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Int_read(Val_as_Val st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Val_to_Obj_read(Val_as_Val st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Val_read(Val_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Ref_read(Val_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Int_read(Val_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Ref_to_Obj_read(Val_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Int_read(Val_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Int_to_Obj_read(Val_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_as_Obj_to_Obj_read(Val_as_Obj st) { - Object[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Ref_to_Val_read(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - val_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Ref_to_Ref_read(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - ref_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Ref_to_Int_read(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Ref_to_Obj_read(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Int_to_Int_read(Ref_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - int_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Int_to_Obj_read(Ref_as_Int st) { - Int64[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_as_Obj_to_Obj_read(Ref_as_Obj st) { - Object[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - obj_consume(arr[i]); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetInt.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetInt.java deleted file mode 100644 index 05428666ed1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetInt.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.set; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64longSetInt extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Int64 get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_set0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Val_set1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_set0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Ref_set1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_set0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Ref_set1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_set0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Int_set1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_set0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Int_set1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_set0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Int_set1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_set0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_as_Obj_set1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_set0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_as_Obj_set1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_set0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_as_Obj_set1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_set0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_as_Obj_set1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetNew.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetNew.java deleted file mode 100644 index 6645ec16d56..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetNew.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.set; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64longSetNew extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Val_set1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Ref_set0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Ref_set1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Ref_set1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Int_set0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Int_set1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Int_set0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Int_set1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Int_set0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Int_set1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Obj_set0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Val_as_Obj_set1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Obj_set0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Ref_as_Obj_set1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Obj_set0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Int_as_Obj_set1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Obj_as_Obj_set0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void New_to_Obj_as_Obj_set1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = new Q64long(i); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetObj.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetObj.java deleted file mode 100644 index d246774c1f3..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetObj.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.set; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64longSetObj extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Object get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_set0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Val_set1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_set0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Ref_set1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_set0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Ref_set1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Q64long)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_set0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Int_set1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_set0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Int_set1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_set0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Int_set1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = (Int64)get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_set0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_as_Obj_set1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_set0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_as_Obj_set1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_set0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_as_Obj_set1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_set0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_as_Obj_set1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetRef.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetRef.java deleted file mode 100644 index ab9bf4aee19..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetRef.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.set; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64longSetRef extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64long get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Val_set1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_set0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Ref_set1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Ref_set1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_set0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Int_set1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_set0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Int_set1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_set0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Int_set1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_set0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_as_Obj_set1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_set0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_as_Obj_set1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_set0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_as_Obj_set1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_set0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_as_Obj_set1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetVal.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetVal.java deleted file mode 100644 index d151c9495ce..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/set/Inline64longSetVal.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.set; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64longSetVal extends StatesQ64long { - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static Q64long get(int i) { - return new Q64long(i); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set0(Val_as_Val st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Val_set1(Val_as_Val st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_set0(Val_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Ref_set1(Val_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set0(Ref_as_Ref st) { - Q64long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Ref_set1(Ref_as_Ref st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_set0(Val_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Int_set1(Val_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_set0(Ref_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Int_set1(Ref_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_set0(Int_as_Int st) { - Int64[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Int_set1(Int_as_Int st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_set0(Val_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_as_Obj_set1(Val_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_set0(Ref_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_as_Obj_set1(Ref_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_set0(Int_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_as_Obj_set1(Int_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_set0(Obj_as_Obj st) { - Object[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = get(i); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_as_Obj_set1(Obj_as_Obj st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = get(i); - } - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Identity64long.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Identity64long.java deleted file mode 100644 index b35eb2bb24f..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Identity64long.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.sum; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesR64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.ByLong; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Identity64long extends StatesR64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Ref_fields(Ref_as_Ref st) { - long s = 0; - R64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Abs_sum(Ref_as_Abs st) { - long s = 0; - A64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Int_sum(Ref_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Abs_as_Abs_sum(Abs_as_Abs st) { - long s = 0; - A64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Abs_as_Int_sum(Abs_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Int_as_Int_sum(By_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Inline64long.java deleted file mode 100644 index 06ab8935d50..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/sum/Inline64long.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.sum; - -import org.openjdk.bench.valhalla.arraytotal.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.ByLong; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64long extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Val_fields0(Val_as_Val st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Val_fields1(Val_as_Val st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Ref_fields0(Val_as_Ref st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Ref_fields1(Val_as_Ref st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Ref_fields0(Ref_as_Ref st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Ref_fields1(Ref_as_Ref st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].v0; - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Val_sum0(Val_as_Val st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Val_sum1(Val_as_Val st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Ref_sum0(Val_as_Ref st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Ref_sum1(Val_as_Ref st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Int_sum0(Val_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Val_as_Int_sum1(Val_as_By st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Ref_sum0(Ref_as_Ref st) { - long s = 0; - Q64long[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Ref_sum1(Ref_as_Ref st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Int_sum0(Ref_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Ref_as_Int_sum1(Ref_as_By st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Int_as_Int_sum0(By_as_By st) { - long s = 0; - ByLong[] arr = st.arr; - for(int i=0; i < arr.length; i++) { - s += arr[i].longSum(); - } - return s; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Int_as_Int_sum1(By_as_By st) { - long s = 0; - int len = st.arr.length; - for(int i=0; i < len; i++) { - s += st.arr[i].longSum(); - } - return s; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesQ64long.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesQ64long.java deleted file mode 100644 index b2ab9b6b855..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesQ64long.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.util; - -import org.openjdk.bench.valhalla.types.ByLong; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64long extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - } - - public static abstract class RefState extends SizeState { - public Q64long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - } - - public static abstract class ValState extends SizeState { - public Q64long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByLong[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new Q64long(i); - } - } - } - - public static class Val_as_By extends ByState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Ref_as_By extends ByState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class By_as_By extends ByState { - @Setup - public void setup() { - arr = new ByLong[size]; - fill(); - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesR64long.java b/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesR64long.java deleted file mode 100644 index 34756a077e3..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/arraytotal/util/StatesR64long.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.arraytotal.util; - -import org.openjdk.bench.valhalla.types.ByLong; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesR64long extends SizeBase { - - public static abstract class ObjState extends SizeState { - public Object[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64long(i); - } - } - } - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64long(i); - } - } - } - - public static abstract class AbsState extends SizeState { - public A64long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64long(i); - } - } - } - - public static abstract class RefState extends SizeState { - public R64long[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64long(i); - } - } - } - - // naming convention: _as_ - - public static class Obj_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[size]; - fill(); - } - } - - public static class Int_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Abs_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class Ref_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Abs_as_Int extends IntState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Abs_as_Abs extends AbsState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class Ref_as_Abs extends AbsState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static abstract class ByState extends SizeState { - public ByLong[] arr; - void fill() { - for (int i = 0; i < arr.length; i++) { - arr[i] = new R64long(i); - } - } - } - - public static class Ref_as_By extends ByState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Abs_as_By extends ByState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class By_as_By extends ByState { - @Setup - public void setup() { - arr = new ByLong[size]; - fill(); - } - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64byte.java b/test/micro/org/openjdk/bench/valhalla/callconv/Inline64byte.java deleted file mode 100644 index 0da81dff9d1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64byte.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class Inline64byte { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract Q64byte compute(Q64byte v1); - public abstract Q64byte compute(Q64byte v1, Q64byte v2); - public abstract Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4); - public abstract Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public Q64byte compute(Q64byte v1) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public Q64byte compute(Q64byte v1) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) { - return v1; - } - - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public Q64byte compute(Q64byte v1) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) { - return v1; - } - - @Override - public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) { - return v1; - } - - } - - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - Q64byte a0 = new Q64byte(42); - Q64byte a1 = new Q64byte(43); - Q64byte a2 = new Q64byte(44); - Q64byte a3 = new Q64byte(45); - Q64byte a4 = new Q64byte(46); - Q64byte a5 = new Q64byte(47); - Q64byte a6 = new Q64byte(48); - Q64byte a7 = new Q64byte(49); - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args1(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args2(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args4(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args8(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64byte_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64int.java b/test/micro/org/openjdk/bench/valhalla/callconv/Inline64int.java deleted file mode 100644 index 24b58a39992..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64int.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class Inline64int { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract Q64int compute(Q64int v1); - public abstract Q64int compute(Q64int v1, Q64int v2); - public abstract Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4); - public abstract Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4, Q64int v5, Q64int v6, Q64int v7, Q64int v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public Q64int compute(Q64int v1) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4, Q64int v5, Q64int v6, Q64int v7, Q64int v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public Q64int compute(Q64int v1) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4, Q64int v5, Q64int v6, Q64int v7, Q64int v8) { - return v1; - } - - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public Q64int compute(Q64int v1) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4) { - return v1; - } - - @Override - public Q64int compute(Q64int v1, Q64int v2, Q64int v3, Q64int v4, Q64int v5, Q64int v6, Q64int v7, Q64int v8) { - return v1; - } - - } - - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - Q64int a0 = new Q64int(42); - Q64int a1 = new Q64int(43); - Q64int a2 = new Q64int(44); - Q64int a3 = new Q64int(45); - Q64int a4 = new Q64int(46); - Q64int a5 = new Q64int(47); - Q64int a6 = new Q64int(48); - Q64int a7 = new Q64int(49); - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args1(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args2(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args4(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args8(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64int_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/callconv/Inline64long.java deleted file mode 100644 index 55d0e3fe80b..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/Inline64long.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class Inline64long { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract Q64long compute(Q64long v1); - public abstract Q64long compute(Q64long v1, Q64long v2); - public abstract Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4); - public abstract Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public Q64long compute(Q64long v1) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public Q64long compute(Q64long v1) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { - return v1; - } - - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public Q64long compute(Q64long v1) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { - return v1; - } - - @Override - public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { - return v1; - } - - } - - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - Q64long a0 = new Q64long(42); - Q64long a1 = new Q64long(43); - Q64long a2 = new Q64long(44); - Q64long a3 = new Q64long(45); - Q64long a4 = new Q64long(46); - Q64long a5 = new Q64long(47); - Q64long a6 = new Q64long(48); - Q64long a7 = new Q64long(49); - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args1(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args2(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args4(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args8(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long Q64long_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpResult.java b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive1.java similarity index 53% rename from test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpResult.java rename to test/micro/org/openjdk/bench/valhalla/callconv/Primitive1.java index 5a4758fcb06..8fbda154758 100644 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsCmpResult.java +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.acmp.array; +package org.openjdk.bench.valhalla.callconv; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -31,66 +31,78 @@ import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import java.util.Arrays; import java.util.concurrent.TimeUnit; -/* - * For proper results it should be executed: - * java -jar target/benchmarks.jar IdentityIsCmpResult -wmb IdentityIsCmpResult.Obj_equals050 - */ - @Fork(3) -@Warmup(iterations = 3, time = 1) +@Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityIsCmpResult extends StatesR64long { +public class Primitive1 { - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static boolean cmp_Obj(Object[] objects1, Object[] objects2) { - boolean s = false; - for (int i = 0; i < SIZE; i++) { - s ^= objects1[i] == objects2[i]; - } - return s; + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public abstract static class InvocationLogic { + public abstract int compute(int v1); } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl1 extends InvocationLogic { + @Override + public int compute(int v1) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl2 extends InvocationLogic { + @Override + public int compute(int v1) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl3 extends InvocationLogic { + @Override + public int compute(int v1) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } } + int a0 = 42; + @Benchmark @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void primitive_args1(Blackhole bh, StateTargets st) { + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(a0)); + } } } diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpBranch.java b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive2.java similarity index 52% rename from test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpBranch.java rename to test/micro/org/openjdk/bench/valhalla/callconv/Primitive2.java index 8c7713261c3..ae7065b1391 100644 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpBranch.java +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.acmp.array; +package org.openjdk.bench.valhalla.callconv; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -31,70 +31,79 @@ import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import java.util.Arrays; import java.util.concurrent.TimeUnit; -/* - * For proper results it should be executed: - * java -jar target/benchmarks.jar IdentityIsNotCmpBranch -wmb IdentityIsNotCmpBranch.Obj_equals050 - */ - @Fork(3) -@Warmup(iterations = 3, time = 1) +@Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityIsNotCmpBranch extends StatesR64long { +public class Primitive2 { - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static int cmp_Obj(Object[] objects1, Object[] objects2) { - int s = 0; - for (int i = 0; i < SIZE; i++) { - if (objects1[i] != objects2[i]) { - s += 1; - } else { - s -= 1; - } - } - return s; + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public abstract static class InvocationLogic { + public abstract int compute(int v1, int v2); } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl1 extends InvocationLogic { + @Override + public int compute(int v1, int v2) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl2 extends InvocationLogic { + @Override + public int compute(int v1, int v2) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl3 extends InvocationLogic { + @Override + public int compute(int v1, int v2) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } } + int a0 = 42; + int a1 = 43; + @Benchmark @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public int Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void primitive_args2(Blackhole bh, StateTargets st) { + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(a0, a1)); + } } } diff --git a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpResult.java b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive4.java similarity index 50% rename from test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpResult.java rename to test/micro/org/openjdk/bench/valhalla/callconv/Primitive4.java index 61be99a7387..d31471b5e8c 100644 --- a/test/micro/org/openjdk/bench/valhalla/acmp/array/IdentityIsNotCmpResult.java +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.acmp.array; +package org.openjdk.bench.valhalla.callconv; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -31,61 +31,81 @@ import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import java.util.Arrays; import java.util.concurrent.TimeUnit; @Fork(3) -@Warmup(iterations = 3, time = 1) +@Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityIsNotCmpResult extends StatesR64long { +public class Primitive4 { - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - private static boolean cmp_Obj(Object[] objects1, Object[] objects2) { - boolean s = false; - for (int i = 0; i < SIZE; i++) { - s ^= objects1[i] != objects2[i]; - } - return s; + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public abstract static class InvocationLogic { + public abstract int compute(int v1, int v2, int v3, int v4); } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals000(ObjState00 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl1 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals025(ObjState25 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl2 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals050(ObjState50 st) { - return cmp_Obj(st.arr1, st.arr2); + public static class InvokeImpl3 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4) { + return v1; + } } - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals075(ObjState75 st) { - return cmp_Obj(st.arr1, st.arr2); + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } } + int a0 = 42; + int a1 = 43; + int a2 = 44; + int a3 = 45; + @Benchmark @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.INLINE) - public boolean Obj_equals100(ObjState100 st) { - return cmp_Obj(st.arr1, st.arr2); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void primitive_args4(Blackhole bh, StateTargets st) { + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(a0, a1, a2, a3)); + } } } diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Primitive8.java b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive8.java new file mode 100644 index 00000000000..0eddbc37f2f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Primitive8.java @@ -0,0 +1,115 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.callconv; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Primitive8 { + + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public abstract static class InvocationLogic { + public abstract int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8); + } + + public static class InvokeImpl1 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { + return v1; + } + } + + public static class InvokeImpl2 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { + return v1; + } + } + + public static class InvokeImpl3 extends InvocationLogic { + @Override + public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { + return v1; + } + } + + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } + } + + int a0 = 42; + int a1 = 43; + int a2 = 44; + int a3 = 45; + int a4 = 46; + int a5 = 47; + int a6 = 48; + int a7 = 49; + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void primitive_args8(Blackhole bh, StateTargets st) { + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(a0, a1, a2, a3, a4, a5, a6, a7)); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveByte.java b/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveByte.java deleted file mode 100644 index 872feb73074..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveByte.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class PrimitiveByte { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract byte compute(byte v1); - public abstract byte compute(byte v1, byte v2); - public abstract byte compute(byte v1, byte v2, byte v3, byte v4); - public abstract byte compute(byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7, byte v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public byte compute(byte v1) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7, byte v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public byte compute(byte v1) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7, byte v8) { - return v1; - } - - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public byte compute(byte v1) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4) { - return v1; - } - - @Override - public byte compute(byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7, byte v8) { - return v1; - } - - } - - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - byte a0 = 42; - byte a1 = 43; - byte a2 = 44; - byte a3 = 45; - byte a4 = 46; - byte a5 = 47; - byte a6 = 48; - byte a7 = 49; - - @CompilerControl(CompilerControl.Mode.INLINE) - public byte args1(InvocationLogic[] logic) { - byte r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public byte args2(InvocationLogic[] logic) { - byte r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public byte args4(InvocationLogic[] logic) { - byte r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public byte args8(InvocationLogic[] logic) { - byte r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - byte r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - byte r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - byte r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - byte r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public byte byte_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveInt.java b/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveInt.java deleted file mode 100644 index 1626cb8b9d9..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveInt.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class PrimitiveInt { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract int compute(int v1); - public abstract int compute(int v1, int v2); - public abstract int compute(int v1, int v2, int v3, int v4); - public abstract int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public int compute(int v1) { - return v1; - } - - @Override - public int compute(int v1, int v2) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public int compute(int v1) { - return v1; - } - - @Override - public int compute(int v1, int v2) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { - return v1; - } - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public int compute(int v1) { - return v1; - } - - @Override - public int compute(int v1, int v2) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4) { - return v1; - } - - @Override - public int compute(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) { - return v1; - } - } - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - int a0 = 42; - int a1 = 43; - int a2 = 44; - int a3 = 45; - int a4 = 46; - int a5 = 47; - int a6 = 48; - int a7 = 49; - - @CompilerControl(CompilerControl.Mode.INLINE) - public int args1(InvocationLogic[] logic) { - int r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public int args2(InvocationLogic[] logic) { - int r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public int args4(InvocationLogic[] logic) { - int r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public int args8(InvocationLogic[] logic) { - int r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - int r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - int r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - int r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - int r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int int_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveLong.java b/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveLong.java deleted file mode 100644 index 0cc5476522a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/callconv/PrimitiveLong.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.callconv; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class PrimitiveLong { - - public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 - - public abstract static class InvocationLogic { - public abstract long compute(long v1); - public abstract long compute(long v1, long v2); - public abstract long compute(long v1, long v2, long v3, long v4); - public abstract long compute(long v1, long v2, long v3, long v4, long v5, long v6, long v7, long v8); - } - - public static class InvokeImpl1 extends InvocationLogic { - - @Override - public long compute(long v1) { - return v1; - } - - @Override - public long compute(long v1, long v2) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4, long v5, long v6, long v7, long v8) { - return v1; - } - - } - - public static class InvokeImpl2 extends InvocationLogic { - - @Override - public long compute(long v1) { - return v1; - } - - @Override - public long compute(long v1, long v2) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4, long v5, long v6, long v7, long v8) { - return v1; - } - - } - - public static class InvokeImpl3 extends InvocationLogic { - - @Override - public long compute(long v1) { - return v1; - } - - @Override - public long compute(long v1, long v2) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4) { - return v1; - } - - @Override - public long compute(long v1, long v2, long v3, long v4, long v5, long v6, long v7, long v8) { - return v1; - } - - } - - - private static InvocationLogic getImpl(int i, int targets) { - switch (i % targets) { - case 0: - return new InvokeImpl1(); - case 1: - return new InvokeImpl2(); - case 2: - return new InvokeImpl3(); - } - return null; - } - - @State(Scope.Thread) - public static class StateTargets0 { - InvokeImpl1[] arr; - @Setup - public void setup() { - arr = new InvokeImpl1[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = new InvokeImpl1(); - } - } - } - - @State(Scope.Thread) - public static abstract class StateTargets { - InvocationLogic[] arr; - - public void init(int targets) { - arr = new InvocationLogic[SIZE]; - for(int i=0; i < arr.length; i++) { - arr[i] = getImpl(i, targets); - } - } - } - - public static class StateTargets1 extends StateTargets { - @Setup - public void setup() { - init(1); - } - } - - public static class StateTargets2 extends StateTargets { - @Setup - public void setup() { - init(2); - } - } - - public static class StateTargets3 extends StateTargets { - @Setup - public void setup() { - init(3); - } - } - - long a0 = 42; - long a1 = 43; - long a2 = 44; - long a3 = 45; - long a4 = 46; - long a5 = 47; - long a6 = 48; - long a7 = 49; - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args1(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args2(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args4(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.INLINE) - public long args8(InvocationLogic[] logic) { - long r = 0; - for(InvocationLogic t : logic) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args1_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args2_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args4_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args8_targets0(StateTargets0 st) { - InvokeImpl1[] arr = st.arr; - long r = 0; - for(InvocationLogic t : arr) { - r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args1_targets1(StateTargets1 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args2_targets1(StateTargets1 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args4_targets1(StateTargets1 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args8_targets1(StateTargets1 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args1_targets2(StateTargets2 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args2_targets2(StateTargets2 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args4_targets2(StateTargets2 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args8_targets2(StateTargets2 st) { - return args8(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args1_targets3(StateTargets3 st) { - return args1(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args2_targets3(StateTargets3 st) { - return args2(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args4_targets3(StateTargets3 st) { - return args4(st.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public long long_args8_targets3(StateTargets3 st) { - return args8(st.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Value1.java b/test/micro/org/openjdk/bench/valhalla/callconv/Value1.java new file mode 100644 index 00000000000..b4875646cc8 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Value1.java @@ -0,0 +1,126 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.callconv; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value1 { + + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public static value class ValueInt1 { + + public final int v0; + + public ValueInt1(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + public static ValueInt1 valueOf(int value) { + return new ValueInt1(value); + } + } + + public abstract static class InvocationLogic { + public abstract ValueInt1 compute(ValueInt1 v1); + } + + public static class InvokeImpl1 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1) { + return v1; + } + } + + public static class InvokeImpl2 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1) { + return v1; + } + } + + public static class InvokeImpl3 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1) { + return v1; + } + } + + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } + } + + ValueInt1 a0 = ValueInt1.valueOf(42); + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args1(Blackhole bh, StateTargets st) { + ValueInt1 v0 = a0; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0)); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Value2.java b/test/micro/org/openjdk/bench/valhalla/callconv/Value2.java new file mode 100644 index 00000000000..c80bce3e00e --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Value2.java @@ -0,0 +1,171 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.callconv; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value2 { + + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public static value class ValueInt1 { + + public final int v0; + + public ValueInt1(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + public static ValueInt1 valueOf(int value) { + return new ValueInt1(value); + } + } + + public static value class ValueInt2 { + + public final int v0, v1; + + public ValueInt2(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int value0() { + return v0; + } + + public static ValueInt2 valueOf(int v0, int v1) { + return new ValueInt2(v0, v1); + } + } + + public abstract static class InvocationLogic { + public abstract ValueInt1 compute(ValueInt1 v1, ValueInt1 v2); + public abstract ValueInt2 compute(ValueInt2 v1); + } + + public static class InvokeImpl1 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1) { + return v1; + } + } + + public static class InvokeImpl2 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1) { + return v1; + } + } + + public static class InvokeImpl3 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1) { + return v1; + } + } + + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } + } + + ValueInt1 a0 = ValueInt1.valueOf(42); + ValueInt1 a1 = ValueInt1.valueOf(43); + ValueInt2 b0 = ValueInt2.valueOf(42, 43); + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args2(Blackhole bh, StateTargets st) { + ValueInt1 v0 = a0; + ValueInt1 v1 = a1; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args1(Blackhole bh, StateTargets st) { + ValueInt2 v0 = b0; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0)); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Value4.java b/test/micro/org/openjdk/bench/valhalla/callconv/Value4.java new file mode 100644 index 00000000000..2958459f889 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Value4.java @@ -0,0 +1,224 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.callconv; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value4 { + + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public static value class ValueInt1 { + + public final int v0; + + public ValueInt1(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + public static ValueInt1 valueOf(int value) { + return new ValueInt1(value); + } + } + + public static value class ValueInt2 { + + public final int v0, v1; + + public ValueInt2(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int value0() { + return v0; + } + + public static ValueInt2 valueOf(int v0, int v1) { + return new ValueInt2(v0, v1); + } + } + + public static value class ValueInt4 { + + public final int v0, v1, v2, v3; + + public ValueInt4(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int value0() { + return v0; + } + + public static ValueInt4 valueOf(int v0, int v1, int v2, int v3) { + return new ValueInt4(v0, v1, v2, v3); + } + } + + public abstract static class InvocationLogic { + public abstract ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4); + public abstract ValueInt2 compute(ValueInt2 v1, ValueInt2 v2); + public abstract ValueInt4 compute(ValueInt4 v1); + } + + public static class InvokeImpl1 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1) { + return v1; + } + } + + public static class InvokeImpl2 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1) { + return v1; + } + } + + public static class InvokeImpl3 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1) { + return v1; + } + } + + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } + } + + ValueInt1 a0 = ValueInt1.valueOf(42); + ValueInt1 a1 = ValueInt1.valueOf(43); + ValueInt1 a2 = ValueInt1.valueOf(44); + ValueInt1 a3 = ValueInt1.valueOf(45); + + ValueInt2 b0 = ValueInt2.valueOf(42, 43); + ValueInt2 b1 = ValueInt2.valueOf(44, 45); + + ValueInt4 c0 = ValueInt4.valueOf(42, 43, 44, 45); + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args4(Blackhole bh, StateTargets st) { + ValueInt1 v0 = a0; + ValueInt1 v1 = a1; + ValueInt1 v2 = a2; + ValueInt1 v3 = a3; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1, v2, v3)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args2(Blackhole bh, StateTargets st) { + ValueInt2 v0 = b0; + ValueInt2 v1 = b1; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args1(Blackhole bh, StateTargets st) { + ValueInt4 v0 = c0; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0)); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/callconv/Value8.java b/test/micro/org/openjdk/bench/valhalla/callconv/Value8.java new file mode 100644 index 00000000000..ce1735c41d3 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/callconv/Value8.java @@ -0,0 +1,288 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.callconv; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value8 { + + public static final int SIZE = 96; // must be divisible by 2 and 3 and around 100 + + public static value class ValueInt1 { + + public final int v0; + + public ValueInt1(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } + + public static ValueInt1 valueOf(int value) { + return new ValueInt1(value); + } + } + + public static value class ValueInt2 { + + public final int v0, v1; + + public ValueInt2(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int value0() { + return v0; + } + + public static ValueInt2 valueOf(int v0, int v1) { + return new ValueInt2(v0, v1); + } + } + + public static value class ValueInt4 { + + public final int v0, v1, v2, v3; + + public ValueInt4(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int value0() { + return v0; + } + + public static ValueInt4 valueOf(int v0, int v1, int v2, int v3) { + return new ValueInt4(v0, v1, v2, v3); + } + } + + public static value class ValueInt8 { + + public final int v0, v1, v2, v3, v4, v5, v6, v7; + + public ValueInt8(int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + this.v7 = v7; + } + + public int value0() { + return v0; + } + + public static ValueInt8 valueOf(int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7) { + return new ValueInt8(v0, v1, v2, v3, v4, v5, v6, v7); + } + } + + public abstract static class InvocationLogic { + public abstract ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4, ValueInt1 v5, ValueInt1 v6, ValueInt1 v7, ValueInt1 v8); + public abstract ValueInt2 compute(ValueInt2 v1, ValueInt2 v2, ValueInt2 v3, ValueInt2 v4); + public abstract ValueInt4 compute(ValueInt4 v1, ValueInt4 v2); + public abstract ValueInt8 compute(ValueInt8 v1); + } + + public static class InvokeImpl1 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4, ValueInt1 v5, ValueInt1 v6, ValueInt1 v7, ValueInt1 v8) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2, ValueInt2 v3, ValueInt2 v4) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1, ValueInt4 v2) { + return v1; + } + @Override + public ValueInt8 compute(ValueInt8 v1) { + return v1; + } + } + + public static class InvokeImpl2 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4, ValueInt1 v5, ValueInt1 v6, ValueInt1 v7, ValueInt1 v8) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2, ValueInt2 v3, ValueInt2 v4) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1, ValueInt4 v2) { + return v1; + } + @Override + public ValueInt8 compute(ValueInt8 v1) { + return v1; + } + } + + public static class InvokeImpl3 extends InvocationLogic { + @Override + public ValueInt1 compute(ValueInt1 v1, ValueInt1 v2, ValueInt1 v3, ValueInt1 v4, ValueInt1 v5, ValueInt1 v6, ValueInt1 v7, ValueInt1 v8) { + return v1; + } + @Override + public ValueInt2 compute(ValueInt2 v1, ValueInt2 v2, ValueInt2 v3, ValueInt2 v4) { + return v1; + } + @Override + public ValueInt4 compute(ValueInt4 v1, ValueInt4 v2) { + return v1; + } + @Override + public ValueInt8 compute(ValueInt8 v1) { + return v1; + } + } + + @State(Scope.Thread) + public static class StateTargets { + InvocationLogic[] arr; + + @Setup + public void setup() { + arr = new InvocationLogic[SIZE]; + Arrays.setAll(arr, i -> getImpl(i, 3)); + } + + private InvocationLogic getImpl(int i, int targets) { + return switch (i % targets) { + case 0 -> new InvokeImpl1(); + case 1 -> new InvokeImpl2(); + default -> new InvokeImpl3(); + }; + } + } + + ValueInt1 a0 = ValueInt1.valueOf(42); + ValueInt1 a1 = ValueInt1.valueOf(43); + ValueInt1 a2 = ValueInt1.valueOf(44); + ValueInt1 a3 = ValueInt1.valueOf(45); + ValueInt1 a4 = ValueInt1.valueOf(46); + ValueInt1 a5 = ValueInt1.valueOf(47); + ValueInt1 a6 = ValueInt1.valueOf(48); + ValueInt1 a7 = ValueInt1.valueOf(49); + + ValueInt2 b0 = ValueInt2.valueOf(42, 43); + ValueInt2 b1 = ValueInt2.valueOf(44, 45); + ValueInt2 b2 = ValueInt2.valueOf(46, 47); + ValueInt2 b3 = ValueInt2.valueOf(48, 49); + + ValueInt4 c0 = ValueInt4.valueOf(42, 43, 44, 45); + ValueInt4 c1 = ValueInt4.valueOf(46, 47, 48, 49); + + ValueInt8 d0 = ValueInt8.valueOf(42, 43, 44, 45, 46, 47, 48, 49); + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args8(Blackhole bh, StateTargets st) { + ValueInt1 v0 = a0; + ValueInt1 v1 = a1; + ValueInt1 v2 = a2; + ValueInt1 v3 = a3; + ValueInt1 v4 = a4; + ValueInt1 v5 = a5; + ValueInt1 v6 = a6; + ValueInt1 v7 = a7; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1, v2, v3, v4, v5, v6, v7)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args4(Blackhole bh, StateTargets st) { + ValueInt2 v0 = b0; + ValueInt2 v1 = b1; + ValueInt2 v2 = b2; + ValueInt2 v3 = b3; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1, v2, v3)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args2(Blackhole bh, StateTargets st) { + ValueInt4 v0 = c0; + ValueInt4 v1 = c1; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0, v1)); + } + } + + @Benchmark + @OperationsPerInvocation(SIZE) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void value_args1(Blackhole bh, StateTargets st) { + ValueInt8 v0 = d0; + InvocationLogic[] arr = st.arr; + for (InvocationLogic t : arr) { + bh.consume(t.compute(v0)); + } + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/CopyBase.java b/test/micro/org/openjdk/bench/valhalla/field/copy/CopyBase.java new file mode 100644 index 00000000000..68d7028eef7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/field/copy/CopyBase.java @@ -0,0 +1,55 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.field.copy; + + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +public class CopyBase { + + @State(Scope.Thread) + public static abstract class SizeState { + + @Param({ + "100", // tiny size, to fit into all caches and check codegeneration quality + "1000000" // large size, to be out of all caches and memory effects + }) + public int size; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Identity.java b/test/micro/org/openjdk/bench/valhalla/field/copy/Identity.java new file mode 100644 index 00000000000..eb2cc8fc8bb --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/field/copy/Identity.java @@ -0,0 +1,123 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.field.copy; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; + +public class Identity extends CopyBase { + + public static class RefWrapper { + public IdentityInt f; + + public RefWrapper(IdentityInt f) { + this.f = f; + } + } + + public static class IntWrapper { + public InterfaceInt f; + + public IntWrapper(IdentityInt f) { + this.f = f; + } + } + + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt implements InterfaceInt { + public final int value; + public IdentityInt(int value) { + this.value = value; + } + public int value() { + return value; + } + } + + + public static class RefState extends SizeState { + public RefWrapper[] arr; + + @Setup + public void setup() { + arr = new RefWrapper[size]; + for (int i = 0; i < size; i++) { + arr[i] = new RefWrapper(new IdentityInt(i)); + } + } + } + + public static class IntState extends SizeState { + public IntWrapper[] arr; + + @Setup + public void setup() { + arr = new IntWrapper[size]; + for (int i = 0; i < size; i++) { + arr[i] = new IntWrapper(new IdentityInt(i)); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy(RefWrapper[] dst, RefWrapper[] src) { + for (int i = 0; i < src.length; i++) { + dst[i].f = src[i].f; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_to_int(IntWrapper[] dst, RefWrapper[] src) { + for (int i = 0; i < src.length; i++) { + dst[i].f = src[i].f; + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void copy_to_ref(RefWrapper[] dst, IntWrapper[] src) { + for (int i = 0; i < src.length; i++) { + dst[i].f = (IdentityInt) src[i].f; + } + } + + @Benchmark + public void copy_ref(RefState st1, RefState st2) { + copy(st1.arr, st2.arr); + } + + @Benchmark + public void copy_ref_to_int(IntState st1, RefState st2) { + copy_to_int(st1.arr, st2.arr); + } + + @Benchmark + public void copy_int_to_ref(RefState st1, IntState st2) { + copy_to_ref(st1.arr, st2.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline128int.java b/test/micro/org/openjdk/bench/valhalla/field/copy/Inline128int.java deleted file mode 100644 index 3d19efe610a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline128int.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.field.copy; - -import org.openjdk.bench.valhalla.field.util.StatesQ128int; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline128int extends StatesQ128int { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(RefState s, ValState d) { - RefWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(ValState s, RefState d) { - ValWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(ValState s, ValState d) { - ValWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64long.java deleted file mode 100644 index a4a9f702364..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Inline64long.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.copy; - -import org.openjdk.bench.valhalla.field.util.StatesQ64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Inline64long extends StatesQ64long { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Obj_copy(ObjState s, ObjState d) { - ObjWrapper[] src = s.arr; - ObjWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Int_copy(ObjState s, IntState d) { - ObjWrapper[] src = s.arr; - IntWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = (Int64) src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Ref_copy(ObjState s, RefState d) { - ObjWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = (Q64long)src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Obj_to_Val_copy(ObjState s, ValState d) { - ObjWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = (Q64long) src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Obj_copy(IntState s, ObjState d) { - IntWrapper[] src = s.arr; - ObjWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Int_copy(IntState s, IntState d) { - IntWrapper[] src = s.arr; - IntWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Ref_copy(IntState s, RefState d) { - IntWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = (Q64long)src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Int_to_Val_copy(IntState s, ValState d) { - IntWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = (Q64long) src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Obj_copy(RefState s, ObjState d) { - RefWrapper[] src = s.arr; - ObjWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Int_copy(RefState s, IntState d) { - RefWrapper[] src = s.arr; - IntWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Ref_copy(RefState s, RefState d) { - RefWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Ref_to_Val_copy(RefState s, ValState d) { - RefWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Obj_copy(ValState s, ObjState d) { - ValWrapper[] src = s.arr; - ObjWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Int_copy(ValState s, IntState d) { - ValWrapper[] src = s.arr; - IntWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Ref_copy(ValState s, RefState d) { - ValWrapper[] src = s.arr; - RefWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void Val_to_Val_copy(ValState s, ValState d) { - ValWrapper[] src = s.arr; - ValWrapper[] dst = d.arr; - for (int i = 0; i < src.length; i++) { - dst[i].f = src[i].f; - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/copy/Primitive128.java b/test/micro/org/openjdk/bench/valhalla/field/copy/Primitive128.java deleted file mode 100644 index e8767277348..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/copy/Primitive128.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.field.copy; - -import org.openjdk.bench.valhalla.field.util.PrimitiveStates; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; - -public class Primitive128 extends PrimitiveStates { - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void p128int_copy(Primitive128int s, Primitive128int d) { - P128int[] src = s.arr; - P128int[] dst = d.arr; - for(int i=0; i>> 56), (byte) (v >>> 48), (byte) (v >>> 40), (byte) (v >>> 32), (byte) (v >>> 24), (byte) (v >>> 16), (byte) (v >>> 8), (byte) (v)); - } - - public P64byte(byte v0, byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7) { - this.f0 = v0; - this.f1 = v1; - this.f2 = v2; - this.f3 = v3; - this.f4 = v4; - this.f5 = v5; - this.f6 = v6; - this.f7 = v7; - } - - } - - public static class Primitive64byte extends SizeState { - public P64byte[] arr; - @Setup - public void setup() { - arr = new P64byte[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new P64byte(i); - } - } - } - - - public static class P64int { - - public int f0; - public int f1; - - public P64int(long v) { - this((int) (v >>> 32), (int) v); - } - - public P64int(int hi, int lo) { - this.f0 = hi; - this.f1 = lo; - } - - } - - public static class Primitive64int extends SizeState { - public P64int[] arr; - @Setup - public void setup() { - arr = new P64int[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new P64int(i); - } - } - } - - public static class P64long { - - public long f0; - - public P64long(long v0) { - this.f0 = v0; - } - - } - - public static class Primitive64long extends SizeState { - public P64long[] arr; - @Setup - public void setup() { - arr = new P64long[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new P64long(i); - } - } - } - - - public static class P32int { - - public int f0; - - public P32int(int val) { - this.f0 = val; - } - } - - public static class Primitive32int extends SizeState { - public P32int[] arr; - @Setup - public void setup() { - arr = new P32int[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new P32int(i); - } - } - } - - public static class P128int { - - public int f0; - public int f1; - public int f2; - public int f3; - - public P128int(long v) { - this(0, 0, (int) (v >>> 32), (int) v); - } - - public P128int(int v0, int v1, int v2, int v3) { - this.f0 = v0; - this.f1 = v1; - this.f2 = v2; - this.f3 = v3; - } - } - - public static class Primitive128int extends SizeState { - public P128int[] arr; - @Setup - public void setup() { - arr = new P128int[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new P128int(i); - } - } - } - -} - diff --git a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ128int.java b/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ128int.java deleted file mode 100644 index 3994ce05244..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ128int.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.util; - -import org.openjdk.bench.valhalla.types.Int128; -import org.openjdk.bench.valhalla.types.Q128int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ128int extends SizeBase { - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - public static class ObjState extends SizeState { - public ObjWrapper[] arr; - @Setup - public void setup() { - arr = new ObjWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ObjWrapper(new Q128int(i)); - } - } - } - - public static class IntWrapper { - public Int128 f; - - public IntWrapper(Int128 f) { - this.f = f; - } - } - - public static class IntState extends SizeState { - public IntWrapper[] arr; - @Setup - public void setup() { - arr = new IntWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Q128int(i)); - } - } - } - - - public static class RefWrapper { - public Q128int f; - - public RefWrapper(Q128int f) { - this.f = f; - } - } - - public static class RefState extends SizeState { - public RefWrapper[] arr; - @Setup - public void setup() { - arr = new RefWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new RefWrapper(new Q128int(i)); - } - } - } - - - public static class ValWrapper { - public Q128int f; - - public ValWrapper(Q128int f) { - this.f = f; - } - } - - public static class ValState extends SizeState { - public ValWrapper[] arr; - @Setup - public void setup() { - arr = new ValWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ValWrapper(new Q128int(i)); - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ32int.java b/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ32int.java deleted file mode 100644 index 9aa1cdcf905..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ32int.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.util; - -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ32int extends SizeBase { - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - public static class ObjState extends SizeState { - public ObjWrapper[] arr; - @Setup - public void setup() { - arr = new ObjWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ObjWrapper(new Q32int(i)); - } - } - } - - public static class IntWrapper { - public Int32 f; - - public IntWrapper(Int32 f) { - this.f = f; - } - } - - public static class IntState extends SizeState { - public IntWrapper[] arr; - @Setup - public void setup() { - arr = new IntWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Q32int(i)); - } - } - } - - - public static class RefWrapper { - public Q32int f; - - public RefWrapper(Q32int f) { - this.f = f; - } - } - - public static class RefState extends SizeState { - public RefWrapper[] arr; - @Setup - public void setup() { - arr = new RefWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new RefWrapper(new Q32int(i)); - } - } - } - - - public static class ValWrapper { - public Q32int f; - - public ValWrapper(Q32int f) { - this.f = f; - } - } - - public static class ValState extends SizeState { - public ValWrapper[] arr; - @Setup - public void setup() { - arr = new ValWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ValWrapper(new Q32int(i)); - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64byte.java b/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64byte.java deleted file mode 100644 index 43e0ee3fe74..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64byte.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.util; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64byte; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64byte extends SizeBase { - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - public static class ObjState extends SizeState { - public ObjWrapper[] arr; - @Setup - public void setup() { - arr = new ObjWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ObjWrapper(new Q64byte(i)); - } - } - } - - public static class IntWrapper { - public Int64 f; - - public IntWrapper(Int64 f) { - this.f = f; - } - } - - public static class IntState extends SizeState { - public IntWrapper[] arr; - @Setup - public void setup() { - arr = new IntWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Q64byte(i)); - } - } - } - - - public static class RefWrapper { - public Q64byte f; - - public RefWrapper(Q64byte f) { - this.f = f; - } - } - - public static class RefState extends SizeState { - public RefWrapper[] arr; - @Setup - public void setup() { - arr = new RefWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new RefWrapper(new Q64byte(i)); - } - } - } - - - public static class ValWrapper { - public Q64byte f; - - public ValWrapper(Q64byte f) { - this.f = f; - } - } - - public static class ValState extends SizeState { - public ValWrapper[] arr; - @Setup - public void setup() { - arr = new ValWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ValWrapper(new Q64byte(i)); - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64int.java b/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64int.java deleted file mode 100644 index 72a110e9529..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64int.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.util; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64int; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64int extends SizeBase { - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - public static class ObjState extends SizeState { - public ObjWrapper[] arr; - @Setup - public void setup() { - arr = new ObjWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ObjWrapper(new Q64int(i)); - } - } - } - - public static class IntWrapper { - public Int64 f; - - public IntWrapper(Int64 f) { - this.f = f; - } - } - - public static class IntState extends SizeState { - public IntWrapper[] arr; - @Setup - public void setup() { - arr = new IntWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Q64int(i)); - } - } - } - - - public static class RefWrapper { - public Q64int f; - - public RefWrapper(Q64int f) { - this.f = f; - } - } - - public static class RefState extends SizeState { - public RefWrapper[] arr; - @Setup - public void setup() { - arr = new RefWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new RefWrapper(new Q64int(i)); - } - } - } - - - public static class ValWrapper { - public Q64int f; - - public ValWrapper(Q64int f) { - this.f = f; - } - } - - public static class ValState extends SizeState { - public ValWrapper[] arr; - @Setup - public void setup() { - arr = new ValWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ValWrapper(new Q64int(i)); - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64long.java b/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64long.java deleted file mode 100644 index 0ba97710151..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/field/util/StatesQ64long.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.field.util; - -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.jmh.annotations.Setup; - -public class StatesQ64long extends SizeBase { - - public static class ObjWrapper { - public Object f; - - public ObjWrapper(Object f) { - this.f = f; - } - } - - public static class ObjState extends SizeState { - public ObjWrapper[] arr; - @Setup - public void setup() { - arr = new ObjWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ObjWrapper(new Q64long(i)); - } - } - } - - public static class IntWrapper { - public Int64 f; - - public IntWrapper(Int64 f) { - this.f = f; - } - } - - public static class IntState extends SizeState { - public IntWrapper[] arr; - @Setup - public void setup() { - arr = new IntWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Q64long(i)); - } - } - } - - - public static class RefWrapper { - public Q64long f; - - public RefWrapper(Q64long f) { - this.f = f; - } - } - - public static class RefState extends SizeState { - public RefWrapper[] arr; - @Setup - public void setup() { - arr = new RefWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new RefWrapper(new Q64long(i)); - } - } - } - - - public static class ValWrapper { - public Q64long f; - - public ValWrapper(Q64long f) { - this.f = f; - } - } - - public static class ValState extends SizeState { - public ValWrapper[] arr; - @Setup - public void setup() { - arr = new ValWrapper[size]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new ValWrapper(new Q64long(i)); - } - } - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineRec.java b/test/micro/org/openjdk/bench/valhalla/hash/Value1.java similarity index 55% rename from test/micro/org/openjdk/bench/valhalla/invoke/InlineRec.java rename to test/micro/org/openjdk/bench/valhalla/hash/Value1.java index 6fbde6e4ca0..06f321ac13c 100644 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineRec.java +++ b/test/micro/org/openjdk/bench/valhalla/hash/Value1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,80 +20,75 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.invoke; +package org.openjdk.bench.valhalla.hash; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import java.util.concurrent.TimeUnit; -@Fork(3) +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) @Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class InlineRec { +public class Value1 { - @Param("100") - public int depth; + public static value class ValueInt1Hash { - public static value class V { - final int v; + public final int v0; - public V(int v) { - this.v = v; + public ValueInt1Hash(int v0) { + this.v0 = v0; } - public V addL(V y) { - return this.v == 0 ? y : new V(this.v - 1).addL(new V(y.v + 1)); + public int value() { + return v0; } - public V addR(V y) { - return y.v == 0 ? this : new V(this.v + 1).addR(new V(y.v - 1)); + @Override + public int hashCode() { + return v0; } - } - public static V s_addL(V x, V y) { - return x.v == 0 ? y : s_addL(new V(x.v - 1), new V(y.v + 1)); } - public static V s_addR(V x, V y) { - return y.v == 0 ? x : s_addR(new V(x.v + 1), new V(y.v - 1)); - } + public static value class ValueInt1 { + + public final int v0; + + public ValueInt1(int v0) { + this.v0 = v0; + } + + public int value() { + return v0; + } - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int statL() { - return s_addL(new V(depth), new V(depth)).v; } + @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int statR() { - return s_addR(new V(depth), new V(depth)).v; + public int explicit() { + return new ValueInt1Hash(42).hashCode(); } @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int instL() { - return new V(depth).addL(new V(depth)).v; + public int implicit() { + return new ValueInt1(42).hashCode(); } @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int instR() { - return new V(depth).addR(new V(depth)).v; + public int direct() { + return System.identityHashCode(new ValueInt1(42)); } - - } diff --git a/test/micro/org/openjdk/bench/valhalla/hash/Value8.java b/test/micro/org/openjdk/bench/valhalla/hash/Value8.java new file mode 100644 index 00000000000..204aa4afdb9 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/hash/Value8.java @@ -0,0 +1,108 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.hash; + + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value8 { + + public static value class ValueInt8 { + + public final int v0, v1, v2, v3, v4, v5, v6, v7; + + public ValueInt8(int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + this.v7 = v7; + } + + public int value0() { + return v0; + } + + } + + public static value class ValueInt8Hash { + + public final int v0, v1, v2, v3, v4, v5, v6, v7; + + public ValueInt8Hash(int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + this.v7 = v7; + } + + public int value0() { + return v0; + } + + @Override + public int hashCode() { + return (((((((v0 * 31) + v1) * 31 + v2) * 31 + v3) * 31 + v4) * 31 + v5) * 31 + v6) * 31 + v7; + } + } + + + @Benchmark + public int explicit() { + return new ValueInt8Hash(42, 43, 44, 45, 46, 47, 48, 49).hashCode(); + } + + @Benchmark + public int implicit() { + return new ValueInt8(42, 43, 44, 45, 46, 47, 48, 49).hashCode(); + } + + @Benchmark + public int direct() { + return System.identityHashCode(new ValueInt8(42, 43, 44, 45, 46, 47, 48, 49)); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/IdentityArray.java b/test/micro/org/openjdk/bench/valhalla/invoke/IdentityArray.java deleted file mode 100644 index 2e18e12efe1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/IdentityArray.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class IdentityArray { - - public static final int SIZE = 128; - - public interface MyInterface { - public int my_method(); - } - - public static class Ref1 implements MyInterface { - public final int f0; - public Ref1(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static class Ref2 implements MyInterface { - public final int f0; - public Ref2(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static class Ref3 implements MyInterface { - public final int f0; - public Ref3(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - @State(Scope.Thread) - public static abstract class IntState { - public MyInterface[] arr; - } - - @State(Scope.Thread) - public static abstract class Ref1State { - public Ref1[] arr; - } - - public static class Ref1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Ref1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1(i); - } - } - } - - public static class Ref1_as_Int extends IntState { - @Setup - public void setup() { - arr = new Ref1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1(i); - } - } - } - - public static class Int1_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1(i); - } - } - } - - public static class Ref2_as_Int extends IntState { - @Setup - public void setup() { - arr = new Ref2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref2(i); - } - } - } - - public static class Int2_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref2(i); - } - } - } - - public static class Ref3_as_Int extends IntState { - @Setup - public void setup() { - arr = new Ref3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref3(i); - } - } - } - - public static class Int3_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref3(i); - } - } - } - - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(MyInterface[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Ref1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_r(Ref1_as_Ref st0, Ref1_as_Ref st1, Ref1_as_Ref st2, Ref1_as_Ref st3, Ref1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_r(Ref1_as_Int st0, Ref1_as_Int st1, Ref1_as_Int st2, Ref1_as_Int st3, Ref1_as_Int st4, Ref1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_i(Int1_as_Int st0, Int1_as_Int st1, Int1_as_Int st2, Int1_as_Int st3, Int1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref1_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref1_as_Int st2, Ref2_as_Int st3, Ref1_as_Int st4, Ref2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int1_as_Int st2, Int2_as_Int st3, Int1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref2_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref3_as_Int st2, Ref1_as_Int st3, Ref2_as_Int st4, Ref3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int3_as_Int st2, Int1_as_Int st3, Int2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_ri(Ref1_as_Int st0, Int2_as_Int st1, Ref3_as_Int st2, Int1_as_Int st3, Ref2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - -} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray0.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray0.java deleted file mode 100644 index a9d07db1ecd..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray0.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineArray0 { - - public static final int SIZE = 128; - - public interface MyInterface { - public int my_method(); - } - - public static value class Val1 implements MyInterface { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static value class Val2 implements MyInterface { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static value class Val3 implements MyInterface { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - @State(Scope.Thread) - public static abstract class IntState { - public MyInterface[] arr; - } - - @State(Scope.Thread) - public static abstract class Ref1State { - public Val1[] arr; - } - - @State(Scope.Thread) - public static abstract class Val1State { - public Val1[] arr; - } - - public static class Val1_as_Val extends Val1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Int1_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val2_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Ref2_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Int2_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Val3_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Ref3_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Int3_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(MyInterface[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val_v(Val1_as_Val st0, Val1_as_Val st1, Val1_as_Val st2, Val1_as_Val st3, Val1_as_Val st4, Val1_as_Val st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_v(Val1_as_Ref st0, Val1_as_Ref st1, Val1_as_Ref st2, Val1_as_Ref st3, Val1_as_Ref st4, Val1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_r(Ref1_as_Ref st0, Ref1_as_Ref st1, Ref1_as_Ref st2, Ref1_as_Ref st3, Ref1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_vr(Val1_as_Ref st0, Ref1_as_Ref st1, Val1_as_Ref st2, Ref1_as_Ref st3, Val1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_v(Val1_as_Int st0, Val1_as_Int st1, Val1_as_Int st2, Val1_as_Int st3, Val1_as_Int st4, Val1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_r(Ref1_as_Int st0, Ref1_as_Int st1, Ref1_as_Int st2, Ref1_as_Int st3, Ref1_as_Int st4, Ref1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_i(Int1_as_Int st0, Int1_as_Int st1, Int1_as_Int st2, Int1_as_Int st3, Int1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vr(Val1_as_Int st0, Ref1_as_Int st1, Val1_as_Int st2, Ref1_as_Int st3, Val1_as_Int st4, Ref1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vi(Val1_as_Int st0, Int1_as_Int st1, Val1_as_Int st2, Int1_as_Int st3, Val1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref1_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vri(Val1_as_Int st0, Ref1_as_Int st1, Int1_as_Int st2, Val1_as_Int st3, Ref1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_v(Val1_as_Int st0, Val2_as_Int st1, Val1_as_Int st2, Val2_as_Int st3, Val1_as_Int st4, Val2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref1_as_Int st2, Ref2_as_Int st3, Ref1_as_Int st4, Ref2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int1_as_Int st2, Int2_as_Int st3, Int1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vr(Val1_as_Int st0, Ref2_as_Int st1, Val2_as_Int st2, Ref1_as_Int st3, Val1_as_Int st4, Ref2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vi(Val1_as_Int st0, Int2_as_Int st1, Val2_as_Int st2, Int1_as_Int st3, Val1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref2_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vri(Val1_as_Int st0, Ref1_as_Int st1, Int1_as_Int st2, Val2_as_Int st3, Ref2_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_v(Val1_as_Int st0, Val2_as_Int st1, Val3_as_Int st2, Val1_as_Int st3, Val2_as_Int st4, Val3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref3_as_Int st2, Ref1_as_Int st3, Ref2_as_Int st4, Ref3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int3_as_Int st2, Int1_as_Int st3, Int2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vr(Val1_as_Int st0, Ref2_as_Int st1, Val3_as_Int st2, Ref1_as_Int st3, Val2_as_Int st4, Ref3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vi(Val1_as_Int st0, Int2_as_Int st1, Val3_as_Int st2, Int1_as_Int st3, Val3_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_ri(Ref1_as_Int st0, Int2_as_Int st1, Ref3_as_Int st2, Int1_as_Int st3, Ref2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vri(Val1_as_Int st0, Ref2_as_Int st1, Int3_as_Int st2, Val2_as_Int st3, Ref3_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray1.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray1.java deleted file mode 100644 index 54357b3818a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArray1.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineArray1 { - - public static final int SIZE = 128; - - public interface MyInterface { - public int my_method(); - } - - public static value class Val1 implements MyInterface { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - public static value class Val2 implements MyInterface { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - public static value class Val3 implements MyInterface { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - @State(Scope.Thread) - public static abstract class IntState { - public MyInterface[] arr; - } - - @State(Scope.Thread) - public static abstract class Ref1State { - public Val1[] arr; - } - - @State(Scope.Thread) - public static abstract class Val1State { - public Val1[] arr; - } - - public static class Val1_as_Val extends Val1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Int1_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val2_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Ref2_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Int2_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Val3_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Ref3_as_Int extends IntState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Int3_as_Int extends IntState { - @Setup - public void setup() { - arr = new MyInterface[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(MyInterface[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].my_method(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val_v(Val1_as_Val st0, Val1_as_Val st1, Val1_as_Val st2, Val1_as_Val st3, Val1_as_Val st4, Val1_as_Val st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_v(Val1_as_Ref st0, Val1_as_Ref st1, Val1_as_Ref st2, Val1_as_Ref st3, Val1_as_Ref st4, Val1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_r(Ref1_as_Ref st0, Ref1_as_Ref st1, Ref1_as_Ref st2, Ref1_as_Ref st3, Ref1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_vr(Val1_as_Ref st0, Ref1_as_Ref st1, Val1_as_Ref st2, Ref1_as_Ref st3, Val1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_v(Val1_as_Int st0, Val1_as_Int st1, Val1_as_Int st2, Val1_as_Int st3, Val1_as_Int st4, Val1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_r(Ref1_as_Int st0, Ref1_as_Int st1, Ref1_as_Int st2, Ref1_as_Int st3, Ref1_as_Int st4, Ref1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_i(Int1_as_Int st0, Int1_as_Int st1, Int1_as_Int st2, Int1_as_Int st3, Int1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vr(Val1_as_Int st0, Ref1_as_Int st1, Val1_as_Int st2, Ref1_as_Int st3, Val1_as_Int st4, Ref1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vi(Val1_as_Int st0, Int1_as_Int st1, Val1_as_Int st2, Int1_as_Int st3, Val1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref1_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int_vri(Val1_as_Int st0, Ref1_as_Int st1, Int1_as_Int st2, Val1_as_Int st3, Ref1_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_v(Val1_as_Int st0, Val2_as_Int st1, Val1_as_Int st2, Val2_as_Int st3, Val1_as_Int st4, Val2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref1_as_Int st2, Ref2_as_Int st3, Ref1_as_Int st4, Ref2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int1_as_Int st2, Int2_as_Int st3, Int1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vr(Val1_as_Int st0, Ref2_as_Int st1, Val2_as_Int st2, Ref1_as_Int st3, Val1_as_Int st4, Ref2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vi(Val1_as_Int st0, Int2_as_Int st1, Val2_as_Int st2, Int1_as_Int st3, Val1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_ri(Ref1_as_Int st0, Int1_as_Int st1, Ref2_as_Int st2, Int1_as_Int st3, Ref1_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int_vri(Val1_as_Int st0, Ref1_as_Int st1, Int1_as_Int st2, Val2_as_Int st3, Ref2_as_Int st4, Int2_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_v(Val1_as_Int st0, Val2_as_Int st1, Val3_as_Int st2, Val1_as_Int st3, Val2_as_Int st4, Val3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_r(Ref1_as_Int st0, Ref2_as_Int st1, Ref3_as_Int st2, Ref1_as_Int st3, Ref2_as_Int st4, Ref3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_i(Int1_as_Int st0, Int2_as_Int st1, Int3_as_Int st2, Int1_as_Int st3, Int2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vr(Val1_as_Int st0, Ref2_as_Int st1, Val3_as_Int st2, Ref1_as_Int st3, Val2_as_Int st4, Ref3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vi(Val1_as_Int st0, Int2_as_Int st1, Val3_as_Int st2, Int1_as_Int st3, Val3_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_ri(Ref1_as_Int st0, Int2_as_Int st1, Ref3_as_Int st2, Int1_as_Int st3, Ref2_as_Int st4, Int3_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int_vri(Val1_as_Int st0, Ref2_as_Int st1, Int3_as_Int st2, Val2_as_Int st3, Ref3_as_Int st4, Int1_as_Int st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashExplicit.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashExplicit.java deleted file mode 100644 index 3f539efdd5b..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashExplicit.java +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineArrayHashExplicit { - - public static final int SIZE = 128; - - public static value class Val1 { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - @Override - public int hashCode() { - return f0; - } - } - - public static value class Val2 { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - @Override - public int hashCode() { - return f0; - } - } - - public static value class Val3 { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - @Override - public int hashCode() { - return f0; - } - } - - @State(Scope.Thread) - public static abstract class ObjState { - public Object[] arr; - } - - @State(Scope.Thread) - public static abstract class Ref1State { - public Val1[] arr; - } - - @State(Scope.Thread) - public static abstract class Val1State { - public Val1[] arr; - } - - public static class Val1_as_Val extends Val1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Obj1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Ref2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Obj2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Val3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Ref3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Obj3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceObj(Object[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val_v(Val1_as_Val st0, Val1_as_Val st1, Val1_as_Val st2, Val1_as_Val st3, Val1_as_Val st4, Val1_as_Val st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_v(Val1_as_Ref st0, Val1_as_Ref st1, Val1_as_Ref st2, Val1_as_Ref st3, Val1_as_Ref st4, Val1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_r(Ref1_as_Ref st0, Ref1_as_Ref st1, Ref1_as_Ref st2, Ref1_as_Ref st3, Ref1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_vr(Val1_as_Ref st0, Ref1_as_Ref st1, Val1_as_Ref st2, Ref1_as_Ref st3, Val1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_v(Val1_as_Obj st0, Val1_as_Obj st1, Val1_as_Obj st2, Val1_as_Obj st3, Val1_as_Obj st4, Val1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_r(Ref1_as_Obj st0, Ref1_as_Obj st1, Ref1_as_Obj st2, Ref1_as_Obj st3, Ref1_as_Obj st4, Ref1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_o(Obj1_as_Obj st0, Obj1_as_Obj st1, Obj1_as_Obj st2, Obj1_as_Obj st3, Obj1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vr(Val1_as_Obj st0, Ref1_as_Obj st1, Val1_as_Obj st2, Ref1_as_Obj st3, Val1_as_Obj st4, Ref1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vo(Val1_as_Obj st0, Obj1_as_Obj st1, Val1_as_Obj st2, Obj1_as_Obj st3, Val1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_ro(Ref1_as_Obj st0, Obj1_as_Obj st1, Ref1_as_Obj st2, Obj1_as_Obj st3, Ref1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vro(Val1_as_Obj st0, Ref1_as_Obj st1, Obj1_as_Obj st2, Val1_as_Obj st3, Ref1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_v(Val1_as_Obj st0, Val2_as_Obj st1, Val1_as_Obj st2, Val2_as_Obj st3, Val1_as_Obj st4, Val2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_r(Ref1_as_Obj st0, Ref2_as_Obj st1, Ref1_as_Obj st2, Ref2_as_Obj st3, Ref1_as_Obj st4, Ref2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_o(Obj1_as_Obj st0, Obj2_as_Obj st1, Obj1_as_Obj st2, Obj2_as_Obj st3, Obj1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vr(Val1_as_Obj st0, Ref2_as_Obj st1, Val2_as_Obj st2, Ref1_as_Obj st3, Val1_as_Obj st4, Ref2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vo(Val1_as_Obj st0, Obj2_as_Obj st1, Val2_as_Obj st2, Obj1_as_Obj st3, Val1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_ro(Ref1_as_Obj st0, Obj1_as_Obj st1, Ref2_as_Obj st2, Obj1_as_Obj st3, Ref1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vro(Val1_as_Obj st0, Ref1_as_Obj st1, Obj1_as_Obj st2, Val2_as_Obj st3, Ref2_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_v(Val1_as_Obj st0, Val2_as_Obj st1, Val3_as_Obj st2, Val1_as_Obj st3, Val2_as_Obj st4, Val3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_r(Ref1_as_Obj st0, Ref2_as_Obj st1, Ref3_as_Obj st2, Ref1_as_Obj st3, Ref2_as_Obj st4, Ref3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_o(Obj1_as_Obj st0, Obj2_as_Obj st1, Obj3_as_Obj st2, Obj1_as_Obj st3, Obj2_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vr(Val1_as_Obj st0, Ref2_as_Obj st1, Val3_as_Obj st2, Ref1_as_Obj st3, Val2_as_Obj st4, Ref3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vo(Val1_as_Obj st0, Obj2_as_Obj st1, Val3_as_Obj st2, Obj1_as_Obj st3, Val3_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_ro(Ref1_as_Obj st0, Obj2_as_Obj st1, Ref3_as_Obj st2, Obj1_as_Obj st3, Ref2_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vro(Val1_as_Obj st0, Ref2_as_Obj st1, Obj3_as_Obj st2, Val2_as_Obj st3, Ref3_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashImplicit.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashImplicit.java deleted file mode 100644 index 609a1dc6d3a..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineArrayHashImplicit.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineArrayHashImplicit { - - public static final int SIZE = 128; - - public static value class Val1 { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - } - - public static value class Val2 { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - } - - public static value class Val3 { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - } - - @State(Scope.Thread) - public static abstract class ObjState { - public Object[] arr; - } - - @State(Scope.Thread) - public static abstract class Ref1State { - public Val1[] arr; - } - - @State(Scope.Thread) - public static abstract class Val1State { - public Val1[] arr; - } - - public static class Val1_as_Val extends Val1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Ref extends Ref1State { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Ref1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val1[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Obj1_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1(i); - } - } - } - - public static class Val2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Ref2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val2[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Obj2_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val2(i); - } - } - } - - public static class Val3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Ref3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Val3[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - public static class Obj3_as_Obj extends ObjState { - @Setup - public void setup() { - arr = new Object[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val3(i); - } - } - } - - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceObj(Object[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].hashCode(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val_v(Val1_as_Val st0, Val1_as_Val st1, Val1_as_Val st2, Val1_as_Val st3, Val1_as_Val st4, Val1_as_Val st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_v(Val1_as_Ref st0, Val1_as_Ref st1, Val1_as_Ref st2, Val1_as_Ref st3, Val1_as_Ref st4, Val1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_r(Ref1_as_Ref st0, Ref1_as_Ref st1, Ref1_as_Ref st2, Ref1_as_Ref st3, Ref1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref_vr(Val1_as_Ref st0, Ref1_as_Ref st1, Val1_as_Ref st2, Ref1_as_Ref st3, Val1_as_Ref st4, Ref1_as_Ref st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_v(Val1_as_Obj st0, Val1_as_Obj st1, Val1_as_Obj st2, Val1_as_Obj st3, Val1_as_Obj st4, Val1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_r(Ref1_as_Obj st0, Ref1_as_Obj st1, Ref1_as_Obj st2, Ref1_as_Obj st3, Ref1_as_Obj st4, Ref1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_o(Obj1_as_Obj st0, Obj1_as_Obj st1, Obj1_as_Obj st2, Obj1_as_Obj st3, Obj1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vr(Val1_as_Obj st0, Ref1_as_Obj st1, Val1_as_Obj st2, Ref1_as_Obj st3, Val1_as_Obj st4, Ref1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vo(Val1_as_Obj st0, Obj1_as_Obj st1, Val1_as_Obj st2, Obj1_as_Obj st3, Val1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_ro(Ref1_as_Obj st0, Obj1_as_Obj st1, Ref1_as_Obj st2, Obj1_as_Obj st3, Ref1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Obj_vro(Val1_as_Obj st0, Ref1_as_Obj st1, Obj1_as_Obj st2, Val1_as_Obj st3, Ref1_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_v(Val1_as_Obj st0, Val2_as_Obj st1, Val1_as_Obj st2, Val2_as_Obj st3, Val1_as_Obj st4, Val2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_r(Ref1_as_Obj st0, Ref2_as_Obj st1, Ref1_as_Obj st2, Ref2_as_Obj st3, Ref1_as_Obj st4, Ref2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_o(Obj1_as_Obj st0, Obj2_as_Obj st1, Obj1_as_Obj st2, Obj2_as_Obj st3, Obj1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vr(Val1_as_Obj st0, Ref2_as_Obj st1, Val2_as_Obj st2, Ref1_as_Obj st3, Val1_as_Obj st4, Ref2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vo(Val1_as_Obj st0, Obj2_as_Obj st1, Val2_as_Obj st2, Obj1_as_Obj st3, Val1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_ro(Ref1_as_Obj st0, Obj1_as_Obj st1, Ref2_as_Obj st2, Obj1_as_Obj st3, Ref1_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Obj_vro(Val1_as_Obj st0, Ref1_as_Obj st1, Obj1_as_Obj st2, Val2_as_Obj st3, Ref2_as_Obj st4, Obj2_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_v(Val1_as_Obj st0, Val2_as_Obj st1, Val3_as_Obj st2, Val1_as_Obj st3, Val2_as_Obj st4, Val3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_r(Ref1_as_Obj st0, Ref2_as_Obj st1, Ref3_as_Obj st2, Ref1_as_Obj st3, Ref2_as_Obj st4, Ref3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_o(Obj1_as_Obj st0, Obj2_as_Obj st1, Obj3_as_Obj st2, Obj1_as_Obj st3, Obj2_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vr(Val1_as_Obj st0, Ref2_as_Obj st1, Val3_as_Obj st2, Ref1_as_Obj st3, Val2_as_Obj st4, Ref3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vo(Val1_as_Obj st0, Obj2_as_Obj st1, Val3_as_Obj st2, Obj1_as_Obj st3, Val3_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_ro(Ref1_as_Obj st0, Obj2_as_Obj st1, Ref3_as_Obj st2, Obj1_as_Obj st3, Ref2_as_Obj st4, Obj3_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Obj_vro(Val1_as_Obj st0, Ref2_as_Obj st1, Obj3_as_Obj st2, Val2_as_Obj st3, Ref3_as_Obj st4, Obj1_as_Obj st5) { - return reduceObj(st0.arr) + - reduceObj(st1.arr) + - reduceObj(st2.arr) + - reduceObj(st3.arr) + - reduceObj(st4.arr) + - reduceObj(st5.arr); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineField.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineField.java deleted file mode 100644 index 6bc57c0663c..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineField.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineField { - - public static final int SIZE = 128; - - public interface MyInterface { - public int my_method(); - } - - public static value class Val1 implements MyInterface { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static value class Val2 implements MyInterface { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static value class Val3 implements MyInterface { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - @Override - public int my_method() { - return f0; - } - } - - public static class Val1Wrapper { - public Val1 f; - - public Val1Wrapper(Val1 f) { - this.f = f; - } - } - - public static class Ref1Wrapper { - public Val1 f; - - public Ref1Wrapper(Val1 f) { - this.f = f; - } - } - - public static class IntWrapper { - public MyInterface f; - - public IntWrapper(MyInterface f) { - this.f = f; - } - } - - @State(Scope.Thread) - public static class Val1State { - public Val1Wrapper[] arr; - @Setup - public void setup() { - arr = new Val1Wrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1Wrapper(new Val1(i)); - } - } - } - - @State(Scope.Thread) - public static class Ref1State { - public Ref1Wrapper[] arr; - @Setup - public void setup() { - arr = new Ref1Wrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1Wrapper(new Val1(i)); - } - } - } - - @State(Scope.Thread) - public static class IntStateBase { - public IntWrapper[] arr; - } - - public static class Int1State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val1(i)); - } - } - } - - public static class Int2State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val2(i)); - } - } - } - - public static class Int3State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val3(i)); - } - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1Wrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Ref1Wrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(IntWrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val(Val1State st0, Val1State st1, Val1State st2, Val1State st3, Val1State st4, Val1State st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref(Ref1State st0, Ref1State st1, Ref1State st2, Ref1State st3, Ref1State st4, Ref1State st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int(Int1State st0, Int1State st1, Int1State st2, Int1State st3, Int1State st4, Int1State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int(Int1State st0, Int2State st1, Int1State st2, Int2State st3, Int1State st4, Int2State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int(Int1State st0, Int2State st1, Int3State st2, Int1State st3, Int2State st4, Int3State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/InlineField1.java b/test/micro/org/openjdk/bench/valhalla/invoke/InlineField1.java deleted file mode 100644 index 3b9c9f3e119..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/invoke/InlineField1.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.invoke; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@Fork(3) -@Warmup(iterations = 5, time = 1) -@Measurement(iterations = 5, time = 1) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class InlineField1 { - - public static final int SIZE = 128; - - public interface MyInterface { - public int my_method(); - } - - public static value class Val1 implements MyInterface { - public final int f0; - public Val1(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - public static value class Val2 implements MyInterface { - public final int f0; - public Val2(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - public static value class Val3 implements MyInterface { - public final int f0; - public Val3(int f0) { - this.f0 = f0; - } - @Override - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int my_method() { - return f0; - } - } - - public static class Val1Wrapper { - public Val1 f; - - public Val1Wrapper(Val1 f) { - this.f = f; - } - } - - public static class Ref1Wrapper { - public Val1 f; - - public Ref1Wrapper(Val1 f) { - this.f = f; - } - } - - public static class IntWrapper { - public MyInterface f; - - public IntWrapper(MyInterface f) { - this.f = f; - } - } - - @State(Scope.Thread) - public static class Val1State { - public Val1Wrapper[] arr; - @Setup - public void setup() { - arr = new Val1Wrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Val1Wrapper(new Val1(i)); - } - } - } - - @State(Scope.Thread) - public static class Ref1State { - public Ref1Wrapper[] arr; - @Setup - public void setup() { - arr = new Ref1Wrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1Wrapper(new Val1(i)); - } - } - } - - @State(Scope.Thread) - public static class IntStateBase { - public IntWrapper[] arr; - } - - public static class Int1State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val1(i)); - } - } - } - - public static class Int2State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val2(i)); - } - } - } - - public static class Int3State extends IntStateBase { - @Setup - public void setup() { - arr = new IntWrapper[SIZE]; - for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Val3(i)); - } - } - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceVal(Val1Wrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Ref1Wrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(IntWrapper[] arr) { - int r = 0; - for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); - } - return r; - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Val(Val1State st0, Val1State st1, Val1State st2, Val1State st3, Val1State st4, Val1State st5) { - return reduceVal(st0.arr) + - reduceVal(st1.arr) + - reduceVal(st2.arr) + - reduceVal(st3.arr) + - reduceVal(st4.arr) + - reduceVal(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref(Ref1State st0, Ref1State st1, Ref1State st2, Ref1State st3, Ref1State st4, Ref1State st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int(Int1State st0, Int1State st1, Int1State st2, Int1State st3, Int1State st4, Int1State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int(Int1State st0, Int2State st1, Int1State st2, Int2State st3, Int1State st4, Int2State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - @Benchmark - @OperationsPerInvocation(SIZE * 6) - @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int(Int1State st0, Int2State st1, Int3State st2, Int1State st3, Int2State st4, Int3State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); - } - - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/array/Identity.java b/test/micro/org/openjdk/bench/valhalla/invoke/array/Identity.java new file mode 100644 index 00000000000..34565b22e98 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/array/Identity.java @@ -0,0 +1,309 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.array; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Identity { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + public static class IdentityInt0 implements InterfaceInt { + public final int value; + public IdentityInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static class IdentityInt1 implements InterfaceInt { + public final int value; + public IdentityInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static class IdentityInt2 implements InterfaceInt { + public final int value; + public IdentityInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @State(Scope.Thread) + public static class Int0State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2(i); + } + } + } + + @State(Scope.Thread) + public static class Ref0State { + public IdentityInt0[] arr; + @Setup + public void setup() { + arr = new IdentityInt0[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Ref1State { + public IdentityInt1[] arr; + @Setup + public void setup() { + arr = new IdentityInt1[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Ref2State { + public IdentityInt2[] arr; + @Setup + public void setup() { + arr = new IdentityInt2[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2(i); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(InterfaceInt[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_ref(IdentityInt0[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_ref(st0.arr) + + reduce_ref(st1.arr) + + reduce_ref(st2.arr) + + reduce_ref(st3.arr) + + reduce_ref(st4.arr) + + reduce_ref(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_r(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_ri(Ref0State st0, Int0State st1, Ref0State st2, Int0State st3, Ref0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_r(Ref0State st0, Ref0State st1, Ref0State st2, Ref1State st3, Ref1State st4, Ref1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_ri(Ref0State st0, Int0State st1, Ref0State st2, Int1State st3, Ref1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_r(Ref0State st0, Ref0State st1, Ref1State st2, Ref1State st3, Ref2State st4, Ref2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_ri(Ref0State st0, Int0State st1, Ref1State st2, Int1State st3, Ref2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/array/Value.java b/test/micro/org/openjdk/bench/valhalla/invoke/array/Value.java new file mode 100644 index 00000000000..97d54dd5494 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/array/Value.java @@ -0,0 +1,308 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.array; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @State(Scope.Thread) + public static class Int0State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + @State(Scope.Thread) + public static class Val0State { + public ValueInt0[] arr; + @Setup + public void setup() { + arr = new ValueInt0[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Val1State { + public ValueInt1[] arr; + @Setup + public void setup() { + arr = new ValueInt1[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Val22State { + public ValueInt2[] arr; + @Setup + public void setup() { + arr = new ValueInt2[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(InterfaceInt[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValueInt0[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_v(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_vi(Val0State st0, Int0State st1, Val0State st2, Int0State st3, Val0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_v(Val0State st0, Val0State st1, Val0State st2, Val1State st3, Val1State st4, Val1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_vi(Val0State st0, Int0State st1, Val0State st2, Int1State st3, Val1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_v(Val0State st0, Val0State st1, Val1State st2, Val1State st3, Val22State st4, Val22State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_vi(Val0State st0, Int0State st1, Val1State st2, Int1State st3, Val22State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFree.java b/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFree.java new file mode 100644 index 00000000000..493af9ba755 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFree.java @@ -0,0 +1,309 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.array; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class ValueNullFree { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @State(Scope.Thread) + public static class Int0State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + @State(Scope.Thread) + public static class Val0State { + public ValueInt0[] arr; + @Setup + public void setup() { + arr = (ValueInt0[]) ValueClass.newNullRestrictedAtomicArray(ValueInt0.class, SIZE, new ValueInt0(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Val1State { + public ValueInt1[] arr; + @Setup + public void setup() { + arr = (ValueInt1[]) ValueClass.newNullRestrictedAtomicArray(ValueInt1.class, SIZE, new ValueInt1(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Val22State { + public ValueInt2[] arr; + @Setup + public void setup() { + arr = (ValueInt2[]) ValueClass.newNullRestrictedAtomicArray(ValueInt2.class, SIZE, new ValueInt2(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(InterfaceInt[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValueInt0[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_v(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_vi(Val0State st0, Int0State st1, Val0State st2, Int0State st3, Val0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_v(Val0State st0, Val0State st1, Val0State st2, Val1State st3, Val1State st4, Val1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_vi(Val0State st0, Int0State st1, Val0State st2, Int1State st3, Val1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_v(Val0State st0, Val0State st1, Val1State st2, Val1State st3, Val22State st4, Val22State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_vi(Val0State st0, Int0State st1, Val1State st2, Int1State st3, Val22State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFreeNonAtomic.java new file mode 100644 index 00000000000..eb17228d517 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/array/ValueNullFreeNonAtomic.java @@ -0,0 +1,313 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.array; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class ValueNullFreeNonAtomic { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @LooselyConsistentValue + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @LooselyConsistentValue + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @State(Scope.Thread) + public static class Int0State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public InterfaceInt[] arr; + @Setup + public void setup() { + arr = new InterfaceInt[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + @State(Scope.Thread) + public static class Val0State { + public ValueInt0[] arr; + @Setup + public void setup() { + arr = (ValueInt0[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt0.class, SIZE, new ValueInt0(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt0(i); + } + } + } + + @State(Scope.Thread) + public static class Val1State { + public ValueInt1[] arr; + @Setup + public void setup() { + arr = (ValueInt1[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt1.class, SIZE, new ValueInt1(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt1(i); + } + } + } + + @State(Scope.Thread) + public static class Val22State { + public ValueInt2[] arr; + @Setup + public void setup() { + arr = (ValueInt2[]) ValueClass.newNullRestrictedNonAtomicArray(ValueInt2.class, SIZE, new ValueInt2(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2(i); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(InterfaceInt[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValueInt0[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_v(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1_vi(Val0State st0, Int0State st1, Val0State st2, Int0State st3, Val0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_v(Val0State st0, Val0State st1, Val0State st2, Val1State st3, Val1State st4, Val1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2_vi(Val0State st0, Int0State st1, Val0State st2, Int1State st3, Val1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_v(Val0State st0, Val0State st1, Val1State st2, Val1State st3, Val22State st4, Val22State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3_vi(Val0State st0, Int0State st1, Val1State st2, Int1State st3, Val22State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/IdentityField.java b/test/micro/org/openjdk/bench/valhalla/invoke/field/Identity.java similarity index 50% rename from test/micro/org/openjdk/bench/valhalla/invoke/IdentityField.java rename to test/micro/org/openjdk/bench/valhalla/invoke/field/Identity.java index 730372d54a6..ff03fdd6b87 100644 --- a/test/micro/org/openjdk/bench/valhalla/invoke/IdentityField.java +++ b/test/micro/org/openjdk/bench/valhalla/invoke/field/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.invoke; +package org.openjdk.bench.valhalla.invoke.field; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -43,124 +43,136 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @State(Scope.Thread) -public class IdentityField { +public class Identity { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + public static final int SIZE = 128; - public interface MyInterface { - public int my_method(); + public interface InterfaceInt { + public int value(); } - public static class Ref1 implements MyInterface { - public final int f0; - public Ref1(int f0) { - this.f0 = f0; + public static class IdentityInt0 implements InterfaceInt { + public final int value; + public IdentityInt0(int value) { + this.value = value; } @Override - public int my_method() { - return f0; + public int value() { + return value; } } - public static class Ref2 implements MyInterface { - public final int f0; - public Ref2(int f0) { - this.f0 = f0; + public static class IdentityInt1 implements InterfaceInt { + public final int value; + public IdentityInt1(int value) { + this.value = value; } @Override - public int my_method() { - return f0; + public int value() { + return value; } } - public static class Ref3 implements MyInterface { - public final int f0; - public Ref3(int f0) { - this.f0 = f0; + public static class IdentityInt2 implements InterfaceInt { + public final int value; + public IdentityInt2(int value) { + this.value = value; } @Override - public int my_method() { - return f0; + public int value() { + return value; } } - public static class Ref1Wrapper { - public Ref1 f; + public static class IntWrapper { + final InterfaceInt f; - public Ref1Wrapper(Ref1 f) { + public IntWrapper(InterfaceInt f) { this.f = f; } } - public static class IntWrapper { - public MyInterface f; + public static class RefWrapper { + final IdentityInt0 f; - public IntWrapper(MyInterface f) { + public RefWrapper(IdentityInt0 f) { this.f = f; } } @State(Scope.Thread) - public static class Ref1State { - public Ref1Wrapper[] arr; + public static class Int0State { + public IntWrapper[] arr; @Setup public void setup() { - arr = new Ref1Wrapper[SIZE]; + arr = new IntWrapper[SIZE]; for (int i = 0; i < arr.length; i++) { - arr[i] = new Ref1Wrapper(new Ref1(i)); + arr[i] = new IntWrapper(new IdentityInt0(i)); } } } @State(Scope.Thread) - public static class IntStateBase { + public static class Int1State { public IntWrapper[] arr; - } - - public static class Int1State extends IntStateBase { @Setup public void setup() { arr = new IntWrapper[SIZE]; for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Ref1(i)); + arr[i] = new IntWrapper(new IdentityInt1(i)); } } } - public static class Int2State extends IntStateBase { + @State(Scope.Thread) + public static class Int2State { + public IntWrapper[] arr; @Setup public void setup() { arr = new IntWrapper[SIZE]; for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Ref2(i)); + arr[i] = new IntWrapper(new IdentityInt2(i)); } } } - public static class Int3State extends IntStateBase { + @State(Scope.Thread) + public static class Ref0State { + public RefWrapper[] arr; @Setup public void setup() { - arr = new IntWrapper[SIZE]; + arr = new RefWrapper[SIZE]; for (int i = 0; i < arr.length; i++) { - arr[i] = new IntWrapper(new Ref3(i)); + arr[i] = new RefWrapper(new IdentityInt0(i)); } } } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceRef(Ref1Wrapper[] arr) { + public int reduce_int(IntWrapper[] arr) { int r = 0; for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); + r += arr[i].f.value(); } return r; } @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int reduceInt(IntWrapper[] arr) { + public int reduce_ref(RefWrapper[] arr) { int r = 0; for (int i = 0; i < arr.length; i++) { - r += arr[i].f.my_method(); + r += arr[i].f.value(); } return r; } @@ -168,51 +180,49 @@ public int reduceInt(IntWrapper[] arr) { @Benchmark @OperationsPerInvocation(SIZE * 6) @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Ref(Ref1State st0, Ref1State st1, Ref1State st2, Ref1State st3, Ref1State st4, Ref1State st5) { - return reduceRef(st0.arr) + - reduceRef(st1.arr) + - reduceRef(st2.arr) + - reduceRef(st3.arr) + - reduceRef(st4.arr) + - reduceRef(st5.arr); + public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_ref(st0.arr) + + reduce_ref(st1.arr) + + reduce_ref(st2.arr) + + reduce_ref(st3.arr) + + reduce_ref(st4.arr) + + reduce_ref(st5.arr); } @Benchmark @OperationsPerInvocation(SIZE * 6) @CompilerControl(CompilerControl.Mode.INLINE) - public int target1_Int(Int1State st0, Int1State st1, Int1State st2, Int1State st3, Int1State st4, Int1State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); + public int target1(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); } @Benchmark @OperationsPerInvocation(SIZE * 6) @CompilerControl(CompilerControl.Mode.INLINE) - public int target2_Int(Int1State st0, Int2State st1, Int1State st2, Int2State st3, Int1State st4, Int2State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); + public int target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); } @Benchmark @OperationsPerInvocation(SIZE * 6) @CompilerControl(CompilerControl.Mode.INLINE) - public int target3_Int(Int1State st0, Int2State st1, Int3State st2, Int1State st3, Int2State st4, Int3State st5) { - return reduceInt(st0.arr) + - reduceInt(st1.arr) + - reduceInt(st2.arr) + - reduceInt(st3.arr) + - reduceInt(st4.arr) + - reduceInt(st5.arr); + public int target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); } - - -} +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/field/Value.java b/test/micro/org/openjdk/bench/valhalla/invoke/field/Value.java new file mode 100644 index 00000000000..620e7474f08 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/field/Value.java @@ -0,0 +1,228 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.field; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Value { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static class IntWrapper { + final InterfaceInt f; + + public IntWrapper(InterfaceInt f) { + this.f = f; + } + } + + public static class ValWrapper { + final ValueInt0 f; + + public ValWrapper(ValueInt0 f) { + this.f = f; + } + } + + @State(Scope.Thread) + public static class Int0State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt0(i)); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt1(i)); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt2(i)); + } + } + } + + @State(Scope.Thread) + public static class Ref0State { + public ValWrapper[] arr; + @Setup + public void setup() { + arr = new ValWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValWrapper(new ValueInt0(i)); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(IntWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFree.java b/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFree.java new file mode 100644 index 00000000000..15bcfd320ec --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFree.java @@ -0,0 +1,232 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.field; + +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class ValueNullFree { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static class IntWrapper { + final InterfaceInt f; + + public IntWrapper(InterfaceInt f) { + this.f = f; + } + } + + public static class ValWrapper { + @Strict + @NullRestricted + final ValueInt0 f; + + public ValWrapper(ValueInt0 f) { + this.f = f; + } + } + + @State(Scope.Thread) + public static class Int0State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt0(i)); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt1(i)); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt2(i)); + } + } + } + + @State(Scope.Thread) + public static class Ref0State { + public ValWrapper[] arr; + @Setup + public void setup() { + arr = new ValWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValWrapper(new ValueInt0(i)); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(IntWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFreeNonAtomic.java new file mode 100644 index 00000000000..30bad0164af --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/invoke/field/ValueNullFreeNonAtomic.java @@ -0,0 +1,236 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.invoke.field; + +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class ValueNullFreeNonAtomic { + + /* + virtual method invocations: + target0 - statically known target method. + target1 - the single invoked method (should be inlined) + target2 - two invoked method (should be inlined, cache-inline) + target3 - thee invoked method (shouldn't be inlined) + + */ + + + public static final int SIZE = 128; + + public interface InterfaceInt { + public int value(); + } + + @LooselyConsistentValue + public static value class ValueInt0 implements InterfaceInt { + public final int value; + public ValueInt0(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @LooselyConsistentValue + public static value class ValueInt1 implements InterfaceInt { + public final int value; + public ValueInt1(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + @LooselyConsistentValue + public static value class ValueInt2 implements InterfaceInt { + public final int value; + public ValueInt2(int value) { + this.value = value; + } + @Override + public int value() { + return value; + } + } + + public static class IntWrapper { + final InterfaceInt f; + + public IntWrapper(InterfaceInt f) { + this.f = f; + } + } + + public static class ValWrapper { + @Strict + @NullRestricted + final ValueInt0 f; + + public ValWrapper(ValueInt0 f) { + this.f = f; + } + } + + @State(Scope.Thread) + public static class Int0State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt0(i)); + } + } + } + + @State(Scope.Thread) + public static class Int1State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt1(i)); + } + } + } + + @State(Scope.Thread) + public static class Int2State { + public IntWrapper[] arr; + @Setup + public void setup() { + arr = new IntWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IntWrapper(new ValueInt2(i)); + } + } + } + + @State(Scope.Thread) + public static class Ref0State { + public ValWrapper[] arr; + @Setup + public void setup() { + arr = new ValWrapper[SIZE]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValWrapper(new ValueInt0(i)); + } + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_int(IntWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int reduce_val(ValWrapper[] arr) { + int r = 0; + for (int i = 0; i < arr.length; i++) { + r += arr[i].f.value(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) { + return reduce_val(st0.arr) + + reduce_val(st1.arr) + + reduce_val(st2.arr) + + reduce_val(st3.arr) + + reduce_val(st4.arr) + + reduce_val(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target1(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + + @Benchmark + @OperationsPerInvocation(SIZE * 6) + @CompilerControl(CompilerControl.Mode.INLINE) + public int target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) { + return reduce_int(st0.arr) + + reduce_int(st1.arr) + + reduce_int(st2.arr) + + reduce_int(st3.arr) + + reduce_int(st4.arr) + + reduce_int(st5.arr); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/mandelbrot/Identity.java b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Identity.java new file mode 100644 index 00000000000..d8fbd7d7c08 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Identity.java @@ -0,0 +1,82 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.mandelbrot; + +import org.openjdk.jmh.annotations.Benchmark; + +public class Identity extends MandelbrotBase { + + @Benchmark + public int[][] mandelbrot() { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + points[x][y] = count(coordToComplex(x, y, size, size)); + } + } + return points; + } + + private IdentityComplex coordToComplex(int x, int y, int width, int height) { + double cx = ((double) x) / (((double) width) / 2.0) - 1.0; + double cy = ((double) y) / (((double) height) / 2.0) - 1.0; + return new IdentityComplex(cy * SCALE, cx * SCALE); + } + + private static int count(IdentityComplex c) { + IdentityComplex z = c; + for (int i = 1; i < MAX_ITER; i++) { + if (z.length() >= 2.0) return i; + z = z.mul(z).add(c); + } + return MAX_ITER; + } + + public static class IdentityComplex { + + public final double re; + public final double im; + + public IdentityComplex(double re, double im) { + this.re = re; + this.im = im; + } + + public double re() { return re; } + + public double im() { return im; } + + public IdentityComplex add(IdentityComplex that) { + return new IdentityComplex(this.re + that.re, this.im + that.im); + } + + public IdentityComplex mul(IdentityComplex that) { + return new IdentityComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + + public double length() { + return Math.sqrt(re * re + im * im); + } + + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/mandelbrot/MandelbrotBase.java b/test/micro/org/openjdk/bench/valhalla/mandelbrot/MandelbrotBase.java new file mode 100644 index 00000000000..39a7c93dec0 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/mandelbrot/MandelbrotBase.java @@ -0,0 +1,60 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.mandelbrot; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(3) +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.SECONDS) +@BenchmarkMode(Mode.Throughput) +@State(Scope.Thread) +public abstract class MandelbrotBase { + + @Param("500") + int size; + + public static final double SCALE = 2.0; + public static final int MAX_ITER = 400; + + int[][] points; // color points + + @Setup() + public void setup() { + points = new int[size][size]; + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/set/Primitive64.java b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Primitive.java similarity index 54% rename from test/micro/org/openjdk/bench/valhalla/array/set/Primitive64.java rename to test/micro/org/openjdk/bench/valhalla/mandelbrot/Primitive.java index 554b0dd90ed..6835316dd65 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/set/Primitive64.java +++ b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Primitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,30 +20,35 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.set; +package org.openjdk.bench.valhalla.mandelbrot; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -public class Primitive64 extends PrimitiveStates { +public class Primitive extends MandelbrotBase { @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void set0(Primitive64long st) { - long[] arr = st.arr; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; + public int[][] mandelbrot() { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + points[x][y] = count(x, y, size, size); + } } + return points; } - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void set1(Primitive64long st) { - int len = st.arr.length; - for (int i = 0; i < len; i++) { - st.arr[i] = i; + private int count(int x, int y, int width, int height) { + double cx = (((double) x) / (((double) width) / 2.0) - 1.0) * SCALE; + double cy = (((double) y) / (((double) height) / 2.0) - 1.0) * SCALE; + double zx = cx; + double zy = cy; + for (int i = 1; i < MAX_ITER; i++) { + if (Math.sqrt(zx * zx + zy * zy) >= 2.0) return i; + double tx = zx * zx - zy * zy + cx; + double ty = 2 * zx * zy + cy; + zx = tx; + zy = ty; } + return MAX_ITER; } } diff --git a/test/micro/org/openjdk/bench/valhalla/mandelbrot/Value.java b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Value.java new file mode 100644 index 00000000000..3abb5b1ac8c --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/mandelbrot/Value.java @@ -0,0 +1,130 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.mandelbrot; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value extends MandelbrotBase { + + private ValueComplex coordToComplex(int x, int y, int width, int height) { + double cx = ((double) x) / (((double) width) / 2.0) - 1.0; + double cy = ((double) y) / (((double) height) / 2.0) - 1.0; + return new ValueComplex(cy * SCALE, cx * SCALE); + } + + private static int count(ValueComplex c) { + ValueComplex z = c; + for (int i = 1; i < MAX_ITER; i++) { + if (z.length() >= 2.0) return i; + z = z.mul(z).add(c); + } + return MAX_ITER; + } + + @Benchmark + public int[][] mandelbrot_value() { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + points[x][y] = count(coordToComplex(x, y, size, size)); + } + } + return points; + } + + private Complex coordToComplex_interface(int x, int y, int width, int height) { + double cx = ((double) x) / (((double) width) / 2.0) - 1.0; + double cy = ((double) y) / (((double) height) / 2.0) - 1.0; + return new ValueComplex(cy * SCALE, cx * SCALE); + } + + private static int count_interface(Complex c) { + Complex z = c; + for (int i = 1; i < MAX_ITER; i++) { + if (z.length() >= 2.0) return i; + z = z.mul(z).add(c); + } + return MAX_ITER; + } + + @Benchmark + public int[][] mandelbrot_interface() { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + points[x][y] = count_interface(coordToComplex_interface(x, y, size, size)); + } + } + return points; + } + + public static interface Complex { + public Complex add(Complex that); + public Complex mul(Complex that); + public double length(); + public double re(); + public double im(); + } + + public static value class ValueComplex implements Complex { + + public final double re; + public final double im; + + public ValueComplex(double re, double im) { + this.re = re; + this.im = im; + } + + @Override + public double re() { return re; } + + @Override + public double im() { return im; } + + public ValueComplex add(ValueComplex that) { + return new ValueComplex(this.re + that.re, this.im + that.im); + } + + @Override + public Complex add(Complex that) { + return new ValueComplex(this.re + that.re(), this.im + that.im()); + } + + public ValueComplex mul(ValueComplex that) { + return new ValueComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + + @Override + public Complex mul(Complex that) { + return new ValueComplex(this.re * that.re() - this.im * that.im(), + this.re * that.im() + this.im * that.re()); + } + + public double length() { + return Math.sqrt(re * re + im * im); + } + + } +} diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/Identity.java b/test/micro/org/openjdk/bench/valhalla/matrix/Identity.java index 6eebde19823..96d119e9afd 100644 --- a/test/micro/org/openjdk/bench/valhalla/matrix/Identity.java +++ b/test/micro/org/openjdk/bench/valhalla/matrix/Identity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,86 +22,175 @@ */ package org.openjdk.bench.valhalla.matrix; -import org.openjdk.bench.valhalla.types.Complex; -import org.openjdk.bench.valhalla.types.RComplex; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Setup; import java.util.concurrent.ThreadLocalRandom; -public abstract class Identity extends Base { - public static final Complex IZERO = new RComplex(0,0); - public static final RComplex RZERO = new RComplex(0,0); +public class Identity extends MatrixBase { - private static void populate(Complex[][] m) { - int size = m.length; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - m[i][j] = new RComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); - } - } + public static IdentityComplex[][] create_matrix_ref(int size) { + return new IdentityComplex[size][size]; } - public static class Ref extends Identity { - RComplex[][] A; - RComplex[][] B; + public static Complex[][] create_matrix_int(int size) { + return new Complex[size][size]; + } - @Setup - public void setup() { - A = new RComplex[size][size]; - populate(A); - B = new RComplex[size][size]; - populate(B); - } + public static abstract class RefState extends SizeState { + IdentityComplex[][] A; + IdentityComplex[][] B; - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public RComplex[][] multiply() { - int size = A.length; - RComplex[][] R = new RComplex[size][size]; + static void populate(IdentityComplex[][] m) { + int size = m.length; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { - RComplex s = RZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; + m[i][j] = new IdentityComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); } } - return R; } } - public static class Int extends Identity { + public static abstract class IntState extends SizeState { Complex[][] A; Complex[][] B; + static void populate(Complex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new IdentityComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static class Ref_as_Ref extends RefState { @Setup public void setup() { - A = new Complex[size][size]; - populate(A); - B = new Complex[size][size]; - populate(B); + populate(A = create_matrix_ref(size)); + populate(B = create_matrix_ref(size)); } + } - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public Complex[][] multiply() { - int size = A.length; - Complex[][] R = new Complex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - Complex s = IZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; + public static class Ref_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_ref(size)); + populate(B = create_matrix_ref(size)); + } + } + + public static class Int_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_int(size)); + populate(B = create_matrix_int(size)); + } + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public IdentityComplex[][] mult_ref_as_ref(Ref_as_Ref st) { + IdentityComplex[][] A = st.A; + IdentityComplex[][] B = st.B; + int size = st.size; + IdentityComplex[][] R = create_matrix_ref(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + IdentityComplex s = new IdentityComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_ref_as_int(Ref_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_ref(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new IdentityComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_int_as_int(Int_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_int(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new IdentityComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); } + R[i][j] = s; } - return R; } + return R; + } + + public interface Complex { + double re(); + double im(); + Complex add(Complex that); + Complex mul(Complex that); + } + + public static class IdentityComplex implements Complex { + + private final double re; + private final double im; + + public IdentityComplex(double re, double im) { + this.re = re; + this.im = im; + } + + @Override + public double re() { return re; } + + @Override + public double im() { return im; } + + @Override + public IdentityComplex add(Complex that) { + return new IdentityComplex(this.re + that.re(), this.im + that.im()); + } + + public IdentityComplex add(IdentityComplex that) { + return new IdentityComplex(this.re + that.re, this.im + that.im); + } + + @Override + public IdentityComplex mul(Complex that) { + return new IdentityComplex(this.re * that.re() - this.im * that.im(), + this.re * that.im() + this.im * that.re()); + } + + public IdentityComplex mul(IdentityComplex that) { + return new IdentityComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + } } diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/Inline.java b/test/micro/org/openjdk/bench/valhalla/matrix/Inline.java deleted file mode 100644 index ad5dd80d288..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/matrix/Inline.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.matrix; - -import org.openjdk.bench.valhalla.types.Complex; -import org.openjdk.bench.valhalla.types.QComplex; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Setup; - -import java.util.concurrent.ThreadLocalRandom; - -public abstract class Inline extends Base { - - public static final Complex IZERO = new QComplex(0,0); - public static final QComplex VZERO = new QComplex(0,0); - public static final QComplex RZERO = new QComplex(0,0); - - private static void populate(Complex[][] m) { - int size = m.length; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - m[i][j] = new QComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); - } - } - } - -// public static class Ref extends Inline { -// -// } - - public static class Ref extends Inline { - QComplex[][] A; - QComplex[][] B; - - @Setup - public void setup() { - A = new QComplex[size][size]; - populate(A); - B = new QComplex[size][size]; - populate(B); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public QComplex[][] multiply() { - int size = A.length; - QComplex[][] R = new QComplex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - QComplex s = RZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; - } - } - return R; - } - -// @Benchmark -// public QComplex[][] multiplyCacheFriendly() { -// int size = A.length; -// QComplex[][] R = new QComplex[size][size]; -// for (int i = 0; i < size; i++) { -// for (int k = 0; k < size; k++) { -// QComplex aik = A[i][k]; -// for (int j = 0; j < size; j++) { -// R[i][j] = R[i][j].add(aik.mul(B[k][j])); -// } -// } -// } -// return R; -// } - - } - - public static class Val extends Inline { - QComplex[][] A; - QComplex[][] B; - - @Setup - public void setup() { - A = new QComplex[size][size]; - populate(A); - B = new QComplex[size][size]; - populate(B); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public QComplex[][] multiply() { - int size = A.length; - QComplex[][] R = new QComplex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - QComplex s = VZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; - } - } - return R; - } - -// @Benchmark -// public QComplex[][] multiplyCacheFriendly() { -// int size = A.length; -// QComplex[][] R = new QComplex[size][size]; -// for (int i = 0; i < size; i++) { -// for (int k = 0; k < size; k++) { -// QComplex aik = A[i][k]; -// for (int j = 0; j < size; j++) { -// R[i][j] = R[i][j].add(aik.mul(B[k][j])); -// } -// } -// } -// return R; -// } - - } - - public static class Int extends Inline { - Complex[][] A; - Complex[][] B; - - @Setup - public void setup() { - A = new Complex[size][size]; - populate(A); - B = new Complex[size][size]; - populate(B); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public Complex[][] multiply() { - int size = A.length; - Complex[][] R = new Complex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - Complex s = IZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; - } - } - return R; - } - } - - public static class ICov extends Inline { - Complex[][] A; - Complex[][] B; - - @Setup - public void setup() { - A = new QComplex[size][size]; - populate(A); - B = new QComplex[size][size]; - populate(B); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public Complex[][] multiply() { - int size = A.length; - Complex[][] R = new QComplex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - Complex s = IZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; - } - } - return R; - } - -// @Benchmark -// public Complex[][] multiplyCacheFriendly() { -// int size = A.length; -// Complex[][] R = new QComplex[size][size]; -// for (int i = 0; i < size; i++) { -// for (int k = 0; k < size; k++) { -// Complex aik = A[i][k]; -// for (int j = 0; j < size; j++) { -// R[i][j] = R[i][j].add(aik.mul(B[k][j])); -// } -// } -// } -// return R; -// } - - } - - public static class RCov extends Inline { - QComplex[][] A; - QComplex[][] B; - - @Setup - public void setup() { - A = new QComplex[size][size]; - populate(A); - B = new QComplex[size][size]; - populate(B); - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public QComplex[][] multiply() { - int size = A.length; - QComplex[][] R = new QComplex[size][size]; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - QComplex s = RZERO; - for (int k = 0; k < size; k++) { - s = s.add(A[i][k].mul(B[k][j])); - } - R[i][j] = s; - } - } - return R; - } - -// @Benchmark -// public Complex[][] multiplyCacheFriendly() { -// int size = A.length; -// Complex[][] R = new QComplex[size][size]; -// for (int i = 0; i < size; i++) { -// for (int k = 0; k < size; k++) { -// Complex aik = A[i][k]; -// for (int j = 0; j < size; j++) { -// R[i][j] = R[i][j].add(aik.mul(B[k][j])); -// } -// } -// } -// return R; -// } - - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/Base.java b/test/micro/org/openjdk/bench/valhalla/matrix/MatrixBase.java similarity index 83% rename from test/micro/org/openjdk/bench/valhalla/matrix/Base.java rename to test/micro/org/openjdk/bench/valhalla/matrix/MatrixBase.java index 2a1eb6f23f0..cbfb536b498 100644 --- a/test/micro/org/openjdk/bench/valhalla/matrix/Base.java +++ b/test/micro/org/openjdk/bench/valhalla/matrix/MatrixBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,18 +36,18 @@ @Fork(3) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Warmup(iterations = 3, time = 3) +@Warmup(iterations = 5, time = 3) @Measurement(iterations = 3, time = 8) @BenchmarkMode(Mode.AverageTime) -@State(Scope.Thread) -public class Base { +public class MatrixBase { - - @Param({ - "20", - "100", - "360", - }) - public int size; + @State(Scope.Thread) + public static abstract class SizeState { + @Param({ + "20", + "360", + }) + public int size; + } } diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/Primitive.java b/test/micro/org/openjdk/bench/valhalla/matrix/Primitive.java index 4d187972de5..743044e004f 100644 --- a/test/micro/org/openjdk/bench/valhalla/matrix/Primitive.java +++ b/test/micro/org/openjdk/bench/valhalla/matrix/Primitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -28,46 +28,51 @@ import java.util.concurrent.ThreadLocalRandom; -public class Primitive extends Base { +public class Primitive extends MatrixBase { - double[][] A; - double[][] B; + public static class PrimState extends SizeState { + double[][] A; + double[][] B; - @Setup - public void setup() { - A = populate(new double[size][size*2]); - B = populate(new double[size][size*2]); - } + @Setup + public void setup() { + A = populate(new double[size][size * 2]); + B = populate(new double[size][size * 2]); + } - private double[][] populate(double[][] m) { - int size = m.length; - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - m[i][j*2+0] = ThreadLocalRandom.current().nextDouble(); - m[i][j*2+1] = ThreadLocalRandom.current().nextDouble(); + private double[][] populate(double[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j * 2] = ThreadLocalRandom.current().nextDouble(); + m[i][j * 2 + 1] = ThreadLocalRandom.current().nextDouble(); + } } + return m; } - return m; + } @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public double[][] multiply() { - int size = A.length; + public double[][] multiply(PrimState st) { + double[][] A = st.A; + double[][] B = st.B; + int size = st.size; double[][] R = new double[size][size * 2]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { double s_re = 0; double s_im = 0; for (int k = 0; k < size; k++) { - double are = A[i][k * 2 + 0]; + double are = A[i][k * 2]; double aim = A[i][k * 2 + 1]; - double bre = B[k][j * 2 + 0]; + double bre = B[k][j * 2]; double bim = B[k][j * 2 + 1]; s_re += are * bre - aim * bim; s_im += are * bim + bre * aim; } - R[i][j * 2 + 0] = s_re; + R[i][j * 2] = s_re; R[i][j * 2 + 1] = s_im; } } diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/Value.java b/test/micro/org/openjdk/bench/valhalla/matrix/Value.java new file mode 100644 index 00000000000..fbc37ee1212 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/matrix/Value.java @@ -0,0 +1,197 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.matrix; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +import java.util.concurrent.ThreadLocalRandom; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value extends MatrixBase { + + public static ValueComplex[][] create_matrix_val(int size) { + return new ValueComplex[size][size]; + } + + public static Complex[][] create_matrix_int(int size) { + return new Complex[size][size]; + } + + public static abstract class ValState extends SizeState { + ValueComplex[][] A; + ValueComplex[][] B; + + static void populate(ValueComplex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static abstract class IntState extends SizeState { + Complex[][] A; + Complex[][] B; + + static void populate(Complex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static class Val_as_Val extends ValState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Val_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Int_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_int(size)); + populate(B = create_matrix_int(size)); + } + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueComplex[][] mult_val_as_val(Val_as_Val st) { + ValueComplex[][] A = st.A; + ValueComplex[][] B = st.B; + int size = st.size; + ValueComplex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + ValueComplex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_val_as_int(Val_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_int_as_int(Int_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_int(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + public interface Complex { + double re(); + double im(); + Complex add(Complex that); + Complex mul(Complex that); + } + + public static value class ValueComplex implements Complex { + + private final double re; + private final double im; + + public ValueComplex(double re, double im) { + this.re = re; + this.im = im; + } + + @Override + public double re() { return re; } + + @Override + public double im() { return im; } + + @Override + public ValueComplex add(Complex that) { + return new ValueComplex(this.re + that.re(), this.im + that.im()); + } + + public ValueComplex add(ValueComplex that) { + return new ValueComplex(this.re + that.re, this.im + that.im); + } + + @Override + public ValueComplex mul(Complex that) { + return new ValueComplex(this.re * that.re() - this.im * that.im(), + this.re * that.im() + this.im * that.re()); + } + + public ValueComplex mul(ValueComplex that) { + return new ValueComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFree.java b/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFree.java new file mode 100644 index 00000000000..5d484035f20 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFree.java @@ -0,0 +1,204 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.matrix; + +import jdk.internal.value.ValueClass; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +import java.util.concurrent.ThreadLocalRandom; + + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueNullFree extends MatrixBase { + + public static ValueComplex[][] create_matrix_val(int size) { + ValueComplex[][] x; + x = new ValueComplex[size][]; + for (int i = 0; i < size; i++) { + x[i] = (ValueComplex[]) ValueClass.newNullRestrictedAtomicArray(ValueComplex.class, size, new ValueComplex(0, 0)); + } + return x; + } + + public static Complex[][] create_matrix_int(int size) { + return new Complex[size][size]; + } + + public static abstract class ValState extends SizeState { + ValueComplex[][] A; + ValueComplex[][] B; + + static void populate(ValueComplex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static abstract class IntState extends SizeState { + Complex[][] A; + Complex[][] B; + + static void populate(Complex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static class Val_as_Val extends ValState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Val_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Int_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_int(size)); + populate(B = create_matrix_int(size)); + } + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueComplex[][] mult_val_as_val(Val_as_Val st) { + ValueComplex[][] A = st.A; + ValueComplex[][] B = st.B; + int size = st.size; + ValueComplex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + ValueComplex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_val_as_int(Val_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_int_as_int(Int_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_int(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + public interface Complex { + double re(); + double im(); + Complex add(Complex that); + Complex mul(Complex that); + } + + public static value class ValueComplex implements Complex { + + private final double re; + private final double im; + + public ValueComplex(double re, double im) { + this.re = re; + this.im = im; + } + + @Override + public double re() { return re; } + + @Override + public double im() { return im; } + + @Override + public ValueComplex add(Complex that) { + return new ValueComplex(this.re + that.re(), this.im + that.im()); + } + + public ValueComplex add(ValueComplex that) { + return new ValueComplex(this.re + that.re, this.im + that.im); + } + + @Override + public ValueComplex mul(Complex that) { + return new ValueComplex(this.re * that.re() - this.im * that.im(), + this.re * that.im() + this.im * that.re()); + } + + public ValueComplex mul(ValueComplex that) { + return new ValueComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFreeNonAtomic.java new file mode 100644 index 00000000000..513765822df --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/matrix/ValueNullFreeNonAtomic.java @@ -0,0 +1,206 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.matrix; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +import java.util.concurrent.ThreadLocalRandom; + + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueNullFreeNonAtomic extends MatrixBase { + + public static ValueComplex[][] create_matrix_val(int size) { + ValueComplex[][] x; + x = new ValueComplex[size][]; + for (int i = 0; i < size; i++) { + x[i] = (ValueComplex[]) ValueClass.newNullRestrictedNonAtomicArray(ValueComplex.class, size, new ValueComplex(0, 0)); + } + return x; + } + + public static Complex[][] create_matrix_int(int size) { + return new Complex[size][size]; + } + + public static abstract class ValState extends SizeState { + ValueComplex[][] A; + ValueComplex[][] B; + + static void populate(ValueComplex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static abstract class IntState extends SizeState { + Complex[][] A; + Complex[][] B; + + static void populate(Complex[][] m) { + int size = m.length; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = new ValueComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble()); + } + } + } + } + + public static class Val_as_Val extends ValState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Val_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_val(size)); + populate(B = create_matrix_val(size)); + } + } + + public static class Int_as_Int extends IntState { + @Setup + public void setup() { + populate(A = create_matrix_int(size)); + populate(B = create_matrix_int(size)); + } + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public ValueComplex[][] mult_val_as_val(Val_as_Val st) { + ValueComplex[][] A = st.A; + ValueComplex[][] B = st.B; + int size = st.size; + ValueComplex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + ValueComplex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_val_as_int(Val_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_val(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Complex[][] mult_int_as_int(Int_as_Int st) { + Complex[][] A = st.A; + Complex[][] B = st.B; + int size = st.size; + Complex[][] R = create_matrix_int(size); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + Complex s = new ValueComplex(0,0); + for (int k = 0; k < size; k++) { + s = s.add(A[i][k].mul(B[k][j])); + } + R[i][j] = s; + } + } + return R; + } + + public interface Complex { + double re(); + double im(); + Complex add(Complex that); + Complex mul(Complex that); + } + + @LooselyConsistentValue + public static value class ValueComplex implements Complex { + + private final double re; + private final double im; + + public ValueComplex(double re, double im) { + this.re = re; + this.im = im; + } + + @Override + public double re() { return re; } + + @Override + public double im() { return im; } + + @Override + public ValueComplex add(Complex that) { + return new ValueComplex(this.re + that.re(), this.im + that.im()); + } + + public ValueComplex add(ValueComplex that) { + return new ValueComplex(this.re + that.re, this.im + that.im); + } + + @Override + public ValueComplex mul(Complex that) { + return new ValueComplex(this.re * that.re() - this.im * that.im(), + this.re * that.im() + this.im * that.re()); + } + + public ValueComplex mul(ValueComplex that) { + return new ValueComplex(this.re * that.re - this.im * that.im, + this.re * that.im + this.im * that.re); + } + + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/sum/Identity.java b/test/micro/org/openjdk/bench/valhalla/sum/Identity.java new file mode 100644 index 00000000000..3c574668b63 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/sum/Identity.java @@ -0,0 +1,440 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.sum; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; + +public class Identity extends SumBase { + + public interface InterfaceSum { + public int sum(); + } + + public static class IdentityInt implements InterfaceSum { + public final int v0; + public IdentityInt(int value) { + this.v0 = value; + } + public int sum() { + return v0; + } + } + + public static class IdentityInt2_w2_d0 implements InterfaceSum { + public final int v0, v1; + + public IdentityInt2_w2_d0(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int sum() { + return v0 + v1; + } + } + + public static class IdentityInt2_w2_d1 implements InterfaceSum { + public final IdentityInt v0, v1; + + public IdentityInt2_w2_d1(IdentityInt v0, IdentityInt v1) { + this.v0 = v0; + this.v1 = v1; + } + + public IdentityInt2_w2_d1(int v0, int v1) { + this(new IdentityInt(v0), new IdentityInt(v1)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static class IdentityInt4_w4_d0 implements InterfaceSum { + public final int v0, v1, v2, v3; + + public IdentityInt4_w4_d0(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int sum() { + return v0 + v1 + v2 + v3; + } + } + + public static class IdentityInt4_w4_d1 implements InterfaceSum { + public final IdentityInt v0, v1, v2, v3; + + public IdentityInt4_w4_d1(IdentityInt v0, IdentityInt v1, IdentityInt v2, IdentityInt v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public IdentityInt4_w4_d1(int v0, int v1, int v2, int v3) { + this(new IdentityInt(v0), new IdentityInt(v1), new IdentityInt(v2), new IdentityInt(v3)); + } + + public int sum() { + return v0.sum() + v1.sum() + v2.sum() + v3.sum(); + } + } + + public static class IdentityInt4_w2_d1 implements InterfaceSum { + public final IdentityInt2_w2_d0 v0, v1; + + public IdentityInt4_w2_d1(IdentityInt2_w2_d0 v0, IdentityInt2_w2_d0 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public IdentityInt4_w2_d1(int v0, int v1, int v2, int v3) { + this(new IdentityInt2_w2_d0(v0, v1), new IdentityInt2_w2_d0(v2, v3)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static class IdentityInt4_w2_d2 implements InterfaceSum { + + public final IdentityInt2_w2_d1 v0, v1; + + public IdentityInt4_w2_d2(IdentityInt2_w2_d1 v0, IdentityInt2_w2_d1 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public IdentityInt4_w2_d2(int v0, int v1, int v2, int v3) { + this(new IdentityInt2_w2_d1(v0, v1), new IdentityInt2_w2_d1(v2, v3)); + } + public int sum() { + return v0.sum() + v1.sum(); + } + + } + + public static class RefState_of_Int extends SizeState { + public IdentityInt[] arr; + @Setup + public void setup() { + arr = new IdentityInt[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + public static class IntState_of_Int extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt(i); + } + } + } + + public static class RefState_of_Int2_w2_d0 extends SizeState { + public IdentityInt2_w2_d0[] arr; + @Setup + public void setup() { + arr = new IdentityInt2_w2_d0[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class RefState_of_Int2_w2_d1 extends SizeState { + public IdentityInt2_w2_d1[] arr; + @Setup + public void setup() { + arr = new IdentityInt2_w2_d1[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class RefState_of_Int4_w4_d0 extends SizeState { + public IdentityInt4_w4_d0[] arr; + @Setup + public void setup() { + arr = new IdentityInt4_w4_d0[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class RefState_of_Int4_w4_d1 extends SizeState { + public IdentityInt4_w4_d1[] arr; + @Setup + public void setup() { + arr = new IdentityInt4_w4_d1[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class RefState_of_Int4_w2_d1 extends SizeState { + public IdentityInt4_w2_d1[] arr; + @Setup + public void setup() { + arr = new IdentityInt4_w2_d1[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class RefState_of_Int4_w2_d2 extends SizeState { + public IdentityInt4_w2_d2[] arr; + @Setup + public void setup() { + arr = new IdentityInt4_w2_d2[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d2 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new IdentityInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_interface(InterfaceSum[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int(IdentityInt[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int2_w2_d0(IdentityInt2_w2_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int2_w2_d1(IdentityInt2_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int4_w4_d0(IdentityInt4_w4_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int4_w4_d1(IdentityInt4_w4_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int4_w2_d1(IdentityInt4_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_ref_of_Int4_w2_d2(IdentityInt4_w2_d2[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @Benchmark + public int sum_interface_of_Int(IntState_of_Int st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d0(IntState_of_Int2_w2_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d1(IntState_of_Int2_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d0(IntState_of_Int4_w4_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d1(IntState_of_Int4_w4_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d1(IntState_of_Int4_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d2(IntState_of_Int4_w2_d2 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_ref_of_Int(RefState_of_Int st) { + return sum_ref_of_Int(st.arr); + } + + @Benchmark + public int sum_ref_of_Int2_w2_d0(RefState_of_Int2_w2_d0 st) { + return sum_ref_of_Int2_w2_d0(st.arr); + } + + @Benchmark + public int sum_ref_of_Int2_w2_d1(RefState_of_Int2_w2_d1 st) { + return sum_ref_of_Int2_w2_d1(st.arr); + } + + @Benchmark + public int sum_ref_of_Int4_w4_d0(RefState_of_Int4_w4_d0 st) { + return sum_ref_of_Int4_w4_d0(st.arr); + } + + @Benchmark + public int sum_ref_of_Int4_w4_d1(RefState_of_Int4_w4_d1 st) { + return sum_ref_of_Int4_w4_d1(st.arr); + } + + @Benchmark + public int sum_ref_of_Int4_w2_d1(RefState_of_Int4_w2_d1 st) { + return sum_ref_of_Int4_w2_d1(st.arr); + } + + @Benchmark + public int sum_ref_of_Int4_w2_d2(RefState_of_Int4_w2_d2 st) { + return sum_ref_of_Int4_w2_d2(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64int.java b/test/micro/org/openjdk/bench/valhalla/sum/Primitive.java similarity index 65% rename from test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64int.java rename to test/micro/org/openjdk/bench/valhalla/sum/Primitive.java index 531ed2a93ff..bc7d6105a8c 100644 --- a/test/micro/org/openjdk/bench/valhalla/array/sum/Primitive64int.java +++ b/test/micro/org/openjdk/bench/valhalla/sum/Primitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,23 +20,38 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.array.sum; +package org.openjdk.bench.valhalla.sum; -import org.openjdk.bench.valhalla.array.util.PrimitiveStates; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Setup; -public class Primitive64int extends PrimitiveStates { +public class Primitive extends SumBase { + + public static class PrimitiveState extends SizeState { + public int[] arr; + + @Setup + public void setup() { + arr = new int[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + } - @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int sum(Primitive64int st) { + private static int sum_primitive(int[] src) { int s = 0; - int[] values = st.arr; - for (int i = 0; i < values.length; i++) { - s += values[i]; + for (int v : src) { + s += v; } return s; } + @Benchmark + public void sum(PrimitiveState st) { + sum_primitive(st.arr); + } + } diff --git a/test/micro/org/openjdk/bench/valhalla/util/SizeBase.java b/test/micro/org/openjdk/bench/valhalla/sum/SumBase.java similarity index 93% rename from test/micro/org/openjdk/bench/valhalla/util/SizeBase.java rename to test/micro/org/openjdk/bench/valhalla/sum/SumBase.java index 11d518f9707..79496c08244 100644 --- a/test/micro/org/openjdk/bench/valhalla/util/SizeBase.java +++ b/test/micro/org/openjdk/bench/valhalla/sum/SumBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,8 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.valhalla.util; +package org.openjdk.bench.valhalla.sum; + import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -39,7 +40,7 @@ @Measurement(iterations = 5, time = 1) @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) -public class SizeBase { +public class SumBase { @State(Scope.Thread) public static abstract class SizeState { diff --git a/test/micro/org/openjdk/bench/valhalla/sum/Value.java b/test/micro/org/openjdk/bench/valhalla/sum/Value.java new file mode 100644 index 00000000000..00695288710 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/sum/Value.java @@ -0,0 +1,442 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.sum; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) +public class Value extends SumBase { + + public interface InterfaceSum { + public int sum(); + } + + public static value class ValueInt implements InterfaceSum { + public final int v0; + public ValueInt(int value) { + this.v0 = value; + } + public int sum() { + return v0; + } + } + + public static value class ValueInt2_w2_d0 implements InterfaceSum { + public final int v0, v1; + + public ValueInt2_w2_d0(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int sum() { + return v0 + v1; + } + } + + public static value class ValueInt2_w2_d1 implements InterfaceSum { + public final ValueInt v0, v1; + + public ValueInt2_w2_d1(ValueInt v0, ValueInt v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt2_w2_d1(int v0, int v1) { + this(new ValueInt(v0), new ValueInt(v1)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static value class ValueInt4_w4_d0 implements InterfaceSum { + public final int v0, v1, v2, v3; + + public ValueInt4_w4_d0(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int sum() { + return v0 + v1 + v2 + v3; + } + } + + public static value class ValueInt4_w4_d1 implements InterfaceSum { + public final ValueInt v0, v1, v2, v3; + + public ValueInt4_w4_d1(ValueInt v0, ValueInt v1, ValueInt v2, ValueInt v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public ValueInt4_w4_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt(v0), new ValueInt(v1), new ValueInt(v2), new ValueInt(v3)); + } + + public int sum() { + return v0.sum() + v1.sum() + v2.sum() + v3.sum(); + } + } + + public static value class ValueInt4_w2_d1 implements InterfaceSum { + public final ValueInt2_w2_d0 v0, v1; + + public ValueInt4_w2_d1(ValueInt2_w2_d0 v0, ValueInt2_w2_d0 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d0(v0, v1), new ValueInt2_w2_d0(v2, v3)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static value class ValueInt4_w2_d2 implements InterfaceSum { + + public final ValueInt2_w2_d1 v0, v1; + + public ValueInt4_w2_d2(ValueInt2_w2_d1 v0, ValueInt2_w2_d1 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d2(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d1(v0, v1), new ValueInt2_w2_d1(v2, v3)); + } + public int sum() { + return v0.sum() + v1.sum(); + } + + } + + public static class ValState_of_Int extends SizeState { + public ValueInt[] arr; + @Setup + public void setup() { + arr = new ValueInt[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState_of_Int extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class ValState_of_Int2_w2_d0 extends SizeState { + public ValueInt2_w2_d0[] arr; + @Setup + public void setup() { + arr = new ValueInt2_w2_d0[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int2_w2_d1 extends SizeState { + public ValueInt2_w2_d1[] arr; + @Setup + public void setup() { + arr = new ValueInt2_w2_d1[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int4_w4_d0 extends SizeState { + public ValueInt4_w4_d0[] arr; + @Setup + public void setup() { + arr = new ValueInt4_w4_d0[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w4_d1 extends SizeState { + public ValueInt4_w4_d1[] arr; + @Setup + public void setup() { + arr = new ValueInt4_w4_d1[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d1 extends SizeState { + public ValueInt4_w2_d1[] arr; + @Setup + public void setup() { + arr = new ValueInt4_w2_d1[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d2 extends SizeState { + public ValueInt4_w2_d2[] arr; + @Setup + public void setup() { + arr = new ValueInt4_w2_d2[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d2 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_interface(InterfaceSum[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int(ValueInt[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d0(ValueInt2_w2_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d1(ValueInt2_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d0(ValueInt4_w4_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d1(ValueInt4_w4_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d1(ValueInt4_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d2(ValueInt4_w2_d2[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @Benchmark + public int sum_interface_of_Int(IntState_of_Int st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d0(IntState_of_Int2_w2_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d1(IntState_of_Int2_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d0(IntState_of_Int4_w4_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d1(IntState_of_Int4_w4_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d1(IntState_of_Int4_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d2(IntState_of_Int4_w2_d2 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_val_of_Int(ValState_of_Int st) { + return sum_val_of_Int(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d0(ValState_of_Int2_w2_d0 st) { + return sum_val_of_Int2_w2_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d1(ValState_of_Int2_w2_d1 st) { + return sum_val_of_Int2_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d0(ValState_of_Int4_w4_d0 st) { + return sum_val_of_Int4_w4_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d1(ValState_of_Int4_w4_d1 st) { + return sum_val_of_Int4_w4_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d1(ValState_of_Int4_w2_d1 st) { + return sum_val_of_Int4_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d2(ValState_of_Int4_w2_d2 st) { + return sum_val_of_Int4_w2_d2(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFree.java b/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFree.java new file mode 100644 index 00000000000..7b0f64f691c --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFree.java @@ -0,0 +1,452 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.sum; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueNullFree extends SumBase { + + public interface InterfaceSum { + public int sum(); + } + + public static value class ValueInt implements InterfaceSum { + public final int v0; + public ValueInt(int value) { + this.v0 = value; + } + public int sum() { + return v0; + } + } + + public static value class ValueInt2_w2_d0 implements InterfaceSum { + public final int v0, v1; + + public ValueInt2_w2_d0(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int sum() { + return v0 + v1; + } + } + + public static value class ValueInt2_w2_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt v0, v1; + + public ValueInt2_w2_d1(ValueInt v0, ValueInt v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt2_w2_d1(int v0, int v1) { + this(new ValueInt(v0), new ValueInt(v1)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static value class ValueInt4_w4_d0 implements InterfaceSum { + public final int v0, v1, v2, v3; + + public ValueInt4_w4_d0(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int sum() { + return v0 + v1 + v2 + v3; + } + } + + public static value class ValueInt4_w4_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt v0, v1, v2, v3; + + public ValueInt4_w4_d1(ValueInt v0, ValueInt v1, ValueInt v2, ValueInt v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public ValueInt4_w4_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt(v0), new ValueInt(v1), new ValueInt(v2), new ValueInt(v3)); + } + + public int sum() { + return v0.sum() + v1.sum() + v2.sum() + v3.sum(); + } + } + + public static value class ValueInt4_w2_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt2_w2_d0 v0, v1; + + public ValueInt4_w2_d1(ValueInt2_w2_d0 v0, ValueInt2_w2_d0 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d0(v0, v1), new ValueInt2_w2_d0(v2, v3)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + public static value class ValueInt4_w2_d2 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt2_w2_d1 v0, v1; + + public ValueInt4_w2_d2(ValueInt2_w2_d1 v0, ValueInt2_w2_d1 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d2(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d1(v0, v1), new ValueInt2_w2_d1(v2, v3)); + } + public int sum() { + return v0.sum() + v1.sum(); + } + + } + + public static class ValState_of_Int extends SizeState { + public ValueInt[] arr; + @Setup + public void setup() { + arr = (ValueInt[])ValueClass.newNullRestrictedAtomicArray(ValueInt.class, size * 4, new ValueInt(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState_of_Int extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class ValState_of_Int2_w2_d0 extends SizeState { + public ValueInt2_w2_d0[] arr; + @Setup + public void setup() { + arr = (ValueInt2_w2_d0[])ValueClass.newNullRestrictedAtomicArray(ValueInt2_w2_d0.class, size * 2, new ValueInt2_w2_d0(0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int2_w2_d1 extends SizeState { + public ValueInt2_w2_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt2_w2_d1[])ValueClass.newNullRestrictedAtomicArray(ValueInt2_w2_d1.class, size * 4, new ValueInt2_w2_d1(0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int4_w4_d0 extends SizeState { + public ValueInt4_w4_d0[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w4_d0[])ValueClass.newNullRestrictedAtomicArray(ValueInt4_w4_d0.class, size, new ValueInt4_w4_d0(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w4_d1 extends SizeState { + public ValueInt4_w4_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w4_d1[])ValueClass.newNullRestrictedAtomicArray(ValueInt4_w4_d1.class, size, new ValueInt4_w4_d1(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d1 extends SizeState { + public ValueInt4_w2_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w2_d1[])ValueClass.newNullRestrictedAtomicArray(ValueInt4_w2_d1.class, size, new ValueInt4_w2_d1(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d2 extends SizeState { + public ValueInt4_w2_d2[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w2_d2[])ValueClass.newNullRestrictedAtomicArray(ValueInt4_w2_d2.class, size, new ValueInt4_w2_d2(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d2 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_interface(InterfaceSum[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int(ValueInt[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d0(ValueInt2_w2_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d1(ValueInt2_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d0(ValueInt4_w4_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d1(ValueInt4_w4_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d1(ValueInt4_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d2(ValueInt4_w2_d2[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @Benchmark + public int sum_interface_of_Int(IntState_of_Int st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d0(IntState_of_Int2_w2_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d1(IntState_of_Int2_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d0(IntState_of_Int4_w4_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d1(IntState_of_Int4_w4_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d1(IntState_of_Int4_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d2(IntState_of_Int4_w2_d2 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_val_of_Int(ValState_of_Int st) { + return sum_val_of_Int(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d0(ValState_of_Int2_w2_d0 st) { + return sum_val_of_Int2_w2_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d1(ValState_of_Int2_w2_d1 st) { + return sum_val_of_Int2_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d0(ValState_of_Int4_w4_d0 st) { + return sum_val_of_Int4_w4_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d1(ValState_of_Int4_w4_d1 st) { + return sum_val_of_Int4_w4_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d1(ValState_of_Int4_w2_d1 st) { + return sum_val_of_Int4_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d2(ValState_of_Int4_w2_d2 st) { + return sum_val_of_Int4_w2_d2(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFreeNonAtomic.java b/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFreeNonAtomic.java new file mode 100644 index 00000000000..7d70516da6a --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/sum/ValueNullFreeNonAtomic.java @@ -0,0 +1,460 @@ +/* + * 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. + * + * 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. + */ +package org.openjdk.bench.valhalla.sum; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import jdk.internal.vm.annotation.Strict; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Setup; + +@Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"}) +public class ValueNullFreeNonAtomic extends SumBase { + + public interface InterfaceSum { + public int sum(); + } + + @LooselyConsistentValue + public static value class ValueInt implements InterfaceSum { + public final int v0; + public ValueInt(int value) { + this.v0 = value; + } + public int sum() { + return v0; + } + } + + @LooselyConsistentValue + public static value class ValueInt2_w2_d0 implements InterfaceSum { + public final int v0, v1; + + public ValueInt2_w2_d0(int v0, int v1) { + this.v0 = v0; + this.v1 = v1; + } + + public int sum() { + return v0 + v1; + } + } + + @LooselyConsistentValue + public static value class ValueInt2_w2_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt v0, v1; + + public ValueInt2_w2_d1(ValueInt v0, ValueInt v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt2_w2_d1(int v0, int v1) { + this(new ValueInt(v0), new ValueInt(v1)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + @LooselyConsistentValue + public static value class ValueInt4_w4_d0 implements InterfaceSum { + public final int v0, v1, v2, v3; + + public ValueInt4_w4_d0(int v0, int v1, int v2, int v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public int sum() { + return v0 + v1 + v2 + v3; + } + } + + @LooselyConsistentValue + public static value class ValueInt4_w4_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt v0, v1, v2, v3; + + public ValueInt4_w4_d1(ValueInt v0, ValueInt v1, ValueInt v2, ValueInt v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + public ValueInt4_w4_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt(v0), new ValueInt(v1), new ValueInt(v2), new ValueInt(v3)); + } + + public int sum() { + return v0.sum() + v1.sum() + v2.sum() + v3.sum(); + } + } + + @LooselyConsistentValue + public static value class ValueInt4_w2_d1 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt2_w2_d0 v0, v1; + + public ValueInt4_w2_d1(ValueInt2_w2_d0 v0, ValueInt2_w2_d0 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d1(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d0(v0, v1), new ValueInt2_w2_d0(v2, v3)); + } + + public int sum() { + return v0.sum() + v1.sum(); + } + } + + @LooselyConsistentValue + public static value class ValueInt4_w2_d2 implements InterfaceSum { + @Strict + @NullRestricted + public final ValueInt2_w2_d1 v0, v1; + + public ValueInt4_w2_d2(ValueInt2_w2_d1 v0, ValueInt2_w2_d1 v1) { + this.v0 = v0; + this.v1 = v1; + } + + public ValueInt4_w2_d2(int v0, int v1, int v2, int v3) { + this(new ValueInt2_w2_d1(v0, v1), new ValueInt2_w2_d1(v2, v3)); + } + public int sum() { + return v0.sum() + v1.sum(); + } + + } + + public static class ValState_of_Int extends SizeState { + public ValueInt[] arr; + @Setup + public void setup() { + arr = (ValueInt[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt.class, size * 4, new ValueInt(0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class IntState_of_Int extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 4]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt(i); + } + } + } + + public static class ValState_of_Int2_w2_d0 extends SizeState { + public ValueInt2_w2_d0[] arr; + @Setup + public void setup() { + arr = (ValueInt2_w2_d0[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt2_w2_d0.class, size * 2, new ValueInt2_w2_d0(0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d0(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int2_w2_d1 extends SizeState { + public ValueInt2_w2_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt2_w2_d1[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt2_w2_d1.class, size * 4, new ValueInt2_w2_d1(0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class IntState_of_Int2_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size * 2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt2_w2_d1(2 * i, 2 * i + 1); + } + } + } + + public static class ValState_of_Int4_w4_d0 extends SizeState { + public ValueInt4_w4_d0[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w4_d0[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt4_w4_d0.class, size, new ValueInt4_w4_d0(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d0 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d0(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w4_d1 extends SizeState { + public ValueInt4_w4_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w4_d1[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt4_w4_d1.class, size, new ValueInt4_w4_d1(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w4_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w4_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d1 extends SizeState { + public ValueInt4_w2_d1[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w2_d1[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt4_w2_d1.class, size, new ValueInt4_w2_d1(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d1 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d1(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class ValState_of_Int4_w2_d2 extends SizeState { + public ValueInt4_w2_d2[] arr; + @Setup + public void setup() { + arr = (ValueInt4_w2_d2[])ValueClass.newNullRestrictedNonAtomicArray(ValueInt4_w2_d2.class, size, new ValueInt4_w2_d2(0, 0, 0, 0)); + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + public static class IntState_of_Int4_w2_d2 extends SizeState { + public InterfaceSum[] arr; + @Setup + public void setup() { + arr = new InterfaceSum[size]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new ValueInt4_w2_d2(4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3); + } + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_interface(InterfaceSum[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int(ValueInt[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d0(ValueInt2_w2_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int2_w2_d1(ValueInt2_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d0(ValueInt4_w4_d0[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w4_d1(ValueInt4_w4_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d1(ValueInt4_w2_d1[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int sum_val_of_Int4_w2_d2(ValueInt4_w2_d2[] src) { + int s = 0; + for (var v : src) { + s += v.sum(); + } + return s; + } + + @Benchmark + public int sum_interface_of_Int(IntState_of_Int st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d0(IntState_of_Int2_w2_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int2_w2_d1(IntState_of_Int2_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d0(IntState_of_Int4_w4_d0 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w4_d1(IntState_of_Int4_w4_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d1(IntState_of_Int4_w2_d1 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_interface_of_Int4_w2_d2(IntState_of_Int4_w2_d2 st) { + return sum_interface(st.arr); + } + + @Benchmark + public int sum_val_of_Int(ValState_of_Int st) { + return sum_val_of_Int(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d0(ValState_of_Int2_w2_d0 st) { + return sum_val_of_Int2_w2_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int2_w2_d1(ValState_of_Int2_w2_d1 st) { + return sum_val_of_Int2_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d0(ValState_of_Int4_w4_d0 st) { + return sum_val_of_Int4_w4_d0(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w4_d1(ValState_of_Int4_w4_d1 st) { + return sum_val_of_Int4_w4_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d1(ValState_of_Int4_w2_d1 st) { + return sum_val_of_Int4_w2_d1(st.arr); + } + + @Benchmark + public int sum_val_of_Int4_w2_d2(ValState_of_Int4_w2_d2 st) { + return sum_val_of_Int4_w2_d2(st.arr); + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Identity64.java b/test/micro/org/openjdk/bench/valhalla/traversal/Identity64.java deleted file mode 100644 index ef0eb1d0fde..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Identity64.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.traversal; - -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.types.A64long; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.R64long; -import org.openjdk.bench.valhalla.util.Utils; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Setup; - -public class Identity64 extends SizeBase { - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new R64long(a[i]); - } - } - } - - public static abstract class AbsState extends SizeState { - public A64long[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new R64long(a[i]); - } - } - } - - public static abstract class RefState extends SizeState { - public R64long[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new R64long(a[i]); - } - } - } - - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Abs_as_Int extends IntState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Abs_as_Abs extends AbsState { - @Setup - public void setup() { - arr = new A64long[size]; - fill(); - } - } - - public static class Ref_as_Abs extends AbsState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new R64long[size]; - fill(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_walk(Int_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Abs_as_Int_walk(Abs_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Int_walk(Ref_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Abs_as_Abs_walk(Abs_as_Abs s) { - int steps = 0; - A64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Abs_walk(Ref_as_Abs s) { - int steps = 0; - A64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_walk(Ref_as_Ref s) { - int steps = 0; - A64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Inline32.java b/test/micro/org/openjdk/bench/valhalla/traversal/Inline32.java deleted file mode 100644 index 749b527d919..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Inline32.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.traversal; - -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.types.Int32; -import org.openjdk.bench.valhalla.types.Q32int; -import org.openjdk.bench.valhalla.util.Utils; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Setup; - -public class Inline32 extends SizeBase { - - public static abstract class IntState extends SizeState { - public Int32[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q32int(a[i]); - } - } - } - - public static abstract class RefState extends SizeState { - public Q32int[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q32int(a[i]); - } - } - } - - public static abstract class ValState extends SizeState { - public Q32int[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q32int(a[i]); - } - } - } - - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int32[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q32int[size]; - fill(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_walk(Int_as_Int s) { - int steps = 0; - Int32[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_walk(Ref_as_Ref s) { - int steps = 0; - Q32int[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_walk(Val_as_Val s) { - int steps = 0; - Q32int[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/traversal/Inline64.java b/test/micro/org/openjdk/bench/valhalla/traversal/Inline64.java deleted file mode 100644 index 6c889450295..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/traversal/Inline64.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.traversal; - -import org.openjdk.bench.valhalla.util.SizeBase; -import org.openjdk.bench.valhalla.types.Int64; -import org.openjdk.bench.valhalla.types.Q64long; -import org.openjdk.bench.valhalla.util.Utils; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Setup; - -public class Inline64 extends SizeBase { - - public static abstract class IntState extends SizeState { - public Int64[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q64long(a[i]); - } - } - } - - public static abstract class RefState extends SizeState { - public Q64long[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q64long(a[i]); - } - } - } - - public static abstract class ValState extends SizeState { - public Q64long[] arr; - void fill() { - int[] a = Utils.makeRandomRing(arr.length); - for (int i = 0; i < a.length; i++) { - arr[i] = new Q64long(a[i]); - } - } - } - - - public static class Int_as_Int extends IntState { - @Setup - public void setup() { - arr = new Int64[size]; - fill(); - } - } - - public static class Ref_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Int extends IntState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Ref_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Ref extends RefState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - public static class Val_as_Val extends ValState { - @Setup - public void setup() { - arr = new Q64long[size]; - fill(); - } - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Int_as_Int_walk(Int_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Int_walk(Ref_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Int_walk(Val_as_Int s) { - int steps = 0; - Int64[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Ref_as_Ref_walk(Ref_as_Ref s) { - int steps = 0; - Q64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Ref_walk(Val_as_Ref s) { - int steps = 0; - Q64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - - @Benchmark - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public int Val_as_Val_walk(Val_as_Val s) { - int steps = 0; - Q64long[] values = s.arr; - for (int i = values[0].intValue(); i != 0; i = values[i].intValue()) steps++; - return steps; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/A64long.java b/test/micro/org/openjdk/bench/valhalla/types/A64long.java deleted file mode 100644 index 4d2719a1265..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/A64long.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public abstract class A64long implements Int64, ByLong { - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Int32.java b/test/micro/org/openjdk/bench/valhalla/types/Int32.java deleted file mode 100644 index 9d9045250ae..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Int32.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public interface Int32 extends Comparable { - - public long longValue(); - - public int intValue(); - - public Int32 neg(); - - public Int32 add(Int32 o); - - public Int32 sub(Int32 o); - - public Int32 mult(Int32 o); - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Int64.java b/test/micro/org/openjdk/bench/valhalla/types/Int64.java deleted file mode 100644 index 6b501dfc2c1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Int64.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.types; - -public interface Int64 { - - public long longValue(); - - public int intValue(); - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Opt.java b/test/micro/org/openjdk/bench/valhalla/types/Opt.java deleted file mode 100644 index 210546c0ab6..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Opt.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public interface Opt { - - public T get(); - public boolean isPresent(); - public boolean isEmpty(); - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q128byte.java b/test/micro/org/openjdk/bench/valhalla/types/Q128byte.java deleted file mode 100644 index 497b5f0762d..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q128byte.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q128byte implements Int128, ByByte { - - public final Q64byte v0; - public final Q64byte v1; - - public Q128byte(long v) { - this(0, v); - } - - public Q128byte(long hi, long lo) { - this.v0 = new Q64byte(hi); - this.v1 = new Q64byte(lo); - } - - @Override - public int intValue() { - return v1.intValue(); - } - - @Override - public long longValue() { - return loValue(); - } - - @Override - public long hiValue() { - return v0.longValue(); - } - - @Override - public long loValue() { - return v1.longValue(); - } - - @Override - public byte byteSum() { - return (byte) (v0.byteSum() + v1.byteSum()); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q128int.java b/test/micro/org/openjdk/bench/valhalla/types/Q128int.java deleted file mode 100644 index 650fc95e2b6..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q128int.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q128int implements Int128, ByInt { - - public final Q64int v0; - public final Q64int v1; - - public Q128int() { - this(0, 0); - } - - public Q128int(long v) { - this(0, v); - } - - public Q128int(long hi, long lo) { - this.v0 = new Q64int(hi); - this.v1 = new Q64int(lo); - } - - @Override - public int intValue() { - return v1.intValue(); - } - - @Override - public long longValue() { - return loValue(); - } - - @Override - public long hiValue() { - return v0.longValue(); - } - - @Override - public long loValue() { - return v1.longValue(); - } - - @Override - public int intSum() { - return v0.intSum() + v1.intSum(); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q128long.java b/test/micro/org/openjdk/bench/valhalla/types/Q128long.java deleted file mode 100644 index 8957c5c29bb..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q128long.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q128long implements Int128, ByLong { - - public final long v0; - public final long v1; - - public Q128long(long v) { - this(0, v); - } - - public Q128long(long hi, long lo) { - this.v0 = hi; - this.v1 = lo; - } - - @Override - public int intValue() { - return (int)longValue(); - } - - @Override - public long longValue() { - return loValue(); - } - - @Override - public long hiValue() { - return v0; - } - - @Override - public long loValue() { - return v1; - } - - @Override - public long longSum() { - return v0 + v1; - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q32byte.java b/test/micro/org/openjdk/bench/valhalla/types/Q32byte.java deleted file mode 100644 index 200d28c40b9..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q32byte.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q32byte implements Int32, ByByte { - - public final byte v0; - public final byte v1; - public final byte v2; - public final byte v3; - - public Q32byte() { - this(0); - } - - public Q32byte(int v) { - this((byte) (v >>> 24), (byte) (v >>> 16), (byte) (v >>> 8), (byte) (v)); - } - - public Q32byte(byte v0, byte v1, byte v2, byte v3) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - } - - private static final int MASK = 0xFF; - - @Override - public long longValue() { - return (long) intValue(); - } - - @Override - public int intValue() { - return (((v0 & MASK) << 24) | ((v1 & MASK) << 16) | ((v2 & MASK) << 8) | (v3 & MASK)); - } - - @Override - public Int32 neg() { - return new Q32byte(-intValue()); - } - - @Override - public Int32 add(Int32 o) { - return new Q32byte(intValue() + o.intValue()); - } - - @Override - public Int32 sub(Int32 o) { - return new Q32byte(intValue() - o.intValue()); - } - - @Override - public Int32 mult(Int32 o) { - return new Q32byte(intValue() * o.intValue()); - } - - @Override - public int compareTo(Int32 o) { - return Integer.compare(intValue(), o.intValue()); - } - - @Override - public byte byteSum() { - return (byte) (v0 + v1 + v2 + v3); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q32int.java b/test/micro/org/openjdk/bench/valhalla/types/Q32int.java deleted file mode 100644 index 6cee8dbad25..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q32int.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q32int implements Int32, ByInt { - - public final int v0; - - public Q32int() { - v0 = 0; - } - - public Q32int(int val) { - this.v0 = val; - } - - @Override - public long longValue() { - return (long)v0; - } - - @Override - public int intValue() { - return v0; - } - - @Override - public Int32 neg() { - return new Q32int(-v0); - } - - @Override - public Int32 add(Int32 o) { - return new Q32int(v0 + o.intValue()); - } - - public Int32 add(Q32int o) { - return new Q32int(v0 + o.v0); - } - - @Override - public Int32 sub(Int32 o) { - return new Q32int(v0 - o.intValue()); - } - - public Int32 sub(Q32int o) { - return new Q32int(v0 - o.v0); - } - - @Override - public Int32 mult(Int32 o) { - return new Q32int(v0 * o.intValue()); - } - - public Int32 mult(Q32int o) { - return new Q32int(v0 * o.v0); - } - - @Override - public int compareTo(Int32 o) { - return Integer.compare(v0, o.intValue()); - } - - public int compareTo(Q32int o) { - return Integer.compare(v0, o.v0); - } - - @Override - public int intSum() { - return v0; - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q64byte.java b/test/micro/org/openjdk/bench/valhalla/types/Q64byte.java deleted file mode 100644 index a40ec985acc..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q64byte.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q64byte implements Int64, ByByte { - - public final Q32byte v0; - public final Q32byte v1; - - public Q64byte() { - this.v0 = new Q32byte(); - this.v1 = new Q32byte(); - } - - public Q64byte(long v) { - this((int) (v >>> 32), (int) v); - } - - public Q64byte(int hi, int lo) { - this.v0 = new Q32byte(hi); - this.v1 = new Q32byte(lo); - } - - private static final long MASK = 0xFFFFFFFFL; - - @Override - public long longValue() { - return (v0.intValue() & MASK) << 32 | (v1.intValue() & MASK); - } - - @Override - public int intValue() { - return v1.intValue(); - } - - @Override - public byte byteSum() { - return (byte) (v0.byteSum() + v1.byteSum()); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q64int.java b/test/micro/org/openjdk/bench/valhalla/types/Q64int.java deleted file mode 100644 index 750d72f3091..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q64int.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q64int implements Int64, ByInt { - - public final Q32int v0; - public final Q32int v1; - - public Q64int() { - this(0); - } - - public Q64int(long v) { - this((int) (v >>> 32), (int) v); - } - - public Q64int(int hi, int lo) { - this.v0 = new Q32int(hi); - this.v1 = new Q32int(lo); - } - - private static final long MASK = 0xFFFFFFFFL; - - @Override - public long longValue() { - return (v0.intValue() & MASK) << 32 | (v1.intValue() & MASK); - } - - @Override - public int intValue() { - return v1.intValue(); - } - - @Override - public int intSum() { - return v0.intSum() + v1.intSum(); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q64long.java b/test/micro/org/openjdk/bench/valhalla/types/Q64long.java deleted file mode 100644 index f924853860d..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/Q64long.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class Q64long implements Int64, ByLong { - - public final long v0; - - public Q64long() { - this(0); - } - - public Q64long(long v0) { - this.v0 = v0; - } - - @Override - public long longValue() { - return v0; - } - - @Override - public int intValue() { - return (int)v0; - } - - @Override - public long longSum() { - return v0; - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/QComplex.java b/test/micro/org/openjdk/bench/valhalla/types/QComplex.java deleted file mode 100644 index c7461685d76..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/QComplex.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public value class QComplex implements Complex { - - public final double re; - public final double im; - - public QComplex(double re, double im) { - this.re = re; - this.im = im; - } - - @Override - public double re() { return re; } - - @Override - public double im() { return im; } - - @Override - public QComplex add(Complex that) { - return new QComplex(this.re + that.re(), this.im + that.im()); - } - - public QComplex add(QComplex that) { - return new QComplex(this.re + that.re, this.im + that.im); - } - - @Override - public QComplex mul(Complex that) { - return new QComplex(this.re * that.re() - this.im * that.im(), - this.re * that.im() + this.im * that.re()); - } - - public QComplex mul(QComplex that) { - return new QComplex(this.re * that.re - this.im * that.im, - this.re * that.im + this.im * that.re); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/QOpt.java b/test/micro/org/openjdk/bench/valhalla/types/QOpt.java deleted file mode 100644 index 51dbfbac321..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/QOpt.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -import java.util.NoSuchElementException; - -public value class QOpt implements Opt { - - public final T value; - - private QOpt(T value) { - this.value = value; - } - - public static QOpt of() { - return new QOpt<>(null); - } - - public static QOpt of(T value) { - return new QOpt<>(value); - } - - public T get() { - if (value == null) { - throw new NoSuchElementException("No value present"); - } - return value; - } - - public boolean isPresent() { - return value != null; - } - - public boolean isEmpty() { - return value == null; - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/R128int.java b/test/micro/org/openjdk/bench/valhalla/types/R128int.java deleted file mode 100644 index fc14bfb7595..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/R128int.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.types; - -public class R128int implements Int128, ByInt { - - public final int v0; - public final int v1; - public final int v2; - public final int v3; - - public R128int(long v) { - this(0, 0, (int) (v >>> 32), (int) v); - } - - public R128int(int v0, int v1, int v2, int v3) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - } - - private static final long MASK = 0xFFFFFFFFL; - - @Override - public int intValue() { - return v3; - } - - @Override - public long longValue() { - return loValue(); - } - - @Override - public long hiValue() { - return (v0 & MASK) << 32 | (v1 & MASK); - } - - @Override - public long loValue() { - return (v2 & MASK) << 32 | (v3 & MASK); - } - - @Override - public int intSum() { - return v0 + v1 + v2 + v3; - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/R32byte.java b/test/micro/org/openjdk/bench/valhalla/types/R32byte.java deleted file mode 100644 index 549cb6f36a6..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/R32byte.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public class R32byte implements Int32, ByByte { - - public final byte v0; - public final byte v1; - public final byte v2; - public final byte v3; - - public R32byte(int v) { - this((byte) (v >>> 24), (byte) (v >>> 16), (byte) (v >>> 8), (byte) (v)); - } - - public R32byte(byte v0, byte v1, byte v2, byte v3) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - } - - private static final int MASK = 0xFF; - - @Override - public long longValue() { - return (long) intValue(); - } - - @Override - public int intValue() { - return (((v0 & MASK) << 24) | ((v1 & MASK) << 16) | ((v2 & MASK) << 8) | (v3 & MASK)); - } - - @Override - public Int32 neg() { - return new R32byte(-intValue()); - } - - @Override - public Int32 add(Int32 o) { - return new R32byte(intValue() + o.intValue()); - } - - @Override - public Int32 sub(Int32 o) { - return new R32byte(intValue() - o.intValue()); - } - - @Override - public Int32 mult(Int32 o) { - return new R32byte(intValue() * o.intValue()); - } - - @Override - public int compareTo(Int32 o) { - return Integer.compare(intValue(), o.intValue()); - } - - @Override - public byte byteSum() { - return (byte) (v0 + v1 + v2 + v3); - } - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/R32int.java b/test/micro/org/openjdk/bench/valhalla/types/R32int.java deleted file mode 100644 index 2863c3e7bb6..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/R32int.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -public class R32int implements Int32, ByInt { - - public final int v0; - - public R32int() { - this.v0 = 0; - } - - public R32int(int val) { - this.v0 = val; - } - - @Override - public long longValue() { - return v0; - } - - @Override - public int intValue() { - return v0; - } - - @Override - public Int32 neg() { - return new R32int(-v0); - } - - @Override - public Int32 add(Int32 o) { - return new R32int(v0 + o.intValue()); - } - - public Int32 add(R32int o) { - return new R32int(v0 + o.v0); - } - - @Override - public Int32 sub(Int32 o) { - return new R32int(v0 - o.intValue()); - } - - public Int32 sub(R32int o) { - return new R32int(v0 - o.v0); - } - - @Override - public Int32 mult(Int32 o) { - return new R32int(v0 * o.intValue()); - } - - public Int32 mult(R32int o) { - return new R32int(v0 * o.v0); - } - - @Override - public int compareTo(Int32 o) { - return Integer.compare(v0, o.intValue()); - } - - public int compareTo(R32int o) { - return Integer.compare(v0, o.v0); - } - - @Override - public int intSum() { - return v0; - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/R64byte.java b/test/micro/org/openjdk/bench/valhalla/types/R64byte.java deleted file mode 100644 index c60645f53c1..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/R64byte.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.types; - -public class R64byte implements Int64, ByByte { - - public final byte v0; - public final byte v1; - public final byte v2; - public final byte v3; - public final byte v4; - public final byte v5; - public final byte v6; - public final byte v7; - - public R64byte(long v) { - this((byte) (v >>> 56), (byte) (v >>> 48), (byte) (v >>> 40), (byte) (v >>> 32), (byte) (v >>> 24), (byte) (v >>> 16), (byte) (v >>> 8), (byte) (v)); - } - - public R64byte(byte v0, byte v1, byte v2, byte v3, byte v4, byte v5, byte v6, byte v7) { - this.v0 = v0; - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - this.v4 = v4; - this.v5 = v5; - this.v6 = v6; - this.v7 = v7; - } - - private static final long MASK = 0xFFL; - private static final int IMASK = 0xFF; - - @Override - public long longValue() { - return ((v0 & MASK) << 56) | ((v1 & MASK) << 48) | ((v2 & MASK) << 40) | ((v3 & MASK) << 32) | ((v4 & MASK) << 24) | ((v5 & MASK) << 16) | ((v6 & MASK) << 8) | (v7 & MASK); - } - - @Override - public int intValue() { - return ((v4 & IMASK) << 24) | ((v5 & IMASK) << 16) | ((v6 & IMASK) << 8) | (v7 & IMASK); - } - - @Override - public byte byteSum() { - return (byte) (v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7); - } -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/RComplex.java b/test/micro/org/openjdk/bench/valhalla/types/RComplex.java deleted file mode 100644 index e50ceab9822..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/RComplex.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ -package org.openjdk.bench.valhalla.types; - -public class RComplex implements Complex { - - public final double re; - public final double im; - - public RComplex(double re, double im) { - this.re = re; - this.im = im; - } - - @Override - public double re() { return re; } - - @Override - public double im() { return im; } - - @Override - public RComplex add(Complex that) { - return new RComplex(this.re + that.re(), this.im + that.im()); - } - - public RComplex add(RComplex that) { - return new RComplex(this.re + that.re, this.im + that.im); - } - - @Override - public RComplex mul(Complex that) { - return new RComplex(this.re * that.re() - this.im * that.im(), - this.re * that.im() + this.im * that.re()); - } - - public RComplex mul(RComplex that) { - return new RComplex(this.re * that.re - this.im * that.im, - this.re * that.im + this.im * that.re); - } - - -} diff --git a/test/micro/org/openjdk/bench/valhalla/types/ROpt.java b/test/micro/org/openjdk/bench/valhalla/types/ROpt.java deleted file mode 100644 index f90d0fd5d08..00000000000 --- a/test/micro/org/openjdk/bench/valhalla/types/ROpt.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2020, 2024, 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. - */ -package org.openjdk.bench.valhalla.types; - -import java.util.NoSuchElementException; - -public class ROpt implements Opt { - - public T value; - - private ROpt() { - this.value = null; - } - - private ROpt(T value) { - this.value = value; - } - - public static ROpt of() { - return new ROpt<>(null); - } - - public static ROpt of(T value) { - return new ROpt<>(value); - } - - public T get() { - if (value == null) { - throw new NoSuchElementException("No value present"); - } - return value; - } - - public boolean isPresent() { - return value != null; - } - - public boolean isEmpty() { - return value == null; - } -} diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java index 6e41ec0610e..5e1ef72f2c3 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -49,6 +53,12 @@ public class AllDead { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java index 2a2bf060833..bc62d838f57 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -49,6 +53,12 @@ public class AllLive { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java index 4de7c4a8f84..2591b23763a 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java @@ -26,15 +26,19 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -49,6 +53,12 @@ public class DifferentObjectSizesArray { static Object[] largeObjArray; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { largeObjArray = GarbageGenerator.generateAndFillLargeObjArray(false); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java index 960223f5035..9dd39bcf783 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.HashMap; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class DifferentObjectSizesHashMap { static HashMap largeMap; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { largeMap = GarbageGenerator.generateAndFillHashMap(false); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java index d1fea505ac0..6fd1fe05555 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.TreeMap; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -49,6 +53,12 @@ public class DifferentObjectSizesTreeMap { */ static TreeMap largeMap; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { largeMap = GarbageGenerator.generateAndFillTreeMap(false); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java index 339e31d7032..ef62a269acb 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class HalfDeadFirstPart { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java index 07eda82f2c9..471d86b88cb 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class HalfDeadInterleaved { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java index a5d6dce91a9..bcf495cfd5f 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class HalfDeadInterleavedChunks { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java index 838aeb4820b..9340d1047ce 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class HalfDeadSecondPart { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java index eaba46e04e9..c48bc5b1d15 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java @@ -26,16 +26,20 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -50,6 +54,12 @@ public class HalfHashedHalfDead { static ArrayList holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = GarbageGenerator.generateObjectArrays(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java index 96461c8106c..6f31c4014a8 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java @@ -25,14 +25,23 @@ import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) public class NoObjects { /* @@ -43,6 +52,12 @@ public class NoObjects { * test for consistency. */ + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Benchmark public void gc() { System.gc(); diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java index ef2c436efd7..2a213fe795b 100644 --- a/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java +++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java @@ -26,15 +26,19 @@ import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) +@Warmup(iterations = 5) +@Measurement(iterations = 5) @Fork(value=25, jvmArgs={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @@ -49,6 +53,12 @@ public class OneBigObject { static Object[] holder; + @Setup(Level.Trial) + public void preRun() { + // Compact right now, kicking out all unrelated objects + System.gc(); + } + @Setup(Level.Iteration) public void generateGarbage() { holder = new Object[1024*1024*128];