diff --git a/.github/actions/get-gtest/action.yml b/.github/actions/get-gtest/action.yml
index 1df1052285d..5de2b10cd32 100644
--- a/.github/actions/get-gtest/action.yml
+++ b/.github/actions/get-gtest/action.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2022, 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
@@ -43,7 +43,7 @@ runs:
uses: actions/checkout@v4
with:
repository: google/googletest
- ref: 'release-${{ steps.version.outputs.value }}'
+ ref: 'v${{ steps.version.outputs.value }}'
path: gtest
- name: 'Export path to where GTest is installed'
diff --git a/.github/actions/get-jtreg/action.yml b/.github/actions/get-jtreg/action.yml
index ab0927919db..faedcc18807 100644
--- a/.github/actions/get-jtreg/action.yml
+++ b/.github/actions/get-jtreg/action.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -56,8 +56,14 @@ runs:
- name: 'Build JTReg'
run: |
+ # If runner architecture is x64 set JAVA_HOME_17_X64 otherwise set to JAVA_HOME_17_arm64
+ if [[ '${{ runner.arch }}' == 'X64' ]]; then
+ JDK="$JAVA_HOME_17_X64"
+ else
+ JDK="$JAVA_HOME_17_arm64"
+ fi
# Build JTReg and move files to the proper locations
- bash make/build.sh --jdk "$JAVA_HOME_11_X64"
+ bash make/build.sh --jdk "$JDK"
mkdir ../installed
mv build/images/jtreg/* ../installed
working-directory: jtreg/src
diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml
index b03fcb144fd..c3d499a32a0 100644
--- a/.github/workflows/build-macos.yml
+++ b/.github/workflows/build-macos.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2022, 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
@@ -31,6 +31,9 @@ on:
platform:
required: true
type: string
+ runs-on:
+ required: true
+ type: string
extra-conf-options:
required: false
type: string
@@ -55,7 +58,7 @@ on:
jobs:
build-macos:
name: build
- runs-on: macos-11
+ runs-on: ${{ inputs.runs-on }}
strategy:
fail-fast: false
@@ -74,7 +77,7 @@ jobs:
id: bootjdk
uses: ./.github/actions/get-bootjdk
with:
- platform: macos-x64
+ platform: ${{ inputs.platform }}
- name: 'Get JTReg'
id: jtreg
@@ -87,7 +90,7 @@ jobs:
- name: 'Install toolchain and dependencies'
run: |
# Run Homebrew installation and xcode-select
- brew install make
+ brew install autoconf make
sudo xcode-select --switch /Applications/Xcode_${{ inputs.xcode-toolset-version }}.app/Contents/Developer
# This will make GNU make available as 'make' and not only as 'gmake'
echo '/usr/local/opt/make/libexec/gnubin' >> $GITHUB_PATH
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 9e2f11eb4d3..07c47c9d592 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2022, 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
@@ -223,7 +223,8 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-x64
- xcode-toolset-version: '12.5.1'
+ runs-on: 'macos-13'
+ xcode-toolset-version: '14.3.1'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
if: needs.select.outputs.macos-x64 == 'true'
@@ -234,8 +235,8 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-aarch64
- xcode-toolset-version: '12.5.1'
- extra-conf-options: '--openjdk-target=aarch64-apple-darwin'
+ runs-on: 'macos-14'
+ xcode-toolset-version: '14.3.1'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
if: needs.select.outputs.macos-aarch64 == 'true'
@@ -298,7 +299,17 @@ jobs:
with:
platform: macos-x64
bootjdk-platform: macos-x64
- runs-on: macos-11
+ runs-on: macos-13
+
+ test-macos-aarch64:
+ name: macos-aarch64
+ needs:
+ - build-macos-aarch64
+ uses: ./.github/workflows/test.yml
+ with:
+ platform: macos-aarch64
+ bootjdk-platform: macos-aarch64
+ runs-on: macos-14
test-windows-x64:
name: windows-x64
@@ -333,26 +344,23 @@ jobs:
- test-windows-x64
steps:
- # Hack to get hold of the api environment variables that are only defined for actions
- - name: 'Get API configuration'
- id: api
- uses: actions/github-script@v7
- with:
- script: 'return { url: process.env["ACTIONS_RUNTIME_URL"], token: process.env["ACTIONS_RUNTIME_TOKEN"] }'
-
- name: 'Remove bundle artifacts'
run: |
# Find and remove all bundle artifacts
- ALL_ARTIFACT_URLS="$(curl -s \
- -H 'Accept: application/json;api-version=6.0-preview' \
- -H 'Authorization: Bearer ${{ fromJson(steps.api.outputs.result).token }}' \
- '${{ fromJson(steps.api.outputs.result).url }}_apis/pipelines/workflows/${{ github.run_id }}/artifacts?api-version=6.0-preview')"
- BUNDLE_ARTIFACT_URLS="$(echo "$ALL_ARTIFACT_URLS" | jq -r -c '.value | map(select(.name|startswith("bundles-"))) | .[].url')"
- for url in $BUNDLE_ARTIFACT_URLS; do
- echo "Removing $url"
- curl -s \
- -H 'Accept: application/json;api-version=6.0-preview' \
- -H 'Authorization: Bearer ${{ fromJson(steps.api.outputs.result).token }}' \
- -X DELETE "$url" \
+ # See: https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28
+ ALL_ARTIFACT_IDS="$(curl -sL \
+ -H 'Accept: application/vnd.github+json' \
+ -H 'Authorization: Bearer ${{ github.token }}' \
+ -H 'X-GitHub-Api-Version: 2022-11-28' \
+ '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts')"
+ BUNDLE_ARTIFACT_IDS="$(echo "$ALL_ARTIFACT_IDS" | jq -r -c '.artifacts | map(select(.name|startswith("bundles-"))) | .[].id')"
+ for id in $BUNDLE_ARTIFACT_IDS; do
+ echo "Removing $id"
+ curl -sL \
+ -X DELETE \
+ -H 'Accept: application/vnd.github+json' \
+ -H 'Authorization: Bearer ${{ github.token }}' \
+ -H 'X-GitHub-Api-Version: 2022-11-28' \
+ "${{ github.api_url }}/repos/${{ github.repository }}/actions/artifacts/$id" \
|| echo "Failed to remove bundle"
done
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6889a5b0237..a8885866c12 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2022, 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
@@ -147,7 +147,7 @@ jobs:
run: |
# On macOS we need to install some dependencies for testing
brew install make
- sudo xcode-select --switch /Applications/Xcode_11.7.app/Contents/Developer
+ sudo xcode-select --switch /Applications/Xcode_14.3.1.app/Contents/Developer
# This will make GNU make available as 'make' and not only as 'gmake'
echo '/usr/local/opt/make/libexec/gnubin' >> $GITHUB_PATH
if: runner.os == 'macOS'
diff --git a/.jcheck/conf b/.jcheck/conf
index c39a4fe49e6..046197ae090 100644
--- a/.jcheck/conf
+++ b/.jcheck/conf
@@ -1,10 +1,11 @@
[general]
project=jdk-updates
jbs=JDK
-version=17.0.12
+version=17.0.13
[checks]
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
+warning=issuestitle,binary
[repository]
tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d)
diff --git a/doc/building.html b/doc/building.html
index 31044787bba..bcc81dd3d38 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -514,10 +514,10 @@
Advanced Make Control Variables
Running Tests
Most of the JDK tests are using the JTReg test framework. Make sure that your configuration knows where to find your installation of JTReg. If this is not picked up automatically, use the --with-jtreg=<path to jtreg home>
option to point to the JTReg framework. Note that this option should point to the JTReg home, i.e. the top directory, containing lib/jtreg.jar
etc.
The Adoption Group provides recent builds of jtreg here. Download the latest .tar.gz
file, unpack it, and point --with-jtreg
to the jtreg
directory that you just unpacked.
-Building of Hotspot Gtest suite requires the source code of Google Test framework. The top directory, which contains both googletest
and googlemock
directories, should be specified via --with-gtest
. The supported version of Google Test is 1.8.1, whose source code can be obtained:
+Building of Hotspot Gtest suite requires the source code of Google Test framework. The top directory, which contains both googletest
and googlemock
directories, should be specified via --with-gtest
. The supported version of Google Test is 1.13.0, whose source code can be obtained:
-- by downloading and unpacking the source bundle from here
-- or by checking out
release-1.8.1
tag of googletest
project: git clone -b release-1.8.1 https://github.com/google/googletest
+- by downloading and unpacking the source bundle from here
+- or by checking out
v1.13.0
tag of googletest
project: git clone -b v1.13.0 https://github.com/google/googletest
To execute the most basic tests (tier 1), use:
make run-test-tier1
diff --git a/doc/building.md b/doc/building.md
index 6a8eabfc7b5..150a3306c29 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -852,13 +852,14 @@ https://ci.adoptium.net/view/Dependencies/job/dependency_pipeline/lastSuccessful
Download the latest `.tar.gz` file, unpack it, and point `--with-jtreg` to the
`jtreg` directory that you just unpacked.
-Building of Hotspot Gtest suite requires the source code of Google Test framework.
-The top directory, which contains both `googletest` and `googlemock`
-directories, should be specified via `--with-gtest`.
-The supported version of Google Test is 1.8.1, whose source code can be obtained:
-
- * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/release-1.8.1)
- * or by checking out `release-1.8.1` tag of `googletest` project: `git clone -b release-1.8.1 https://github.com/google/googletest`
+Building of Hotspot Gtest suite requires the source code of Google
+Test framework. The top directory, which contains both `googletest`
+and `googlemock` directories, should be specified via `--with-gtest`.
+The minimum supported version of Google Test is 1.13.0, whose source
+code can be obtained:
+
+ * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/v1.13.0)
+ * or by checking out `v1.13.0` tag of `googletest` project: `git clone -b v1.13.0 https://github.com/google/googletest`
To execute the most basic tests (tier 1), use:
```
diff --git a/doc/testing.html b/doc/testing.html
index a64a891b5b8..862b207a2d5 100644
--- a/doc/testing.html
+++ b/doc/testing.html
@@ -67,7 +67,7 @@ Configuration
Test selection
All functionality is available using the test
make target. In this use case, the test or tests to be executed is controlled using the TEST
variable. To speed up subsequent test runs with no source code changes, test-only
can be used instead, which do not depend on the source and test image build.
For some common top-level tests, direct make targets have been generated. This includes all JTReg test groups, the hotspot gtest, and custom tests (if present). This means that make test-tier1
is equivalent to make test TEST="tier1"
, but the latter is more tab-completion friendly. For more complex test runs, the test TEST="x"
solution needs to be used.
-The test specifications given in TEST
is parsed into fully qualified test descriptors, which clearly and unambigously show which tests will be run. As an example, :tier1
will expand to jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 jtreg:$(TOPDIR)/test/nashorn:tier1 jtreg:$(TOPDIR)/test/jaxp:tier1
. You can always submit a list of fully qualified test descriptors in the TEST
variable if you want to shortcut the parser.
+The test specifications given in TEST
is parsed into fully qualified test descriptors, which clearly and unambigously show which tests will be run. As an example, :tier1
will expand to include all subcomponent test directories that define `tier1`, for example: jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 ...
. You can always submit a list of fully qualified test descriptors in the TEST
variable if you want to shortcut the parser.
Common Test Groups
Ideally, all tests are run for every change but this may not be practical due to the limited testing resources, the scope of the change, etc.
The source tree currently defines a few common test groups in the relevant TEST.groups
files. There are test groups that cover a specific component, for example hotspot_gc
. It is a good idea to look into TEST.groups
files to get a sense what tests are relevant to a particular JDK component.
diff --git a/doc/testing.md b/doc/testing.md
index 3cdc0d662d6..bddc6ba3ee9 100644
--- a/doc/testing.md
+++ b/doc/testing.md
@@ -58,11 +58,11 @@ test runs, the `test TEST="x"` solution needs to be used.
The test specifications given in `TEST` is parsed into fully qualified test
descriptors, which clearly and unambigously show which tests will be run. As an
-example, `:tier1` will expand to `jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1
-jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1
-jtreg:$(TOPDIR)/test/nashorn:tier1 jtreg:$(TOPDIR)/test/jaxp:tier1`. You can
-always submit a list of fully qualified test descriptors in the `TEST` variable
-if you want to shortcut the parser.
+example, `:tier1` will expand to include all subcomponent test directories
+that define `tier1`, for example: `jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1
+jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 ...`. You
+can always submit a list of fully qualified test descriptors in the `TEST`
+variable if you want to shortcut the parser.
### Common Test Groups
diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac
index 52baed8af93..173d533359d 100644
--- a/make/autoconf/configure.ac
+++ b/make/autoconf/configure.ac
@@ -300,9 +300,11 @@ AC_OUTPUT
# After AC_OUTPUT, we need to do final work
CUSTOM_CONFIG_OUTPUT_GENERATED_HOOK
-BASIC_POST_CONFIG_OUTPUT
# Finally output some useful information to the user
HELP_PRINT_SUMMARY_AND_WARNINGS
CUSTOM_SUMMARY_AND_WARNINGS_HOOK
HELP_REPEAT_WARNINGS
+
+# All output is done. Do the post-config output management.
+BASIC_POST_CONFIG_OUTPUT
diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index f5ce6d27992..f7f2ad53000 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -419,7 +419,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
[
#### OS DEFINES, these should be independent on toolchain
if test "x$OPENJDK_TARGET_OS" = xlinux; then
- CFLAGS_OS_DEF_JVM="-DLINUX"
+ CFLAGS_OS_DEF_JVM="-DLINUX -D_FILE_OFFSET_BITS=64"
CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
elif test "x$OPENJDK_TARGET_OS" = xmacosx; then
CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE"
diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4
index 69ea97ddf4a..93a2b30dc7e 100644
--- a/make/autoconf/lib-tests.m4
+++ b/make/autoconf/lib-tests.m4
@@ -27,8 +27,9 @@
# Setup libraries and functionalities needed to test the JDK.
################################################################################
-# Minimum supported version
+# Minimum supported versions
JTREG_MINIMUM_VERSION=7.3.1
+GTEST_MINIMUM_VERSION=1.13.0
###############################################################################
#
@@ -58,20 +59,13 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_GTEST],
AC_MSG_RESULT([$GTEST_FRAMEWORK_SRC])
UTIL_FIXUP_PATH([GTEST_FRAMEWORK_SRC])
- # Try to verify version. We require 1.8.1, but this can not be directly
- # determined. :-( Instead, there are different, incorrect version
- # numbers we can look for.
- GTEST_VERSION_1="`$GREP GOOGLETEST_VERSION $GTEST_FRAMEWORK_SRC/CMakeLists.txt | $SED -E -e 's/set\(GOOGLETEST_VERSION (.*)\)/\1/'`"
- if test "x$GTEST_VERSION_1" != "x1.9.0"; then
- AC_MSG_ERROR([gtest at $GTEST_FRAMEWORK_SRC does not seem to be version 1.8.1])
- fi
-
- # We cannot grep for "AC_IN*T" as a literal since then m4 will treat it as a macro
- # and expand it.
- # Additional [] needed to keep m4 from mangling shell constructs.
- [ GTEST_VERSION_2="`$GREP -A1 ^.C_INIT $GTEST_FRAMEWORK_SRC/configure.ac | $TAIL -n 1 | $SED -E -e 's/ +\[(.*)],/\1/'`" ]
- if test "x$GTEST_VERSION_2" != "x1.8.0"; then
- AC_MSG_ERROR([gtest at $GTEST_FRAMEWORK_SRC does not seem to be version 1.8.1 B])
+ # Verify that the version is the required one.
+ # This is a simplified version of TOOLCHAIN_CHECK_COMPILER_VERSION
+ gtest_version="`$GREP GOOGLETEST_VERSION $GTEST_FRAMEWORK_SRC/CMakeLists.txt | $SED -E -e 's/set\(GOOGLETEST_VERSION (.*)\)/\1/'`"
+ comparable_actual_version=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", [$]1, [$]2, [$]3, [$]4) }' <<< "$gtest_version"`
+ comparable_minimum_version=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", [$]1, [$]2, [$]3, [$]4) }' <<< "$GTEST_MINIMUM_VERSION"`
+ if test $comparable_actual_version -lt $comparable_minimum_version ; then
+ AC_MSG_ERROR([gtest version is too old, at least version $GTEST_MINIMUM_VERSION is required])
fi
fi
fi
diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf
index 1d2c643d0d4..28323491481 100644
--- a/make/conf/github-actions.conf
+++ b/make/conf/github-actions.conf
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2022, 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
@@ -25,17 +25,21 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
-GTEST_VERSION=1.8.1
+GTEST_VERSION=1.13.0
JTREG_VERSION=7.3.1+1
LINUX_X64_BOOT_JDK_EXT=tar.gz
LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.11_9.tar.gz
LINUX_X64_BOOT_JDK_SHA256=aa7fb6bb342319d227a838af5c363bfa1b4a670c209372f9e6585bd79da6220c
-WINDOWS_X64_BOOT_JDK_EXT=zip
-WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_windows_hotspot_17.0.11_9.zip
-WINDOWS_X64_BOOT_JDK_SHA256=fdd6664d4131370398fbc8bfbb7b46dbfec4a22a090a511fe5c379dae188c390
-
MACOS_X64_BOOT_JDK_EXT=tar.gz
MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_mac_hotspot_17.0.11_9.tar.gz
MACOS_X64_BOOT_JDK_SHA256=f8b96724618f4df557c47f11048d1084e98ed3eb87f0dbd5b84f768a80c3348e
+
+MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
+MACOS_AARCH64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.11_9.tar.gz
+MACOS_AARCH64_BOOT_JDK_SHA256=09a162c58dd801f7cfacd87e99703ed11fb439adc71cfa14ceb2d3194eaca01c
+
+WINDOWS_X64_BOOT_JDK_EXT=zip
+WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_windows_hotspot_17.0.11_9.zip
+WINDOWS_X64_BOOT_JDK_SHA256=fdd6664d4131370398fbc8bfbb7b46dbfec4a22a090a511fe5c379dae188c390
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index 4ee43abe774..64dcb7723a9 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -1242,7 +1242,7 @@ var getJibProfilesDependencies = function (input, common) {
gtest: {
organization: common.organization,
ext: "tar.gz",
- revision: "1.8.1"
+ revision: "1.13.0+1.0"
},
};
diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf
index 63ce4fe97be..d5ba88b6955 100644
--- a/make/conf/version-numbers.conf
+++ b/make/conf/version-numbers.conf
@@ -28,12 +28,12 @@
DEFAULT_VERSION_FEATURE=17
DEFAULT_VERSION_INTERIM=0
-DEFAULT_VERSION_UPDATE=12
+DEFAULT_VERSION_UPDATE=13
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
-DEFAULT_VERSION_DATE=2024-07-16
+DEFAULT_VERSION_DATE=2024-10-15
DEFAULT_VERSION_CLASSFILE_MAJOR=61 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
diff --git a/make/data/cacerts/ssltlsrootecc2022 b/make/data/cacerts/ssltlsrootecc2022
new file mode 100644
index 00000000000..706e6aefb4e
--- /dev/null
+++ b/make/data/cacerts/ssltlsrootecc2022
@@ -0,0 +1,21 @@
+Owner: CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US
+Issuer: CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US
+Serial number: 1403f5abfb378b17405be243b2a5d1c4
+Valid from: Thu Aug 25 16:33:48 GMT 2022 until: Sun Aug 19 16:33:47 GMT 2046
+Signature algorithm name: SHA384withECDSA
+Subject Public Key Algorithm: 384-bit EC (secp384r1) key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT
+U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2
+MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh
+dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm
+acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN
+SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
+GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW
+uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp
+15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN
+b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==
+-----END CERTIFICATE-----
diff --git a/make/data/cacerts/ssltlsrootrsa2022 b/make/data/cacerts/ssltlsrootrsa2022
new file mode 100644
index 00000000000..ad456b0b5f4
--- /dev/null
+++ b/make/data/cacerts/ssltlsrootrsa2022
@@ -0,0 +1,39 @@
+Owner: CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US
+Issuer: CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US
+Serial number: 6fbedaad73bd0840e28b4dbed4f75b91
+Valid from: Thu Aug 25 16:34:22 GMT 2022 until: Sun Aug 19 16:34:21 GMT 2046
+Signature algorithm name: SHA256withRSA
+Subject Public Key Algorithm: 4096-bit RSA key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO
+MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD
+DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX
+DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw
+b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP
+L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY
+t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins
+S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3
+PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO
+L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3
+R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w
+dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS
++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS
+d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG
+AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f
+gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z
+NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM
+QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf
+R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ
+DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW
+P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy
+lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq
+bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w
+AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q
+r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji
+Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU
+98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
+-----END CERTIFICATE-----
diff --git a/make/data/cldr/common/main/ff_Adlm.xml b/make/data/cldr/common/main/ff_Adlm.xml
index 02feba420c8..05bb2c6db95 100644
--- a/make/data/cldr/common/main/ff_Adlm.xml
+++ b/make/data/cldr/common/main/ff_Adlm.xml
@@ -272,7 +272,7 @@ CLDR data files are interpreted according to the LDML specification (http://unic
𞤄𞤢𞤸𞤢𞤥𞤢𞥄𞤧
𞤄𞤵𞥅𞤼𞤢𞥄𞤲
𞤅𞤵𞤪𞤭𞥅𞤪𞤫 𞤄𞤵𞥅𞤾𞤫𞥅
- 𞤄𞤮𞤼𞤧𞤵𞤱𞤢𞥄𞤲𞤢
+ 𞤄𞤮𞤼𞤧𞤵𞤱𞤢𞥄𞤲𞤢
𞤄𞤫𞤤𞤢𞤪𞤵𞥅𞤧
𞤄𞤫𞤤𞤭𞥅𞥁
𞤑𞤢𞤲𞤢𞤣𞤢𞥄
@@ -2245,7 +2245,7 @@ CLDR data files are interpreted according to the LDML specification (http://unic
𞤐𞤵𞥅𞤳
- 𞤋𞤼𞥆𞤮𞤳𞤮𞤪𞤼𞤮𞥅𞤪𞤥𞤭𞥅𞤼
+ 𞤋𞤼𞥆𞤮𞤳𞤮𞤪𞤼𞤮𞥅𞤪𞤥𞤭𞥅𞤼
𞤁𞤢𞥄𞤲𞤥𞤢𞤪𞤳𞥃𞤢𞥄𞤾𞤲
diff --git a/make/data/currency/CurrencyData.properties b/make/data/currency/CurrencyData.properties
index 26f4aa24d88..550662ec38a 100644
--- a/make/data/currency/CurrencyData.properties
+++ b/make/data/currency/CurrencyData.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 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
@@ -32,7 +32,7 @@ formatVersion=3
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
-dataVersion=176
+dataVersion=177
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -56,8 +56,8 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036
TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\
UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
- XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWL932-\
- ZWN942-ZWR935
+ XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWG924-\
+ ZWL932-ZWN942-ZWR935
# Mappings from ISO 3166 country codes to ISO 4217 currency codes.
@@ -582,7 +582,7 @@ YE=YER
# ZAMBIA
ZM=ZMW
# ZIMBABWE
-ZW=ZWL
+ZW=ZWG
# List of currencies with non-2digit decimals for minor units,
diff --git a/make/data/lsrdata/language-subtag-registry.txt b/make/data/lsrdata/language-subtag-registry.txt
index 4737c50e425..3079d77ed8b 100644
--- a/make/data/lsrdata/language-subtag-registry.txt
+++ b/make/data/lsrdata/language-subtag-registry.txt
@@ -1,4 +1,4 @@
-File-Date: 2024-03-07
+File-Date: 2024-06-14
%%
Type: language
Subtag: aa
@@ -9402,6 +9402,7 @@ Macrolanguage: doi
%%
Type: language
Subtag: dgr
+Description: Tlicho
Description: Dogrib
Description: Tłı̨chǫ
Added: 2005-10-16
@@ -15255,6 +15256,11 @@ Description: Isu (Menchum Division)
Added: 2009-07-29
%%
Type: language
+Subtag: isv
+Description: Interslavic
+Added: 2024-05-15
+%%
+Type: language
Subtag: itb
Description: Binongan Itneg
Added: 2009-07-29
@@ -48003,7 +48009,9 @@ Type: variant
Subtag: laukika
Description: Classical Sanskrit
Added: 2010-07-28
+Deprecated: 2024-06-08
Prefix: sa
+Comments: Preferred tag is cls
%%
Type: variant
Subtag: lemosin
@@ -48379,9 +48387,11 @@ Type: variant
Subtag: vaidika
Description: Vedic Sanskrit
Added: 2010-07-28
+Deprecated: 2024-06-08
Prefix: sa
Comments: The most ancient dialect of Sanskrit used in verse and prose
composed until about the 4th century B.C.E.
+Comments: Preferred tag is vsn
%%
Type: variant
Subtag: valbadia
diff --git a/make/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh
index b2b10769d15..889b7f914a4 100644
--- a/make/devkit/createJMHBundle.sh
+++ b/make/devkit/createJMHBundle.sh
@@ -44,7 +44,7 @@ rm -f *
fetchJar() {
url="${MAVEN_MIRROR}/$1/$2/$3/$2-$3.jar"
if command -v curl > /dev/null; then
- curl -O --fail $url
+ curl -OL --fail $url
elif command -v wget > /dev/null; then
wget $url
else
diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk
index 65edd047571..230aa54f73a 100644
--- a/make/hotspot/lib/CompileJvm.gmk
+++ b/make/hotspot/lib/CompileJvm.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -151,6 +151,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc), \
DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang), \
+ DISABLED_WARNINGS_clang_notificationThread.cpp := bitwise-instead-of-logical, \
+ DISABLED_WARNINGS_clang_serviceThread.cpp := bitwise-instead-of-logical, \
DISABLED_WARNINGS_xlc := $(DISABLED_WARNINGS_xlc), \
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft), \
ASFLAGS := $(JVM_ASFLAGS), \
diff --git a/make/hotspot/lib/JvmFlags.gmk b/make/hotspot/lib/JvmFlags.gmk
index 0c292ad866c..943e8dcbb8c 100644
--- a/make/hotspot/lib/JvmFlags.gmk
+++ b/make/hotspot/lib/JvmFlags.gmk
@@ -67,10 +67,12 @@ JVM_CFLAGS_TARGET_DEFINES += \
#
ifeq ($(DEBUG_LEVEL), release)
+ # release builds disable uses of assert macro from .
+ JVM_CFLAGS_DEBUGLEVEL := -DNDEBUG
# For hotspot, release builds differ internally between "optimized" and "product"
# in that "optimize" does not define PRODUCT.
ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized)
- JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT
+ JVM_CFLAGS_DEBUGLEVEL += -DPRODUCT
endif
else ifeq ($(DEBUG_LEVEL), fastdebug)
JVM_CFLAGS_DEBUGLEVEL := -DASSERT
diff --git a/make/modules/java.base/Launcher.gmk b/make/modules/java.base/Launcher.gmk
index 700ddefda49..1ab3846c143 100644
--- a/make/modules/java.base/Launcher.gmk
+++ b/make/modules/java.base/Launcher.gmk
@@ -78,7 +78,8 @@ ifeq ($(call isTargetOs, macosx aix linux), true)
NAME := jspawnhelper, \
SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKEXE) -I$(TOPDIR)/src/$(MODULE)/unix/native/libjava, \
+ CFLAGS := $(CFLAGS_JDKEXE) $(VERSION_CFLAGS) \
+ -I$(TOPDIR)/src/$(MODULE)/unix/native/libjava, \
EXTRA_OBJECT_FILES := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc.o, \
LDFLAGS := $(LDFLAGS_JDKEXE), \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \
diff --git a/make/modules/java.base/lib/CoreLibraries.gmk b/make/modules/java.base/lib/CoreLibraries.gmk
index bb09d8cf8a2..c1db028fff8 100644
--- a/make/modules/java.base/lib/CoreLibraries.gmk
+++ b/make/modules/java.base/lib/CoreLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -92,6 +92,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJAVA_CFLAGS), \
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
+ ProcessImpl_md.c_CFLAGS := $(VERSION_CFLAGS), \
EXTRA_HEADER_DIRS := libfdlibm, \
WARNINGS_AS_ERRORS_xlc := false, \
DISABLED_WARNINGS_gcc := unused-result unused-function, \
@@ -136,7 +137,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBZIP, \
$(LIBZ_CFLAGS), \
CFLAGS_unix := $(BUILD_LIBZIP_MMAP) -UDEBUG, \
DISABLED_WARNINGS_gcc := unused-function implicit-fallthrough, \
- DISABLED_WARNINGS_clang := format-nonliteral, \
+ DISABLED_WARNINGS_clang := format-nonliteral deprecated-non-prototype, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS_unix := -ljvm -ljava $(LIBZ_LIBS), \
@@ -205,7 +206,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
DISABLED_WARNINGS_gcc := unused-function implicit-fallthrough, \
- DISABLED_WARNINGS_clang := sometimes-uninitialized format-nonliteral, \
+ DISABLED_WARNINGS_clang := sometimes-uninitialized format-nonliteral deprecated-non-prototype, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS_unix := $(LIBZ_LIBS), \
diff --git a/make/modules/java.desktop/Java.gmk b/make/modules/java.desktop/Java.gmk
index 4b1c14a1133..b7cf961a847 100644
--- a/make/modules/java.desktop/Java.gmk
+++ b/make/modules/java.desktop/Java.gmk
@@ -67,6 +67,7 @@ EXCLUDE_FILES += \
ifeq ($(call isTargetOs, macosx), true)
# exclude all X11 on Mac.
EXCLUDES += \
+ sun/awt/screencast \
sun/awt/X11 \
sun/java2d/x11 \
sun/java2d/jules \
diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk
index 46e3b1677f7..bf6a987149a 100644
--- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk
+++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -146,7 +146,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
DISABLED_WARNINGS_gcc := sign-compare unused-result maybe-uninitialized \
format-nonliteral parentheses unused-value unused-function, \
DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer \
- sign-compare format-nonliteral, \
+ sign-compare format-nonliteral deprecated-non-prototype, \
DISABLED_WARNINGS_microsoft := 4244 4267 4996, \
LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_macosx := -L$(INSTALL_LIBRARIES_HERE), \
@@ -194,6 +194,9 @@ ifeq ($(call isTargetOs, windows macosx), false)
LIBAWT_XAWT_EXCLUDES := medialib debug
+ LIBPIPEWIRE_HEADER_DIRS := \
+ $(TOPDIR)/src/$(MODULE)/unix/native/libpipewire/include
+
LIBAWT_XAWT_EXTRA_HEADER_DIRS := \
$(LIBAWT_DEFAULT_HEADER_DIRS) \
libawt_xawt/awt \
@@ -203,7 +206,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
common/font \
common/java2d/opengl \
common/java2d/x11 \
- #
+ $(LIBPIPEWIRE_HEADER_DIRS)
LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \
$(FONTCONFIG_CFLAGS) \
@@ -456,7 +459,10 @@ else
endif
# hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later.
- LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc
+ # hb-subset and hb-style APIs are not needed, excluded to cut on compilation time.
+ LIBFONTMANAGER_EXCLUDE_FILES += hb-ft.cc hb-subset-cff-common.cc \
+ hb-subset-cff1.cc hb-subset-cff2.cc hb-subset-input.cc hb-subset-plan.cc \
+ hb-subset.cc hb-subset-instancer-solver.cc gsubgpos-context.cc hb-style.cc
# list of disabled warnings and the compilers for which it was specifically added.
# array-bounds -> GCC 12 on Alpine Linux
@@ -767,7 +773,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
maybe-uninitialized shift-negative-value implicit-fallthrough \
unused-function, \
DISABLED_WARNINGS_clang := incompatible-pointer-types sign-compare \
- deprecated-declarations null-pointer-subtraction $(LIBZ_DISABLED_WARNINGS_CLANG), \
+ deprecated-declarations null-pointer-subtraction deprecated-non-prototype $(LIBZ_DISABLED_WARNINGS_CLANG), \
DISABLED_WARNINGS_microsoft := 4018 4244 4267, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
@@ -828,6 +834,7 @@ ifeq ($(call isTargetOs, macosx), true)
incompatible-pointer-types parentheses-equality extra-tokens \
sign-compare semicolon-before-method-body format-nonliteral undef \
pointer-arith, \
+ DISABLED_WARNINGS_clang_MTLRenderer.m := gnu-folding-constant, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN) \
-L$(INSTALL_LIBRARIES_HERE), \
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
index 1fea866cc1d..e755d4cee88 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
@@ -505,7 +505,7 @@ class Address {
if (size == 0) // It's a byte
i->f(_ext.shift() >= 0, 12);
else {
- assert(_ext.shift() <= 0 || _ext.shift() == (int)size, "bad shift");
+ guarantee(_ext.shift() <= 0 || _ext.shift() == (int)size, "bad shift");
i->f(_ext.shift() > 0, 12);
}
i->f(0b10, 11, 10);
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index a35b8b84481..7abb2205414 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -1050,6 +1050,110 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
}
}
+// Look up the method for a megamorphic invokeinterface call in a single pass over itable:
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
+// - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
+// The target method is determined by .
+// The receiver klass is in recv_klass.
+// On success, the result will be in method_result, and execution falls through.
+// On failure, execution transfers to the given label.
+void MacroAssembler::lookup_interface_method_stub(Register recv_klass,
+ Register holder_klass,
+ Register resolved_klass,
+ Register method_result,
+ Register temp_itbl_klass,
+ Register scan_temp,
+ int itable_index,
+ Label& L_no_such_interface) {
+ // 'method_result' is only used as output register at the very end of this method.
+ // Until then we can reuse it as 'holder_offset'.
+ Register holder_offset = method_result;
+ assert_different_registers(resolved_klass, recv_klass, holder_klass, temp_itbl_klass, scan_temp, holder_offset);
+
+ int vtable_start_offset = in_bytes(Klass::vtable_start_offset());
+ int itable_offset_entry_size = itableOffsetEntry::size() * wordSize;
+ int ioffset = itableOffsetEntry::interface_offset_in_bytes();
+ int ooffset = itableOffsetEntry::offset_offset_in_bytes();
+
+ Label L_loop_search_resolved_entry, L_resolved_found, L_holder_found;
+
+ ldrw(scan_temp, Address(recv_klass, Klass::vtable_length_offset()));
+ add(recv_klass, recv_klass, vtable_start_offset + ioffset);
+ // itableOffsetEntry[] itable = recv_klass + Klass::vtable_start_offset() + sizeof(vtableEntry) * recv_klass->_vtable_len;
+ // temp_itbl_klass = itable[0]._interface;
+ int vtblEntrySize = vtableEntry::size_in_bytes();
+ assert(vtblEntrySize == wordSize, "ldr lsl shift amount must be 3");
+ ldr(temp_itbl_klass, Address(recv_klass, scan_temp, Address::lsl(exact_log2(vtblEntrySize))));
+ mov(holder_offset, zr);
+ // scan_temp = &(itable[0]._interface)
+ lea(scan_temp, Address(recv_klass, scan_temp, Address::lsl(exact_log2(vtblEntrySize))));
+
+ // Initial checks:
+ // - if (holder_klass != resolved_klass), go to "scan for resolved"
+ // - if (itable[0] == holder_klass), shortcut to "holder found"
+ // - if (itable[0] == 0), no such interface
+ cmp(resolved_klass, holder_klass);
+ br(Assembler::NE, L_loop_search_resolved_entry);
+ cmp(holder_klass, temp_itbl_klass);
+ br(Assembler::EQ, L_holder_found);
+ cbz(temp_itbl_klass, L_no_such_interface);
+
+ // Loop: Look for holder_klass record in itable
+ // do {
+ // temp_itbl_klass = *(scan_temp += itable_offset_entry_size);
+ // if (temp_itbl_klass == holder_klass) {
+ // goto L_holder_found; // Found!
+ // }
+ // } while (temp_itbl_klass != 0);
+ // goto L_no_such_interface // Not found.
+ Label L_search_holder;
+ bind(L_search_holder);
+ ldr(temp_itbl_klass, Address(pre(scan_temp, itable_offset_entry_size)));
+ cmp(holder_klass, temp_itbl_klass);
+ br(Assembler::EQ, L_holder_found);
+ cbnz(temp_itbl_klass, L_search_holder);
+
+ b(L_no_such_interface);
+
+ // Loop: Look for resolved_class record in itable
+ // while (true) {
+ // temp_itbl_klass = *(scan_temp += itable_offset_entry_size);
+ // if (temp_itbl_klass == 0) {
+ // goto L_no_such_interface;
+ // }
+ // if (temp_itbl_klass == resolved_klass) {
+ // goto L_resolved_found; // Found!
+ // }
+ // if (temp_itbl_klass == holder_klass) {
+ // holder_offset = scan_temp;
+ // }
+ // }
+ //
+ Label L_loop_search_resolved;
+ bind(L_loop_search_resolved);
+ ldr(temp_itbl_klass, Address(pre(scan_temp, itable_offset_entry_size)));
+ bind(L_loop_search_resolved_entry);
+ cbz(temp_itbl_klass, L_no_such_interface);
+ cmp(resolved_klass, temp_itbl_klass);
+ br(Assembler::EQ, L_resolved_found);
+ cmp(holder_klass, temp_itbl_klass);
+ br(Assembler::NE, L_loop_search_resolved);
+ mov(holder_offset, scan_temp);
+ b(L_loop_search_resolved);
+
+ // See if we already have a holder klass. If not, go and scan for it.
+ bind(L_resolved_found);
+ cbz(holder_offset, L_search_holder);
+ mov(scan_temp, holder_offset);
+
+ // Finally, scan_temp contains holder_klass vtable offset
+ bind(L_holder_found);
+ ldrw(method_result, Address(scan_temp, ooffset - ioffset));
+ add(recv_klass, recv_klass, itable_index * wordSize + itableMethodEntry::method_offset_in_bytes()
+ - vtable_start_offset - ioffset); // substract offsets to restore the original value of recv_klass
+ ldr(method_result, Address(recv_klass, method_result, Address::uxtw(0)));
+}
+
// virtual method calling
void MacroAssembler::lookup_virtual_method(Register recv_klass,
RegisterOrConstant vtable_index,
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
index 3f6ebb41f2a..9b1c0a93539 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
@@ -918,6 +918,15 @@ class MacroAssembler: public Assembler {
Label& no_such_interface,
bool return_method = true);
+ void lookup_interface_method_stub(Register recv_klass,
+ Register holder_klass,
+ Register resolved_klass,
+ Register method_result,
+ Register temp_reg,
+ Register temp_reg2,
+ int itable_index,
+ Label& L_no_such_interface);
+
// virtual method calling
// n.b. x86 allows RegisterOrConstant for vtable_index
void lookup_virtual_method(Register recv_klass,
diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
index d5a5503213c..66b2769aca5 100644
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
@@ -28,7 +28,6 @@
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "gc/shared/collectedHeap.hpp"
-#include "memory/resourceArea.hpp"
#include "nativeInst_aarch64.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
@@ -189,8 +188,6 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
CompiledICLocker::is_safe(addr_at(0)),
"concurrent code patching");
- ResourceMark rm;
- int code_size = NativeInstruction::instruction_size;
address addr_call = addr_at(0);
bool reachable = Assembler::reachable_from_branch_at(addr_call, dest);
assert(NativeCall::is_call_at(addr_call), "unexpected code at call site");
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
index 039e9c17b46..0d53be49de5 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
@@ -212,10 +212,9 @@ void VM_Version::initialize() {
}
}
- // Neoverse N1, N2 and V1
- if (_cpu == CPU_ARM && ((_model == 0xd0c || _model2 == 0xd0c)
- || (_model == 0xd49 || _model2 == 0xd49)
- || (_model == 0xd40 || _model2 == 0xd40))) {
+ // Neoverse N1, N2, V1, V2
+ if (_cpu == CPU_ARM && (model_is(0xd0c) || model_is(0xd49) ||
+ model_is(0xd40) || model_is(0xd4f))) {
if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
}
@@ -238,8 +237,8 @@ void VM_Version::initialize() {
if (_cpu == CPU_ARM && (_model == 0xd07 || _model2 == 0xd07)) _features |= CPU_STXR_PREFETCH;
char buf[512];
- sprintf(buf, "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision);
- if (_model2) sprintf(buf+strlen(buf), "(0x%03x)", _model2);
+ int buf_used_len = os::snprintf_checked(buf, sizeof(buf), "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision);
+ if (_model2) os::snprintf_checked(buf + buf_used_len, sizeof(buf) - buf_used_len, "(0x%03x)", _model2);
#define ADD_FEATURE_IF_SUPPORTED(id, name, bit) if (_features & CPU_##id) strcat(buf, ", " name);
CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED)
#undef ADD_FEATURE_IF_SUPPORTED
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
index 3f186f56e75..46c77e48b8f 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
@@ -142,6 +142,10 @@ class VM_Version : public Abstract_VM_Version {
static int cpu_variant() { return _variant; }
static int cpu_revision() { return _revision; }
+ static bool model_is(int cpu_model) {
+ return _model == cpu_model || _model2 == cpu_model;
+ }
+
static bool is_zva_enabled() { return 0 <= _zva_length; }
static int zva_length() {
assert(is_zva_enabled(), "ZVA not available");
diff --git a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
index acef8d21abc..11aba1d339b 100644
--- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
@@ -175,7 +175,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// so all registers except arguments are free at this point.
const Register recv_klass_reg = r10;
const Register holder_klass_reg = r16; // declaring interface klass (DECC)
- const Register resolved_klass_reg = rmethod; // resolved interface klass (REFC)
+ const Register resolved_klass_reg = r17; // resolved interface klass (REFC)
const Register temp_reg = r11;
const Register temp_reg2 = r15;
const Register icholder_reg = rscratch2;
@@ -192,28 +192,13 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(recv_klass_reg, j_rarg0);
// Receiver subtype check against REFC.
- __ lookup_interface_method(// inputs: rec. class, interface
- recv_klass_reg, resolved_klass_reg, noreg,
- // outputs: scan temp. reg1, scan temp. reg2
- temp_reg2, temp_reg,
- L_no_such_interface,
- /*return_method=*/false);
-
- const ptrdiff_t typecheckSize = __ pc() - start_pc;
- start_pc = __ pc();
-
// Get selected method from declaring class and itable index
- __ lookup_interface_method(// inputs: rec. class, interface, itable index
- recv_klass_reg, holder_klass_reg, itable_index,
- // outputs: method, scan temp. reg
- rmethod, temp_reg,
- L_no_such_interface);
-
- const ptrdiff_t lookupSize = __ pc() - start_pc;
+ __ lookup_interface_method_stub(recv_klass_reg, holder_klass_reg, resolved_klass_reg, rmethod,
+ temp_reg, temp_reg2, itable_index, L_no_such_interface);
// Reduce "estimate" such that "padding" does not drop below 8.
- const ptrdiff_t estimate = 124;
- const ptrdiff_t codesize = typecheckSize + lookupSize;
+ const ptrdiff_t estimate = 144;
+ const ptrdiff_t codesize = __ pc() - start_pc;
slop_delta = (int)(estimate - codesize);
slop_bytes += slop_delta;
assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize);
diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad
index d9ade024b91..f40595ca62f 100644
--- a/src/hotspot/cpu/arm/arm.ad
+++ b/src/hotspot/cpu/arm/arm.ad
@@ -243,7 +243,7 @@ uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
#ifndef PRODUCT
void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
char reg[128];
- ra_->dump_register(this, reg);
+ ra_->dump_register(this, reg, sizeof(reg));
st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg);
}
#endif
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index d26e3c883e7..87ceeeda94a 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -1946,7 +1946,7 @@ uint MachNopNode::size(PhaseRegAlloc *ra_) const {
void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
char reg_str[128];
- ra_->dump_register(this, reg_str);
+ ra_->dump_register(this, reg_str, sizeof(reg_str));
st->print("ADDI %s, SP, %d \t// box node", reg_str, offset);
}
#endif
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index b05646ac20c..b24778aee30 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -5811,6 +5811,14 @@ void Assembler::xorw(Register dst, Register src) {
emit_arith(0x33, 0xC0, dst, src);
}
+void Assembler::xorw(Register dst, Address src) {
+ InstructionMark im(this);
+ emit_int8(0x66);
+ prefix(src, dst);
+ emit_int8(0x33);
+ emit_operand(dst, src, 0);
+}
+
// AVX 3-operands scalar float-point arithmetic instructions
void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) {
@@ -10513,17 +10521,6 @@ void Assembler::movsbq(Register dst, Register src) {
emit_int24(0x0F, (unsigned char)0xBE, (0xC0 | encode));
}
-void Assembler::movslq(Register dst, int32_t imm32) {
- // dbx shows movslq(rcx, 3) as movq $0x0000000049000000,(%rbx)
- // and movslq(r8, 3); as movl $0x0000000048000000,(%rbx)
- // as a result we shouldn't use until tested at runtime...
- ShouldNotReachHere();
- InstructionMark im(this);
- int encode = prefixq_and_encode(dst->encoding());
- emit_int8(0xC7 | encode);
- emit_int32(imm32);
-}
-
void Assembler::movslq(Address dst, int32_t imm32) {
assert(is_simm32(imm32), "lost bits");
InstructionMark im(this);
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index e8a61efe992..d6c6a5d01ef 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -1584,7 +1584,6 @@ class Assembler : public AbstractAssembler {
// Move signed 32bit immediate to 64bit extending sign
void movslq(Address dst, int32_t imm64);
- void movslq(Register dst, int32_t imm64);
void movslq(Register dst, Address src);
void movslq(Register dst, Register src);
@@ -2116,6 +2115,7 @@ class Assembler : public AbstractAssembler {
void xorb(Address dst, Register src);
void xorb(Register dst, Address src);
void xorw(Register dst, Register src);
+ void xorw(Register dst, Address src);
void xorq(Register dst, Address src);
void xorq(Address dst, int32_t imm32);
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index da4a40ba3f9..0422d51821a 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -1516,7 +1516,12 @@ void MacroAssembler::call(AddressLiteral entry) {
void MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
+#ifdef _LP64
+ // Needs full 64-bit immediate for later patching.
+ mov64(rax, (intptr_t)Universe::non_oop_word());
+#else
movptr(rax, (intptr_t)Universe::non_oop_word());
+#endif
call(AddressLiteral(entry, rh));
}
@@ -2685,7 +2690,15 @@ void MacroAssembler::movptr(Register dst, Address src) {
// src should NEVER be a real pointer. Use AddressLiteral for true pointers
void MacroAssembler::movptr(Register dst, intptr_t src) {
- LP64_ONLY(mov64(dst, src)) NOT_LP64(movl(dst, src));
+#ifdef _LP64
+ if (is_simm32(src)) {
+ movq(dst, checked_cast(src));
+ } else {
+ mov64(dst, src);
+ }
+#else
+ movl(dst, src);
+#endif
}
void MacroAssembler::movptr(Address dst, Register src) {
@@ -3902,6 +3915,125 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
}
}
+// Look up the method for a megamorphic invokeinterface call in a single pass over itable:
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
+// - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
+// The target method is determined by .
+// The receiver klass is in recv_klass.
+// On success, the result will be in method_result, and execution falls through.
+// On failure, execution transfers to the given label.
+void MacroAssembler::lookup_interface_method_stub(Register recv_klass,
+ Register holder_klass,
+ Register resolved_klass,
+ Register method_result,
+ Register scan_temp,
+ Register temp_reg2,
+ Register receiver,
+ int itable_index,
+ Label& L_no_such_interface) {
+ assert_different_registers(recv_klass, method_result, holder_klass, resolved_klass, scan_temp, temp_reg2, receiver);
+ Register temp_itbl_klass = method_result;
+ Register temp_reg = (temp_reg2 == noreg ? recv_klass : temp_reg2); // reuse recv_klass register on 32-bit x86 impl
+
+ int vtable_base = in_bytes(Klass::vtable_start_offset());
+ int itentry_off = itableMethodEntry::method_offset_in_bytes();
+ int scan_step = itableOffsetEntry::size() * wordSize;
+ int vte_size = vtableEntry::size_in_bytes();
+ int ioffset = itableOffsetEntry::interface_offset_in_bytes();
+ int ooffset = itableOffsetEntry::offset_offset_in_bytes();
+ Address::ScaleFactor times_vte_scale = Address::times_ptr;
+ assert(vte_size == wordSize, "adjust times_vte_scale");
+
+ Label L_loop_scan_resolved_entry, L_resolved_found, L_holder_found;
+
+ // temp_itbl_klass = recv_klass.itable[0]
+ // scan_temp = &recv_klass.itable[0] + step
+ movl(scan_temp, Address(recv_klass, Klass::vtable_length_offset()));
+ movptr(temp_itbl_klass, Address(recv_klass, scan_temp, times_vte_scale, vtable_base + ioffset));
+ lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base + ioffset + scan_step));
+ xorptr(temp_reg, temp_reg);
+
+ // Initial checks:
+ // - if (holder_klass != resolved_klass), go to "scan for resolved"
+ // - if (itable[0] == 0), no such interface
+ // - if (itable[0] == holder_klass), shortcut to "holder found"
+ cmpptr(holder_klass, resolved_klass);
+ jccb(Assembler::notEqual, L_loop_scan_resolved_entry);
+ testptr(temp_itbl_klass, temp_itbl_klass);
+ jccb(Assembler::zero, L_no_such_interface);
+ cmpptr(holder_klass, temp_itbl_klass);
+ jccb(Assembler::equal, L_holder_found);
+
+ // Loop: Look for holder_klass record in itable
+ // do {
+ // tmp = itable[index];
+ // index += step;
+ // if (tmp == holder_klass) {
+ // goto L_holder_found; // Found!
+ // }
+ // } while (tmp != 0);
+ // goto L_no_such_interface // Not found.
+ Label L_scan_holder;
+ bind(L_scan_holder);
+ movptr(temp_itbl_klass, Address(scan_temp, 0));
+ addptr(scan_temp, scan_step);
+ cmpptr(holder_klass, temp_itbl_klass);
+ jccb(Assembler::equal, L_holder_found);
+ testptr(temp_itbl_klass, temp_itbl_klass);
+ jccb(Assembler::notZero, L_scan_holder);
+
+ jmpb(L_no_such_interface);
+
+ // Loop: Look for resolved_class record in itable
+ // do {
+ // tmp = itable[index];
+ // index += step;
+ // if (tmp == holder_klass) {
+ // // Also check if we have met a holder klass
+ // holder_tmp = itable[index-step-ioffset];
+ // }
+ // if (tmp == resolved_klass) {
+ // goto L_resolved_found; // Found!
+ // }
+ // } while (tmp != 0);
+ // goto L_no_such_interface // Not found.
+ //
+ Label L_loop_scan_resolved;
+ bind(L_loop_scan_resolved);
+ movptr(temp_itbl_klass, Address(scan_temp, 0));
+ addptr(scan_temp, scan_step);
+ bind(L_loop_scan_resolved_entry);
+ cmpptr(holder_klass, temp_itbl_klass);
+ cmovl(Assembler::equal, temp_reg, Address(scan_temp, ooffset - ioffset - scan_step));
+ cmpptr(resolved_klass, temp_itbl_klass);
+ jccb(Assembler::equal, L_resolved_found);
+ testptr(temp_itbl_klass, temp_itbl_klass);
+ jccb(Assembler::notZero, L_loop_scan_resolved);
+
+ jmpb(L_no_such_interface);
+
+ Label L_ready;
+
+ // See if we already have a holder klass. If not, go and scan for it.
+ bind(L_resolved_found);
+ testptr(temp_reg, temp_reg);
+ jccb(Assembler::zero, L_scan_holder);
+ jmpb(L_ready);
+
+ bind(L_holder_found);
+ movl(temp_reg, Address(scan_temp, ooffset - ioffset - scan_step));
+
+ // Finally, temp_reg contains holder_klass vtable offset
+ bind(L_ready);
+ assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
+ if (temp_reg2 == noreg) { // recv_klass register is clobbered for 32-bit x86 impl
+ load_klass(scan_temp, receiver, noreg);
+ movptr(method_result, Address(scan_temp, temp_reg, Address::times_1, itable_index * wordSize + itentry_off));
+ } else {
+ movptr(method_result, Address(recv_klass, temp_reg, Address::times_1, itable_index * wordSize + itentry_off));
+ }
+}
+
// virtual method calling
void MacroAssembler::lookup_virtual_method(Register recv_klass,
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index 88c2b0c6641..7bad3b11064 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -556,6 +556,16 @@ class MacroAssembler: public Assembler {
Label& no_such_interface,
bool return_method = true);
+ void lookup_interface_method_stub(Register recv_klass,
+ Register holder_klass,
+ Register resolved_klass,
+ Register method_result,
+ Register scan_temp,
+ Register temp_reg2,
+ Register receiver,
+ int itable_index,
+ Label& L_no_such_interface);
+
// virtual method calling
void lookup_virtual_method(Register recv_klass,
RegisterOrConstant vtable_index,
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
index dcc48a6c1f0..78372e1408c 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
@@ -798,6 +798,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
const Register rounds = 0;
const Register pos = r12;
+ const Register tail = r15;
Label PRELOOP_START, EXIT_PRELOOP, REMAINDER, REMAINDER_16, LOOP, END, EXIT, END_LOOP,
AES192, AES256, AES192_REMAINDER16, REMAINDER16_END_LOOP, AES256_REMAINDER16,
@@ -1228,29 +1229,36 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
// Save encrypted counter value in xmm0 for next invocation, before XOR operation
movdqu(Address(saved_encCounter_start, 0), xmm0);
// XOR encryted block cipher in xmm0 with PT to produce CT
- evpxorq(xmm0, xmm0, Address(src_addr, pos, Address::times_1, 0), Assembler::AVX_128bit);
// extract upto 15 bytes of CT from xmm0 as specified by length register
testptr(len_reg, 8);
jcc(Assembler::zero, EXTRACT_TAIL_4BYTES);
- pextrq(Address(dest_addr, pos), xmm0, 0);
+ pextrq(tail, xmm0, 0);
+ xorq(tail, Address(src_addr, pos, Address::times_1, 0));
+ movq(Address(dest_addr, pos), tail);
psrldq(xmm0, 8);
addl(pos, 8);
bind(EXTRACT_TAIL_4BYTES);
testptr(len_reg, 4);
jcc(Assembler::zero, EXTRACT_TAIL_2BYTES);
- pextrd(Address(dest_addr, pos), xmm0, 0);
+ pextrd(tail, xmm0, 0);
+ xorl(tail, Address(src_addr, pos, Address::times_1, 0));
+ movl(Address(dest_addr, pos), tail);
psrldq(xmm0, 4);
addq(pos, 4);
bind(EXTRACT_TAIL_2BYTES);
testptr(len_reg, 2);
jcc(Assembler::zero, EXTRACT_TAIL_1BYTE);
- pextrw(Address(dest_addr, pos), xmm0, 0);
+ pextrw(tail, xmm0, 0);
+ xorw(tail, Address(src_addr, pos, Address::times_1, 0));
+ movw(Address(dest_addr, pos), tail);
psrldq(xmm0, 2);
addl(pos, 2);
bind(EXTRACT_TAIL_1BYTE);
testptr(len_reg, 1);
jcc(Assembler::zero, END);
- pextrb(Address(dest_addr, pos), xmm0, 0);
+ pextrb(tail, xmm0, 0);
+ xorb(tail, Address(src_addr, pos, Address::times_1, 0));
+ movb(Address(dest_addr, pos), tail);
addl(pos, 1);
bind(END);
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
index 09322205f06..30032260469 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
@@ -179,14 +179,16 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// rax: CompiledICHolder
// rcx: Receiver
- // Most registers are in use; we'll use rax, rbx, rsi, rdi
+ // Most registers are in use; we'll use rax, rbx, rcx, rdx, rsi, rdi
// (If we need to make rsi, rdi callee-save, do a push/pop here.)
const Register recv_klass_reg = rsi;
const Register holder_klass_reg = rax; // declaring interface klass (DECC)
- const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
- const Register temp_reg = rdi;
+ const Register resolved_klass_reg = rdi; // resolved interface klass (REFC)
+ const Register temp_reg = rdx;
+ const Register method = rbx;
+ const Register icholder_reg = rax;
+ const Register receiver = rcx;
- const Register icholder_reg = rax;
__ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
__ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
@@ -198,35 +200,26 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(recv_klass_reg, rcx, noreg);
start_pc = __ pc();
+ __ push(rdx); // temp_reg
// Receiver subtype check against REFC.
- // Destroys recv_klass_reg value.
- __ lookup_interface_method(// inputs: rec. class, interface
- recv_klass_reg, resolved_klass_reg, noreg,
- // outputs: scan temp. reg1, scan temp. reg2
- recv_klass_reg, temp_reg,
- L_no_such_interface,
- /*return_method=*/false);
-
- const ptrdiff_t typecheckSize = __ pc() - start_pc;
- start_pc = __ pc();
-
// Get selected method from declaring class and itable index
- const Register method = rbx;
- __ load_klass(recv_klass_reg, rcx, noreg); // restore recv_klass_reg
- __ lookup_interface_method(// inputs: rec. class, interface, itable index
- recv_klass_reg, holder_klass_reg, itable_index,
- // outputs: method, scan temp. reg
- method, temp_reg,
- L_no_such_interface);
-
+ __ lookup_interface_method_stub(recv_klass_reg, // input
+ holder_klass_reg, // input
+ resolved_klass_reg, // input
+ method, // output
+ temp_reg,
+ noreg,
+ receiver, // input (x86_32 only: to restore recv_klass value)
+ itable_index,
+ L_no_such_interface);
const ptrdiff_t lookupSize = __ pc() - start_pc;
// We expect we need index_dependent_slop extra bytes. Reason:
// The emitted code in lookup_interface_method changes when itable_index exceeds 31.
// For windows, a narrow estimate was found to be 104. Other OSes not tested.
const ptrdiff_t estimate = 104;
- const ptrdiff_t codesize = typecheckSize + lookupSize + index_dependent_slop;
+ const ptrdiff_t codesize = lookupSize + index_dependent_slop;
slop_delta = (int)(estimate - codesize);
slop_bytes += slop_delta;
assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize);
@@ -246,6 +239,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
}
#endif // ASSERT
+ __ pop(rdx);
address ame_addr = __ pc();
__ jmp(Address(method, Method::from_compiled_offset()));
@@ -255,6 +249,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// We force resolving of the call site by jumping to the "handle
// wrong method" stub, and so let the interpreter runtime do all the
// dirty work.
+ __ pop(rdx);
__ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
masm->flush();
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
index c6181f2d007..0d17756a30d 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
@@ -176,10 +176,12 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them)
const Register recv_klass_reg = r10;
const Register holder_klass_reg = rax; // declaring interface klass (DECC)
- const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
+ const Register resolved_klass_reg = r14; // resolved interface klass (REFC)
const Register temp_reg = r11;
+ const Register temp_reg2 = r13;
+ const Register method = rbx;
+ const Register icholder_reg = rax;
- const Register icholder_reg = rax;
__ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
__ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
@@ -193,25 +195,16 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
start_pc = __ pc();
// Receiver subtype check against REFC.
- // Destroys recv_klass_reg value.
- __ lookup_interface_method(// inputs: rec. class, interface
- recv_klass_reg, resolved_klass_reg, noreg,
- // outputs: scan temp. reg1, scan temp. reg2
- recv_klass_reg, temp_reg,
- L_no_such_interface,
- /*return_method=*/false);
-
- const ptrdiff_t typecheckSize = __ pc() - start_pc;
- start_pc = __ pc();
-
// Get selected method from declaring class and itable index
- const Register method = rbx;
- __ load_klass(recv_klass_reg, j_rarg0, temp_reg); // restore recv_klass_reg
- __ lookup_interface_method(// inputs: rec. class, interface, itable index
- recv_klass_reg, holder_klass_reg, itable_index,
- // outputs: method, scan temp. reg
- method, temp_reg,
- L_no_such_interface);
+ __ lookup_interface_method_stub(recv_klass_reg, // input
+ holder_klass_reg, // input
+ resolved_klass_reg, // input
+ method, // output
+ temp_reg,
+ temp_reg2,
+ noreg,
+ itable_index,
+ L_no_such_interface);
const ptrdiff_t lookupSize = __ pc() - start_pc;
@@ -219,7 +212,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// The emitted code in lookup_interface_method changes when itable_index exceeds 15.
// For linux, a very narrow estimate would be 112, but Solaris requires some more space (130).
const ptrdiff_t estimate = 136;
- const ptrdiff_t codesize = typecheckSize + lookupSize + index_dependent_slop;
+ const ptrdiff_t codesize = lookupSize + index_dependent_slop;
slop_delta = (int)(estimate - codesize);
slop_bytes += slop_delta;
assert(slop_delta >= 0, "itable #%d: Code size estimate (%d) for lookup_interface_method too small, required: %d", itable_index, (int)estimate, (int)codesize);
diff --git a/src/hotspot/os/aix/attachListener_aix.cpp b/src/hotspot/os/aix/attachListener_aix.cpp
index 461b7fc874f..fbc77f873eb 100644
--- a/src/hotspot/os/aix/attachListener_aix.cpp
+++ b/src/hotspot/os/aix/attachListener_aix.cpp
@@ -266,7 +266,7 @@ int AixAttachListener::init() {
//
AixAttachOperation* AixAttachListener::read_request(int s) {
char ver_str[8];
- sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
+ os::snprintf_checked(ver_str, sizeof(ver_str), "%d", ATTACH_PROTOCOL_VER);
// The request is a sequence of strings so we first figure out the
// expected count and the maximum possible length of the request.
@@ -311,7 +311,7 @@ AixAttachOperation* AixAttachListener::read_request(int s) {
if ((strlen(buf) != strlen(ver_str)) ||
(atoi(buf) != ATTACH_PROTOCOL_VER)) {
char msg[32];
- sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
+ os::snprintf_checked(msg, sizeof(msg), "%d\n", ATTACH_ERROR_BADVERSION);
write_fully(s, msg, strlen(msg));
return NULL;
}
@@ -441,7 +441,7 @@ void AixAttachOperation::complete(jint result, bufferedStream* st) {
// write operation result
char msg[32];
- sprintf(msg, "%d\n", result);
+ os::snprintf_checked(msg, sizeof(msg), "%d\n", result);
int rc = AixAttachListener::write_fully(this->socket(), msg, strlen(msg));
// write any result data
@@ -544,7 +544,7 @@ bool AttachListener::is_init_trigger() {
char fn[PATH_MAX + 1];
int ret;
struct stat64 st;
- sprintf(fn, ".attach_pid%d", os::current_process_id());
+ os::snprintf_checked(fn, sizeof(fn), ".attach_pid%d", os::current_process_id());
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == -1) {
log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index 32e014059da..3744f49a65e 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -536,7 +536,7 @@ void os::init_system_properties_values() {
#endif
#define EXTENSIONS_DIR "/lib/ext"
- // Buffer that fits several sprintfs.
+ // Buffer that fits several snprintfs.
// Note that the space for the trailing null is provided
// by the nulls included by the sizeof operator.
const size_t bufsize =
@@ -584,13 +584,14 @@ void os::init_system_properties_values() {
// Concatenate user and invariant part of ld_library_path.
// That's +1 for the colon and +1 for the trailing '\0'.
- char *ld_library_path = NEW_C_HEAP_ARRAY(char, strlen(v) + 1 + sizeof(DEFAULT_LIBPATH) + 1, mtInternal);
- sprintf(ld_library_path, "%s%s" DEFAULT_LIBPATH, v, v_colon);
+ size_t pathsize = strlen(v) + 1 + sizeof(DEFAULT_LIBPATH) + 1;
+ char *ld_library_path = NEW_C_HEAP_ARRAY(char, pathsize, mtInternal);
+ os::snprintf_checked(ld_library_path, pathsize, "%s%s" DEFAULT_LIBPATH, v, v_colon);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
// Extensions directories.
- sprintf(buf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
+ os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
Arguments::set_ext_dirs(buf);
FREE_C_HEAP_ARRAY(char, buf);
@@ -2068,7 +2069,7 @@ static bool checked_mprotect(char* addr, size_t size, int prot) {
//
// See http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/mprotect.htm
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
bool rc = ::mprotect(addr, size, prot) == 0 ? true : false;
if (!rc) {
@@ -2107,7 +2108,7 @@ static bool checked_mprotect(char* addr, size_t size, int prot) {
// A valid strategy is just to try again. This usually works. :-/
::usleep(1000);
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
if (::mprotect(addr, size, prot) == 0) {
const bool read_protected_2 =
(SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
diff --git a/src/hotspot/os/bsd/attachListener_bsd.cpp b/src/hotspot/os/bsd/attachListener_bsd.cpp
index b8702c5aa76..a79df5dbdd4 100644
--- a/src/hotspot/os/bsd/attachListener_bsd.cpp
+++ b/src/hotspot/os/bsd/attachListener_bsd.cpp
@@ -247,7 +247,7 @@ int BsdAttachListener::init() {
//
BsdAttachOperation* BsdAttachListener::read_request(int s) {
char ver_str[8];
- sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
+ size_t ver_str_len = os::snprintf_checked(ver_str, sizeof(ver_str), "%d", ATTACH_PROTOCOL_VER);
// The request is a sequence of strings so we first figure out the
// expected count and the maximum possible length of the request.
@@ -287,11 +287,11 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) {
// The first string is so check it now to
// check for protocol mis-match
if (str_count == 1) {
- if ((strlen(buf) != strlen(ver_str)) ||
+ if ((strlen(buf) != ver_str_len) ||
(atoi(buf) != ATTACH_PROTOCOL_VER)) {
char msg[32];
- sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
- write_fully(s, msg, strlen(msg));
+ int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", ATTACH_ERROR_BADVERSION);
+ write_fully(s, msg, msg_len);
return NULL;
}
}
@@ -410,8 +410,8 @@ void BsdAttachOperation::complete(jint result, bufferedStream* st) {
// write operation result
char msg[32];
- sprintf(msg, "%d\n", result);
- int rc = BsdAttachListener::write_fully(this->socket(), msg, strlen(msg));
+ int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", result);
+ int rc = BsdAttachListener::write_fully(this->socket(), msg, msg_len);
// write any result data
if (rc == 0) {
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 071045c6a6e..65101650372 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -338,7 +338,7 @@ void os::init_system_properties_values() {
#ifndef __APPLE__
- // Buffer that fits several sprintfs.
+ // Buffer that fits several snprintfs.
// Note that the space for the colon and the trailing null are provided
// by the nulls included by the sizeof operator.
const size_t bufsize =
@@ -394,17 +394,16 @@ void os::init_system_properties_values() {
const char *v_colon = ":";
if (v == NULL) { v = ""; v_colon = ""; }
// That's +1 for the colon and +1 for the trailing '\0'.
- char *ld_library_path = NEW_C_HEAP_ARRAY(char,
- strlen(v) + 1 +
- sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1,
- mtInternal);
- sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
+ const size_t ld_library_path_size = strlen(v) + 1 + sizeof(SYS_EXT_DIR) +
+ sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1;
+ char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal);
+ os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
}
// Extensions directories.
- sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
+ os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
Arguments::set_ext_dirs(buf);
FREE_C_HEAP_ARRAY(char, buf);
@@ -419,7 +418,7 @@ void os::init_system_properties_values() {
size_t system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) +
sizeof(SYS_EXTENSIONS_DIRS);
- // Buffer that fits several sprintfs.
+ // Buffer that fits several snprintfs.
// Note that the space for the colon and the trailing null are provided
// by the nulls included by the sizeof operator.
const size_t bufsize =
@@ -489,11 +488,9 @@ void os::init_system_properties_values() {
// could cause a change in behavior, but Apple's Java6 behavior
// can be achieved by putting "." at the beginning of the
// JAVA_LIBRARY_PATH environment variable.
- char *ld_library_path = NEW_C_HEAP_ARRAY(char,
- strlen(v) + 1 + strlen(l) + 1 +
- system_ext_size + 3,
- mtInternal);
- sprintf(ld_library_path, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.",
+ const size_t ld_library_path_size = strlen(v) + 1 + strlen(l) + 1 + system_ext_size + 3;
+ char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal);
+ os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.",
v, v_colon, l, l_colon, user_home_dir);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
@@ -504,7 +501,7 @@ void os::init_system_properties_values() {
// Note that the space for the colon and the trailing null are provided
// by the nulls included by the sizeof operator (so actually one byte more
// than necessary is allocated).
- sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS,
+ os::snprintf_checked(buf, bufsize, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS,
user_home_dir, Arguments::get_java_home());
Arguments::set_ext_dirs(buf);
@@ -1609,7 +1606,7 @@ bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
#if defined(__OpenBSD__)
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
if (::mprotect(addr, size, prot) == 0) {
return true;
}
@@ -1711,7 +1708,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) {
#if defined(__OpenBSD__)
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with PROT_NONE", p2i(addr), p2i(addr+size));
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with PROT_NONE", p2i(addr), p2i(addr+size));
return ::mprotect(addr, size, PROT_NONE) == 0;
#elif defined(__APPLE__)
if (exec) {
@@ -1781,7 +1778,7 @@ static bool bsd_mprotect(char* addr, size_t size, int prot) {
assert(addr == bottom, "sanity check");
size = align_up(pointer_delta(addr, bottom, 1) + size, os::Bsd::page_size());
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(bottom), p2i(bottom+size), prot);
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(bottom), p2i(bottom+size), prot);
return ::mprotect(bottom, size, prot) == 0;
}
@@ -2090,16 +2087,25 @@ jint os::init_2(void) {
if (status != 0) {
log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno));
} else {
- nbr_files.rlim_cur = nbr_files.rlim_max;
-
-#ifdef __APPLE__
- // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if
- // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must
- // be used instead
- nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur);
-#endif
+ rlim_t rlim_original = nbr_files.rlim_cur;
+
+ // On macOS according to setrlimit(2), OPEN_MAX must be used instead
+ // of RLIM_INFINITY, but testing on macOS >= 10.6, reveals that
+ // we can, in fact, use even RLIM_INFINITY, so try the max value
+ // that the system claims can be used first, same as other BSD OSes.
+ // However, some terminals (ksh) will internally use "int" type
+ // to store this value and since RLIM_INFINITY overflows an "int"
+ // we might end up with a negative value, so cap the system limit max
+ // at INT_MAX instead, just in case, for everyone.
+ nbr_files.rlim_cur = MIN(INT_MAX, nbr_files.rlim_max);
status = setrlimit(RLIMIT_NOFILE, &nbr_files);
+ if (status != 0) {
+ // If that fails then try lowering the limit to either OPEN_MAX
+ // (which is safe) or the original limit, whichever was greater.
+ nbr_files.rlim_cur = MAX(OPEN_MAX, rlim_original);
+ status = setrlimit(RLIMIT_NOFILE, &nbr_files);
+ }
if (status != 0) {
log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno));
}
diff --git a/src/hotspot/os/bsd/os_perf_bsd.cpp b/src/hotspot/os/bsd/os_perf_bsd.cpp
index e69bfc79558..546cef8edc5 100644
--- a/src/hotspot/os/bsd/os_perf_bsd.cpp
+++ b/src/hotspot/os/bsd/os_perf_bsd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -39,6 +39,7 @@
#include
#include
#include
+ #include
#endif
static const double NANOS_PER_SEC = 1000000000.0;
@@ -46,10 +47,10 @@ static const double NANOS_PER_SEC = 1000000000.0;
class CPUPerformanceInterface::CPUPerformance : public CHeapObj {
friend class CPUPerformanceInterface;
private:
- long _total_cpu_nanos;
+ uint64_t _jvm_real;
long _total_csr_nanos;
- long _jvm_user_nanos;
- long _jvm_system_nanos;
+ uint64_t _jvm_user;
+ uint64_t _jvm_system;
long _jvm_context_switches;
long _used_ticks;
long _total_ticks;
@@ -83,11 +84,11 @@ class CPUPerformanceInterface::CPUPerformance : public CHeapObj {
};
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
- _total_cpu_nanos= 0;
- _total_csr_nanos= 0;
+ _jvm_real = 0;
+ _total_csr_nanos = 0;
_jvm_context_switches = 0;
- _jvm_user_nanos = 0;
- _jvm_system_nanos = 0;
+ _jvm_user = 0;
+ _jvm_system = 0;
_used_ticks = 0;
_total_ticks = 0;
_active_processor_count = 0;
@@ -148,42 +149,35 @@ int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
#ifdef __APPLE__
int result = cpu_load_total_process(psystemTotalLoad);
- mach_port_t task = mach_task_self();
- mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
- task_info_data_t task_info_data;
- kern_return_t kr = task_info(task, TASK_ABSOLUTETIME_INFO, (task_info_t)task_info_data, &task_info_count);
- if (kr != KERN_SUCCESS) {
+
+ struct tms buf;
+ clock_t jvm_real = times(&buf);
+ if (jvm_real == (clock_t) (-1)) {
return OS_ERR;
}
- task_absolutetime_info_t absolutetime_info = (task_absolutetime_info_t)task_info_data;
int active_processor_count = os::active_processor_count();
- long jvm_user_nanos = absolutetime_info->total_user;
- long jvm_system_nanos = absolutetime_info->total_system;
-
- long total_cpu_nanos;
- if(!now_in_nanos(&total_cpu_nanos)) {
- return OS_ERR;
- }
+ uint64_t jvm_user = buf.tms_utime;
+ uint64_t jvm_system = buf.tms_stime;
- if (_total_cpu_nanos == 0 || active_processor_count != _active_processor_count) {
- // First call or change in active processor count
+ if (active_processor_count != _active_processor_count) {
+ // Change in active processor count
result = OS_ERR;
- }
+ } else {
+ uint64_t delta = active_processor_count * (jvm_real - _jvm_real);
+ if (delta == 0) {
+ // Avoid division by zero
+ return OS_ERR;
+ }
- long delta_nanos = active_processor_count * (total_cpu_nanos - _total_cpu_nanos);
- if (delta_nanos == 0) {
- // Avoid division by zero
- return OS_ERR;
+ *pjvmUserLoad = normalize((double)(jvm_user - _jvm_user) / delta);
+ *pjvmKernelLoad = normalize((double)(jvm_system - _jvm_system) / delta);
}
- *pjvmUserLoad = normalize((double)(jvm_user_nanos - _jvm_user_nanos)/delta_nanos);
- *pjvmKernelLoad = normalize((double)(jvm_system_nanos - _jvm_system_nanos)/delta_nanos);
-
_active_processor_count = active_processor_count;
- _total_cpu_nanos = total_cpu_nanos;
- _jvm_user_nanos = jvm_user_nanos;
- _jvm_system_nanos = jvm_system_nanos;
+ _jvm_real = jvm_real;
+ _jvm_user = jvm_user;
+ _jvm_system = jvm_system;
return result;
#else
diff --git a/src/hotspot/os/linux/attachListener_linux.cpp b/src/hotspot/os/linux/attachListener_linux.cpp
index 0ce76721ec3..ecdd21a4869 100644
--- a/src/hotspot/os/linux/attachListener_linux.cpp
+++ b/src/hotspot/os/linux/attachListener_linux.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -182,6 +182,8 @@ int LinuxAttachListener::init() {
char initial_path[UNIX_PATH_MAX]; // socket file during setup
int listener; // listener socket (file descriptor)
+ static_assert(sizeof(off_t) == 8, "Expected Large File Support in this file");
+
// register function to cleanup
if (!_atexit_registered) {
_atexit_registered = true;
@@ -247,7 +249,7 @@ int LinuxAttachListener::init() {
//
LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
char ver_str[8];
- sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
+ os::snprintf_checked(ver_str, sizeof(ver_str), "%d", ATTACH_PROTOCOL_VER);
// The request is a sequence of strings so we first figure out the
// expected count and the maximum possible length of the request.
@@ -290,7 +292,7 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
if ((strlen(buf) != strlen(ver_str)) ||
(atoi(buf) != ATTACH_PROTOCOL_VER)) {
char msg[32];
- sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
+ os::snprintf_checked(msg, sizeof(msg), "%d\n", ATTACH_ERROR_BADVERSION);
write_fully(s, msg, strlen(msg));
return NULL;
}
@@ -384,7 +386,7 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() {
// write the given buffer to the socket
int LinuxAttachListener::write_fully(int s, char* buf, int len) {
do {
- int n = ::write(s, buf, len);
+ ssize_t n = ::write(s, buf, len);
if (n == -1) {
if (errno != EINTR) return -1;
} else {
@@ -410,7 +412,7 @@ void LinuxAttachOperation::complete(jint result, bufferedStream* st) {
// write operation result
char msg[32];
- sprintf(msg, "%d\n", result);
+ os::snprintf_checked(msg, sizeof(msg), "%d\n", result);
int rc = LinuxAttachListener::write_fully(this->socket(), msg, strlen(msg));
// write any result data
@@ -444,14 +446,14 @@ AttachOperation* AttachListener::dequeue() {
void AttachListener::vm_start() {
char fn[UNIX_PATH_MAX];
- struct stat64 st;
+ struct stat st;
int ret;
int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
- RESTARTABLE(::stat64(fn, &st), ret);
+ RESTARTABLE(::stat(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
@@ -471,8 +473,8 @@ int AttachListener::pd_init() {
bool AttachListener::check_socket_file() {
int ret;
- struct stat64 st;
- ret = stat64(LinuxAttachListener::path(), &st);
+ struct stat st;
+ ret = stat(LinuxAttachListener::path(), &st);
if (ret == -1) { // need to restart attach listener.
log_debug(attach)("Socket file %s does not exist - Restart Attach Listener",
LinuxAttachListener::path());
@@ -511,14 +513,14 @@ bool AttachListener::is_init_trigger() {
}
char fn[PATH_MAX + 1];
int ret;
- struct stat64 st;
- sprintf(fn, ".attach_pid%d", os::current_process_id());
- RESTARTABLE(::stat64(fn, &st), ret);
+ struct stat st;
+ os::snprintf_checked(fn, sizeof(fn), ".attach_pid%d", os::current_process_id());
+ RESTARTABLE(::stat(fn, &st), ret);
if (ret == -1) {
log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
os::get_temp_directory(), os::current_process_id());
- RESTARTABLE(::stat64(fn, &st), ret);
+ RESTARTABLE(::stat(fn, &st), ret);
if (ret == -1) {
log_debug(attach)("Failed to find attach file: %s", fn);
}
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 63b7562f118..7c951cee51c 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -430,7 +430,7 @@ void os::init_system_properties_values() {
#define SYS_EXT_DIR "/usr/java/packages"
#define EXTENSIONS_DIR "/lib/ext"
- // Buffer that fits several sprintfs.
+ // Buffer that fits several snprintfs.
// Note that the space for the colon and the trailing null are provided
// by the nulls included by the sizeof operator.
const size_t bufsize =
@@ -485,17 +485,15 @@ void os::init_system_properties_values() {
const char *v_colon = ":";
if (v == NULL) { v = ""; v_colon = ""; }
// That's +1 for the colon and +1 for the trailing '\0'.
- char *ld_library_path = NEW_C_HEAP_ARRAY(char,
- strlen(v) + 1 +
- sizeof(SYS_EXT_DIR) + sizeof("/lib/") + sizeof(DEFAULT_LIBPATH) + 1,
- mtInternal);
- sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib:" DEFAULT_LIBPATH, v, v_colon);
+ size_t pathsize = strlen(v) + 1 + sizeof(SYS_EXT_DIR) + sizeof("/lib/") + sizeof(DEFAULT_LIBPATH) + 1;
+ char *ld_library_path = NEW_C_HEAP_ARRAY(char, pathsize, mtInternal);
+ os::snprintf_checked(ld_library_path, pathsize, "%s%s" SYS_EXT_DIR "/lib:" DEFAULT_LIBPATH, v, v_colon);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
}
// Extensions directories.
- sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
+ os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
Arguments::set_ext_dirs(buf);
FREE_C_HEAP_ARRAY(char, buf);
@@ -2745,6 +2743,8 @@ int os::vm_allocation_granularity() {
void linux_wrap_code(char* base, size_t size) {
static volatile jint cnt = 0;
+ static_assert(sizeof(off_t) == 8, "Expected Large File Support in this file");
+
if (!UseOprofile) {
return;
}
@@ -3589,7 +3589,7 @@ static bool linux_mprotect(char* addr, size_t size, int prot) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if (addr != g_assert_poison)
#endif
- Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(bottom), p2i(bottom+size), prot);
+ Events::log_memprotect(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(bottom), p2i(bottom+size), prot);
return ::mprotect(bottom, size, prot) == 0;
}
@@ -4992,14 +4992,14 @@ int os::open(const char *path, int oflag, int mode) {
oflag |= O_CLOEXEC;
#endif
- int fd = ::open64(path, oflag, mode);
+ int fd = ::open(path, oflag, mode);
if (fd == -1) return -1;
//If the open succeeded, the file might still be a directory
{
- struct stat64 buf64;
- int ret = ::fstat64(fd, &buf64);
- int st_mode = buf64.st_mode;
+ struct stat buf;
+ int ret = ::fstat(fd, &buf);
+ int st_mode = buf.st_mode;
if (ret != -1) {
if ((st_mode & S_IFMT) == S_IFDIR) {
@@ -5036,17 +5036,17 @@ int os::open(const char *path, int oflag, int mode) {
int os::create_binary_file(const char* path, bool rewrite_existing) {
int oflags = O_WRONLY | O_CREAT;
oflags |= rewrite_existing ? O_TRUNC : O_EXCL;
- return ::open64(path, oflags, S_IREAD | S_IWRITE);
+ return ::open(path, oflags, S_IREAD | S_IWRITE);
}
// return current position of file pointer
jlong os::current_file_offset(int fd) {
- return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR);
+ return (jlong)::lseek(fd, (off_t)0, SEEK_CUR);
}
// move file pointer to the specified offset
jlong os::seek_to_file_offset(int fd, jlong offset) {
- return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
+ return (jlong)::lseek(fd, (off_t)offset, SEEK_SET);
}
// This code originates from JDK's sysAvailable
@@ -5055,10 +5055,10 @@ jlong os::seek_to_file_offset(int fd, jlong offset) {
int os::available(int fd, jlong *bytes) {
jlong cur, end;
int mode;
- struct stat64 buf64;
+ struct stat buf;
- if (::fstat64(fd, &buf64) >= 0) {
- mode = buf64.st_mode;
+ if (::fstat(fd, &buf) >= 0) {
+ mode = buf.st_mode;
if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
int n;
if (::ioctl(fd, FIONREAD, &n) >= 0) {
@@ -5067,11 +5067,11 @@ int os::available(int fd, jlong *bytes) {
}
}
}
- if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) {
+ if ((cur = ::lseek(fd, 0L, SEEK_CUR)) == -1) {
return 0;
- } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) {
+ } else if ((end = ::lseek(fd, 0L, SEEK_END)) == -1) {
return 0;
- } else if (::lseek64(fd, cur, SEEK_SET) == -1) {
+ } else if (::lseek(fd, cur, SEEK_SET) == -1) {
return 0;
}
*bytes = end - cur;
diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp
index 7c42379a0a7..c37e25c42eb 100644
--- a/src/hotspot/os/linux/os_perf_linux.cpp
+++ b/src/hotspot/os/linux/os_perf_linux.cpp
@@ -847,7 +847,7 @@ SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
_dir = os::opendir("/proc");
_entry = NULL;
- _valid = true;
+ _valid = _dir != NULL; // May be null if /proc is not accessible.
next_process();
return true;
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index 370396bb9c6..4307a189edf 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -279,6 +279,7 @@ static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) {
}
static int util_posix_fallocate(int fd, off_t offset, off_t len) {
+ static_assert(sizeof(off_t) == 8, "Expected Large File Support in this file");
#ifdef __APPLE__
fstore_t store = { F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len };
// First we try to get a continuous chunk of disk space
@@ -720,7 +721,7 @@ void os::dll_unload(void *lib) {
}
jlong os::lseek(int fd, jlong offset, int whence) {
- return (jlong) BSD_ONLY(::lseek) NOT_BSD(::lseek64)(fd, offset, whence);
+ return (jlong) AIX_ONLY(::lseek64) NOT_AIX(::lseek)(fd, offset, whence);
}
int os::fsync(int fd) {
@@ -728,7 +729,7 @@ int os::fsync(int fd) {
}
int os::ftruncate(int fd, jlong length) {
- return BSD_ONLY(::ftruncate) NOT_BSD(::ftruncate64)(fd, length);
+ return AIX_ONLY(::ftruncate64) NOT_AIX(::ftruncate)(fd, length);
}
const char* os::get_current_directory(char *buf, size_t buflen) {
@@ -739,9 +740,9 @@ FILE* os::open(int fd, const char* mode) {
return ::fdopen(fd, mode);
}
-size_t os::write(int fd, const void *buf, unsigned int nBytes) {
- size_t res;
- RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
+ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
+ ssize_t res;
+ RESTARTABLE(::write(fd, buf, nBytes), res);
return res;
}
diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp
index c1f9601cff9..261921adec4 100644
--- a/src/hotspot/os/posix/os_posix.hpp
+++ b/src/hotspot/os/posix/os_posix.hpp
@@ -27,7 +27,7 @@
// Note: the Posix API aims to capture functionality available on all Posix
// compliant platforms, but in practice the implementations may depend on
-// non-Posix functionality. For example, the use of lseek64 and ftruncate64.
+// non-Posix functionality.
// This use of non-Posix API's is made possible by compiling/linking in a mode
// that is not restricted to being fully Posix complaint, such as by declaring
// -D_GNU_SOURCE. But be aware that in doing so we may enable non-Posix
diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp
index 5d3416e2869..5652802aac2 100644
--- a/src/hotspot/os/posix/perfMemory_posix.cpp
+++ b/src/hotspot/os/posix/perfMemory_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -89,38 +89,25 @@ static void save_memory_to_file(char* addr, size_t size) {
const char* destfile = PerfMemory::get_perfdata_file_path();
assert(destfile[0] != '\0', "invalid PerfData file path");
- int result;
+ int fd;
- RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR),
- result);
- if (result == OS_ERR) {
- if (PrintMiscellaneous && Verbose) {
- warning("Could not create Perfdata save file: %s: %s\n",
- destfile, os::strerror(errno));
- }
+ RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR), fd);
+ if (fd == OS_ERR) {
+ warning("Could not create Perfdata save file: %s: %s\n",
+ destfile, os::strerror(errno));
} else {
- int fd = result;
+ ssize_t result;
- for (size_t remaining = size; remaining > 0;) {
-
- RESTARTABLE(::write(fd, addr, remaining), result);
- if (result == OS_ERR) {
- if (PrintMiscellaneous && Verbose) {
- warning("Could not write Perfdata save file: %s: %s\n",
- destfile, os::strerror(errno));
- }
- break;
- }
-
- remaining -= (size_t)result;
- addr += result;
+ bool successful_write = os::write(fd, addr, size);
+ if (!successful_write) {
+ warning("Could not write Perfdata save file: %s: %s\n",
+ destfile, os::strerror(errno));
}
+
result = ::close(fd);
- if (PrintMiscellaneous && Verbose) {
- if (result == OS_ERR) {
- warning("Could not close %s: %s\n", destfile, os::strerror(errno));
- }
+ if (result == OS_ERR) {
+ warning("Could not close %s: %s\n", destfile, os::strerror(errno));
}
}
FREE_C_HEAP_ARRAY(char, destfile);
@@ -880,9 +867,9 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
- int result;
- RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), result);
- if (result == OS_ERR) {
+ int fd;
+ RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), fd);
+ if (fd == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
@@ -898,9 +885,6 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
- // save the file descriptor
- int fd = result;
-
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
@@ -933,6 +917,8 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
}
#endif
+ ssize_t result;
+
// truncate the file to get rid of any existing data
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
@@ -959,11 +945,11 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
int zero_int = 0;
result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
if (result == -1 ) break;
- RESTARTABLE(::write(fd, &zero_int, 1), result);
- if (result != 1) {
+ if (!os::write(fd, &zero_int, 1)) {
if (errno == ENOSPC) {
warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
}
+ result = OS_ERR;
break;
}
}
@@ -971,7 +957,7 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
if (result != -1) {
return fd;
} else {
- ::close(fd);
+ os::close(fd);
return -1;
}
}
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index d3d359e90c2..c4b82d4f6a1 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -385,8 +385,9 @@ void os::init_system_properties_values() {
char path[MAX_PATH];
char buf[2 * MAX_PATH + 2 * sizeof(EXT_DIR) + sizeof(PACKAGE_DIR) + 1];
GetWindowsDirectory(path, MAX_PATH);
- sprintf(buf, "%s%s;%s%s%s", Arguments::get_java_home(), EXT_DIR,
- path, PACKAGE_DIR, EXT_DIR);
+ os::snprintf_checked(buf, sizeof(buf), "%s%s;%s%s%s",
+ Arguments::get_java_home(), EXT_DIR,
+ path, PACKAGE_DIR, EXT_DIR);
Arguments::set_ext_dirs(buf);
}
#undef EXT_DIR
@@ -4842,8 +4843,19 @@ FILE* os::open(int fd, const char* mode) {
return ::_fdopen(fd, mode);
}
-size_t os::write(int fd, const void *buf, unsigned int nBytes) {
- return ::write(fd, buf, nBytes);
+ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
+ ssize_t original_len = (ssize_t)nBytes;
+ while (nBytes > 0) {
+ unsigned int len = nBytes > INT_MAX ? INT_MAX : (unsigned int)nBytes;
+ // On Windows, ::write takes 'unsigned int' no of bytes, so nBytes should be split if larger.
+ ssize_t written_bytes = ::write(fd, buf, len);
+ if (written_bytes < 0) {
+ return OS_ERR;
+ }
+ nBytes -= written_bytes;
+ buf = (char *)buf + written_bytes;
+ }
+ return original_len;
}
int os::close(int fd) {
diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
index f8e6787505b..f3b80be3c02 100644
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -253,7 +253,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
stub = SharedRuntime::get_handle_wrong_method_stub();
}
- else if ((sig == USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV) &&
+ else if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) &&
// A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults
// in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6),
// especially when we try to read from the safepoint polling page. So the check
diff --git a/src/hotspot/share/adlc/adlc.hpp b/src/hotspot/share/adlc/adlc.hpp
index 19567f05d40..ec3a0c4e153 100644
--- a/src/hotspot/share/adlc/adlc.hpp
+++ b/src/hotspot/share/adlc/adlc.hpp
@@ -108,4 +108,8 @@ typedef unsigned int uintptr_t;
// it everywhere it needs to be available.
extern ArchDesc* globalAD;
+// Performs snprintf and asserts the result is non-negative (so there was not
+// an encoding error) and that the output was not truncated.
+extern int snprintf_checked(char* buf, size_t len, const char* fmt, ...);
+
#endif // SHARE_ADLC_ADLC_HPP
diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp
index 283713bb1f8..bcbf3ab7e1b 100644
--- a/src/hotspot/share/adlc/adlparse.cpp
+++ b/src/hotspot/share/adlc/adlparse.cpp
@@ -211,8 +211,9 @@ void ADLParser::instr_parse(void) {
return;
}
assert(match_rules_cnt < 100," too many match rule clones");
- char* buf = (char*) AdlAllocateHeap(strlen(instr->_ident) + 4);
- sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++);
+ const size_t buf_size = strlen(instr->_ident) + 4;
+ char* buf = (char*) AdlAllocateHeap(buf_size);
+ snprintf_checked(buf, buf_size, "%s_%d", instr->_ident, match_rules_cnt++);
rule->_result = buf;
// Check for commutative operations with tree operands.
matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
@@ -2805,8 +2806,9 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) {
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
const char* prefix = "__ins_encode_";
- char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1);
- sprintf(ec_name, "%s%s", prefix, inst._ident);
+ const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1;
+ char* ec_name = (char*) AdlAllocateHeap(ec_name_size);
+ snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident);
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
EncClass* encoding = _AD._encode->add_EncClass(ec_name);
@@ -3276,8 +3278,9 @@ void ADLParser::constant_parse(InstructForm& inst) {
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
const char* prefix = "__constant_";
- char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1);
- sprintf(ec_name, "%s%s", prefix, inst._ident);
+ const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1;
+ char* ec_name = (char*) AdlAllocateHeap(ec_name_size);
+ snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident);
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
EncClass* encoding = _AD._encode->add_EncClass(ec_name);
@@ -4596,8 +4599,9 @@ char *ADLParser::get_ident_or_literal_constant(const char* description) {
// Grab a constant expression.
param = get_paren_expr(description);
if (param[0] != '(') {
- char* buf = (char*) AdlAllocateHeap(strlen(param) + 3);
- sprintf(buf, "(%s)", param);
+ const size_t buf_size = strlen(param) + 3;
+ char* buf = (char*) AdlAllocateHeap(buf_size);
+ snprintf_checked(buf, buf_size, "(%s)", param);
param = buf;
}
assert(is_literal_constant(param),
@@ -5204,8 +5208,9 @@ void ADLParser::next_line() {
char* ADLParser::get_line_string(int linenum) {
const char* file = _AD._ADL_file._name;
int line = linenum ? linenum : this->linenum();
- char* location = (char *)AdlAllocateHeap(strlen(file) + 100);
- sprintf(location, "\n#line %d \"%s\"\n", line, file);
+ const size_t location_size = strlen(file) + 100;
+ char* location = (char *)AdlAllocateHeap(location_size);
+ snprintf_checked(location, location_size, "\n#line %d \"%s\"\n", line, file);
return location;
}
diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp
index cd9aab9e2ed..1d83cb18117 100644
--- a/src/hotspot/share/adlc/archDesc.cpp
+++ b/src/hotspot/share/adlc/archDesc.cpp
@@ -815,7 +815,7 @@ static const char *getRegMask(const char *reg_class_name) {
const char *mask = "_mask";
int length = (int)strlen(rc_name) + (int)strlen(mask) + 5;
char *regMask = new char[length];
- sprintf(regMask,"%s%s()", rc_name, mask);
+ snprintf_checked(regMask, length, "%s%s()", rc_name, mask);
delete[] rc_name;
return regMask;
}
@@ -908,7 +908,7 @@ char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) {
const char *stack_or = "STACK_OR_";
int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1;
char *result = new char[length];
- sprintf(result,"%s%s", stack_or, reg_mask_name);
+ snprintf_checked(result, length, "%s%s", stack_or, reg_mask_name);
return result;
}
diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp
index 5abc4365297..b277c5c63f0 100644
--- a/src/hotspot/share/adlc/dfa.cpp
+++ b/src/hotspot/share/adlc/dfa.cpp
@@ -207,13 +207,13 @@ Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, Produc
Expr *c = new Expr("0");
if (mList._lchild) { // If left child, add it in
const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild);
- sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper);
+ snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[0]->_cost[%s]", lchild_to_upper);
c->add(Expr::buffer());
delete[] lchild_to_upper;
}
if (mList._rchild) { // If right child, add it in
const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild);
- sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper);
+ snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[1]->_cost[%s]", rchild_to_upper);
c->add(Expr::buffer());
delete[] rchild_to_upper;
}
@@ -730,7 +730,7 @@ const char *Expr::compute_expr(const Expr *c1, const Expr *c2) {
snprintf(string_buffer, STRING_BUFFER_LENGTH, "%s", c2->_expr);
}
else {
- sprintf( string_buffer, "0");
+ snprintf_checked(string_buffer, STRING_BUFFER_LENGTH, "0");
}
string_buffer[STRING_BUFFER_LENGTH - 1] = '\0';
char *cost = strdup(string_buffer);
diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp
index 854b1b310e4..b45f432dac9 100644
--- a/src/hotspot/share/adlc/formssel.cpp
+++ b/src/hotspot/share/adlc/formssel.cpp
@@ -25,6 +25,8 @@
// FORMS.CPP - Definitions for ADL Parser Forms Classes
#include "adlc.hpp"
+#define remaining_buflen(buffer, position) (sizeof(buffer) - ((position) - (buffer)))
+
//==============================Instructions===================================
//------------------------------InstructForm-----------------------------------
InstructForm::InstructForm(const char *id, bool ideal_only)
@@ -1303,7 +1305,7 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
// Handle special constant table variables.
if (strcmp(rep_var, "constanttablebase") == 0) {
- fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n");
+ fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg, sizeof(reg));\n");
fprintf(fp, " st->print(\"%%s\", reg);\n");
return;
}
@@ -1538,7 +1540,7 @@ Predicate *InstructForm::build_predicate() {
s += strlen(s);
}
// Add predicate to working buffer
- sprintf(s,"/*%s*/(",(char*)i._key);
+ snprintf_checked(s, remaining_buflen(buf, s), "/*%s*/(",(char*)i._key);
s += strlen(s);
mnode->build_instr_pred(s,(char*)i._key, 0, path_bitmask, 0);
s += strlen(s);
@@ -2501,7 +2503,7 @@ void OperandForm::int_format(FILE *fp, FormDict &globals, uint index) {
strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {
// !!!!! !!!!!
fprintf(fp," { char reg_str[128];\n");
- fprintf(fp," ra->dump_register(node,reg_str);\n");
+ fprintf(fp," ra->dump_register(node,reg_str, sizeof(reg_str));\n");
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n");
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
@@ -2509,7 +2511,7 @@ void OperandForm::int_format(FILE *fp, FormDict &globals, uint index) {
} else if (ideal_to_sReg_type(_ident) != Form::none) {
// Special format for Stack Slot Register
fprintf(fp," { char reg_str[128];\n");
- fprintf(fp," ra->dump_register(node,reg_str);\n");
+ fprintf(fp," ra->dump_register(node,reg_str, sizeof(reg_str));\n");
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n");
} else {
@@ -2530,7 +2532,7 @@ void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) {
fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node->in(idx");
if ( index != 0 ) fprintf(fp, "+%d",index);
- fprintf(fp, "),reg_str);\n");
+ fprintf(fp, "),reg_str,sizeof(reg_str));\n");
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n");
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
@@ -2540,7 +2542,7 @@ void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) {
fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node->in(idx");
if ( index != 0 ) fprintf(fp, "+%d",index);
- fprintf(fp, "),reg_str);\n");
+ fprintf(fp, "),reg_str,sizeof(reg_str));\n");
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n");
} else {
@@ -3476,7 +3478,7 @@ void MatchNode::build_internalop( ) {
_rChild->_internalop : _rChild->_opType) : "";
len += (int)strlen(lstr) + (int)strlen(rstr);
subtree = (char *)AdlAllocateHeap(len);
- sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr);
+ snprintf_checked(subtree, len, "_%s_%s_%s", _opType, lstr, rstr);
// Hash the subtree string in _internalOps; if a name exists, use it
iop = (char *)_AD._internalOps[subtree];
// Else create a unique name, and add it to the hash table
@@ -3898,8 +3900,9 @@ void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count
MatchRule* clone = new MatchRule(_AD, this);
// Swap operands of commutative operation
((MatchNode*)clone)->swap_commutative_op(true, count);
- char* buf = (char*) AdlAllocateHeap(strlen(instr_ident) + 4);
- sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++);
+ const size_t buf_size = strlen(instr_ident) + 4;
+ char* buf = (char*) AdlAllocateHeap(buf_size);
+ snprintf_checked(buf, buf_size, "%s_%d", instr_ident, match_rules_cnt++);
clone->_result = buf;
clone->_next = this->_next;
diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp
index 6f6c1bc6e30..5ffd258dc96 100644
--- a/src/hotspot/share/adlc/main.cpp
+++ b/src/hotspot/share/adlc/main.cpp
@@ -467,7 +467,7 @@ static char *base_plus_suffix(const char* base, const char *suffix)
int len = (int)strlen(base) + (int)strlen(suffix) + 1;
char* fname = new char[len];
- sprintf(fname,"%s%s",base,suffix);
+ snprintf_checked(fname,len,"%s%s",base,suffix);
return fname;
}
diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp
index 0a183ab2602..5c7d7ab7e31 100644
--- a/src/hotspot/share/adlc/output_c.cpp
+++ b/src/hotspot/share/adlc/output_c.cpp
@@ -26,6 +26,8 @@
#include "adlc.hpp"
+#define remaining_buflen(buffer, position) (sizeof(buffer) - (position - buffer))
+
// Utilities to characterize effect statements
static bool is_def(int usedef) {
switch(usedef) {
@@ -35,6 +37,16 @@ static bool is_def(int usedef) {
return false;
}
+int snprintf_checked(char* buf, size_t len, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ int result = vsnprintf(buf, len, fmt, args);
+ va_end(args);
+ assert(result >= 0, "snprintf error");
+ assert(static_cast(result) < len, "snprintf truncated");
+ return result;
+}
+
// Define an array containing the machine register names, strings.
static void defineRegNames(FILE *fp, RegisterForm *registers) {
if (registers) {
@@ -197,7 +209,8 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi
return -1;
}
- char *operand_stages = new char [templen];
+ const size_t operand_stages_size = templen;
+ char *operand_stages = new char [operand_stages_size];
operand_stages[0] = 0;
int i = 0;
templen = 0;
@@ -211,7 +224,7 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi
while ( (paramname = pipeclass->_parameters.iter()) != NULL ) {
const PipeClassOperandForm *tmppipeopnd =
(const PipeClassOperandForm *)pipeclass->_localUsage[paramname];
- templen += sprintf(&operand_stages[templen], " stage_%s%c\n",
+ templen += snprintf_checked(&operand_stages[templen], operand_stages_size - templen, " stage_%s%c\n",
tmppipeopnd ? tmppipeopnd->_stage : "undefined",
(++i < paramcount ? ',' : ' ') );
}
@@ -278,6 +291,7 @@ static int pipeline_res_stages_initializer(
int templen = 1 + commentlen + pipeline->_rescount * (max_stage + 14);
// Allocate space for the resource list
+ const size_t resource_stages_size = templen;
char * resource_stages = new char [templen];
templen = 0;
@@ -285,7 +299,7 @@ static int pipeline_res_stages_initializer(
const char * const resname =
res_stages[i] == 0 ? "undefined" : pipeline->_stages.name(res_stages[i]-1);
- templen += sprintf(&resource_stages[templen], " stage_%s%-*s // %s\n",
+ templen += snprintf_checked(&resource_stages[templen], resource_stages_size - templen, " stage_%s%-*s // %s\n",
resname, max_stage - (int)strlen(resname) + 1,
(i < pipeline->_rescount-1) ? "," : "",
pipeline->_reslist.name(i));
@@ -344,7 +358,7 @@ static int pipeline_res_cycles_initializer(
for (i = 0; i < pipeline->_rescount; i++) {
if (max_cycles < res_cycles[i])
max_cycles = res_cycles[i];
- templen = sprintf(temp, "%d", res_cycles[i]);
+ templen = snprintf_checked(temp, sizeof(temp), "%d", res_cycles[i]);
if (cyclelen < templen)
cyclelen = templen;
commentlen += (int)strlen(pipeline->_reslist.name(i));
@@ -353,12 +367,13 @@ static int pipeline_res_cycles_initializer(
templen = 1 + commentlen + (cyclelen + 8) * pipeline->_rescount;
// Allocate space for the resource list
- char * resource_cycles = new char [templen];
+ const size_t resource_cycles_size = templen;
+ char * resource_cycles = new char [resource_cycles_size];
templen = 0;
for (i = 0; i < pipeline->_rescount; i++) {
- templen += sprintf(&resource_cycles[templen], " %*d%c // %s\n",
+ templen += snprintf_checked(&resource_cycles[templen], resource_cycles_size - templen, " %*d%c // %s\n",
cyclelen, res_cycles[i], (i < pipeline->_rescount-1) ? ',' : ' ', pipeline->_reslist.name(i));
}
@@ -431,7 +446,8 @@ static int pipeline_res_mask_initializer(
(cyclemasksize * 12) + masklen + (cycledigit * 2) + 30) * element_count;
// Allocate space for the resource list
- char * resource_mask = new char [templen];
+ const size_t resource_mask_size = templen;
+ char * resource_mask = new char [resource_mask_size];
char * last_comma = NULL;
templen = 0;
@@ -456,7 +472,7 @@ static int pipeline_res_mask_initializer(
}
int formatlen =
- sprintf(&resource_mask[templen], " %s(0x%0*x, %*d, %*d, %s %s(",
+ snprintf_checked(&resource_mask[templen], resource_mask_size - templen, " %s(0x%0*x, %*d, %*d, %s %s(",
pipeline_use_element,
masklen, used_mask,
cycledigit, lb, cycledigit, ub,
@@ -496,7 +512,7 @@ static int pipeline_res_mask_initializer(
for (j = cyclemasksize-1; j >= 0; j--) {
formatlen =
- sprintf(&resource_mask[templen], "0x%08x%s", res_mask[j], j > 0 ? ", " : "");
+ snprintf_checked(&resource_mask[templen], resource_mask_size - templen, "0x%08x%s", res_mask[j], j > 0 ? ", " : "");
templen += formatlen;
}
@@ -527,9 +543,8 @@ static int pipeline_res_mask_initializer(
// "0x012345678, 0x012345678, 4294967295"
char* args = new char [36 + 1];
- int printed = sprintf(args, "0x%x, 0x%x, %u",
- resources_used, resources_used_exclusively, element_count);
- assert(printed <= 36, "overflow");
+ snprintf_checked(args, 36 + 1, "0x%x, 0x%x, %u",
+ resources_used, resources_used_exclusively, element_count);
pipeline_res_args.addName(args);
}
@@ -1066,9 +1081,9 @@ static void build_instruction_index_mapping( FILE *fp, FormDict &globals, PeepMa
InstructForm *inst = globals[inst_name]->is_instruction();
if( inst != NULL ) {
char inst_prefix[] = "instXXXX_";
- sprintf(inst_prefix, "inst%d_", inst_position);
+ snprintf_checked(inst_prefix, sizeof(inst_prefix), "inst%d_", inst_position);
char receiver[] = "instXXXX->";
- sprintf(receiver, "inst%d->", inst_position);
+ snprintf_checked(receiver, sizeof(receiver), "inst%d->", inst_position);
inst->index_temps( fp, globals, inst_prefix, receiver );
}
}
@@ -1162,7 +1177,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
char left_reg_index[] = ",inst4294967295_idx4294967295";
if( left_op_index != 0 ) {
// Must have index into operands
- sprintf(left_reg_index,",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index);
+ snprintf_checked(left_reg_index, sizeof(left_reg_index), ",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index);
} else {
strcpy(left_reg_index, "");
}
@@ -1174,7 +1189,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
char right_reg_index[] = ",inst4294967295_idx4294967295";
if( right_op_index != 0 ) {
// Must have index into operands
- sprintf(right_reg_index,",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index);
+ snprintf_checked(right_reg_index, sizeof(right_reg_index), ",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index);
} else {
strcpy(right_reg_index, "");
}
@@ -2516,19 +2531,19 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) {
const char* arg_name = ins_encode->rep_var_name(inst, param_no);
int idx = inst.operand_position_format(arg_name);
if (strcmp(arg_name, "constanttablebase") == 0) {
- ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n",
+ ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n",
name, type, arg_name);
- nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name);
+ nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name);
// There is no operand for the constanttablebase.
} else if (inst.is_noninput_operand(idx)) {
globalAD->syntax_err(inst._linenum,
"In %s: you can not pass the non-input %s to a postalloc expand encoding.\n",
inst._ident, arg_name);
} else {
- ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n",
+ ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n",
name, idx, type, arg_name);
- nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name);
- ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx);
+ nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name);
+ ob += snprintf_checked(ob, remaining_buflen(opbuf, ob), " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx);
}
param_no++;
}
diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp
index fb178432d8b..14cf71eb09a 100644
--- a/src/hotspot/share/c1/c1_Runtime1.cpp
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp
@@ -657,7 +657,7 @@ JRT_ENTRY(void, Runtime1::throw_range_check_exception(JavaThread* current, int i
const int len = 35;
assert(len < strlen("Index %d out of bounds for length %d"), "Must allocate more space for message.");
char message[2 * jintAsStringSize + len];
- sprintf(message, "Index %d out of bounds for length %d", index, a->length());
+ os::snprintf_checked(message, sizeof(message), "Index %d out of bounds for length %d", index, a->length());
SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message);
JRT_END
@@ -665,7 +665,7 @@ JRT_END
JRT_ENTRY(void, Runtime1::throw_index_exception(JavaThread* current, int index))
NOT_PRODUCT(_throw_index_exception_count++;)
char message[16];
- sprintf(message, "%d", index);
+ os::snprintf_checked(message, sizeof(message), "%d", index);
SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IndexOutOfBoundsException(), message);
JRT_END
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 242b57ee579..a045b18e41c 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -158,7 +158,7 @@ template static void get_header_version(char (&header_version) [N]) {
strncpy(header_version, vm_version, JVM_IDENT_MAX-9);
// Append the hash code as eight hex digits.
- sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
+ os::snprintf_checked(&header_version[JVM_IDENT_MAX-9], 9, "%08x", hash);
header_version[JVM_IDENT_MAX-1] = 0; // Null terminate.
}
@@ -1420,8 +1420,7 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray *heap_me
void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
assert(_file_open, "must be");
- size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
- if (n != nbytes) {
+ if (!os::write(_fd, buffer, nbytes)) {
// If the shared archive is corrupted, close it and remove it.
close();
remove(_full_path);
diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp
index 72a1e78838f..c1fb1d68f4b 100644
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp
@@ -186,7 +186,7 @@ void ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces() {
// on the stack or in the code cache, so we only have to repeat the full walk if
// they were found at that time.
// TODO: have redefinition clean old methods out of the code cache. They still exist in some places.
- bool walk_all_metadata = InstanceKlass::has_previous_versions_and_reset();
+ bool walk_all_metadata = InstanceKlass::should_clean_previous_versions_and_reset();
MetadataOnStackMark md_on_stack(walk_all_metadata, /*redefinition_walk*/false);
clean_deallocate_lists(walk_all_metadata);
diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp
index e5b51ac277c..e4b10f95656 100644
--- a/src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp
@@ -73,7 +73,7 @@ bool ClassLoaderDataGraph::should_clean_metaspaces_and_reset() {
// Only clean metaspaces after full GC.
bool do_cleaning = _safepoint_cleanup_needed;
#if INCLUDE_JVMTI
- do_cleaning = do_cleaning && (_should_clean_deallocate_lists || InstanceKlass::has_previous_versions());
+ do_cleaning = do_cleaning && (_should_clean_deallocate_lists || InstanceKlass::should_clean_previous_versions());
#else
do_cleaning = do_cleaning && _should_clean_deallocate_lists;
#endif
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
index bf817989dc1..cac737125f1 100644
--- a/src/hotspot/share/classfile/javaClasses.cpp
+++ b/src/hotspot/share/classfile/javaClasses.cpp
@@ -2375,17 +2375,18 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
}
// Allocate temporary buffer with extra space for formatting and line number
- char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
+ const size_t buf_size = buf_len + 64;
+ char* buf = NEW_RESOURCE_ARRAY(char, buf_size);
// Print stack trace line in buffer
- sprintf(buf, "\tat %s.%s(", klass_name, method_name);
+ size_t buf_off = os::snprintf_checked(buf, buf_size, "\tat %s.%s(", klass_name, method_name);
// Print module information
if (module_name != NULL) {
if (module_version != NULL) {
- sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version);
+ buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s@%s/", module_name, module_version);
} else {
- sprintf(buf + (int)strlen(buf), "%s/", module_name);
+ buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s/", module_name);
}
}
@@ -2400,17 +2401,17 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
} else {
if (source_file_name != NULL && (line_number != -1)) {
// Sourcename and linenumber
- sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number);
+ buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s:%d)", source_file_name, line_number);
} else if (source_file_name != NULL) {
// Just sourcename
- sprintf(buf + (int)strlen(buf), "%s)", source_file_name);
+ buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s)", source_file_name);
} else {
// Neither sourcename nor linenumber
- sprintf(buf + (int)strlen(buf), "Unknown Source)");
+ buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "Unknown Source)");
}
CompiledMethod* nm = method->code();
if (WizardMode && nm != NULL) {
- sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
+ os::snprintf_checked(buf + buf_off, buf_size - buf_off, "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
}
}
}
diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp
index b8cccbb934a..8df69fd6496 100644
--- a/src/hotspot/share/classfile/symbolTable.cpp
+++ b/src/hotspot/share/classfile/symbolTable.cpp
@@ -56,6 +56,31 @@ const size_t ON_STACK_BUFFER_LENGTH = 128;
// --------------------------------------------------------------------------
+Symbol* volatile TempSymbolCleanupDelayer::_queue[QueueSize] = {};
+volatile uint TempSymbolCleanupDelayer::_index = 0;
+
+// Keep this symbol alive for some time to allow for reuse.
+// Temp symbols for the same string can often be created in quick succession,
+// and this queue allows them to be reused instead of churning.
+void TempSymbolCleanupDelayer::delay_cleanup(Symbol* sym) {
+ assert(sym != nullptr, "precondition");
+ sym->increment_refcount();
+ uint i = Atomic::add(&_index, 1u) % QueueSize;
+ Symbol* old = Atomic::xchg(&_queue[i], sym);
+ if (old != nullptr) {
+ old->decrement_refcount();
+ }
+}
+
+void TempSymbolCleanupDelayer::drain_queue() {
+ for (uint i = 0; i < QueueSize; i++) {
+ Symbol* sym = Atomic::xchg(&_queue[i], (Symbol*) nullptr);
+ if (sym != nullptr) {
+ sym->decrement_refcount();
+ }
+ }
+}
+
inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
if (value->equals(key, len)) {
return true;
diff --git a/src/hotspot/share/classfile/symbolTable.hpp b/src/hotspot/share/classfile/symbolTable.hpp
index a0b7287f936..8441a52713e 100644
--- a/src/hotspot/share/classfile/symbolTable.hpp
+++ b/src/hotspot/share/classfile/symbolTable.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -33,6 +33,16 @@
class JavaThread;
template class GrowableArray;
+class TempSymbolCleanupDelayer : AllStatic {
+ static Symbol* volatile _queue[];
+ static volatile uint _index;
+
+public:
+ static const uint QueueSize = 128;
+ static void delay_cleanup(Symbol* s);
+ static void drain_queue();
+};
+
// TempNewSymbol acts as a handle class in a handle/body idiom and is
// responsible for proper resource management of the body (which is a Symbol*).
// The body is resource managed by a reference counting scheme.
@@ -54,7 +64,14 @@ class TempNewSymbol : public StackObj {
// Conversion from a Symbol* to a TempNewSymbol.
// Does not increment the current reference count.
- TempNewSymbol(Symbol *s) : _temp(s) {}
+ TempNewSymbol(Symbol *s) : _temp(s) {
+ // Delay cleanup for temp symbols. Refcount is incremented while in
+ // queue. But don't requeue existing entries, or entries that are held
+ // elsewhere - it's a waste of effort.
+ if (s != nullptr && s->refcount() == 1) {
+ TempSymbolCleanupDelayer::delay_cleanup(s);
+ }
+ }
// Copy constructor increments reference count.
TempNewSymbol(const TempNewSymbol& rhs) : _temp(rhs._temp) {
diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp
index 590cce18ba2..5ad53e9eca1 100644
--- a/src/hotspot/share/classfile/verifier.cpp
+++ b/src/hotspot/share/classfile/verifier.cpp
@@ -32,6 +32,7 @@
#include "classfile/stackMapTableFormat.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
+#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verifier.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
@@ -211,6 +212,12 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) {
exception_name == vmSymbols::java_lang_ClassFormatError())) {
log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
+ // Exclude any classes that fail over during dynamic dumping
+ if (CDS_ONLY(DynamicDumpSharedSpaces) NOT_CDS(false)) {
+ ResourceMark rm;
+ log_warning(cds)("Skipping %s: Failed over class verification while dynamic dumping", klass->name()->as_C_string());
+ SystemDictionaryShared::set_excluded(klass);
+ }
message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
exception_message = message_buffer;
exception_name = inference_verify(
diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp
index bca8b7dc9d0..f4753fd6cff 100644
--- a/src/hotspot/share/code/codeCache.cpp
+++ b/src/hotspot/share/code/codeCache.cpp
@@ -101,22 +101,37 @@ class CodeBlob_sizes {
scopes_pcs_size = 0;
}
- int total() { return total_size; }
- bool is_empty() { return count == 0; }
-
- void print(const char* title) {
- tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, metadata %d%%, data %d%%, pcs %d%%])",
- count,
- title,
- (int)(total() / K),
- header_size * 100 / total_size,
- relocation_size * 100 / total_size,
- code_size * 100 / total_size,
- stub_size * 100 / total_size,
- scopes_oop_size * 100 / total_size,
- scopes_metadata_size * 100 / total_size,
- scopes_data_size * 100 / total_size,
- scopes_pcs_size * 100 / total_size);
+ int total() const { return total_size; }
+ bool is_empty() const { return count == 0; }
+
+ void print(const char* title) const {
+ if (is_empty()) {
+ tty->print_cr(" #%d %s = %dK",
+ count,
+ title,
+ total() / (int)K);
+ } else {
+ tty->print_cr(" #%d %s = %dK (hdr %dK %d%%, loc %dK %d%%, code %dK %d%%, stub %dK %d%%, [oops %dK %d%%, metadata %dK %d%%, data %dK %d%%, pcs %dK %d%%])",
+ count,
+ title,
+ total() / (int)K,
+ header_size / (int)K,
+ header_size * 100 / total_size,
+ relocation_size / (int)K,
+ relocation_size * 100 / total_size,
+ code_size / (int)K,
+ code_size * 100 / total_size,
+ stub_size / (int)K,
+ stub_size * 100 / total_size,
+ scopes_oop_size / (int)K,
+ scopes_oop_size * 100 / total_size,
+ scopes_metadata_size / (int)K,
+ scopes_metadata_size * 100 / total_size,
+ scopes_data_size / (int)K,
+ scopes_data_size * 100 / total_size,
+ scopes_pcs_size / (int)K,
+ scopes_pcs_size * 100 / total_size);
+ }
}
void add(CodeBlob* cb) {
@@ -1468,27 +1483,73 @@ void CodeCache::print() {
#ifndef PRODUCT
if (!Verbose) return;
- CodeBlob_sizes live;
- CodeBlob_sizes dead;
+ CodeBlob_sizes live[CompLevel_full_optimization + 1];
+ CodeBlob_sizes dead[CompLevel_full_optimization + 1];
+ CodeBlob_sizes runtimeStub;
+ CodeBlob_sizes uncommonTrapStub;
+ CodeBlob_sizes deoptimizationStub;
+ CodeBlob_sizes adapter;
+ CodeBlob_sizes bufferBlob;
+ CodeBlob_sizes other;
FOR_ALL_ALLOCABLE_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
- if (!cb->is_alive()) {
- dead.add(cb);
+ if (cb->is_nmethod()) {
+ const int level = cb->as_nmethod()->comp_level();
+ assert(0 <= level && level <= CompLevel_full_optimization, "Invalid compilation level");
+ if (!cb->is_alive()) {
+ dead[level].add(cb);
+ } else {
+ live[level].add(cb);
+ }
+ } else if (cb->is_runtime_stub()) {
+ runtimeStub.add(cb);
+ } else if (cb->is_deoptimization_stub()) {
+ deoptimizationStub.add(cb);
+ } else if (cb->is_uncommon_trap_stub()) {
+ uncommonTrapStub.add(cb);
+ } else if (cb->is_adapter_blob()) {
+ adapter.add(cb);
+ } else if (cb->is_buffer_blob()) {
+ bufferBlob.add(cb);
} else {
- live.add(cb);
+ other.add(cb);
}
}
}
- tty->print_cr("CodeCache:");
tty->print_cr("nmethod dependency checking time %fs", dependentCheckTime.seconds());
- if (!live.is_empty()) {
- live.print("live");
- }
- if (!dead.is_empty()) {
- dead.print("dead");
+ tty->print_cr("nmethod blobs per compilation level:");
+ for (int i = 0; i <= CompLevel_full_optimization; i++) {
+ const char *level_name;
+ switch (i) {
+ case CompLevel_none: level_name = "none"; break;
+ case CompLevel_simple: level_name = "simple"; break;
+ case CompLevel_limited_profile: level_name = "limited profile"; break;
+ case CompLevel_full_profile: level_name = "full profile"; break;
+ case CompLevel_full_optimization: level_name = "full optimization"; break;
+ default: assert(false, "invalid compilation level");
+ }
+ tty->print_cr("%s:", level_name);
+ live[i].print("live");
+ dead[i].print("dead");
+ }
+
+ struct {
+ const char* name;
+ const CodeBlob_sizes* sizes;
+ } non_nmethod_blobs[] = {
+ { "runtime", &runtimeStub },
+ { "uncommon trap", &uncommonTrapStub },
+ { "deoptimization", &deoptimizationStub },
+ { "adapter", &adapter },
+ { "buffer blob", &bufferBlob },
+ { "other", &other },
+ };
+ tty->print_cr("Non-nmethod blobs:");
+ for (auto& blob: non_nmethod_blobs) {
+ blob.sizes->print(blob.name);
}
if (WizardMode) {
diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp
index 306280dfc43..bb597e50106 100644
--- a/src/hotspot/share/code/dependencies.cpp
+++ b/src/hotspot/share/code/dependencies.cpp
@@ -769,7 +769,8 @@ void Dependencies::write_dependency_to(xmlStream* xtty,
xtty->object("x", arg.metadata_value());
}
} else {
- char xn[12]; sprintf(xn, "x%d", j);
+ char xn[12];
+ os::snprintf_checked(xn, sizeof(xn), "x%d", j);
if (arg.is_oop()) {
xtty->object(xn, Handle(thread, arg.oop_value()));
} else {
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index eef8e6b4bbb..f5861d1f3ed 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -1550,7 +1550,7 @@ void nmethod::flush() {
assert_locked_or_safepoint(CodeCache_lock);
// completely deallocate this method
- Events::log(JavaThread::current(), "flushing nmethod " INTPTR_FORMAT, p2i(this));
+ Events::log_nmethod_flush(Thread::current(), "flushing %s nmethod " INTPTR_FORMAT, is_osr_method() ? "osr" : "", p2i(this));
if (PrintMethodFlushing) {
tty->print_cr("*flushing %s nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT
"/Free CodeCache:" SIZE_FORMAT "Kb",
diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp
index 026915246cc..d40a0183415 100644
--- a/src/hotspot/share/compiler/compilationPolicy.cpp
+++ b/src/hotspot/share/compiler/compilationPolicy.cpp
@@ -1011,7 +1011,7 @@ CompLevel CompilationPolicy::common(const methodHandle& method, CompLevel cur_le
if (force_comp_at_level_simple(method)) {
next_level = CompLevel_simple;
} else {
- if (is_trivial(method)) {
+ if (is_trivial(method) || method->is_native()) {
next_level = CompilationModeFlag::disable_intermediate() ? CompLevel_full_optimization : CompLevel_simple;
} else {
switch(cur_level) {
diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp
index db5f2b5e42f..f54308944e2 100644
--- a/src/hotspot/share/compiler/compileBroker.cpp
+++ b/src/hotspot/share/compiler/compileBroker.cpp
@@ -998,7 +998,7 @@ void CompileBroker::init_compiler_sweeper_threads() {
// for JVMCI compiler which can create further ones on demand.
JVMCI_ONLY(if (!UseJVMCICompiler || !UseDynamicNumberOfCompilerThreads || i == 0) {)
// Create a name for our thread.
- sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
+ os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i);
Handle thread_oop = create_thread_oop(name_buffer, CHECK);
thread_handle = JNIHandles::make_global(thread_oop);
JVMCI_ONLY(})
@@ -1022,7 +1022,7 @@ void CompileBroker::init_compiler_sweeper_threads() {
for (int i = 0; i < _c1_count; i++) {
// Create a name for our thread.
- sprintf(name_buffer, "C1 CompilerThread%d", i);
+ os::snprintf_checked(name_buffer, sizeof(name_buffer), "C1 CompilerThread%d", i);
Handle thread_oop = create_thread_oop(name_buffer, CHECK);
jobject thread_handle = JNIHandles::make_global(thread_oop);
_compiler1_objects[i] = thread_handle;
@@ -1095,7 +1095,7 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
// transitions if we bind them to new JavaThreads.
if (!THREAD->can_call_java()) break;
char name_buffer[256];
- sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
+ os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i);
Handle thread_oop;
{
// We have to give up the lock temporarily for the Java calls.
@@ -2731,7 +2731,7 @@ void CompileBroker::print_times(bool per_compiler, bool aggregate) {
char tier_name[256];
for (int tier = CompLevel_simple; tier <= CompilationPolicy::highest_compile_level(); tier++) {
CompilerStatistics* stats = &_stats_per_level[tier-1];
- sprintf(tier_name, "Tier%d", tier);
+ os::snprintf_checked(tier_name, sizeof(tier_name), "Tier%d", tier);
print_times(tier_name, stats);
}
}
diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp
index 1aca61234e5..9d045d4d900 100644
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp
@@ -192,11 +192,14 @@ size_t G1Allocator::unsafe_max_tlab_alloc() {
uint node_index = current_node_index();
HeapRegion* hr = mutator_alloc_region(node_index)->get();
size_t max_tlab = _g1h->max_tlab_size() * wordSize;
- if (hr == NULL) {
+
+ if (hr == NULL || hr->free() < MinTLABSize) {
+ // The next TLAB allocation will most probably happen in a new region,
+ // therefore we can attempt to allocate the maximum allowed TLAB size.
return max_tlab;
- } else {
- return clamp(hr->free(), MinTLABSize, max_tlab);
}
+
+ return MIN2(hr->free(), max_tlab);
}
size_t G1Allocator::used_in_alloc_regions() {
@@ -292,6 +295,8 @@ G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) :
for (uint node_index = 0; node_index < length; node_index++) {
_alloc_buffers[state][node_index] = new PLAB(_g1h->desired_plab_sz(state));
}
+ _num_plab_fills[state] = 0;
+ _num_direct_allocations[state] = 0;
}
}
@@ -324,6 +329,8 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
PLAB* alloc_buf = alloc_buffer(dest, node_index);
alloc_buf->retire();
+ _num_plab_fills[dest.type()]++;
+
size_t actual_plab_size = 0;
HeapWord* buf = _allocator->par_allocate_during_gc(dest,
required_in_plab,
@@ -332,7 +339,7 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
node_index);
assert(buf == NULL || ((actual_plab_size >= required_in_plab) && (actual_plab_size <= plab_word_size)),
- "Requested at minimum " SIZE_FORMAT ", desired " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT,
+ "Requested at minimum %zu, desired %zu words, but got %zu at " PTR_FORMAT,
required_in_plab, plab_word_size, actual_plab_size, p2i(buf));
if (buf != NULL) {
@@ -340,7 +347,7 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
HeapWord* const obj = alloc_buf->allocate(word_sz);
assert(obj != NULL, "PLAB should have been big enough, tried to allocate "
- SIZE_FORMAT " requiring " SIZE_FORMAT " PLAB size " SIZE_FORMAT,
+ "%zu requiring %zu PLAB size %zu",
word_sz, required_in_plab, plab_word_size);
return obj;
}
@@ -351,6 +358,7 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz, node_index);
if (result != NULL) {
_direct_allocated[dest.type()] += word_sz;
+ _num_direct_allocations[dest.type()]++;
}
return result;
}
@@ -368,8 +376,9 @@ void G1PLABAllocator::flush_and_retire_stats() {
buf->flush_and_retire_stats(stats);
}
}
+ stats->add_num_plab_filled(_num_plab_fills[state]);
stats->add_direct_allocated(_direct_allocated[state]);
- _direct_allocated[state] = 0;
+ stats->add_num_direct_allocated(_num_direct_allocations[state]);
}
}
diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp
index c9bf3015dfc..16feef2e6b1 100644
--- a/src/hotspot/share/gc/g1/g1Allocator.hpp
+++ b/src/hotspot/share/gc/g1/g1Allocator.hpp
@@ -161,6 +161,10 @@ class G1PLABAllocator : public CHeapObj {
// Number of words allocated directly (not counting PLAB allocation).
size_t _direct_allocated[G1HeapRegionAttr::Num];
+ // Number of PLAB refills experienced so far.
+ size_t _num_plab_fills[G1HeapRegionAttr::Num];
+ size_t _num_direct_allocations[G1HeapRegionAttr::Num];
+
void flush_and_retire_stats();
inline PLAB* alloc_buffer(G1HeapRegionAttr dest, uint node_index) const;
inline PLAB* alloc_buffer(region_type_t dest, uint node_index) const;
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index eb3586231bd..8acbaae9bb5 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -2545,7 +2545,8 @@ G1HeapSummary G1CollectedHeap::create_g1_heap_summary() {
G1EvacSummary G1CollectedHeap::create_g1_evac_summary(G1EvacStats* stats) {
return G1EvacSummary(stats->allocated(), stats->wasted(), stats->undo_wasted(),
stats->unused(), stats->used(), stats->region_end_waste(),
- stats->regions_filled(), stats->direct_allocated(),
+ stats->regions_filled(), stats->num_plab_filled(),
+ stats->direct_allocated(), stats->num_direct_allocated(),
stats->failure_used(), stats->failure_waste());
}
diff --git a/src/hotspot/share/gc/g1/g1EvacStats.cpp b/src/hotspot/share/gc/g1/g1EvacStats.cpp
index f8acabf6be6..62d5cc3b257 100644
--- a/src/hotspot/share/gc/g1/g1EvacStats.cpp
+++ b/src/hotspot/share/gc/g1/g1EvacStats.cpp
@@ -33,15 +33,19 @@
void G1EvacStats::log_plab_allocation() {
PLABStats::log_plab_allocation();
log_debug(gc, plab)("%s other allocation: "
- "region end waste: " SIZE_FORMAT "B, "
+ "region end waste: %zuB, "
"regions filled: %u, "
- "direct allocated: " SIZE_FORMAT "B, "
- "failure used: " SIZE_FORMAT "B, "
- "failure wasted: " SIZE_FORMAT "B",
+ "num plab filled: %zu, "
+ "direct allocated: %zuB, "
+ "num direct allocated: %zu, "
+ "failure used: %zuB, "
+ "failure wasted: %zuB",
_description,
_region_end_waste * HeapWordSize,
_regions_filled,
+ _num_plab_filled,
_direct_allocated * HeapWordSize,
+ _num_direct_allocated,
_failure_used * HeapWordSize,
_failure_waste * HeapWordSize);
}
@@ -94,7 +98,9 @@ G1EvacStats::G1EvacStats(const char* description, size_t default_per_thread_plab
PLABStats(description, default_per_thread_plab_size, default_per_thread_plab_size * ParallelGCThreads, wt),
_region_end_waste(0),
_regions_filled(0),
+ _num_plab_filled(0),
_direct_allocated(0),
+ _num_direct_allocated(0),
_failure_used(0),
_failure_waste(0) {
}
diff --git a/src/hotspot/share/gc/g1/g1EvacStats.hpp b/src/hotspot/share/gc/g1/g1EvacStats.hpp
index 0bbd1d9661f..c3ecf98efab 100644
--- a/src/hotspot/share/gc/g1/g1EvacStats.hpp
+++ b/src/hotspot/share/gc/g1/g1EvacStats.hpp
@@ -32,7 +32,9 @@ class G1EvacStats : public PLABStats {
private:
size_t _region_end_waste; // Number of words wasted due to skipping to the next region.
uint _regions_filled; // Number of regions filled completely.
+ size_t _num_plab_filled; // Number of PLABs filled and retired.
size_t _direct_allocated; // Number of words allocated directly into the regions.
+ size_t _num_direct_allocated; // Number of direct allocation attempts.
// Number of words in live objects remaining in regions that ultimately suffered an
// evacuation failure. This is used in the regions when the regions are made old regions.
@@ -46,7 +48,9 @@ class G1EvacStats : public PLABStats {
PLABStats::reset();
_region_end_waste = 0;
_regions_filled = 0;
+ _num_plab_filled = 0;
_direct_allocated = 0;
+ _num_direct_allocated = 0;
_failure_used = 0;
_failure_waste = 0;
}
@@ -61,15 +65,19 @@ class G1EvacStats : public PLABStats {
~G1EvacStats();
uint regions_filled() const { return _regions_filled; }
+ size_t num_plab_filled() const { return _num_plab_filled; }
size_t region_end_waste() const { return _region_end_waste; }
size_t direct_allocated() const { return _direct_allocated; }
+ size_t num_direct_allocated() const { return _num_direct_allocated; }
// Amount of space in heapwords used in the failing regions when an evacuation failure happens.
size_t failure_used() const { return _failure_used; }
// Amount of space in heapwords wasted (unused) in the failing regions when an evacuation failure happens.
size_t failure_waste() const { return _failure_waste; }
+ inline void add_num_plab_filled(size_t value);
inline void add_direct_allocated(size_t value);
+ inline void add_num_direct_allocated(size_t value);
inline void add_region_end_waste(size_t value);
inline void add_failure_used_and_waste(size_t used, size_t waste);
};
diff --git a/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp b/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp
index 9ebc1dd57a8..4b4c6e104b7 100644
--- a/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp
+++ b/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp
@@ -33,6 +33,14 @@ inline void G1EvacStats::add_direct_allocated(size_t value) {
Atomic::add(&_direct_allocated, value);
}
+inline void G1EvacStats::add_num_plab_filled(size_t value) {
+ Atomic::add(&_num_plab_filled, value);
+}
+
+inline void G1EvacStats::add_num_direct_allocated(size_t value) {
+ Atomic::add(&_num_direct_allocated, value);
+}
+
inline void G1EvacStats::add_region_end_waste(size_t value) {
Atomic::add(&_region_end_waste, value);
Atomic::inc(&_regions_filled);
diff --git a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp
index f97727c8bc8..e5817ca6f5c 100644
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp
@@ -169,22 +169,6 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
_major_timer.start();
}
-// If the remaining free space in the old generation is less that
-// that expected to be needed by the next collection, do a full
-// collection now.
-bool PSAdaptiveSizePolicy::should_full_GC(size_t old_free_in_bytes) {
-
- // A similar test is done in the scavenge's should_attempt_scavenge(). If
- // this is changed, decide if that test should also be changed.
- bool result = padded_average_promoted_in_bytes() > (float) old_free_in_bytes;
- log_trace(gc, ergo)("%s after scavenge average_promoted " SIZE_FORMAT " padded_average_promoted " SIZE_FORMAT " free in old gen " SIZE_FORMAT,
- result ? "Full" : "No full",
- (size_t) average_promoted_in_bytes(),
- (size_t) padded_average_promoted_in_bytes(),
- old_free_in_bytes);
- return result;
-}
-
void PSAdaptiveSizePolicy::clear_generation_free_space_flags() {
AdaptiveSizePolicy::clear_generation_free_space_flags();
diff --git a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp
index c39514922fc..1b058e2dd29 100644
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp
@@ -306,10 +306,6 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
}
float major_collection_slope() { return _major_collection_estimator->slope();}
- // Given the amount of live data in the heap, should we
- // perform a Full GC?
- bool should_full_GC(size_t live_in_old_gen);
-
// Calculates optimal (free) space sizes for both the young and old
// generations. Stores results in _eden_size and _promo_size.
// Takes current used space in all generations as input, as well
diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp
index c4011fff4e5..ef14ad53aa0 100644
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp
@@ -238,8 +238,7 @@ bool PSScavenge::invoke() {
IsGCActiveMark mark;
const bool scavenge_done = PSScavenge::invoke_no_policy();
- const bool need_full_gc = !scavenge_done ||
- policy->should_full_GC(heap->old_gen()->free_in_bytes());
+ const bool need_full_gc = !scavenge_done;
bool full_gc_done = false;
if (UsePerfData) {
@@ -739,8 +738,6 @@ bool PSScavenge::should_attempt_scavenge() {
// Test to see if the scavenge will likely fail.
PSAdaptiveSizePolicy* policy = heap->size_policy();
- // A similar test is done in the policy's should_full_GC(). If this is
- // changed, decide if that test should also be changed.
size_t avg_promoted = (size_t) policy->padded_average_promoted_in_bytes();
size_t promotion_estimate = MIN2(avg_promoted, young_gen->used_in_bytes());
bool result = promotion_estimate < old_gen->free_in_bytes();
diff --git a/src/hotspot/share/gc/shared/gcHeapSummary.hpp b/src/hotspot/share/gc/shared/gcHeapSummary.hpp
index c1a10fd2b69..c0ed793fb67 100644
--- a/src/hotspot/share/gc/shared/gcHeapSummary.hpp
+++ b/src/hotspot/share/gc/shared/gcHeapSummary.hpp
@@ -177,7 +177,9 @@ class G1EvacSummary : public StackObj {
size_t _region_end_waste; // Number of words wasted due to skipping to the next region.
uint _regions_filled; // Number of regions filled completely.
+ size_t _num_plab_filled; // Number of PLABs refilled/retired.
size_t _direct_allocated; // Number of words allocated directly into the regions.
+ size_t _num_direct_allocated; // Number of direct allocations.
// Number of words in live objects remaining in regions that ultimately suffered an
// evacuation failure. This is used in the regions when the regions are made old regions.
@@ -187,12 +189,23 @@ class G1EvacSummary : public StackObj {
// end of regions.
size_t _failure_waste;
public:
- G1EvacSummary(size_t allocated, size_t wasted, size_t undo_wasted, size_t unused,
- size_t used, size_t region_end_waste, uint regions_filled, size_t direct_allocated,
- size_t failure_used, size_t failure_waste) :
+ G1EvacSummary(size_t allocated,
+ size_t wasted,
+ size_t undo_wasted,
+ size_t unused,
+ size_t used,
+ size_t region_end_waste,
+ uint regions_filled,
+ size_t num_plab_filled,
+ size_t direct_allocated,
+ size_t num_direct_allocated,
+ size_t failure_used,
+ size_t failure_waste) :
_allocated(allocated), _wasted(wasted), _undo_wasted(undo_wasted), _unused(unused),
- _used(used), _region_end_waste(region_end_waste), _regions_filled(regions_filled),
- _direct_allocated(direct_allocated), _failure_used(failure_used), _failure_waste(failure_waste)
+ _used(used), _region_end_waste(region_end_waste),
+ _regions_filled(regions_filled), _num_plab_filled(num_plab_filled),
+ _direct_allocated(direct_allocated),_num_direct_allocated(num_direct_allocated),
+ _failure_used(failure_used), _failure_waste(failure_waste)
{ }
size_t allocated() const { return _allocated; }
@@ -202,7 +215,9 @@ class G1EvacSummary : public StackObj {
size_t used() const { return _used; }
size_t region_end_waste() const { return _region_end_waste; }
uint regions_filled() const { return _regions_filled; }
+ size_t num_plab_filled() const { return _num_plab_filled; }
size_t direct_allocated() const { return _direct_allocated; }
+ size_t num_direct_allocated() const { return _num_direct_allocated; }
size_t failure_used() const { return _failure_used; }
size_t failure_waste() const { return _failure_waste; }
};
diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp
index a68a3604a6a..1167a013e2c 100644
--- a/src/hotspot/share/gc/shared/memAllocator.cpp
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp
@@ -308,18 +308,15 @@ HeapWord* MemAllocator::allocate_inside_tlab_slow(Allocation& allocation) const
PTR_FORMAT " min: " SIZE_FORMAT ", desired: " SIZE_FORMAT,
p2i(mem), min_tlab_size, new_tlab_size);
+ // ...and clear or zap just allocated TLAB, if needed.
if (ZeroTLAB) {
- // ..and clear it.
Copy::zero_to_words(mem, allocation._allocated_tlab_size);
- } else {
- // ...and zap just allocated object.
-#ifdef ASSERT
+ } else if (ZapTLAB) {
// Skip mangling the space corresponding to the object header to
// ensure that the returned space is not considered parsable by
// any concurrent GC thread.
size_t hdr_size = oopDesc::header_size();
Copy::fill_to_words(mem + hdr_size, allocation._allocated_tlab_size - hdr_size, badHeapWordVal);
-#endif // ASSERT
}
tlab.fill(mem, mem + _word_size, allocation._allocated_tlab_size);
diff --git a/src/hotspot/share/gc/shared/oopStorage.inline.hpp b/src/hotspot/share/gc/shared/oopStorage.inline.hpp
index 4bcff174b5f..000700afde6 100644
--- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp
+++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp
@@ -28,8 +28,6 @@
#include "gc/shared/oopStorage.hpp"
#include "memory/allocation.hpp"
-#include "metaprogramming/conditional.hpp"
-#include "metaprogramming/isConst.hpp"
#include "oops/oop.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/align.hpp"
@@ -37,6 +35,8 @@
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
+#include
+
// Array of all active blocks. Refcounted for lock-free reclaim of
// old array when a new array is allocated for expansion.
class OopStorage::ActiveArray {
@@ -361,7 +361,7 @@ inline bool OopStorage::iterate_impl(F f, Storage* storage) {
assert_at_safepoint();
// Propagate const/non-const iteration to the block layer, by using
// const or non-const blocks as corresponding to Storage.
- typedef typename Conditional::value, const Block*, Block*>::type BlockPtr;
+ using BlockPtr = std::conditional_t::value, const Block*, Block*>;
ActiveArray* blocks = storage->_active_array;
size_t limit = blocks->block_count();
for (size_t i = 0; i < limit; ++i) {
diff --git a/src/hotspot/share/gc/shared/oopStorageParState.hpp b/src/hotspot/share/gc/shared/oopStorageParState.hpp
index 3f3d11393d8..e76541483e5 100644
--- a/src/hotspot/share/gc/shared/oopStorageParState.hpp
+++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp
@@ -28,6 +28,8 @@
#include "gc/shared/oopStorage.hpp"
#include "utilities/globalDefinitions.hpp"
+#include
+
//////////////////////////////////////////////////////////////////////////////
// Support for parallel and optionally concurrent state iteration.
//
@@ -167,9 +169,7 @@ template
class OopStorage::ParState {
BasicParState _basic_state;
- typedef typename Conditional::type StoragePtr;
+ using StoragePtr = std::conditional_t;
public:
ParState(StoragePtr storage,
diff --git a/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp b/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp
index ce37d4ede93..9e48ea7c77b 100644
--- a/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp
+++ b/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp
@@ -28,9 +28,10 @@
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/oopStorage.inline.hpp"
-#include "metaprogramming/conditional.hpp"
#include "utilities/macros.hpp"
+#include
+
template
class OopStorage::BasicParState::AlwaysTrueFn {
F _f;
@@ -56,7 +57,7 @@ inline void OopStorage::BasicParState::iterate(F f) {
while (claim_next_segment(&data)) {
assert(data._segment_start < data._segment_end, "invariant");
assert(data._segment_end <= _block_count, "invariant");
- typedef typename Conditional::type BlockPtr;
+ using BlockPtr = std::conditional_t;
size_t i = data._segment_start;
do {
BlockPtr block = _active_array->at(i);
diff --git a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp
index 3b167d752e7..56762d9e5eb 100644
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp
@@ -39,14 +39,8 @@ inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) {
invariants();
HeapWord* obj = top();
if (pointer_delta(end(), obj) >= size) {
- // successful thread-local allocation
-#ifdef ASSERT
- // Skip mangling the space corresponding to the object header to
- // ensure that the returned space is not considered parsable by
- // any concurrent GC thread.
- size_t hdr_size = oopDesc::header_size();
- Copy::fill_to_words(obj + hdr_size, size - hdr_size, badHeapWordVal);
-#endif // ASSERT
+ // Successful thread-local allocation.
+
// This addition is safe because we know that top is
// at least size below end, so the add can't wrap.
set_top(obj + size);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp
index ebc288efda9..d26e085a4b2 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp
@@ -36,13 +36,19 @@
#include "runtime/threadWXSetters.inline.hpp"
bool ShenandoahBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
+ if (!is_armed(nm)) {
+ // Some other thread got here first and healed the oops
+ // and disarmed the nmethod. No need to continue.
+ return true;
+ }
+
ShenandoahReentrantLock* lock = ShenandoahNMethod::lock_for_nmethod(nm);
assert(lock != NULL, "Must be");
ShenandoahReentrantLocker locker(lock);
if (!is_armed(nm)) {
- // Some other thread got here first and healed the oops
- // and disarmed the nmethod.
+ // Some other thread managed to complete while we were
+ // waiting for lock. No need to continue.
return true;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
index 1230030da64..ab80fd59390 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2017, 2021, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2022, 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
@@ -163,13 +164,6 @@ class ShenandoahDisarmNMethodsTask : public AbstractGangTask {
AbstractGangTask("Shenandoah Disarm NMethods"),
_iterator(ShenandoahCodeRoots::table()) {
assert(SafepointSynchronize::is_at_safepoint(), "Only at a safepoint");
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_begin();
- }
-
- ~ShenandoahDisarmNMethodsTask() {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_end();
}
virtual void work(uint worker_id) {
@@ -269,15 +263,7 @@ class ShenandoahUnlinkTask : public AbstractGangTask {
AbstractGangTask("Shenandoah Unlink NMethods"),
_cl(unloading_occurred),
_verifier(verifier),
- _iterator(ShenandoahCodeRoots::table()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_begin();
- }
-
- ~ShenandoahUnlinkTask() {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_end();
- }
+ _iterator(ShenandoahCodeRoots::table()) {}
virtual void work(uint worker_id) {
ICRefillVerifierMark mark(_verifier);
@@ -329,15 +315,7 @@ class ShenandoahNMethodPurgeTask : public AbstractGangTask {
ShenandoahNMethodPurgeTask() :
AbstractGangTask("Shenandoah Purge NMethods"),
_cl(),
- _iterator(ShenandoahCodeRoots::table()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_begin();
- }
-
- ~ShenandoahNMethodPurgeTask() {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _iterator.nmethods_do_end();
- }
+ _iterator(ShenandoahCodeRoots::table()) {}
virtual void work(uint worker_id) {
_iterator.nmethods_do(&_cl);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
index 817f43e6932..9d49d4ca4dd 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2021, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2022, 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
@@ -748,18 +749,9 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask {
_vm_roots(phase),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
_nmethod_itr(ShenandoahCodeRoots::table()),
- _phase(phase) {
- if (ShenandoahHeap::heap()->unload_classes()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _nmethod_itr.nmethods_do_begin();
- }
- }
+ _phase(phase) {}
~ShenandoahConcurrentWeakRootsEvacUpdateTask() {
- if (ShenandoahHeap::heap()->unload_classes()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _nmethod_itr.nmethods_do_end();
- }
// Notify runtime data structures of potentially dead oops
_vm_roots.report_num_dead();
}
@@ -860,19 +852,7 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
_phase(phase),
_vm_roots(phase),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
- _nmethod_itr(ShenandoahCodeRoots::table()) {
- if (!ShenandoahHeap::heap()->unload_classes()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _nmethod_itr.nmethods_do_begin();
- }
- }
-
- ~ShenandoahConcurrentRootsEvacUpdateTask() {
- if (!ShenandoahHeap::heap()->unload_classes()) {
- MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- _nmethod_itr.nmethods_do_end();
- }
- }
+ _nmethod_itr(ShenandoahCodeRoots::table()) {}
void work(uint worker_id) {
ShenandoahConcurrentWorkerSession worker_session(worker_id);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
index d0cc794eeaa..2d2c86d1dfd 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
@@ -361,11 +361,13 @@ class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
_compact_point = _to_region->bottom();
}
- // Object fits into current region, record new location:
+ // Object fits into current region, record new location, if object does not move:
assert(_compact_point + obj_size <= _to_region->end(), "must fit");
shenandoah_assert_not_forwarded(NULL, p);
- _preserved_marks->push_if_necessary(p, p->mark());
- p->forward_to(cast_to_oop(_compact_point));
+ if (_compact_point != cast_from_oop(p)) {
+ _preserved_marks->push_if_necessary(p, p->mark());
+ p->forward_to(cast_to_oop(_compact_point));
+ }
_compact_point += obj_size;
}
};
@@ -845,6 +847,7 @@ class ShenandoahCompactObjectsClosure : public ObjectClosure {
if (p->is_forwarded()) {
HeapWord* compact_from = cast_from_oop(p);
HeapWord* compact_to = cast_from_oop(p->forwardee());
+ assert(compact_from != compact_to, "Forwarded object should move");
Copy::aligned_conjoint_words(compact_from, compact_to, size);
oop new_obj = cast_to_oop(compact_to);
new_obj->init_mark();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index 67ea25d31fa..44443fea52e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -778,18 +778,15 @@ HeapWord* ShenandoahHeap::allocate_from_gclab_slow(Thread* thread, size_t size)
assert (size <= actual_size, "allocation should fit");
+ // ...and clear or zap just allocated TLAB, if needed.
if (ZeroTLAB) {
- // ..and clear it.
Copy::zero_to_words(gclab_buf, actual_size);
- } else {
- // ...and zap just allocated object.
-#ifdef ASSERT
+ } else if (ZapTLAB) {
// Skip mangling the space corresponding to the object header to
// ensure that the returned space is not considered parsable by
// any concurrent GC thread.
size_t hdr_size = oopDesc::header_size();
Copy::fill_to_words(gclab_buf + hdr_size, actual_size - hdr_size, badHeapWordVal);
-#endif // ASSERT
}
gclab->set_buf(gclab_buf, actual_size);
return gclab->allocate(size);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp
index e0f5b9ee71b..6c1f08096fe 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2019, 2021, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2022, 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
@@ -28,6 +29,7 @@
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/safepointVerifiers.hpp"
ShenandoahNMethod::ShenandoahNMethod(nmethod* nm, GrowableArray& oops, bool non_immediate_oops) :
_nm(nm), _oops(NULL), _oops_count(0), _unregistered(false) {
@@ -542,21 +544,40 @@ void ShenandoahNMethodTableSnapshot::concurrent_nmethods_do(NMethodClosure* cl)
}
ShenandoahConcurrentNMethodIterator::ShenandoahConcurrentNMethodIterator(ShenandoahNMethodTable* table) :
- _table(table), _table_snapshot(NULL) {
-}
-
-void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
- assert(CodeCache_lock->owned_by_self(), "Lock must be held");
- _table_snapshot = _table->snapshot_for_iteration();
-}
+ _table(table),
+ _table_snapshot(nullptr),
+ _started_workers(0),
+ _finished_workers(0) {}
void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
- assert(_table_snapshot != NULL, "Must first call nmethod_do_begin()");
- _table_snapshot->concurrent_nmethods_do(cl);
-}
+ // Cannot safepoint when iteration is running, because this can cause deadlocks
+ // with other threads waiting on iteration to be over.
+ NoSafepointVerifier nsv;
-void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
- assert(CodeCache_lock->owned_by_self(), "Lock must be held");
- _table->finish_iteration(_table_snapshot);
- CodeCache_lock->notify_all();
+ MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+
+ if (_finished_workers > 0) {
+ // Some threads have already finished. We are now in rampdown: we are now
+ // waiting for all currently recorded workers to finish. No new workers
+ // should start.
+ return;
+ }
+
+ // Record a new worker and initialize the snapshot if it is a first visitor.
+ if (_started_workers++ == 0) {
+ _table_snapshot = _table->snapshot_for_iteration();
+ }
+
+ // All set, relinquish the lock and go concurrent.
+ {
+ MutexUnlocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ _table_snapshot->concurrent_nmethods_do(cl);
+ }
+
+ // Record completion. Last worker shuts down the iterator and notifies any waiters.
+ uint count = ++_finished_workers;
+ if (count == _started_workers) {
+ _table->finish_iteration(_table_snapshot);
+ CodeCache_lock->notify_all();
+ }
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp
index ba67517fe26..3b4045666de 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp
@@ -187,13 +187,13 @@ class ShenandoahConcurrentNMethodIterator {
private:
ShenandoahNMethodTable* const _table;
ShenandoahNMethodTableSnapshot* _table_snapshot;
+ uint _started_workers;
+ uint _finished_workers;
public:
ShenandoahConcurrentNMethodIterator(ShenandoahNMethodTable* table);
- void nmethods_do_begin();
void nmethods_do(NMethodClosure* cl);
- void nmethods_do_end();
};
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHNMETHOD_HPP
diff --git a/src/hotspot/share/gc/z/zSafeDelete.hpp b/src/hotspot/share/gc/z/zSafeDelete.hpp
index f18d1e4153e..62c3495c57b 100644
--- a/src/hotspot/share/gc/z/zSafeDelete.hpp
+++ b/src/hotspot/share/gc/z/zSafeDelete.hpp
@@ -26,12 +26,13 @@
#include "gc/z/zArray.hpp"
#include "gc/z/zLock.hpp"
-#include "metaprogramming/removeExtent.hpp"
+
+#include
template
class ZSafeDeleteImpl {
private:
- typedef typename RemoveExtent::type ItemT;
+ using ItemT = std::remove_extent_t;
ZLock* _lock;
uint64_t _enabled;
diff --git a/src/hotspot/share/gc/z/zSafeDelete.inline.hpp b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp
index 9db212bd4c2..460193827e0 100644
--- a/src/hotspot/share/gc/z/zSafeDelete.inline.hpp
+++ b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp
@@ -27,9 +27,10 @@
#include "gc/z/zSafeDelete.hpp"
#include "gc/z/zArray.inline.hpp"
-#include "metaprogramming/isArray.hpp"
#include "utilities/debug.hpp"
+#include
+
template
ZSafeDeleteImpl::ZSafeDeleteImpl(ZLock* lock) :
_lock(lock),
@@ -49,7 +50,7 @@ bool ZSafeDeleteImpl::deferred_delete(ItemT* item) {
template
void ZSafeDeleteImpl::immediate_delete(ItemT* item) {
- if (IsArray::value) {
+ if (std::is_array::value) {
delete [] item;
} else {
delete item;
diff --git a/src/hotspot/share/interpreter/bootstrapInfo.cpp b/src/hotspot/share/interpreter/bootstrapInfo.cpp
index 830c015cc39..4070a68e1f9 100644
--- a/src/hotspot/share/interpreter/bootstrapInfo.cpp
+++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp
@@ -230,9 +230,9 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
st = st ? st : tty;
if (_indy_index != -1)
- sprintf(what, "indy#%d", decode_indy_index());
+ os::snprintf_checked(what, sizeof(what), "indy#%d", decode_indy_index());
else
- sprintf(what, "condy");
+ os::snprintf_checked(what, sizeof(what), "condy");
bool have_msg = (msg != NULL && strlen(msg) > 0);
st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s",
(have_msg ? msg : ""), (have_msg ? " " : ""),
@@ -251,11 +251,11 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
for (int i = 0; i < _argc; i++) {
int pos = (int) strlen(argbuf);
if (pos + 20 > (int)sizeof(argbuf)) {
- sprintf(argbuf + pos, "...");
+ os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "...");
break;
}
if (i > 0) argbuf[pos++] = ',';
- sprintf(argbuf+pos, "%d", arg_index(i));
+ os::snprintf_checked(argbuf+pos, sizeof(argbuf) - pos, "%d", arg_index(i));
}
st->print_cr(" argument indexes: {%s}", argbuf);
}
diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp
index b93bb30f0c8..3fc57c76903 100644
--- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp
+++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp
@@ -1942,11 +1942,9 @@ void BytecodeInterpreter::run(interpreterState istate) {
size_t obj_size = ik->size_helper();
HeapWord* result = THREAD->tlab().allocate(obj_size);
if (result != NULL) {
- // Initialize object field block:
- // - if TLAB is pre-zeroed, we can skip this path
- // - in debug mode, ThreadLocalAllocBuffer::allocate mangles
- // this area, and we still need to initialize it
- if (DEBUG_ONLY(true ||) !ZeroTLAB) {
+ // Initialize object field block.
+ if (!ZeroTLAB) {
+ // The TLAB was not pre-zeroed, we need to clear the memory here.
size_t hdr_size = oopDesc::header_size();
Copy::fill_to_words(result + hdr_size, obj_size - hdr_size, 0);
}
diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
index 8e2a1060528..ed5144d4bfa 100644
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
@@ -214,9 +214,6 @@ class StackTraceBlobInstaller {
StackTraceBlobInstaller() : _cache(JfrOptionSet::old_object_queue_size()) {
prepare_for_resolution();
}
- ~StackTraceBlobInstaller() {
- JfrStackTraceRepository::clear_leak_profiler();
- }
void sample_do(ObjectSample* sample) {
if (stack_trace_precondition(sample)) {
install(sample);
@@ -270,11 +267,14 @@ void ObjectSampleCheckpoint::on_rotation(const ObjectSampler* sampler) {
assert(LeakProfiler::is_running(), "invariant");
JavaThread* const thread = JavaThread::current();
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(thread);)
- // can safepoint here
- ThreadInVMfromNative transition(thread);
- MutexLocker lock(ClassLoaderDataGraph_lock);
- // the lock is needed to ensure the unload lists do not grow in the middle of inspection.
- install_stack_traces(sampler);
+ {
+ // can safepoint here
+ ThreadInVMfromNative transition(thread);
+ MutexLocker lock(ClassLoaderDataGraph_lock);
+ // the lock is needed to ensure the unload lists do not grow in the middle of inspection.
+ install_stack_traces(sampler);
+ }
+ JfrStackTraceRepository::clear_leak_profiler();
}
static bool is_klass_unloaded(traceid klass_id) {
diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml
index 5ebb5502b0b..2b3cc8812b5 100644
--- a/src/hotspot/share/jfr/metadata/metadata.xml
+++ b/src/hotspot/share/jfr/metadata/metadata.xml
@@ -350,7 +350,9 @@
+
+
@@ -658,7 +660,7 @@
-
+
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
index affd8849245..dc59166bb51 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
@@ -103,6 +103,9 @@ bool JfrCheckpointManager::initialize() {
// preallocate buffer count to each of the epoch live lists
for (size_t i = 0; i < global_buffer_prealloc_count * 2; ++i) {
Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace);
+ if (buffer == nullptr) {
+ return false;
+ }
_global_mspace->add_to_live_list(buffer, i % 2 == 0);
}
assert(_global_mspace->free_list_is_empty(), "invariant");
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
index 78d6ab48f97..dc2add22020 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
@@ -228,7 +228,7 @@ static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp)
writer->write(cld != NULL ? cld_id(cld, leakp) : 0);
writer->write(mark_symbol(klass, leakp));
writer->write(package_id(klass, leakp));
- writer->write(get_flags(klass));
+ writer->write(klass->modifier_flags());
writer->write(klass->is_hidden());
return 1;
}
@@ -429,8 +429,6 @@ static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
assert(value != NULL, "invariant");
if (USED_PREVIOUS_EPOCH(value)) {
callback->do_artifact(value);
- assert(IS_NOT_SERIALIZED(value), "invariant");
- return;
}
if (IS_SERIALIZED(value)) {
CLEAR_SERIALIZED(value);
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
index 5eb70fb23d2..cad6f6bc079 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
@@ -207,7 +207,7 @@ static const char* create_hidden_klass_symbol(const InstanceKlass* ik, uintptr_t
const oop mirror = ik->java_mirror_no_keepalive();
assert(mirror != NULL, "invariant");
char hash_buf[40];
- sprintf(hash_buf, "/" UINTX_FORMAT, hash);
+ snprintf(hash_buf, sizeof(hash_buf), "/" UINTX_FORMAT, hash);
const size_t hash_len = strlen(hash_buf);
const size_t result_len = ik->name()->utf8_length();
hidden_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
index 29bade3def6..9b7ddcd1273 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -109,7 +109,14 @@ inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) {
inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) {
assert(cld != NULL, "invariant");
- return cld->has_class_mirror_holder() ? 0 : set_used_and_get(cld);
+ if (cld->has_class_mirror_holder()) {
+ return 0;
+ }
+ const Klass* const class_loader_klass = cld->class_loader_klass();
+ if (class_loader_klass != nullptr && should_tag(class_loader_klass)) {
+ load_barrier(class_loader_klass);
+ }
+ return set_used_and_get(cld);
}
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) {
diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
index c7cd5a4d2dd..a611707462c 100644
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
@@ -350,13 +350,17 @@ static void write_repository_files(const RepositoryIterator& iterator, char* con
const ssize_t read_result = os::read_at(current_fd, copy_block, (int)block_size, bytes_read);
if (-1 == read_result) {
log_info(jfr)( // For user, should not be "jfr, system"
- "Unable to recover JFR data");
+ "Unable to recover JFR data, read failed.");
break;
}
bytes_read += (int64_t)read_result;
assert(bytes_read - bytes_written <= (int64_t)block_size, "invariant");
- bytes_written += (int64_t)os::write(emergency_fd, copy_block, bytes_read - bytes_written);
- assert(bytes_read == bytes_written, "invariant");
+ if (!os::write(emergency_fd, copy_block, bytes_read - bytes_written)) {
+ log_info(jfr)( // For user, should not be "jfr, system"
+ "Unable to recover JFR data, write failed.");
+ break;
+ }
+ bytes_written = bytes_read;
}
os::close(current_fd);
}
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
index 0627593611c..657c5645ae7 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
@@ -543,9 +543,7 @@ void JfrRecorderService::pre_safepoint_write() {
ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire());
}
write_storage(_storage, _chunkwriter);
- if (_stack_trace_repository.is_modified()) {
- write_stacktrace(_stack_trace_repository, _chunkwriter, false);
- }
+ write_stacktrace(_stack_trace_repository, _chunkwriter, true);
}
void JfrRecorderService::invoke_safepoint_write() {
diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp
index 82f3362d6ee..1e940ef6f97 100644
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp
@@ -98,11 +98,10 @@ bool JfrStackTraceRepository::is_modified() const {
}
size_t JfrStackTraceRepository::write(JfrChunkWriter& sw, bool clear) {
+ MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
if (_entries == 0) {
return 0;
}
- MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
- assert(_entries > 0, "invariant");
int count = 0;
for (u4 i = 0; i < TABLE_SIZE; ++i) {
JfrStackTrace* stacktrace = _table[i];
diff --git a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp
index 132295230ac..367b4714406 100644
--- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp
+++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp
@@ -85,6 +85,9 @@ bool JfrStringPool::initialize() {
// preallocate buffer count to each of the epoch live lists
for (size_t i = 0; i < string_pool_cache_count * 2; ++i) {
Buffer* const buffer = mspace_allocate(string_pool_buffer_size, _mspace);
+ if (buffer == nullptr) {
+ return false;
+ }
_mspace->add_to_live_list(buffer, i % 2 == 0);
}
assert(_mspace->free_list_is_empty(), "invariant");
diff --git a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp
index f8900a13b4d..52c69473a14 100644
--- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp
+++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -76,14 +76,14 @@ inline void StreamWriterHost::write_bytes(const u1* buf, intptr_t l
assert(len >= 0, "invariant");
while (len > 0) {
const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len;
- const ssize_t num_written = (ssize_t)os::write(_fd, buf, nBytes);
- if (errno == ENOSPC) {
+ const bool successful_write = os::write(_fd, buf, nBytes);
+ if (!successful_write && errno == ENOSPC) {
JfrJavaSupport::abort("Failed to write to jfr stream because no space left on device", false);
}
- guarantee(num_written > 0, "Nothing got written, or os::write() failed");
- _stream_pos += num_written;
- len -= num_written;
- buf += num_written;
+ guarantee(successful_write, "Not all the bytes got written, or os::write() failed");
+ _stream_pos += nBytes;
+ len -= nBytes;
+ buf += nBytes;
}
}
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
index 41478060acc..82fc404c166 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
@@ -303,9 +303,9 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) {
JVMCIObjectArray vmFields = JVMCIENV->new_VMField_array(len, JVMCI_CHECK_NULL);
for (int i = 0; i < len ; i++) {
VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i];
- size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
- char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
- sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
+ const size_t name_buf_size = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 + 1 /* "::" */;
+ char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_size);
+ os::snprintf_checked(name_buf, name_buf_size, "%s::%s", vmField.typeName, vmField.fieldName);
CSTRING_TO_JSTRING(name, name_buf);
CSTRING_TO_JSTRING(type, vmField.typeString);
JVMCIObject box;
diff --git a/src/hotspot/share/memory/iterator.inline.hpp b/src/hotspot/share/memory/iterator.inline.hpp
index cc339f2213d..428a057797f 100644
--- a/src/hotspot/share/memory/iterator.inline.hpp
+++ b/src/hotspot/share/memory/iterator.inline.hpp
@@ -39,6 +39,8 @@
#include "oops/typeArrayKlass.inline.hpp"
#include "utilities/debug.hpp"
+#include
+
// Defaults to strong claiming.
inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) :
ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {}
@@ -94,16 +96,16 @@ inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) {
// p - The oop (or narrowOop) field to pass to the closure
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
closure->do_oop(p);
}
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
// Sanity check
- STATIC_ASSERT((!IsSame::value));
+ STATIC_ASSERT((!std::is_same::value));
closure->OopClosureType::do_oop(p);
}
@@ -115,13 +117,13 @@ inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) {
// Implementation of the non-virtual do_metadata dispatch.
template
-static typename EnableIf::value, bool>::type
+static typename EnableIf::value, bool>::type
call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
return closure->do_metadata();
}
template
-static typename EnableIf::value, bool>::type
+static typename EnableIf::value, bool>::type
call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
return closure->OopClosureType::do_metadata();
}
@@ -134,13 +136,13 @@ inline bool Devirtualizer::do_metadata(OopClosureType* closure) {
// Implementation of the non-virtual do_klass dispatch.
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
closure->do_klass(k);
}
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
closure->OopClosureType::do_klass(k);
}
@@ -153,13 +155,13 @@ inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) {
// Implementation of the non-virtual do_cld dispatch.
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
closure->do_cld(cld);
}
template
-static typename EnableIf::value, void>::type
+static typename EnableIf::value, void>::type
call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
closure->OopClosureType::do_cld(cld);
}
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
index 1e897615eaf..d1882c70e2c 100644
--- a/src/hotspot/share/memory/metaspace.cpp
+++ b/src/hotspot/share/memory/metaspace.cpp
@@ -566,12 +566,6 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
"wrong alignment");
MetaspaceContext::initialize_class_space_context(rs);
-
- // This does currently not work because rs may be the result of a split
- // operation and NMT seems not to be able to handle splits.
- // Will be fixed with JDK-8243535.
- // MemTracker::record_virtual_memory_type((address)rs.base(), mtClass);
-
}
// Returns true if class space has been setup (initialize_class_space).
@@ -840,6 +834,9 @@ void Metaspace::global_initialize() {
CompressedClassSpaceSize));
}
+ // Mark class space as such
+ MemTracker::record_virtual_memory_type((address)rs.base(), mtClass);
+
// Initialize space
Metaspace::initialize_class_space(rs);
diff --git a/src/hotspot/share/memory/metaspace/counters.hpp b/src/hotspot/share/memory/metaspace/counters.hpp
index 066d36279a6..1c474eb9b52 100644
--- a/src/hotspot/share/memory/metaspace/counters.hpp
+++ b/src/hotspot/share/memory/metaspace/counters.hpp
@@ -26,11 +26,12 @@
#ifndef SHARE_MEMORY_METASPACE_COUNTERS_HPP
#define SHARE_MEMORY_METASPACE_COUNTERS_HPP
-#include "metaprogramming/isSigned.hpp"
#include "runtime/atomic.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
+#include
+
namespace metaspace {
// We seem to be counting a lot of things which makes it worthwhile to
@@ -43,7 +44,7 @@ class AbstractCounter {
T _c;
// Only allow unsigned values for now
- STATIC_ASSERT(IsSigned::value == false);
+ STATIC_ASSERT(std::is_signed::value == false);
public:
@@ -88,7 +89,7 @@ class AbstractAtomicCounter {
volatile T _c;
// Only allow unsigned values for now
- STATIC_ASSERT(IsSigned::value == false);
+ STATIC_ASSERT(std::is_signed::value == false);
public:
diff --git a/src/hotspot/share/metaprogramming/conditional.hpp b/src/hotspot/share/metaprogramming/conditional.hpp
deleted file mode 100644
index 2d4fe1a86e8..00000000000
--- a/src/hotspot/share/metaprogramming/conditional.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_CONDITIONAL_HPP
-#define SHARE_METAPROGRAMMING_CONDITIONAL_HPP
-
-#include "memory/allocation.hpp"
-
-// This trait evaluates its typedef called "type" to TrueType iff the condition
-// is true. Otherwise it evaluates to FalseType.
-
-template
-struct Conditional: AllStatic {
- typedef TrueType type;
-};
-
-template
-struct Conditional: AllStatic {
- typedef FalseType type;
-};
-
-#endif // SHARE_METAPROGRAMMING_CONDITIONAL_HPP
diff --git a/src/hotspot/share/metaprogramming/decay.hpp b/src/hotspot/share/metaprogramming/decay.hpp
deleted file mode 100644
index 4dff0500f13..00000000000
--- a/src/hotspot/share/metaprogramming/decay.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_DECAY_HPP
-#define SHARE_METAPROGRAMMING_DECAY_HPP
-
-#include "memory/allocation.hpp"
-#include "metaprogramming/removeCV.hpp"
-#include "metaprogramming/removeReference.hpp"
-
-// This trait trims the type from CV qualifiers and references.
-// This trait provides a subset of the functionality of std::decay;
-// array types and function types are not supported here.
-
-template
-struct Decay: AllStatic {
- typedef typename RemoveCV::type>::type type;
-};
-
-#endif // SHARE_METAPROGRAMMING_DECAY_HPP
diff --git a/src/hotspot/share/metaprogramming/integralConstant.hpp b/src/hotspot/share/metaprogramming/integralConstant.hpp
deleted file mode 100644
index ce22849e3be..00000000000
--- a/src/hotspot/share/metaprogramming/integralConstant.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_INTEGRALCONSTANT_HPP
-#define SHARE_METAPROGRAMMING_INTEGRALCONSTANT_HPP
-
-
-// An Integral Constant is a class providing a compile-time value of an
-// integral type. An Integral Constant is also a nullary metafunction,
-// returning itself. An integral constant object is implicitly
-// convertible to the associated value.
-//
-// A type n is a model of Integral Constant if it meets the following
-// requirements:
-//
-// n::ValueType : The integral type of n::value
-// n::value : An integral constant expression
-// n::type : IsSame::value is true
-// n::value_type const c = n() : c == n::value
-
-// A model of the Integer Constant concept.
-// T is an integral type, and is the value_type.
-// v is an integral constant, and is the value.
-template
-struct IntegralConstant {
- typedef T value_type;
- static const value_type value = v;
- typedef IntegralConstant type;
- operator value_type() { return value; }
-};
-
-// A bool valued IntegralConstant whose value is true.
-typedef IntegralConstant TrueType;
-
-// A bool valued IntegralConstant whose value is false.
-typedef IntegralConstant FalseType;
-
-#endif // SHARE_METAPROGRAMMING_INTEGRALCONSTANT_HPP
diff --git a/src/hotspot/share/metaprogramming/isFloatingPoint.hpp b/src/hotspot/share/metaprogramming/isFloatingPoint.hpp
deleted file mode 100644
index cbc2d838fe6..00000000000
--- a/src/hotspot/share/metaprogramming/isFloatingPoint.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_ISFLOATINGPOINT_HPP
-#define SHARE_METAPROGRAMMING_ISFLOATINGPOINT_HPP
-
-#include "metaprogramming/integralConstant.hpp"
-
-// This metafunction returns true iff the type T (irrespective of CV qualifiers)
-// is a floating point type.
-
-template struct IsFloatingPoint: public FalseType {};
-
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-template <> struct IsFloatingPoint: public TrueType {};
-
-#endif // SHARE_METAPROGRAMMING_ISFLOATINGPOINT_HPP
diff --git a/src/hotspot/share/metaprogramming/isIntegral.hpp b/src/hotspot/share/metaprogramming/isIntegral.hpp
deleted file mode 100644
index cbae6bd5efc..00000000000
--- a/src/hotspot/share/metaprogramming/isIntegral.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_ISINTEGRAL_HPP
-#define SHARE_METAPROGRAMMING_ISINTEGRAL_HPP
-
-#include "metaprogramming/integralConstant.hpp"
-#include "metaprogramming/isSigned.hpp"
-#include "metaprogramming/removeCV.hpp"
-#include
-
-// This metafunction returns true iff the type T (irrespective of CV qualifiers)
-// is an integral type. Note that this is false for enums.
-
-template
-struct IsIntegral
- : public IntegralConstant::type>::is_integer>
-{};
-
-// This metafunction returns true iff the type T (irrespective of CV qualifiers)
-// is a signed integral type. Note that this is false for enums.
-
-template
-struct IsSignedIntegral
- : public IntegralConstant::value && IsSigned::value>
-{};
-
-// This metafunction returns true iff the type T (irrespective of CV qualifiers)
-// is an unsigned integral type. Note that this is false for enums.
-
-template
-struct IsUnsignedIntegral
- : public IntegralConstant::value && !IsSigned::value>
-{};
-
-#endif // SHARE_METAPROGRAMMING_ISINTEGRAL_HPP
diff --git a/src/hotspot/share/metaprogramming/isSigned.hpp b/src/hotspot/share/metaprogramming/isSigned.hpp
deleted file mode 100644
index f04065d2180..00000000000
--- a/src/hotspot/share/metaprogramming/isSigned.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_ISSIGNED_HPP
-#define SHARE_METAPROGRAMMING_ISSIGNED_HPP
-
-#include "metaprogramming/integralConstant.hpp"
-#include "metaprogramming/removeCV.hpp"
-#include
-
-template
-struct IsSigned
- : public IntegralConstant::type>::is_signed>
-{};
-
-#endif // SHARE_METAPROGRAMMING_ISSIGNED_HPP
diff --git a/src/hotspot/share/metaprogramming/removeCV.hpp b/src/hotspot/share/metaprogramming/removeCV.hpp
deleted file mode 100644
index 0c0b2f47fa7..00000000000
--- a/src/hotspot/share/metaprogramming/removeCV.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_REMOVECV_HPP
-#define SHARE_METAPROGRAMMING_REMOVECV_HPP
-
-#include "memory/allocation.hpp"
-
-template
-struct RemoveCV: AllStatic {
- typedef T type;
-};
-
-template
-struct RemoveCV: AllStatic {
- typedef T type;
-};
-
-template
-struct RemoveCV: AllStatic {
- typedef T type;
-};
-
-template
-struct RemoveCV: AllStatic {
- typedef T type;
-};
-
-#endif // SHARE_METAPROGRAMMING_REMOVECV_HPP
diff --git a/src/hotspot/share/metaprogramming/removePointer.hpp b/src/hotspot/share/metaprogramming/removePointer.hpp
deleted file mode 100644
index be0f5b6e6fb..00000000000
--- a/src/hotspot/share/metaprogramming/removePointer.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_REMOVEPOINTER_HPP
-#define SHARE_METAPROGRAMMING_REMOVEPOINTER_HPP
-
-#include "memory/allocation.hpp"
-
-// This metafunction returns for a type T either the underlying type behind
-// the pointer iff T is a pointer type (irrespective of CV qualifiers),
-// or the same type T if T is not a pointer type.
-
-template struct RemovePointer: AllStatic { typedef T type; };
-
-template struct RemovePointer: AllStatic { typedef T type; };
-template struct RemovePointer: AllStatic { typedef T type; };
-template struct RemovePointer: AllStatic { typedef T type; };
-template struct RemovePointer: AllStatic { typedef T type; };
-
-#endif // SHARE_METAPROGRAMMING_REMOVEPOINTER_HPP
diff --git a/src/hotspot/share/metaprogramming/removeReference.hpp b/src/hotspot/share/metaprogramming/removeReference.hpp
deleted file mode 100644
index 274c327a0ad..00000000000
--- a/src/hotspot/share/metaprogramming/removeReference.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_METAPROGRAMMING_REMOVEREFERENCE_HPP
-#define SHARE_METAPROGRAMMING_REMOVEREFERENCE_HPP
-
-#include "memory/allocation.hpp"
-
-// This metafunction returns for a type T either the underlying type behind
-// the reference iff T is a reference type, or the same type T if T is not
-// a reference type.
-
-template struct RemoveReference: AllStatic { typedef T type; };
-
-template struct RemoveReference: AllStatic { typedef T type; };
-
-#endif // SHARE_METAPROGRAMMING_REMOVEREFERENCE_HPP
diff --git a/src/hotspot/share/oops/accessBackend.hpp b/src/hotspot/share/oops/accessBackend.hpp
index 4fa92c53c16..d267e217734 100644
--- a/src/hotspot/share/oops/accessBackend.hpp
+++ b/src/hotspot/share/oops/accessBackend.hpp
@@ -27,21 +27,14 @@
#include "gc/shared/barrierSetConfig.hpp"
#include "memory/allocation.hpp"
-#include "metaprogramming/conditional.hpp"
-#include "metaprogramming/decay.hpp"
#include "metaprogramming/enableIf.hpp"
-#include "metaprogramming/integralConstant.hpp"
-#include "metaprogramming/isFloatingPoint.hpp"
-#include "metaprogramming/isIntegral.hpp"
-#include "metaprogramming/isPointer.hpp"
-#include "metaprogramming/isSame.hpp"
-#include "metaprogramming/isVolatile.hpp"
#include "oops/accessDecorators.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
+#include
// This metafunction returns either oop or narrowOop depending on whether
// an access needs to use compressed oops or not.
@@ -49,7 +42,7 @@ template
struct HeapOopType: AllStatic {
static const bool needs_oop_compress = HasDecorator::value &&
HasDecorator::value;
- typedef typename Conditional::type type;
+ using type = std::conditional_t;
};
namespace AccessInternal {
@@ -67,18 +60,18 @@ namespace AccessInternal {
};
template
- struct MustConvertCompressedOop: public IntegralConstant::value &&
- IsSame::type, narrowOop>::value &&
- IsSame::value> {};
+ std::is_same::type, narrowOop>::value &&
+ std::is_same::value> {};
// This metafunction returns an appropriate oop type if the value is oop-like
// and otherwise returns the same type T.
template
struct EncodedType: AllStatic {
- typedef typename Conditional<
- HasDecorator::value,
- typename HeapOopType::type, T>::type type;
+ using type = std::conditional_t::value,
+ typename HeapOopType::type,
+ T>;
};
template
@@ -92,9 +85,9 @@ namespace AccessInternal {
// locking to support wide atomics or not.
template
#ifdef SUPPORTS_NATIVE_CX8
- struct PossiblyLockedAccess: public IntegralConstant {};
+ struct PossiblyLockedAccess: public std::false_type {};
#else
- struct PossiblyLockedAccess: public IntegralConstant 4)> {};
+ struct PossiblyLockedAccess: public std::integral_constant 4)> {};
#endif
template
@@ -425,7 +418,7 @@ namespace AccessInternal {
// to compile, as desired.
template
struct OopOrNarrowOop: AllStatic {
- typedef typename OopOrNarrowOopInternal::type>::type type;
+ typedef typename OopOrNarrowOopInternal>::type type;
};
inline void* field_addr(oop base, ptrdiff_t byte_offset) {
@@ -617,7 +610,7 @@ namespace AccessInternal {
// not possible.
struct PreRuntimeDispatch: AllStatic {
template
- struct CanHardwireRaw: public IntegralConstant<
+ struct CanHardwireRaw: public std::integral_constant<
bool,
!HasDecorator::value || // primitive access
!HasDecorator::value || // don't care about compressed oops (oop* address)
@@ -1081,20 +1074,20 @@ namespace AccessInternal {
// If this fails to compile, then you have sent in something that is
// not recognized as a valid primitive type to a primitive Access function.
STATIC_ASSERT((HasDecorator::value || // oops have already been validated
- (IsPointer::value || IsIntegral::value) ||
- IsFloatingPoint::value)); // not allowed primitive type
+ (std::is_pointer::value || std::is_integral::value) ||
+ std::is_floating_point::value)); // not allowed primitive type
}
template
inline void store(P* addr, T value) {
verify_types();
- typedef typename Decay::type DecayedP;
- typedef typename Decay::type DecayedT;
+ using DecayedP = std::decay_t;
+ using DecayedT = std::decay_t;
DecayedT decayed_value = value;
// If a volatile address is passed in but no memory ordering decorator,
// set the memory ordering to MO_RELAXED by default.
const DecoratorSet expanded_decorators = DecoratorFixup<
- (IsVolatile::value && !HasDecorator::value) ?
+ (std::is_volatile::value && !HasDecorator::value) ?
(MO_RELAXED | decorators) : decorators>::value;
store_reduce_types(const_cast(addr), decayed_value);
}
@@ -1102,7 +1095,7 @@ namespace AccessInternal {
template
inline void store_at(oop base, ptrdiff_t offset, T value) {
verify_types();
- typedef typename Decay::type DecayedT;
+ using DecayedT = std::decay_t;
DecayedT decayed_value = value;
const DecoratorSet expanded_decorators = DecoratorFixup::value ?
@@ -1113,14 +1106,14 @@ namespace AccessInternal {
template
inline T load(P* addr) {
verify_types();
- typedef typename Decay::type DecayedP;
- typedef typename Conditional::value,
- typename OopOrNarrowOop::type,
- typename Decay::type>::type DecayedT;
+ using DecayedP = std::decay_t;
+ using DecayedT = std::conditional_t::value,
+ typename OopOrNarrowOop::type,
+ std::decay_t>;
// If a volatile address is passed in but no memory ordering decorator,
// set the memory ordering to MO_RELAXED by default.
const DecoratorSet expanded_decorators = DecoratorFixup<
- (IsVolatile::value && !HasDecorator::value) ?
+ (std::is_volatile::value && !HasDecorator::value) ?
(MO_RELAXED | decorators) : decorators>::value;
return load_reduce_types(const_cast(addr));
}
@@ -1128,9 +1121,9 @@ namespace AccessInternal {
template
inline T load_at(oop base, ptrdiff_t offset) {
verify_types();
- typedef typename Conditional::value,
- typename OopOrNarrowOop::type,
- typename Decay::type>::type DecayedT;
+ using DecayedT = std::conditional_t::value,
+ typename OopOrNarrowOop::type,
+ std::decay_t>;
// Expand the decorators (figure out sensible defaults)
// Potentially remember if we need compressed oop awareness
const DecoratorSet expanded_decorators = DecoratorFixup
inline T atomic_cmpxchg(P* addr, T compare_value, T new_value) {
verify_types();
- typedef typename Decay::type DecayedP;
- typedef typename Decay::type DecayedT;
+ using DecayedP = std::decay_t;
+ using DecayedT = std::decay_t;
DecayedT new_decayed_value = new_value;
DecayedT compare_decayed_value = compare_value;
const DecoratorSet expanded_decorators = DecoratorFixup<
@@ -1157,7 +1150,7 @@ namespace AccessInternal {
template
inline T atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {
verify_types();
- typedef typename Decay::type DecayedT;
+ using DecayedT = std::decay_t;
DecayedT new_decayed_value = new_value;
DecayedT compare_decayed_value = compare_value;
// Determine default memory ordering
@@ -1175,8 +1168,8 @@ namespace AccessInternal {
template
inline T atomic_xchg(P* addr, T new_value) {
verify_types();
- typedef typename Decay::type DecayedP;
- typedef typename Decay::type DecayedT;
+ using DecayedP = std::decay_t;
+ using DecayedT = std::decay_t;
DecayedT new_decayed_value = new_value;
// atomic_xchg is only available in SEQ_CST flavour.
const DecoratorSet expanded_decorators = DecoratorFixup::value;
@@ -1187,7 +1180,7 @@ namespace AccessInternal {
template
inline T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {
verify_types();
- typedef typename Decay::type DecayedT;
+ using DecayedT = std::decay_t;
DecayedT new_decayed_value = new_value;
// atomic_xchg is only available in SEQ_CST flavour.
const DecoratorSet expanded_decorators = DecoratorFixup::value ||
- (IsSame::value || IsIntegral::value) ||
- IsFloatingPoint::value)); // arraycopy allows type erased void elements
- typedef typename Decay::type DecayedT;
+ (std::is_same::value || std::is_integral::value) ||
+ std::is_floating_point::value)); // arraycopy allows type erased void elements
+ using DecayedT = std::decay_t;
const DecoratorSet expanded_decorators = DecoratorFixup::value;
return arraycopy_reduce_types(src_obj, src_offset_in_bytes, const_cast(src_raw),
dst_obj, dst_offset_in_bytes, const_cast(dst_raw),
diff --git a/src/hotspot/share/oops/accessBackend.inline.hpp b/src/hotspot/share/oops/accessBackend.inline.hpp
index 1dacb48427f..677af8115c3 100644
--- a/src/hotspot/share/oops/accessBackend.inline.hpp
+++ b/src/hotspot/share/oops/accessBackend.inline.hpp
@@ -34,6 +34,8 @@
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
+#include
+
template
template
inline typename EnableIf<
@@ -251,7 +253,7 @@ RawAccessBarrier::atomic_cmpxchg_maybe_locked(void* addr, T compare_value, T
}
class RawAccessBarrierArrayCopy: public AllStatic {
- template struct IsHeapWordSized: public IntegralConstant { };
+ template struct IsHeapWordSized: public std::integral_constant { };
public:
template
static inline typename EnableIf<
@@ -334,7 +336,7 @@ class RawAccessBarrierArrayCopy: public AllStatic {
}
};
-template<> struct RawAccessBarrierArrayCopy::IsHeapWordSized: public IntegralConstant { };
+template<> struct RawAccessBarrierArrayCopy::IsHeapWordSized: public std::false_type { };
template
template
diff --git a/src/hotspot/share/oops/accessDecorators.hpp b/src/hotspot/share/oops/accessDecorators.hpp
index 21bcff9113d..f7a3462f59a 100644
--- a/src/hotspot/share/oops/accessDecorators.hpp
+++ b/src/hotspot/share/oops/accessDecorators.hpp
@@ -27,9 +27,10 @@
#include "gc/shared/barrierSetConfig.hpp"
#include "memory/allocation.hpp"
-#include "metaprogramming/integralConstant.hpp"
#include "utilities/globalDefinitions.hpp"
+#include
+
// A decorator is an attribute or property that affects the way a memory access is performed in some way.
// There are different groups of decorators. Some have to do with memory ordering, others to do with,
// e.g. strength of references, strength of GC barriers, or whether compression should be applied or not.
@@ -41,7 +42,7 @@ typedef uint64_t DecoratorSet;
// The HasDecorator trait can help at compile-time determining whether a decorator set
// has an intersection with a certain other decorator set
template
-struct HasDecorator: public IntegralConstant {};
+struct HasDecorator: public std::integral_constant {};
// == General Decorators ==
// * DECORATORS_NONE: This is the name for the empty decorator set (in absence of other decorators).
diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp
index 631afa0d321..74d902c86f0 100644
--- a/src/hotspot/share/oops/generateOopMap.cpp
+++ b/src/hotspot/share/oops/generateOopMap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1732,7 +1732,7 @@ void GenerateOopMap::ppop(CellTypeState *out) {
}
void GenerateOopMap::ppush1(CellTypeState in) {
- assert(in.is_reference() | in.is_value(), "sanity check");
+ assert(in.is_reference() || in.is_value(), "sanity check");
push(in);
}
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
index fdee66a8866..2e9a5125014 100644
--- a/src/hotspot/share/oops/instanceKlass.cpp
+++ b/src/hotspot/share/oops/instanceKlass.cpp
@@ -3941,18 +3941,18 @@ void InstanceKlass::set_init_state(ClassState state) {
// Globally, there is at least one previous version of a class to walk
// during class unloading, which is saved because old methods in the class
// are still running. Otherwise the previous version list is cleaned up.
-bool InstanceKlass::_has_previous_versions = false;
+bool InstanceKlass::_should_clean_previous_versions = false;
// Returns true if there are previous versions of a class for class
// unloading only. Also resets the flag to false. purge_previous_version
// will set the flag to true if there are any left, i.e., if there's any
// work to do for next time. This is to avoid the expensive code cache
// walk in CLDG::clean_deallocate_lists().
-bool InstanceKlass::has_previous_versions_and_reset() {
- bool ret = _has_previous_versions;
- log_trace(redefine, class, iklass, purge)("Class unloading: has_previous_versions = %s",
+bool InstanceKlass::should_clean_previous_versions_and_reset() {
+ bool ret = _should_clean_previous_versions;
+ log_trace(redefine, class, iklass, purge)("Class unloading: should_clean_previous_versions = %s",
ret ? "true" : "false");
- _has_previous_versions = false;
+ _should_clean_previous_versions = false;
return ret;
}
@@ -4027,12 +4027,17 @@ void InstanceKlass::purge_previous_version_list() {
version++;
continue;
} else {
- log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
- // found a previous version for next time we do class unloading
- _has_previous_versions = true;
+ if (pvcp->is_shared()) {
+ // Shared previous versions can never be removed so no cleaning is needed.
+ log_trace(redefine, class, iklass, purge)("previous version " PTR_FORMAT " is shared", p2i(pv_node));
+ } else {
+ // Previous version alive, set that clean is needed for next time.
+ _should_clean_previous_versions = true;
+ log_trace(redefine, class, iklass, purge)("previous version " PTR_FORMAT " is alive", p2i(pv_node));
+ }
}
// next previous version
@@ -4132,13 +4137,19 @@ void InstanceKlass::add_previous_version(InstanceKlass* scratch_class,
return;
}
- // Add previous version if any methods are still running.
- // Set has_previous_version flag for processing during class unloading.
- _has_previous_versions = true;
- log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack.");
+ // Add previous version if any methods are still running or if this is
+ // a shared class which should never be removed.
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class);
+ if (cp_ref->is_shared()) {
+ log_trace(redefine, class, iklass, add) ("scratch class added; class is shared");
+ } else {
+ // We only set clean_previous_versions flag for processing during class
+ // unloading for non-shared classes.
+ _should_clean_previous_versions = true;
+ log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack.");
+ }
} // end add_previous_version()
#endif // INCLUDE_JVMTI
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
index 23b773d0195..9f03bc50d48 100644
--- a/src/hotspot/share/oops/instanceKlass.hpp
+++ b/src/hotspot/share/oops/instanceKlass.hpp
@@ -815,7 +815,7 @@ class InstanceKlass: public Klass {
}
private:
- static bool _has_previous_versions;
+ static bool _should_clean_previous_versions;
public:
static void purge_previous_versions(InstanceKlass* ik) {
if (ik->has_been_redefined()) {
@@ -823,8 +823,8 @@ class InstanceKlass: public Klass {
}
}
- static bool has_previous_versions_and_reset();
- static bool has_previous_versions() { return _has_previous_versions; }
+ static bool should_clean_previous_versions_and_reset();
+ static bool should_clean_previous_versions() { return _should_clean_previous_versions; }
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
void set_cached_class_file(JvmtiCachedClassFileData *data) {
@@ -844,7 +844,7 @@ class InstanceKlass: public Klass {
#else // INCLUDE_JVMTI
static void purge_previous_versions(InstanceKlass* ik) { return; };
- static bool has_previous_versions_and_reset() { return false; }
+ static bool should_clean_previous_versions_and_reset() { return false; }
void set_cached_class_file(JvmtiCachedClassFileData *data) {
assert(data == NULL, "unexpected call with JVMTI disabled");
diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp
index 797cd398093..a597f76a2e6 100644
--- a/src/hotspot/share/oops/markWord.hpp
+++ b/src/hotspot/share/oops/markWord.hpp
@@ -25,11 +25,12 @@
#ifndef SHARE_OOPS_MARKWORD_HPP
#define SHARE_OOPS_MARKWORD_HPP
-#include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/primitiveConversions.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/globals.hpp"
+#include