diff --git a/.github/actions/do-build/action.yml b/.github/actions/do-build/action.yml
index 3deb7f4b8f803..79eddf8c70f0e 100644
--- a/.github/actions/do-build/action.yml
+++ b/.github/actions/do-build/action.yml
@@ -66,7 +66,7 @@ runs:
shell: bash
- name: 'Upload build logs'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: failure-logs-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: failure-logs
@@ -74,7 +74,7 @@ runs:
# This is the best way I found to abort the job with an error message
- name: 'Notify about build failures'
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
with:
script: core.setFailed('Build failed. See summary for details.')
if: steps.check.outputs.failure == 'true'
diff --git a/.github/actions/get-bootjdk/action.yml b/.github/actions/get-bootjdk/action.yml
index 1e569dd47c570..25ee1d8dfa0aa 100644
--- a/.github/actions/get-bootjdk/action.yml
+++ b/.github/actions/get-bootjdk/action.yml
@@ -65,7 +65,7 @@ runs:
- name: 'Check cache for BootJDK'
id: get-cached-bootjdk
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: bootjdk/jdk
key: boot-jdk-${{ inputs.platform }}-${{ steps.sha256.outputs.value }}
diff --git a/.github/actions/get-bundles/action.yml b/.github/actions/get-bundles/action.yml
index 956e1520cfbaa..0e52320a35060 100644
--- a/.github/actions/get-bundles/action.yml
+++ b/.github/actions/get-bundles/action.yml
@@ -48,14 +48,14 @@ runs:
steps:
- name: 'Download bundles artifact'
id: download-bundles
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: bundles
continue-on-error: true
- name: 'Download bundles artifact (retry)'
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: bundles
diff --git a/.github/actions/get-jtreg/action.yml b/.github/actions/get-jtreg/action.yml
index 3f5786b22d3dc..faedcc18807c0 100644
--- a/.github/actions/get-jtreg/action.yml
+++ b/.github/actions/get-jtreg/action.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, 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
@@ -41,7 +41,7 @@ runs:
- name: 'Check cache for JTReg'
id: get-cached-jtreg
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: jtreg/installed
key: jtreg-${{ steps.version.outputs.value }}
@@ -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_17_X64"
+ bash make/build.sh --jdk "$JDK"
mkdir ../installed
mv build/images/jtreg/* ../installed
working-directory: jtreg/src
diff --git a/.github/actions/get-msys2/action.yml b/.github/actions/get-msys2/action.yml
index d36957e3b37e6..82022a6e233ea 100644
--- a/.github/actions/get-msys2/action.yml
+++ b/.github/actions/get-msys2/action.yml
@@ -30,8 +30,7 @@ runs:
using: composite
steps:
- name: 'Install MSYS2'
- # use a specific release of msys2/setup-msys2 to prevent jtreg build failures on newer release
- uses: msys2/setup-msys2@7efe20baefed56359985e327d329042cde2434ff
+ uses: msys2/setup-msys2@v2.22.0
with:
install: 'autoconf tar unzip zip make'
path-type: minimal
diff --git a/.github/actions/upload-bundles/action.yml b/.github/actions/upload-bundles/action.yml
index 88f7f6e8107a5..b35ee3a42e98c 100644
--- a/.github/actions/upload-bundles/action.yml
+++ b/.github/actions/upload-bundles/action.yml
@@ -69,7 +69,7 @@ runs:
shell: bash
- name: 'Upload bundles artifact'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: bundles
diff --git a/.github/scripts/gen-test-results.sh b/.github/scripts/gen-test-results.sh
index 73edb8b3d11fe..9e85eef4dc08d 100644
--- a/.github/scripts/gen-test-results.sh
+++ b/.github/scripts/gen-test-results.sh
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# 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
@@ -44,8 +44,8 @@ for test in $failures $errors; do
base_path="$(echo "$test" | tr '#' '_')"
report_file="$report_dir/$base_path.jtr"
hs_err_files=$(ls $report_dir/$base_path/hs_err*.log 2> /dev/null || true)
+ replay_files=$(ls $report_dir/$base_path/replay*.log 2> /dev/null || true)
echo "#### $test"
-
echo 'View test results
'
echo ''
echo '```'
@@ -73,6 +73,20 @@ for test in $failures $errors; do
echo ''
fi
+ if [[ "$replay_files" != "" ]]; then
+ echo 'View HotSpot replay file
'
+ echo ''
+ for replay in $replay_files; do
+ echo '```'
+ echo "$replay:"
+ echo ''
+ cat "$replay"
+ echo '```'
+ done
+
+ echo ' '
+ echo ''
+ fi
done >> $GITHUB_STEP_SUMMARY
# With many failures, the summary can easily exceed 1024 kB, the limit set by Github
diff --git a/.github/scripts/gen-test-summary.sh b/.github/scripts/gen-test-summary.sh
index d016cb38649fd..a612bed552779 100644
--- a/.github/scripts/gen-test-summary.sh
+++ b/.github/scripts/gen-test-summary.sh
@@ -42,6 +42,7 @@ error_count=$(echo $errors | wc -w || true)
if [[ "$failures" = "" && "$errors" = "" ]]; then
# We know something went wrong, but not what
+ echo 'failure=true' >> $GITHUB_OUTPUT
echo 'error-message=Unspecified test suite failure. Please see log for job for details.' >> $GITHUB_OUTPUT
exit 0
fi
diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml
index 77620640f13bc..dbc6a11ea66a0 100644
--- a/.github/workflows/build-cross-compile.yml
+++ b/.github/workflows/build-cross-compile.yml
@@ -120,7 +120,7 @@ jobs:
- name: 'Check cache for sysroot'
id: get-cached-sysroot
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: sysroot
key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('./.github/workflows/build-cross-compile.yml') }}
diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml
index 3022e07b6ee75..90bb6af044ff8 100644
--- a/.github/workflows/build-macos.yml
+++ b/.github/workflows/build-macos.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, 2023, 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-13
+ 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 ebc0f3d961d36..97a3c4b94b882 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, 2023, 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
@@ -228,6 +228,7 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-x64
+ runs-on: 'macos-13'
xcode-toolset-version: '14.3.1'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
@@ -239,8 +240,8 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-aarch64
+ runs-on: 'macos-14'
xcode-toolset-version: '14.3.1'
- extra-conf-options: '--openjdk-target=aarch64-apple-darwin'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
if: needs.select.outputs.macos-aarch64 == 'true'
@@ -321,6 +322,16 @@ jobs:
bootjdk-platform: macos-x64
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
needs:
@@ -357,7 +368,7 @@ jobs:
# 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@v6
+ uses: actions/github-script@v7
with:
script: 'return { url: process.env["ACTIONS_RUNTIME_URL"], token: process.env["ACTIONS_RUNTIME_TOKEN"] }'
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b3590166264bf..a8885866c1241 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -63,6 +63,7 @@ jobs:
- 'hs/tier1 compiler part 1'
- 'hs/tier1 compiler part 2'
- 'hs/tier1 compiler part 3'
+ - 'hs/tier1 compiler not-xcomp'
- 'hs/tier1 gc'
- 'hs/tier1 runtime'
- 'hs/tier1 serviceability'
@@ -90,13 +91,17 @@ jobs:
debug-suffix: -debug
- test-name: 'hs/tier1 compiler part 2'
- test-suite: 'test/hotspot/jtreg/:tier1_compiler_2 test/hotspot/jtreg/:tier1_compiler_not_xcomp'
+ test-suite: 'test/hotspot/jtreg/:tier1_compiler_2'
debug-suffix: -debug
- test-name: 'hs/tier1 compiler part 3'
test-suite: 'test/hotspot/jtreg/:tier1_compiler_3'
debug-suffix: -debug
+ - test-name: 'hs/tier1 compiler not-xcomp'
+ test-suite: 'test/hotspot/jtreg/:tier1_compiler_not_xcomp'
+ debug-suffix: -debug
+
- test-name: 'hs/tier1 gc'
test-suite: 'test/hotspot/jtreg/:tier1_gc'
debug-suffix: -debug
@@ -206,7 +211,7 @@ jobs:
if: always()
- name: 'Upload test results'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
path: results
name: ${{ steps.package.outputs.artifact-name }}
@@ -214,7 +219,7 @@ jobs:
# This is the best way I found to abort the job with an error message
- name: 'Notify about test failures'
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
with:
script: core.setFailed('${{ steps.run-tests.outputs.error-message }}')
if: steps.run-tests.outputs.failure == 'true'
diff --git a/.jcheck/conf b/.jcheck/conf
index 18228df5dfe46..b374bde90a538 100644
--- a/.jcheck/conf
+++ b/.jcheck/conf
@@ -15,7 +15,7 @@ version=0
domain=openjdk.org
[checks "whitespace"]
-files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.gmk|.*\.m4|.*\.ac|Makefile
+files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.properties|.*\.gmk|.*\.m4|.*\.ac|Makefile
ignore-tabs=.*\.gmk|Makefile
[checks "merge"]
diff --git a/doc/building.html b/doc/building.html
index 69fb371a4770f..29d0ace19b0c7 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -92,6 +92,8 @@ Building the JDK
Autoconf
GNU Make
GNU Bash
+Graphviz
+and Pandoc
Running
Configure
@@ -524,7 +526,7 @@ Linux
The basic tooling is provided as part of the core operating system,
but you will most likely need to install developer packages.
For apt-based distributions (Debian, Ubuntu, etc), try this:
-sudo apt-get install build-essential
+sudo apt-get install build-essential autoconf
For rpm-based distributions (Fedora, Red Hat, etc), try this:
sudo yum groupinstall "Development Tools"
For Alpine Linux, aside from basic tooling, install the GNU versions
@@ -599,7 +601,7 @@
All compilers are expected to be able to handle the C11 language
standard for C, and C++14 for C++.
gcc
-The minimum accepted version of gcc is 6.0. Older versions will not
+
The minimum accepted version of gcc is 10.0. Older versions will not
be accepted by configure
.
The JDK is currently known to compile successfully with gcc version
13.2 or newer.
@@ -753,6 +755,8 @@ Fontconfig
sudo apt-get install libfontconfig-dev
.
To install on an rpm-based Linux, try running
sudo yum install fontconfig-devel
.
+To install on Alpine Linux, try running
+sudo apk add fontconfig-dev
.
Use --with-fontconfig-include=<path>
and
--with-fontconfig=<path>
if configure
@@ -860,6 +864,13 @@
GNU Bash
href="https://www.gnu.org/software/bash">GNU Bash . No other shells
are supported.
At least version 3.2 of GNU Bash must be used.
+Graphviz and Pandoc
+In order to build the full docs (see the
+--enable-full-docs
configure option) Graphviz and Pandoc are required. Any recent versions
+should work. For reference, and subject to change, Oracle builds use
+Graphviz 9.0.0 and Pandoc 2.19.2.
To build the JDK, you need a "configuration", which consists of a
directory where to store the build output, coupled with information
@@ -2155,15 +2166,26 @@
Using Multiple
configure
from there, e.g.
mkdir build/<name> && cd build/<name> && bash ../../configure
.
Then you can build that configuration using
-make CONF_NAME=<name>
or
-make CONF=<pattern>
, where
-<pattern>
is a substring matching one or several
-configurations, e.g. CONF=debug
. The special empty pattern
-(CONF=
) will match all available configuration, so
-make CONF= hotspot
will build the hotspot
-target for all configurations. Alternatively, you can execute
-make
in the configuration directory, e.g.
-cd build/<name> && make
.
+make CONF=<selector>
, where
+<selector>
is interpreted as follows:
+
+- If
<selector>
exacly matches the name of a
+configuration, this and only this configuration will be selected.
+- If
<selector>
matches (i.e. is a substring of)
+the names of several configurations, then all these configurations will
+be selected.
+- If
<selector>
is empty (i.e. CONF=
),
+then all configurations will be selected.
+- If
<selector>
begins with !
, then
+all configurations not matching the string following
+!
will be selected.
+
+A more specialized version, CONF_NAME=<name>
also
+exists, which will only match if the given <name>
+exactly matches a single configuration.
+Alternatively, you can execute make
in the configuration
+directory, e.g. cd build/<name> && make
.
+make CONF_NAME=<name>
or
Handling Reconfigurations
If you update the repository and part of the configure script has
changed, the build system will force you to re-run
diff --git a/doc/building.md b/doc/building.md
index abbd935f652ab..14409b4066839 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -349,7 +349,7 @@ will most likely need to install developer packages.
For apt-based distributions (Debian, Ubuntu, etc), try this:
```
-sudo apt-get install build-essential
+sudo apt-get install build-essential autoconf
```
For rpm-based distributions (Fedora, Red Hat, etc), try this:
@@ -403,7 +403,7 @@ C, and C++14 for C++.
### gcc
-The minimum accepted version of gcc is 6.0. Older versions will not be accepted
+The minimum accepted version of gcc is 10.0. Older versions will not be accepted
by `configure`.
The JDK is currently known to compile successfully with gcc version 13.2 or
@@ -572,6 +572,7 @@ required on all platforms except Windows and macOS.
libfontconfig-dev`.
* To install on an rpm-based Linux, try running `sudo yum install
fontconfig-devel`.
+* To install on Alpine Linux, try running `sudo apk add fontconfig-dev`.
Use `--with-fontconfig-include=` and `--with-fontconfig=` if
`configure` does not automatically locate the platform Fontconfig files.
@@ -684,6 +685,14 @@ shells are supported.
At least version 3.2 of GNU Bash must be used.
+### Graphviz and Pandoc
+
+In order to build the full docs (see the `--enable-full-docs`
+configure option) [Graphviz](https://www.graphviz.org) and
+[Pandoc](https://pandoc.org) are required. Any recent versions should
+work. For reference, and subject to change, Oracle builds use Graphviz
+9.0.0 and Pandoc 2.19.2.
+
## Running Configure
To build the JDK, you need a "configuration", which consists of a directory
@@ -1943,12 +1952,25 @@ configuration with the name ``. Alternatively, you can create a directory
under `build` and run `configure` from there, e.g. `mkdir build/ && cd
build/ && bash ../../configure`.
-Then you can build that configuration using `make CONF_NAME=` or `make
-CONF=`, where `` is a substring matching one or several
-configurations, e.g. `CONF=debug`. The special empty pattern (`CONF=`) will
-match *all* available configuration, so `make CONF= hotspot` will build the
-`hotspot` target for all configurations. Alternatively, you can execute `make`
-in the configuration directory, e.g. `cd build/ && make`.
+Then you can build that configuration using `make CONF=`, where
+`` is interpreted as follows:
+
+* If `` exacly matches the name of a configuration, this and only
+ this configuration will be selected.
+* If `` matches (i.e. is a substring of) the names of several
+ configurations, then all these configurations will be selected.
+* If `` is empty (i.e. `CONF=`), then all configurations will be
+ selected.
+* If `` begins with `!`, then all configurations **not** matching the
+ string following `!` will be selected.
+
+A more specialized version, `CONF_NAME=` also exists, which will only
+match if the given `` exactly matches a single configuration.
+
+Alternatively, you can execute `make` in the configuration directory, e.g. `cd
+build/ && make`.
+
+`make CONF_NAME=` or
### Handling Reconfigurations
diff --git a/make/Docs.gmk b/make/Docs.gmk
index 5f9ec99fcae0f..d0c01f0283d43 100644
--- a/make/Docs.gmk
+++ b/make/Docs.gmk
@@ -139,11 +139,6 @@ ifeq ($(IS_DRAFT), true)
endif
DRAFT_TEXT := This specification is not final and is subject to change. \
Use is subject to license terms.
-
- # Workaround stylesheet bug
- HEADER_STYLE := style="margin-top: 9px;"
-else
- HEADER_STYLE := style="margin-top: 14px;"
endif
# $1 - Relative prefix to COPYRIGHT_URL
@@ -339,7 +334,7 @@ define SetupApiDocsGenerationBody
$1_DOC_TITLE := $$($1_LONG_NAME)
Version $$(VERSION_SPECIFICATION) API \
Specification
$1_WINDOW_TITLE := $$(subst &,&,$$($1_SHORT_NAME))$$(DRAFT_MARKER_TITLE)
- $1_HEADER_TITLE := $$($1_SHORT_NAME) \
+ $1_HEADER_TITLE :=
$$($1_SHORT_NAME) \
$$(DRAFT_MARKER_STR)
ifneq ($$($1_OTHER_VERSIONS), )
$1_JAVADOC_BOTTOM := $$(call JAVADOC_BOTTOM,
Other versions.)
@@ -647,7 +642,7 @@ ifeq ($(ENABLE_PANDOC), true)
GLOBAL_SPECS_DEFAULT_CSS_FILE := $(DOCS_OUTPUTDIR)/resources/jdk-default.css
# Unset the following to suppress the link to the tool guides
NAV_LINK_GUIDES := --nav-link-guides
- HEADER_RIGHT_SIDE_INFO :=
$(subst &,&,$(JDK_SHORT_NAME))$(DRAFT_MARKER_STR)
+ HEADER_RIGHT_SIDE_INFO :=
$(subst &,&,$(JDK_SHORT_NAME))$(DRAFT_MARKER_STR)
$(foreach m, $(ALL_MODULES), \
$(eval SPECS_$m := $(call FindModuleSpecsDirs, $m)) \
diff --git a/make/Global.gmk b/make/Global.gmk
index e5e76b475b941..1df6c5fb6bc4b 100644
--- a/make/Global.gmk
+++ b/make/Global.gmk
@@ -87,10 +87,9 @@ help:
$(info $(_) # (gensrc, java, copy, libs, launchers, gendata))
$(info )
$(info Make control variables)
- $(info $(_) CONF= # Build all configurations (note, assignment is empty))
- $(info $(_) CONF=
# Build the configuration(s) with a name matching)
- $(info $(_) # )
- $(info $(_) CONF_NAME= # Build the configuration with exactly the )
+ $(info $(_) CONF= # Select which configuration(s) to build)
+ $(info $(_) CONF= # Select all configurations (note, assignment is empty))
+ $(info $(_) CONF_NAME= # Select the configuration with the name )
$(info $(_) SPEC= # Build the configuration given by the spec file)
$(info $(_) LOG= # Change the log level from warn to )
$(info $(_) # Available log levels are:)
diff --git a/make/Hsdis.gmk b/make/Hsdis.gmk
index 7496a3a2cf1b4..6de0e628a5288 100644
--- a/make/Hsdis.gmk
+++ b/make/Hsdis.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2023, 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
@@ -38,7 +38,7 @@ HSDIS_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/hsdis
REAL_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX)
BUILT_HSDIS_LIB := $(HSDIS_OUTPUT_DIR)/$(REAL_HSDIS_NAME)
-HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT
+HSDIS_LINK_TYPE := C
HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB)
HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB)
@@ -59,8 +59,8 @@ endif
ifeq ($(HSDIS_BACKEND), llvm)
# Use C++ instead of C
+ HSDIS_LINK_TYPE := C++
HSDIS_TOOLCHAIN_CFLAGS := $(CXXFLAGS_JDKLIB)
- HSDIS_TOOLCHAIN := TOOLCHAIN_LINK_CXX
ifeq ($(call isTargetOs, linux), true)
LLVM_OS := pc-linux-gnu
@@ -91,14 +91,11 @@ ifeq ($(HSDIS_BACKEND), binutils)
endif
endif
- $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \
- CC := $(MINGW_BASE)-gcc, \
- LD := $(MINGW_BASE)-ld, \
- OBJCOPY := $(MINGW_BASE)-objcopy, \
- RC := $(RC), \
- SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \
- SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \
- ))
+ BUILD_HSDIS_CC := $(MINGW_BASE)-gcc
+ BUILD_HSDIS_LD := $(MINGW_BASE)-ld
+ BUILD_HSDIS_OBJCOPY := $(MINGW_BASE)-objcopy
+ BUILD_HSDIS_SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT)
+ BUILD_HSDIS_SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT)
MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib
ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), )
@@ -122,8 +119,8 @@ ifeq ($(HSDIS_BACKEND), binutils)
TOOLCHAIN_TYPE := gcc
OPENJDK_TARGET_OS := linux
+ OPENJDK_TARGET_OS_TYPE := unix
CC_OUT_OPTION := -o$(SPACE)
- LD_OUT_OPTION := -o$(SPACE)
GENDEPS_FLAGS := -MMD -MF
CFLAGS_DEBUG_SYMBOLS := -g
DISABLED_WARNINGS :=
@@ -131,7 +128,6 @@ ifeq ($(HSDIS_BACKEND), binutils)
CFLAGS_WARNINGS_ARE_ERRORS := -Werror
SHARED_LIBRARY_FLAGS := -shared
- HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW
HSDIS_TOOLCHAIN_CFLAGS :=
HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH)
MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o
@@ -144,9 +140,9 @@ endif
$(eval $(call SetupJdkLibrary, BUILD_HSDIS, \
NAME := hsdis, \
+ LINK_TYPE := $(HSDIS_LINK_TYPE), \
SRC := $(TOPDIR)/src/utils/hsdis/$(HSDIS_BACKEND), \
EXTRA_HEADER_DIRS := $(TOPDIR)/src/utils/hsdis, \
- TOOLCHAIN := $(HSDIS_TOOLCHAIN), \
OUTPUT_DIR := $(HSDIS_OUTPUT_DIR), \
OBJECT_DIR := $(HSDIS_OUTPUT_DIR), \
DISABLED_WARNINGS_gcc := undef format-nonliteral sign-compare, \
diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk
index 31c80e2f7267f..4b14c4f9ad951 100644
--- a/make/InitSupport.gmk
+++ b/make/InitSupport.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -202,8 +202,14 @@ ifeq ($(HAS_SPEC),)
matching_confs := $$(strip $$(all_confs))
else
# Otherwise select those that contain the given CONF string
- matching_confs := $$(strip $$(foreach var, $$(all_confs), \
- $$(if $$(findstring $$(CONF), $$(var)), $$(var))))
+ ifeq ($$(patsubst !%,,$$(CONF)),)
+ # A CONF starting with ! means we should negate the search term
+ matching_confs := $$(strip $$(foreach var, $$(all_confs), \
+ $$(if $$(findstring $$(subst !,,$$(CONF)), $$(var)), ,$$(var))))
+ else
+ matching_confs := $$(strip $$(foreach var, $$(all_confs), \
+ $$(if $$(findstring $$(CONF), $$(var)), $$(var))))
+ endif
ifneq ($$(filter $$(CONF), $$(matching_confs)), )
# If we found an exact match, use that
matching_confs := $$(CONF)
@@ -421,8 +427,9 @@ else # $(HAS_SPEC)=true
# Cleanup after a compare build
define CleanupCompareBuild
- # If running with a COMPARE_BUILD patch, reverse-apply it
- $(if $(COMPARE_BUILD_PATCH), cd $(topdir) && $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH))
+ # If running with a COMPARE_BUILD patch, reverse-apply it, but continue
+ # even if that fails (can happen with removed files).
+ $(if $(COMPARE_BUILD_PATCH), cd $(topdir) && $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH) || true)
# Move this build away and restore the original build
$(MKDIR) -p $(topdir)/build/compare-build
$(MV) $(OUTPUTDIR) $(COMPARE_BUILD_OUTPUTDIR)
diff --git a/make/Main.gmk b/make/Main.gmk
index 5534a68f13bab..b0b7565c138e2 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -969,20 +969,28 @@ else
jdk.jdeps-gendata: java
- # The ct.sym generation uses all the moduleinfos as input
- jdk.compiler-gendata: $(GENSRC_MODULEINFO_TARGETS) $(JAVA_TARGETS)
- # jdk.compiler-gendata needs the BUILD_JDK. If the BUILD_JDK was supplied
- # externally, no extra prerequisites are needed.
+ # jdk.compiler gendata generates ct.sym, which requires all generated
+ # java source and compiled classes present.
+ jdk.compiler-gendata: $(JAVA_TARGETS)
+
+ # jdk.javadoc gendata generates element-list, which requires all java sources
+ # but not compiled classes.
+ jdk.javadoc-gendata: $(GENSRC_TARGETS)
+
+ # ct.sym and element-list generation also needs the BUILD_JDK. If the
+ # BUILD_JDK was supplied externally, no extra prerequisites are needed.
ifeq ($(CREATE_BUILDJDK), true)
ifneq ($(CREATING_BUILDJDK), true)
# When cross compiling and an external BUILD_JDK wasn't supplied, it's
# produced by the create-buildjdk target.
jdk.compiler-gendata: create-buildjdk
+ jdk.javadoc-gendata: create-buildjdk
endif
else ifeq ($(EXTERNAL_BUILDJDK), false)
# When not cross compiling, the BUILD_JDK is the interim jdk image, and
# the javac launcher is needed.
jdk.compiler-gendata: jdk.compiler-launchers
+ jdk.javadoc-gendata: jdk.compiler-launchers
endif
# Declare dependencies between jmod targets.
diff --git a/make/RunTests.gmk b/make/RunTests.gmk
index b82d2b2b6015d..b0291e4eff4e7 100644
--- a/make/RunTests.gmk
+++ b/make/RunTests.gmk
@@ -620,11 +620,16 @@ define SetupRunMicroTestBody
$1_MICRO_WARMUP_TIME := -w $$(MICRO_WARMUP_TIME)
endif
+# Microbenchmarks are executed from the root of the test image directory.
+# This enables JMH tests to add dependencies using relative paths such as
+# -Djava.library.path=micro/native
+
run-test-$1: pre-run-test
$$(call LogWarn)
$$(call LogWarn, Running test '$$($1_TEST)')
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/micro, ( \
+ $$(CD) $$(TEST_IMAGE_DIR) && \
$$(FIXPATH) $$($1_MICRO_TEST_JDK)/bin/java $$($1_MICRO_JAVA_OPTIONS) \
-jar $$($1_MICRO_BENCHMARKS_JAR) \
$$($1_MICRO_ITER) $$($1_MICRO_FORK) $$($1_MICRO_TIME) \
diff --git a/make/autoconf/basic.m4 b/make/autoconf/basic.m4
index 5a1fbc0795274..91d7a55010887 100644
--- a/make/autoconf/basic.m4
+++ b/make/autoconf/basic.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -123,6 +123,22 @@ AC_DEFUN_ONCE([BASIC_SETUP_BUILD_ENV],
]
)
AC_SUBST(BUILD_ENV)
+
+ if test "x$LOCALE" != x; then
+ # Check if we actually have C.UTF-8; if so, use it
+ if $LOCALE -a | $GREP -q -E "^C\.(utf8|UTF-8)$"; then
+ LOCALE_USED=C.UTF-8
+ else
+ AC_MSG_WARN([C.UTF-8 locale not found, using C locale])
+ LOCALE_USED=C
+ fi
+ else
+ AC_MSG_WARN([locale command not not found, using C locale])
+ LOCALE_USED=C
+ fi
+
+ export LC_ALL=$LOCALE_USED
+ AC_SUBST(LOCALE_USED)
])
###############################################################################
diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4
index f9ecbab7ac099..0c084561f2ef0 100644
--- a/make/autoconf/basic_tools.m4
+++ b/make/autoconf/basic_tools.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -54,6 +54,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
UTIL_REQUIRE_SPECIAL(SED, [AC_PROG_SED])
# Tools only needed on some platforms
+ UTIL_LOOKUP_PROGS(LOCALE, locale)
UTIL_LOOKUP_PROGS(PATHTOOL, cygpath wslpath)
UTIL_LOOKUP_PROGS(CMD, cmd.exe, $PATH:/cygdrive/c/windows/system32:/mnt/c/windows/system32:/c/windows/system32)
])
diff --git a/make/autoconf/build-aux/pkg.m4 b/make/autoconf/build-aux/pkg.m4
index 5f4b22bb27f05..ddb685e9bc35f 100644
--- a/make/autoconf/build-aux/pkg.m4
+++ b/make/autoconf/build-aux/pkg.m4
@@ -25,7 +25,7 @@
# questions.
#
-#
+#
# Copyright © 2004 Scott James Remnant .
#
# This program is free software; you can redistribute it and/or modify
@@ -54,18 +54,18 @@ AC_DEFUN([PKG_PROG_PKG_CONFIG],
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
- AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
- _pkg_min_version=m4_default([$1], [0.9.0])
- AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- PKG_CONFIG=""
- fi
-
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
fi[]dnl
])# PKG_PROG_PKG_CONFIG
@@ -97,7 +97,7 @@ m4_define([_PKG_CONFIG],
elif test -n "$PKG_CONFIG"; then
PKG_CHECK_EXISTS([$3],
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
- [pkg_failed=yes])
+ [pkg_failed=yes])
else
pkg_failed=untried
fi[]dnl
@@ -143,14 +143,14 @@ See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
- else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
fi
- # Put the nasty error message in config.log where it belongs
- echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
- ifelse([$4], , [AC_MSG_ERROR(dnl
+ ifelse([$4], , [AC_MSG_ERROR(dnl
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
@@ -160,10 +160,10 @@ installed software in a non-standard prefix.
_PKG_TEXT
])],
- [AC_MSG_RESULT([no])
+ [AC_MSG_RESULT([no])
$4])
elif test $pkg_failed = untried; then
- ifelse([$4], , [AC_MSG_FAILURE(dnl
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
@@ -171,11 +171,11 @@ path to pkg-config.
_PKG_TEXT
To get pkg-config, see .])],
- [$4])
+ [$4])
else
- $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
- $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
- ifelse([$3], , :, [$3])
+ ifelse([$3], , :, [$3])
fi[]dnl
])# PKG_CHECK_MODULES
diff --git a/make/autoconf/buildjdk-spec.gmk.template b/make/autoconf/buildjdk-spec.gmk.template
index 993ed50390210..924389b94e8b0 100644
--- a/make/autoconf/buildjdk-spec.gmk.template
+++ b/make/autoconf/buildjdk-spec.gmk.template
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 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
@@ -40,6 +40,7 @@ LDCXX := @BUILD_LDCXX@
AS := @BUILD_AS@
NM := @BUILD_NM@
AR := @BUILD_AR@
+LIB := @BUILD_LIB@
OBJCOPY := @BUILD_OBJCOPY@
STRIP := @BUILD_STRIP@
SYSROOT_CFLAGS := @BUILD_SYSROOT_CFLAGS@
diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index df44f7a2d59e2..efc8025a074cf 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -40,7 +40,6 @@ AC_DEFUN([FLAGS_SETUP_SHARED_LIBS],
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1'
SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
- SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
elif test "x$TOOLCHAIN_TYPE" = xclang; then
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
@@ -49,7 +48,6 @@ AC_DEFUN([FLAGS_SETUP_SHARED_LIBS],
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path$(or [$]1,/.)'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1'
- SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,[$]1'
elif test "x$OPENJDK_TARGET_OS" = xaix; then
# Linking is different on aix
@@ -57,14 +55,12 @@ AC_DEFUN([FLAGS_SETUP_SHARED_LIBS],
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
- SET_SHARED_LIBRARY_MAPFILE=''
else
# Default works for linux, might work on other platforms as well.
SHARED_LIBRARY_FLAGS='-shared'
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1'
SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
- SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
# arm specific settings
if test "x$OPENJDK_TARGET_CPU" = "xarm"; then
@@ -80,20 +76,17 @@ AC_DEFUN([FLAGS_SETUP_SHARED_LIBS],
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
- SET_SHARED_LIBRARY_MAPFILE=''
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
SHARED_LIBRARY_FLAGS="-dll"
SET_EXECUTABLE_ORIGIN=''
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
- SET_SHARED_LIBRARY_MAPFILE='-def:[$]1'
fi
AC_SUBST(SET_EXECUTABLE_ORIGIN)
AC_SUBST(SET_SHARED_LIBRARY_ORIGIN)
AC_SUBST(SET_SHARED_LIBRARY_NAME)
- AC_SUBST(SET_SHARED_LIBRARY_MAPFILE)
AC_SUBST(SHARED_LIBRARY_FLAGS)
])
@@ -117,6 +110,16 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_PREFIX_CFLAGS}],
IF_FALSE: [
DEBUG_PREFIX_CFLAGS=
+ ],
+ IF_TRUE: [
+ # Add debug prefix map gcc system include paths, as they cause
+ # non-deterministic debug paths depending on gcc path location.
+ DEBUG_PREFIX_MAP_GCC_INCLUDE_PATHS
+
+ # Add debug prefix map for OUTPUTDIR to handle the scenario when
+ # it is not located within WORKSPACE_ROOT
+ outputdir_slash="${OUTPUTDIR%/}/"
+ DEBUG_PREFIX_CFLAGS="$DEBUG_PREFIX_CFLAGS -fdebug-prefix-map=${outputdir_slash}="
]
)
fi
@@ -158,6 +161,55 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
AC_SUBST(ASFLAGS_DEBUG_SYMBOLS)
])
+# gcc will embed the full system include paths in the debug info
+# resulting in non-deterministic debug symbol files and thus
+# non-reproducible native libraries if gcc includes are located
+# in different paths.
+# Add -fdebug-prefix-map'ings for root and gcc include paths,
+# pointing to a common set of folders so that the binaries are deterministic:
+# root include : /usr/include
+# gcc include : /usr/local/gcc_include
+# g++ include : /usr/local/gxx_include
+AC_DEFUN([DEBUG_PREFIX_MAP_GCC_INCLUDE_PATHS],
+[
+ # Determine gcc system include paths.
+ # Assume default roots to start with:
+ GCC_ROOT_INCLUDE="/usr/include"
+
+ # Determine is sysroot or devkit specified?
+ if test "x$SYSROOT" != "x"; then
+ GCC_ROOT_INCLUDE="${SYSROOT%/}/usr/include"
+ fi
+
+ # Add root include mapping => /usr/include
+ GCC_INCLUDE_DEBUG_MAP_FLAGS="-fdebug-prefix-map=${GCC_ROOT_INCLUDE}/=/usr/include/"
+
+ # Add gcc system include mapping => /usr/local/gcc_include
+ # Find location of stddef.h using build C compiler
+ GCC_SYSTEM_INCLUDE=`$ECHO "#include " | \
+ $CC $CFLAGS -v -E - 2>&1 | \
+ $GREP stddef | $TAIL -1 | $TR -s " " | $CUT -d'"' -f2`
+ if test "x$GCC_SYSTEM_INCLUDE" != "x"; then
+ GCC_SYSTEM_INCLUDE=`$DIRNAME $GCC_SYSTEM_INCLUDE`
+ GCC_INCLUDE_DEBUG_MAP_FLAGS="$GCC_INCLUDE_DEBUG_MAP_FLAGS \
+ -fdebug-prefix-map=${GCC_SYSTEM_INCLUDE}/=/usr/local/gcc_include/"
+ fi
+
+ # Add g++ system include mapping => /usr/local/gxx_include
+ # Find location of cstddef using build C++ compiler
+ GXX_SYSTEM_INCLUDE=`$ECHO "#include " | \
+ $CXX $CXXFLAGS -v -E -x c++ - 2>&1 | \
+ $GREP cstddef | $TAIL -1 | $TR -s " " | $CUT -d'"' -f2`
+ if test "x$GXX_SYSTEM_INCLUDE" != "x"; then
+ GXX_SYSTEM_INCLUDE=`$DIRNAME $GXX_SYSTEM_INCLUDE`
+ GCC_INCLUDE_DEBUG_MAP_FLAGS="$GCC_INCLUDE_DEBUG_MAP_FLAGS \
+ -fdebug-prefix-map=${GXX_SYSTEM_INCLUDE}/=/usr/local/gxx_include/"
+ fi
+
+ # Add to debug prefix cflags
+ DEBUG_PREFIX_CFLAGS="$DEBUG_PREFIX_CFLAGS $GCC_INCLUDE_DEBUG_MAP_FLAGS"
+])
+
AC_DEFUN([FLAGS_SETUP_WARNINGS],
[
# Set default value.
@@ -425,13 +477,14 @@ 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_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
+ CFLAGS_OS_DEF_JVM="-DLINUX -D_FILE_OFFSET_BITS=64"
+ CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64"
elif test "x$OPENJDK_TARGET_OS" = xmacosx; then
CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE"
CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
elif test "x$OPENJDK_TARGET_OS" = xaix; then
- CFLAGS_OS_DEF_JVM="-DAIX"
+ CFLAGS_OS_DEF_JVM="-DAIX -D_LARGE_FILES"
+ CFLAGS_OS_DEF_JDK="-D_LARGE_FILES"
elif test "x$OPENJDK_TARGET_OS" = xbsd; then
CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE"
elif test "x$OPENJDK_TARGET_OS" = xwindows; then
@@ -489,7 +542,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
ALWAYS_DEFINES_JVM="-D_GNU_SOURCE"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
ALWAYS_DEFINES_JVM="-D_REENTRANT"
- ALWAYS_DEFINES_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC"
+ ALWAYS_DEFINES_JDK="-D_GNU_SOURCE -D_REENTRANT -DSTDC"
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
# Access APIs for Windows 8 and above
# see https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170
diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4
index 195c1d341595f..58bc4a44bfbdf 100644
--- a/make/autoconf/flags-ldflags.m4
+++ b/make/autoconf/flags-ldflags.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -93,7 +93,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
BASIC_LDFLAGS_JVM_ONLY="-Wl,-lC_r -bbigtoc"
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
- BASIC_LDFLAGS="-nologo -opt:ref"
+ BASIC_LDFLAGS="-opt:ref"
BASIC_LDFLAGS_JDK_ONLY="-incremental:no"
BASIC_LDFLAGS_JVM_ONLY="-opt:icf,8 -subsystem:windows"
fi
diff --git a/make/autoconf/flags-other.m4 b/make/autoconf/flags-other.m4
index 7e2521ffef3b0..8d4d405b07639 100644
--- a/make/autoconf/flags-other.m4
+++ b/make/autoconf/flags-other.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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,9 +33,6 @@ AC_DEFUN([FLAGS_SETUP_ARFLAGS],
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xaix; then
ARFLAGS="-X64"
- elif test "x$OPENJDK_TARGET_OS" = xwindows; then
- # lib.exe is used as AR to create static libraries.
- ARFLAGS="-nologo -NODEFAULTLIB:MSVCRT"
else
ARFLAGS=""
fi
@@ -43,6 +40,18 @@ AC_DEFUN([FLAGS_SETUP_ARFLAGS],
AC_SUBST(ARFLAGS)
])
+AC_DEFUN([FLAGS_SETUP_LIBFLAGS],
+[
+ # LIB is used to create static libraries on Windows
+ if test "x$OPENJDK_TARGET_OS" = xwindows; then
+ LIBFLAGS="-nodefaultlib:msvcrt"
+ else
+ LIBFLAGS=""
+ fi
+
+ AC_SUBST(LIBFLAGS)
+])
+
AC_DEFUN([FLAGS_SETUP_STRIPFLAGS],
[
## Setup strip.
diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4
index 8c029f7d2f58f..147382f398eed 100644
--- a/make/autoconf/flags.m4
+++ b/make/autoconf/flags.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -364,24 +364,12 @@ AC_DEFUN([FLAGS_SETUP_TOOLCHAIN_CONTROL],
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
CC_OUT_OPTION=-Fo
- LD_OUT_OPTION=-out:
- AR_OUT_OPTION=-out:
else
# The option used to specify the target .o,.a or .so file.
# When compiling, how to specify the to be created object file.
CC_OUT_OPTION='-o$(SPACE)'
- # When linking, how to specify the output
- LD_OUT_OPTION='-o$(SPACE)'
- # When archiving, how to specify the destination static archive.
- if test "x$OPENJDK_TARGET_OS" = xmacosx; then
- AR_OUT_OPTION='-r -cs$(SPACE)'
- else
- AR_OUT_OPTION='-rcs$(SPACE)'
- fi
fi
AC_SUBST(CC_OUT_OPTION)
- AC_SUBST(LD_OUT_OPTION)
- AC_SUBST(AR_OUT_OPTION)
# Generate make dependency files
if test "x$TOOLCHAIN_TYPE" = xgcc; then
@@ -423,6 +411,7 @@ AC_DEFUN([FLAGS_SETUP_FLAGS],
FLAGS_SETUP_LDFLAGS
FLAGS_SETUP_ARFLAGS
+ FLAGS_SETUP_LIBFLAGS
FLAGS_SETUP_STRIPFLAGS
FLAGS_SETUP_RCFLAGS
FLAGS_SETUP_NMFLAGS
diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template
index b78d3da6b32ed..863a51eeb4afa 100644
--- a/make/autoconf/spec.gmk.template
+++ b/make/autoconf/spec.gmk.template
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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,8 @@ COMMA := ,
# What make to use for main processing, after bootstrapping top-level Makefile.
MAKE := @MAKE@
-# Make sure all shell commands are executed with the C locale
-export LC_ALL := C
+# Make sure all shell commands are executed with a proper locale
+export LC_ALL := @LOCALE_USED@
# Make sure we override any local CLASSPATH variable
export CLASSPATH := @CLASSPATH@
@@ -498,8 +498,6 @@ COMPILER_COMMAND_FILE_FLAG := @COMPILER_COMMAND_FILE_FLAG@
COMPILER_BINDCMD_FILE_FLAG := @COMPILER_BINDCMD_FILE_FLAG@
CC_OUT_OPTION := @CC_OUT_OPTION@
-LD_OUT_OPTION := @LD_OUT_OPTION@
-AR_OUT_OPTION := @AR_OUT_OPTION@
# Flags used for overriding the default opt setting for a C/C++ source file.
C_O_FLAG_HIGHEST_JVM := @C_O_FLAG_HIGHEST_JVM@
@@ -604,10 +602,10 @@ BUILD_SYSROOT_LDFLAGS := @BUILD_SYSROOT_LDFLAGS@
AS := @AS@
-# AR is used to create a static library (is ar in unix, lib.exe in windows)
AR := @AR@
ARFLAGS := @ARFLAGS@
-
+LIB := @LIB@
+LIBFLAGS := @LIBFLAGS@
NM := @NM@
NMFLAGS := @NMFLAGS@
STRIP := @STRIP@
@@ -619,10 +617,6 @@ INSTALL_NAME_TOOL := @INSTALL_NAME_TOOL@
METAL := @METAL@
METALLIB := @METALLIB@
-# Options to linker to specify a mapfile.
-# (Note absence of := assignment, because we do not want to evaluate the macro body here)
-SET_SHARED_LIBRARY_MAPFILE = @SET_SHARED_LIBRARY_MAPFILE@
-
#
# Options for generating debug symbols
COMPILE_WITH_DEBUG_SYMBOLS := @COMPILE_WITH_DEBUG_SYMBOLS@
diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4
index 289eec3356b91..de0b6f0adfb17 100644
--- a/make/autoconf/toolchain.m4
+++ b/make/autoconf/toolchain.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -51,7 +51,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
# Minimum supported versions, empty means unspecified
TOOLCHAIN_MINIMUM_VERSION_clang="3.5"
-TOOLCHAIN_MINIMUM_VERSION_gcc="6.0"
+TOOLCHAIN_MINIMUM_VERSION_gcc="10.0"
TOOLCHAIN_MINIMUM_VERSION_microsoft="19.28.0.0" # VS2019 16.8, aka MSVC 14.28
TOOLCHAIN_MINIMUM_VERSION_xlc="16.1.0.0011"
@@ -389,6 +389,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_POST_DETECTION],
# This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2"
CFLAGS="$ORG_CFLAGS"
CXXFLAGS="$ORG_CXXFLAGS"
+
+ # filter out some unwanted additions autoconf may add to CXX; we saw this on macOS with autoconf 2.72
+ UTIL_GET_NON_MATCHING_VALUES(cxx_filtered, $CXX, -std=c++11 -std=gnu++11)
+ CXX="$cxx_filtered"
])
# Check if a compiler is of the toolchain type we expect, and save the version
@@ -728,11 +732,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE],
AC_SUBST(AS)
#
- # Setup the archiver (AR)
+ # Setup tools for creating static libraries (AR/LIB)
#
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
- # The corresponding ar tool is lib.exe (used to create static libraries)
- UTIL_LOOKUP_TOOLCHAIN_PROGS(AR, lib)
+ UTIL_LOOKUP_TOOLCHAIN_PROGS(LIB, lib)
elif test "x$TOOLCHAIN_TYPE" = xgcc; then
UTIL_LOOKUP_TOOLCHAIN_PROGS(AR, ar gcc-ar)
else
diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4
index 349a04a089ee4..3fae951224e3b 100644
--- a/make/autoconf/util.m4
+++ b/make/autoconf/util.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -199,7 +199,7 @@ AC_DEFUN([UTIL_GET_NON_MATCHING_VALUES],
if test -z "$legal_values"; then
$1="$2"
else
- result=`$GREP -Fvx "$legal_values" <<< "$values_to_check" | $GREP -v '^$'`
+ result=`$GREP -Fvx -- "$legal_values" <<< "$values_to_check" | $GREP -v '^$'`
$1=${result//$'\n'/ }
fi
])
@@ -226,7 +226,7 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES],
if test -z "$illegal_values"; then
$1=""
else
- result=`$GREP -Fx "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'`
+ result=`$GREP -Fx -- "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'`
$1=${result//$'\n'/ }
fi
])
diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk
index 252d9dd50da68..3858b652ee65c 100644
--- a/make/common/MakeBase.gmk
+++ b/make/common/MakeBase.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -152,6 +152,10 @@ define SetupLogging
endif
endif
+ ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
+ SHELL := $$(SHELL) -x
+ endif
+
ifeq ($$(LOG_LEVEL), trace)
SHELL_NO_RECURSE := $$(SHELL)
# Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index 68d1dba27ffcc..13b0318b4c776 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -23,9 +23,11 @@
# questions.
#
-# When you read this source. Remember that $(sort ...) has the side effect
-# of removing duplicates. It is actually this side effect that is
-# desired whenever sort is used below!
+################################################################################
+# This is the top-level entry point for our native compilation and linking.
+# It contains the SetupNativeCompilation macro, but is supported by helper
+# macros in the make/common/native directory.
+################################################################################
ifndef _NATIVE_COMPILATION_GMK
_NATIVE_COMPILATION_GMK := 1
@@ -34,463 +36,14 @@ ifeq ($(_MAKEBASE_GMK), )
$(error You must include MakeBase.gmk prior to including NativeCompilation.gmk)
endif
-################################################################################
-# Create exported symbols file for static libraries
-################################################################################
-
-# get the exported symbols from mapfiles and if there
-# is no mapfile, get them from the archive
-define GetSymbols
- $(RM) $$(@D)/$$(basename $$(@F)).symbols; \
- if [ ! -z $$($1_MAPFILE) -a -e $$($1_MAPFILE) ]; then \
- $(ECHO) "Getting symbols from mapfile $$($1_MAPFILE)"; \
- $(AWK) '/global:/','/local:/' $$($1_MAPFILE) | \
- $(SED) -e 's/#.*//;s/global://;s/local://;s/\;//;s/^[ ]*/_/;/^_$$$$/d' | \
- $(EGREP) -v "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" > \
- $$(@D)/$$(basename $$(@F)).symbols || true; \
- $(NM) $(NMFLAGS) $$($1_TARGET) | $(GREP) " T " | \
- $(EGREP) "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" | \
- $(CUT) -d ' ' -f 3 >> $$(@D)/$$(basename $$(@F)).symbols || true;\
- else \
- $(ECHO) "Getting symbols from nm"; \
- $(NM) $(NMFLAGS) -m $$($1_TARGET) | $(GREP) "__TEXT" | \
- $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \
- $(SED) -e 's/.* //' > $$(@D)/$$(basename $$(@F)).symbols; \
- fi
-endef
-
-################################################################################
-# Creates a recipe that creates a compile_commands.json fragment. Remove any
-# occurrences of FIXPATH programs from the command to show the actual invocation.
-#
-# Param 1: Name of file to create
-# Param 2: Working directory
-# Param 3: Source file
-# Param 4: Compile command
-################################################################################
-define WriteCompileCommandsFragment
- $(call LogInfo, Creating compile commands fragment for $(notdir $3))
- $(call MakeDir, $(dir $1))
- $(call WriteFile,{ \
- "directory": "$(strip $(call FixPath, $2))"$(COMMA) \
- "file": "$(strip $(call FixPath, $3))"$(COMMA) \
- "command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\
- $(subst $(FIXPATH),,$(call FixPath, $4)))))" \
- }$(COMMA), \
- $1)
-endef
-
-################################################################################
-# Define a native toolchain configuration that can be used by
-# SetupNativeCompilation calls
-#
-# Parameter 1 is the name of the toolchain definition
-#
-# Remaining parameters are named arguments:
-# EXTENDS - Optional parent definition to get defaults from
-# CC - The C compiler
-# CXX - The C++ compiler
-# LD - The Linker
-# AR - Static linker
-# AS - Assembler
-# MT - Windows MT tool
-# RC - Windows RC tool
-# OBJCOPY - The objcopy tool for debug symbol handling
-# STRIP - The tool to use for stripping debug symbols
-# SYSROOT_CFLAGS - Compiler flags for using the specific sysroot
-# SYSROOT_LDFLAGS - Linker flags for using the specific sysroot
-DefineNativeToolchain = $(NamedParamsMacroTemplate)
-define DefineNativeToolchainBody
- # If extending another definition, get default values from that,
- # otherwise, nothing more needs to be done as variable assignments
- # already happened in NamedParamsMacroTemplate.
- ifneq ($$($1_EXTENDS), )
- $$(call SetIfEmpty, $1_CC, $$($$($1_EXTENDS)_CC))
- $$(call SetIfEmpty, $1_CXX, $$($$($1_EXTENDS)_CXX))
- $$(call SetIfEmpty, $1_LD, $$($$($1_EXTENDS)_LD))
- $$(call SetIfEmpty, $1_AR, $$($$($1_EXTENDS)_AR))
- $$(call SetIfEmpty, $1_AS, $$($$($1_EXTENDS)_AS))
- $$(call SetIfEmpty, $1_MT, $$($$($1_EXTENDS)_MT))
- $$(call SetIfEmpty, $1_RC, $$($$($1_EXTENDS)_RC))
- $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_EXTENDS)_OBJCOPY))
- $$(call SetIfEmpty, $1_STRIP, $$($$($1_EXTENDS)_STRIP))
- $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_EXTENDS)_SYSROOT_CFLAGS))
- $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_EXTENDS)_SYSROOT_LDFLAGS))
- endif
-endef
-
-# Create a default toolchain with the main compiler and linker
-$(eval $(call DefineNativeToolchain, TOOLCHAIN_DEFAULT, \
- CC := $(CC), \
- CXX := $(CXX), \
- LD := $(LD), \
- AR := $(AR), \
- AS := $(AS), \
- MT := $(MT), \
- RC := $(RC), \
- OBJCOPY := $(OBJCOPY), \
- STRIP := $(STRIP), \
- SYSROOT_CFLAGS := $(SYSROOT_CFLAGS), \
- SYSROOT_LDFLAGS := $(SYSROOT_LDFLAGS), \
-))
-
-# Create a toolchain where linking is done with the C++ linker
-$(eval $(call DefineNativeToolchain, TOOLCHAIN_LINK_CXX, \
- EXTENDS := TOOLCHAIN_DEFAULT, \
- LD := $(LDCXX), \
-))
-
-# Create a toolchain with the BUILD compiler, used for build tools that
-# are to be run during the build.
-$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD, \
- CC := $(BUILD_CC), \
- CXX := $(BUILD_CXX), \
- LD := $(BUILD_LD), \
- AR := $(BUILD_AR), \
- AS := $(BUILD_AS), \
- OBJCOPY := $(BUILD_OBJCOPY), \
- STRIP := $(BUILD_STRIP), \
- SYSROOT_CFLAGS := $(BUILD_SYSROOT_CFLAGS), \
- SYSROOT_LDFLAGS := $(BUILD_SYSROOT_LDFLAGS), \
-))
-
-# BUILD toolchain with the C++ linker
-$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD_LINK_CXX, \
- EXTENDS := TOOLCHAIN_BUILD, \
- LD := $(BUILD_LDCXX), \
-))
-
-################################################################################
-
-# Extensions of files handled by this macro.
-NATIVE_SOURCE_EXTENSIONS := %.S %.c %.cpp %.cc %.m %.mm
-
-# Replaces native source extensions with the object file extension in a string.
-# Param 1: the string containing source file names with extensions
-# The surrounding strip is needed to keep additional whitespace out
-define replace_with_obj_extension
-$(strip \
- $(foreach extension, $(NATIVE_SOURCE_EXTENSIONS), \
- $(patsubst $(extension),%$(OBJ_SUFFIX), $(filter $(extension), $1))) \
-)
-endef
-
-# This pattern is used to transform the output of the microsoft CL compiler
-# into a make syntax dependency file (.d)
-WINDOWS_SHOWINCLUDE_SED_PATTERN := \
- -e '/^Note: including file:/!d' \
- -e 's|Note: including file: *||' \
- -e 's|\r||g' \
- -e 's|\\|/|g' \
- -e 's|^\([a-zA-Z]\):|$(WINENV_PREFIX)/\1|g' \
- -e '\|$(TOPDIR)|I !d' \
- -e 's|$$$$| \\|g' \
- #
-
-# This pattern is used to transform a dependency file (.d) to a list
-# of make targets for dependent files (.d.targets)
-DEPENDENCY_TARGET_SED_PATTERN := \
- -e 's/\#.*//' \
- -e 's/^[^:]*: *//' \
- -e 's/ *\\$$$$//' \
- -e 's/^[ ]*//' \
- -e '/^$$$$/ d' \
- -e 's/$$$$/ :/' \
- #
-
-################################################################################
-# When absolute paths are not allowed in the output, and the compiler does not
-# support any options to avoid it, we need to rewrite compile commands to use
-# relative paths. By doing this, the __FILE__ macro will resolve to relative
-# paths. The relevant input paths on the command line are the -I flags and the
-# path to the source file itself.
-#
-# The macro MakeCommandRelative is used to rewrite the command line like this:
-# 'CD $(WORKSPACE_ROOT) && '
-# and changes all paths in cmd to be relative to the workspace root. This only
-# works properly if the build dir is inside the workspace root. If it's not,
-# relative paths are still calculated, but depending on the distance between the
-# dirs, paths in the build dir may end up as essentially absolute anyway.
-#
-# The fix-deps-file macro is used to adjust the contents of the generated make
-# dependency files to contain paths compatible with make.
-#
-REWRITE_PATHS_RELATIVE = false
-ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT)-$(FILE_MACRO_CFLAGS), false-)
- REWRITE_PATHS_RELATIVE = true
-endif
-
-# CCACHE_BASEDIR needs fix-deps-file as makefiles use absolute filenames for
-# object files while CCACHE_BASEDIR will make ccache relativize all paths for
-# its compiler. The compiler then produces relative dependency files.
-# make does not know a relative and absolute filename is the same so it will
-# ignore such dependencies. This only applies when the OUTPUTDIR is inside
-# the WORKSPACE_ROOT.
-ifneq ($(CCACHE), )
- ifneq ($(filter $(WORKSPACE_ROOT)/%, $(OUTPUTDIR)), )
- REWRITE_PATHS_RELATIVE = true
- endif
-endif
-
-ifeq ($(REWRITE_PATHS_RELATIVE), true)
- # Need to handle -I flags as both '-Ifoo' and '-I foo'.
- MakeCommandRelative = \
- $(CD) $(WORKSPACE_ROOT) && \
- $(foreach o, $1, \
- $(if $(filter $(WORKSPACE_ROOT)/% $(OUTPUTDIR)/%, $o), \
- $(call RelativePath, $o, $(WORKSPACE_ROOT)) \
- , \
- $(if $(filter -I$(WORKSPACE_ROOT)/%, $o), \
- -I$(call RelativePath, $(patsubst -I%, %, $o), $(WORKSPACE_ROOT)) \
- , \
- $o \
- ) \
- ) \
- )
-
- # When compiling with relative paths, the deps file may come out with relative
- # paths, and that path may start with './'. First remove any leading ./, then
- # add WORKSPACE_ROOT to any line not starting with /, while allowing for
- # leading spaces. There may also be multiple entries on the same line, so start
- # with splitting such lines.
- # Non GNU sed (BSD on macosx) cannot substitute in literal \n using regex.
- # Instead use a bash escaped literal newline. To avoid having unmatched quotes
- # ruin the ability for an editor to properly syntax highlight this file, define
- # that newline sequence as a separate variable and add the closing quote behind
- # a comment.
- sed_newline := \'$$'\n''#'
- define fix-deps-file
- $(SED) \
- -e 's|\([^ ]\) \{1,\}\([^\\:]\)|\1 \\$(sed_newline) \2|g' \
- $1.tmp \
- | $(SED) \
- -e 's|^\([ ]*\)\./|\1|' \
- -e '/^[ ]*[^/ ]/s|^\([ ]*\)|\1$(WORKSPACE_ROOT)/|' \
- > $1
- endef
-else
- # By default the MakeCommandRelative macro does nothing.
- MakeCommandRelative = $1
-
- # No adjustment is needed.
- define fix-deps-file
- $(MV) $1.tmp $1
- endef
-endif
-
-################################################################################
-# GetEntitlementsFile
-# Find entitlements file for executable when signing on macosx. If no
-# specialized file is found, returns the default file.
-# $1 Executable to find entitlements file for.
-ENTITLEMENTS_DIR := $(TOPDIR)/make/data/macosxsigning
-ifeq ($(MACOSX_CODESIGN_MODE), debug)
- CODESIGN_PLIST_SUFFIX := -debug
-else
- CODESIGN_PLIST_SUFFIX :=
-endif
-DEFAULT_ENTITLEMENTS_FILE := $(ENTITLEMENTS_DIR)/default$(CODESIGN_PLIST_SUFFIX).plist
-
-GetEntitlementsFile = \
- $(foreach f, $(ENTITLEMENTS_DIR)/$(strip $(notdir $1))$(CODESIGN_PLIST_SUFFIX).plist, \
- $(if $(wildcard $f), $f, $(DEFAULT_ENTITLEMENTS_FILE)) \
- )
+include native/CompileFile.gmk
+include native/DebugSymbols.gmk
+include native/Flags.gmk
+include native/Link.gmk
+include native/LinkMicrosoft.gmk
+include native/Paths.gmk
################################################################################
-# Create the recipe needed to compile a single native source file.
-#
-# Parameter 1 is the name of the rule, based on the name of the library/
-# program being build and the name of the source code file, e.g.
-# BUILD_LIBFOO_fooMain.cpp.
-#
-# Remaining parameters are named arguments:
-# FILE - The full path of the source file to compiler
-# BASE - The name of the rule for the entire binary to build ($1)
-#
-SetupCompileNativeFile = $(NamedParamsMacroTemplate)
-define SetupCompileNativeFileBody
- $1_FILENAME := $$(notdir $$($1_FILE))
-
- # The target file to be generated.
- $1_OBJ := $$($$($1_BASE)_OBJECT_DIR)/$$(call replace_with_obj_extension, \
- $$($1_FILENAME))
-
- # Generate the corresponding compile_commands.json fragment.
- $1_OBJ_JSON = $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
- $$(OUTPUTDIR)/,,$$($1_OBJ))).json
- $$($1_BASE)_ALL_OBJS_JSON += $$($1_OBJ_JSON)
-
- # Only continue if this object file hasn't been processed already. This lets
- # the first found source file override any other with the same name.
- ifeq ($$($1_OBJ_PROCESSED), )
- $1_OBJ_PROCESSED := true
- # This is the definite source file to use for $1_FILENAME.
- $1_SRC_FILE := $$($1_FILE)
-
- ifeq ($$($1_OPTIMIZATION), )
- $1_OPT_CFLAGS := $$($$($1_BASE)_OPT_CFLAGS)
- $1_OPT_CXXFLAGS := $$($$($1_BASE)_OPT_CXXFLAGS)
- else
- ifeq ($$($1_OPTIMIZATION), NONE)
- $1_OPT_CFLAGS := $(C_O_FLAG_NONE)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
- else ifeq ($$($1_OPTIMIZATION), LOW)
- $1_OPT_CFLAGS := $(C_O_FLAG_NORM)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
- else ifeq ($$($1_OPTIMIZATION), HIGH)
- $1_OPT_CFLAGS := $(C_O_FLAG_HI)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
- else ifeq ($$($1_OPTIMIZATION), HIGHEST)
- $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
- else ifeq ($$($1_OPTIMIZATION), HIGHEST_JVM)
- $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
- else ifeq ($$($1_OPTIMIZATION), SIZE)
- $1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
- else
- $$(error Unknown value for file OPTIMIZATION: $$($1_OPTIMIZATION))
- endif
- endif
-
- ifneq ($$($$($1_BASE)_PRECOMPILED_HEADER), )
- ifeq ($$(filter $$($1_FILENAME), $$($$($1_BASE)_PRECOMPILED_HEADER_EXCLUDE)), )
- $1_USE_PCH_FLAGS := $$($$($1_BASE)_USE_PCH_FLAGS)
- endif
- endif
-
- ifneq ($(DISABLE_WARNING_PREFIX), )
- $1_WARNINGS_FLAGS := $$(addprefix $(DISABLE_WARNING_PREFIX), \
- $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$$($1_FILENAME)) \
- $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)_$$($1_FILENAME)))
- endif
-
- $1_BASE_CFLAGS := $$($$($1_BASE)_CFLAGS) $$($$($1_BASE)_EXTRA_CFLAGS) \
- $$($$($1_BASE)_SYSROOT_CFLAGS)
- $1_BASE_CXXFLAGS := $$($$($1_BASE)_CXXFLAGS) $$($$($1_BASE)_EXTRA_CXXFLAGS) \
- $$($$($1_BASE)_SYSROOT_CFLAGS) $$($1_EXTRA_CXXFLAGS)
- $1_BASE_ASFLAGS := $$($$($1_BASE)_ASFLAGS) $$($$($1_BASE)_EXTRA_ASFLAGS)
-
- ifneq ($$(filter %.c, $$($1_FILENAME)), )
- # Compile as a C file
- $1_CFLAGS += $$($1_WARNINGS_FLAGS)
- $1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CFLAGS) \
- $$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
- $1_COMPILER := $$($$($1_BASE)_CC)
- else ifneq ($$(filter %.m, $$($1_FILENAME)), )
- # Compile as an Objective-C file
- $1_CFLAGS += $$($1_WARNINGS_FLAGS)
- $1_FLAGS := -x objective-c $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) \
- $$($1_BASE_CFLAGS) $$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
- $1_COMPILER := $$($$($1_BASE)_CC)
- else ifneq ($$(filter %.S, $$($1_FILENAME)), )
- # Compile as preprocessed assembler file
- $1_FLAGS := $(BASIC_ASFLAGS) $$($1_BASE_ASFLAGS)
- $1_COMPILER := $(AS)
-
- # gcc or clang assembly files must contain an appropriate relative .file
- # path for reproducible builds.
- ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
- # If no absolute paths allowed, work out relative source file path
- # for assembly .file substitution, otherwise use full file path
- ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false)
- $1_REL_ASM_SRC := $$(call RelativePath, $$($1_FILE), $(WORKSPACE_ROOT))
- else
- $1_REL_ASM_SRC := $$($1_FILE)
- endif
- $1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
- -include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
- endif
- else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
- # Compile as a C++ or Objective-C++ file
- $1_CXXFLAGS += $$($1_WARNINGS_FLAGS)
- $1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CXXFLAGS) \
- $$($1_OPT_CXXFLAGS) $$($1_CXXFLAGS) -c
- $1_COMPILER := $$($$($1_BASE)_CXX)
- else
- $$(error Internal error in NativeCompilation.gmk: no compiler for file $$($1_FILENAME))
- endif
-
- # And this is the dependency file for this obj file.
- $1_DEPS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_OBJ))
- # The dependency target file lists all dependencies as empty targets to
- # avoid make error "No rule to make target" for removed files
- $1_DEPS_TARGETS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d.targets,$$($1_OBJ))
-
- # Only try to load individual dependency information files if the global
- # file hasn't been loaded (could happen if make was interrupted).
- ifneq ($$($$($1_BASE)_DEPS_FILE_LOADED), true)
- # Include previously generated dependency information. (if it exists)
- -include $$($1_DEPS_FILE)
- -include $$($1_DEPS_TARGETS_FILE)
- endif
-
- ifneq ($$(strip $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)), )
- $1_VARDEPS := $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)
- $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_OBJ).vardeps)
- endif
-
- $1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \
- $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE)
- $1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)
- # For reproducible builds with gcc and clang ensure random symbol generation is
- # seeded deterministically
- ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
- $1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)"
- endif
-
- $$($1_OBJ_JSON): $$($1_OBJ_DEPS)
- $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
- $$($1_COMPILER) $$($1_COMPILE_OPTIONS))
-
- $$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO)
- $$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME)))
- $$(call MakeDir, $$(@D))
- ifneq ($(TOOLCHAIN_TYPE), microsoft)
- $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
- $$($1_COMPILER) $$(GENDEPS_FLAGS) \
- $$(addsuffix .tmp, $$($1_DEPS_FILE)) \
- $$($1_COMPILE_OPTIONS)))
- ifneq ($$($1_DEPS_FILE), )
- $$(call fix-deps-file, $$($1_DEPS_FILE))
- # Create a dependency target file from the dependency file.
- # Solution suggested by:
- # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) \
- > $$($1_DEPS_TARGETS_FILE)
- endif
- else
- # The Visual Studio compiler lacks a feature for generating make
- # dependencies, but by setting -showIncludes, all included files are
- # printed. These are filtered out and parsed into make dependences.
- #
- # Keep as much as possible on one execution line for best performance
- # on Windows. No need to save exit code from compilation since
- # pipefail is always active on Windows.
- ifeq ($$(filter %.S, $$($1_FILENAME)), )
- $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
- $$($1_COMPILER) -showIncludes $$($1_COMPILE_OPTIONS))) \
- | $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
- -e "^$$($1_FILENAME)$$$$" || test "$$$$?" = "1" ; \
- $(ECHO) $$@: \\ > $$($1_DEPS_FILE) ; \
- $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_OBJ).log \
- | $(SORT) -u >> $$($1_DEPS_FILE) ; \
- $(ECHO) >> $$($1_DEPS_FILE) ; \
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) > $$($1_DEPS_TARGETS_FILE)
- else
- # For assembler calls just create empty dependency lists
- $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
- $$($1_COMPILER) $$($1_FLAGS) \
- $(CC_OUT_OPTION)$$($1_OBJ) -Ta $$($1_SRC_FILE))) \
- | $(TR) -d '\r' | $(GREP) -v -e "Assembling:" || test "$$$$?" = "1" ; \
- $(ECHO) > $$($1_DEPS_FILE) ; \
- $(ECHO) > $$($1_DEPS_TARGETS_FILE)
- endif
- endif
- endif
-endef
-
# Setup make rules for creating a native binary (a shared library or an
# executable).
#
@@ -501,7 +54,8 @@ endef
# NAME The base name for the resulting binary, excluding decorations (like *.exe)
# TYPE Type of binary (EXECUTABLE, LIBRARY or STATIC_LIBRARY). Default is LIBRARY.
# SUFFIX Override the default suffix for the output file
-# TOOLCHAIN Name of toolchain setup to use. Defaults to TOOLCHAIN_DEFAULT.
+# TARGET_TYPE The type to target, BUILD or TARGET. Defaults to TARGET.
+# LINK_TYPE The language to use for the linker, C or C++. Defaults to C.
# SRC one or more directory roots to scan for C/C++ files.
# CFLAGS the compiler flags to be used, used both for C and C++.
# CXXFLAGS the compiler flags to be used for c++, if set overrides CFLAGS.
@@ -519,7 +73,8 @@ endef
# used both for C and C++.
# LIBS__ the libraries to link to for the specified target
# OS and toolchain, used both for C and C++.
-# ARFLAGS the archiver flags to be used
+# ARFLAGS the archiver flags to be used on unix platforms
+# LIBFLAGS the flags for the lib tool used on windows
# OBJECT_DIR the directory where we store the object files
# OUTPUT_DIR the directory where the resulting binary is put
# SYMBOLS_DIR the directory where the debug symbols are put, defaults to OUTPUT_DIR
@@ -534,11 +89,18 @@ endef
# VERSIONINFO_RESOURCE Input file for RC. Setting this implies that RC will be run
# RCFLAGS flags for RC.
# EMBED_MANIFEST if true, embed manifest on Windows.
-# MAPFILE mapfile
-# USE_MAPFILE_FOR_SYMBOLS if true and this is a STATIC_BUILD, just copy the
-# mapfile for the output symbols file
-# CC the compiler to use, default is $(CC)
-# LD the linker to use, default is $(LD)
+# CC the C compiler to use
+# CXX the C++ compiler to use
+# LD the Linker to use
+# AR the static linker to use
+# LIB the Windows lib tool to use for creating static libraries
+# AS the assembler to use
+# MT the Windows MT tool to use
+# RC the Windows RC tool to use
+# OBJCOPY the objcopy tool for debug symbol handling
+# STRIP the tool to use for stripping debug symbols
+# SYSROOT_CFLAGS the compiler flags for using the specific sysroot
+# SYSROOT_LDFLAGS the linker flags for using the specific sysroot
# OPTIMIZATION sets optimization level to NONE, LOW, HIGH, HIGHEST, HIGHEST_JVM, SIZE
# DISABLED_WARNINGS_ Disable the given warnings for the specified toolchain
# DISABLED_WARNINGS__ Disable the given warnings for the specified
@@ -573,9 +135,122 @@ endef
# TARGET_DEPS All prerequisites for the target calculated by the macro
# ALL_OBJS All object files
# IMPORT_LIBRARY The import library created for a shared library on Windows
+#
SetupNativeCompilation = $(NamedParamsMacroTemplate)
define SetupNativeCompilationBody
+ # When reading this code, note that macros named Setup are just setting
+ # variables, and macros called Create are setting up rules to create
+ # files. Macros starting with any other verb are more complicated, and can do
+ # all of the above, and also call directly to the shell.
+
+ ###
+ ### Prepare for compilation and linking
+ ###
+
+ $$(eval $$(call VerifyArguments,$1))
+
+ # Setup variables for the rest of this macro to work with
+ $$(eval $$(call SetupBasicVariables,$1))
+
+ # Setup the toolchain to be used
+ $$(eval $$(call SetupToolchain,$1))
+
+ # Find all source files to compile and determine the output object file names
+ $$(eval $$(call SetupSourceFiles,$1))
+ $$(eval $$(call SetupOutputFiles,$1))
+
+ # Setup CFLAGS/CXXFLAGS based on warnings, optimizations, extra flags etc.
+ $$(eval $$(call SetupCompilerFlags,$1))
+
+ # Machinery needed for the build to function properly
+ $$(eval $$(call SetupBuildSystemSupport,$1))
+
+ $$(eval $$(call RemoveSuperfluousOutputFiles,$1))
+
+ # Need to make sure TARGET is first on list before starting to create files
+ $1 := $$($1_TARGET)
+
+ # Have make print information about the library when we start compiling
+ $$(eval $$(call PrintStartInfo,$1))
+
+ ###
+ ### Compile all native source code files
+ ###
+
+ # Create a PCH, if requested
+ $$(eval $$(call CreatePrecompiledHeader,$1))
+
+ # Now call CreateCompiledNativeFile for each source file we are going to compile.
+ $$(foreach file, $$($1_SRCS), \
+ $$(eval $$(call CreateCompiledNativeFile,$1_$$(notdir $$(file)),\
+ FILE := $$(file), \
+ BASE := $1, \
+ )) \
+ )
+
+ ifeq ($(call isTargetOs, windows), true)
+ # On windows we need to create a resource file
+ $$(eval $$(call CreateWindowsResourceFile,$1))
+ endif
+
+ # Setup a library-wide dependency file from individual object file dependency
+ # files, and import it in the makefile.
+ $$(eval $$(call CreateDependencyFile,$1))
+ $$(eval $$(call ImportDependencyFile,$1))
+
+ ###
+ ### Link the object files into a native output library/executable
+ ###
+
+ # Handle native debug symbols
+ $$(eval $$(call CreateDebugSymbols,$1))
+
+ # Prepare for linking
+ $$(eval $$(call SetupLinkerFlags,$1))
+ ifneq ($(TOOLCHAIN_TYPE), microsoft)
+ $$(eval $$(call SetupLinking,$1))
+ endif
+
+ $$(eval $$(call SetupObjectFileList,$1))
+
+ # Link the individually compiled files into a single unit
+ ifneq ($(TOOLCHAIN_TYPE), microsoft)
+ $$(eval $$(call CreateLinkedResult,$1))
+ else
+ $$(eval $$(call CreateLinkedResultMicrosoft,$1))
+ endif
+
+ ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
+ # Override all targets (this is a hack)
+ $1 := $$($1_ALL_OBJS_JSON)
+ endif
+endef
+
+################################################################################
+# Verify that user passed arguments are valid
+define VerifyArguments
+ ifneq ($$($1_NAME), $(basename $$($1_NAME)))
+ $$(error NAME must not contain any directory path in $1)
+ endif
+ ifneq ($(findstring $$($1_SUFFIX), $$($1_NAME)), )
+ $$(error NAME should be specified without suffix: $$($1_SUFFIX) in $1)
+ endif
+ ifneq ($(findstring $$($1_PREFIX), $$($1_NAME)), )
+ $$(error NAME should be specified without prefix: $$($1_PREFIX) in $1)
+ endif
+ ifeq ($$($1_OUTPUT_DIR), )
+ $$(error OUTPUT_DIR is missing in $1)
+ endif
+ ifneq ($$($1_MANIFEST), )
+ ifeq ($$($1_MANIFEST_VERSION), )
+ $$(error If MANIFEST is provided, then MANIFEST_VERSION is required in $1)
+ endif
+ endif
+endef
+################################################################################
+# Setup basic variables
+define SetupBasicVariables
# If type is unspecified, default to LIBRARY
ifeq ($$($1_TYPE), )
$1_TYPE := LIBRARY
@@ -589,8 +264,6 @@ define SetupNativeCompilationBody
endif
endif
- $$(call SetIfEmpty, $1_COMPILE_WITH_DEBUG_SYMBOLS, $$(COMPILE_WITH_DEBUG_SYMBOLS))
-
# STATIC_LIBS is set from Main.gmk when building static versions of certain
# native libraries.
ifeq ($(STATIC_LIBS), true)
@@ -600,15 +273,6 @@ define SetupNativeCompilationBody
# jmods.
$1_OBJECT_DIR := $$($1_OBJECT_DIR)/static
$1_OUTPUT_DIR := $$($1_OBJECT_DIR)
- # For release builds where debug symbols are configured to be moved to
- # separate debuginfo files, disable debug symbols for static libs instead.
- # We don't currently support this configuration and we don't want symbol
- # information in release builds unless explicitly asked to provide it.
- ifeq ($(DEBUG_LEVEL), release)
- ifeq ($(COPY_DEBUG_SYMBOLS), true)
- $1_COMPILE_WITH_DEBUG_SYMBOLS := false
- endif
- endif
endif
ifeq ($$($1_TYPE), EXECUTABLE)
@@ -629,248 +293,53 @@ define SetupNativeCompilationBody
endif
endif
- ifneq ($$($1_NAME), $(basename $$($1_NAME)))
- $$(error NAME must not contain any directory path in $1)
- endif
- ifneq ($(findstring $$($1_SUFFIX), $$($1_NAME)), )
- $$(error NAME should be specified without suffix: $$($1_SUFFIX) in $1)
- endif
- ifneq ($(findstring $$($1_PREFIX), $$($1_NAME)), )
- $$(error NAME should be specified without prefix: $$($1_PREFIX) in $1)
- endif
- ifeq ($$($1_OUTPUT_DIR), )
- $$(error OUTPUT_DIR is missing in $1)
- endif
- ifneq ($$($1_MANIFEST), )
- ifeq ($$($1_MANIFEST_VERSION), )
- $$(error If MANIFEST is provided, then MANIFEST_VERSION is required in $1)
- endif
- endif
-
$1_BASENAME := $$($1_PREFIX)$$($1_NAME)$$($1_SUFFIX)
$1_TARGET := $$($1_OUTPUT_DIR)/$$($1_BASENAME)
$1_NOSUFFIX := $$($1_PREFIX)$$($1_NAME)
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
+endef
-# Need to make sure TARGET is first on list
- $1 := $$($1_TARGET)
-
- # Setup the toolchain to be used
- $$(call SetIfEmpty, $1_TOOLCHAIN, TOOLCHAIN_DEFAULT)
- $$(call SetIfEmpty, $1_CC, $$($$($1_TOOLCHAIN)_CC))
- $$(call SetIfEmpty, $1_CXX, $$($$($1_TOOLCHAIN)_CXX))
- $$(call SetIfEmpty, $1_LD, $$($$($1_TOOLCHAIN)_LD))
- $$(call SetIfEmpty, $1_AR, $$($$($1_TOOLCHAIN)_AR))
- $$(call SetIfEmpty, $1_AS, $$($$($1_TOOLCHAIN)_AS))
- $$(call SetIfEmpty, $1_MT, $$($$($1_TOOLCHAIN)_MT))
- $$(call SetIfEmpty, $1_RC, $$($$($1_TOOLCHAIN)_RC))
- $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_TOOLCHAIN)_OBJCOPY))
- $$(call SetIfEmpty, $1_STRIP, $$($$($1_TOOLCHAIN)_STRIP))
- $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_CFLAGS))
- $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_LDFLAGS))
-
- $$(foreach d, $$($1_SRC), $$(if $$(wildcard $$d), , \
- $$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
-
- $1_SRCS_RAW := $$(call FindFiles, $$($1_SRC))
- # Order src files according to the order of the src dirs
- $1_SRCS := $$(foreach d, $$($1_SRC), $$(filter $$d%, $$($1_SRCS_RAW)))
- $1_SRCS := $$(filter $$(NATIVE_SOURCE_EXTENSIONS), $$($1_SRCS))
- # Extract the C/C++ files.
- ifneq ($$($1_EXCLUDE_PATTERNS), )
- # We must not match the exclude pattern against the src root(s).
- $1_SRCS_WITHOUT_ROOTS := $$($1_SRCS)
- $$(foreach i, $$($1_SRC), $$(eval $1_SRCS_WITHOUT_ROOTS := $$(patsubst \
- $$i/%,%, $$($1_SRCS_WITHOUT_ROOTS))))
- $1_ALL_EXCLUDE_FILES := $$(call containing, $$($1_EXCLUDE_PATTERNS), \
- $$($1_SRCS_WITHOUT_ROOTS))
- endif
- ifneq ($$($1_EXCLUDE_FILES), )
- $1_ALL_EXCLUDE_FILES += $$($1_EXCLUDE_FILES)
- endif
- ifneq ($$($1_ALL_EXCLUDE_FILES), )
- $1_EXCLUDE_FILES_PAT := $$($1_ALL_EXCLUDE_FILES) \
- $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_ALL_EXCLUDE_FILES)))
- $1_EXCLUDE_FILES_PAT := $$(addprefix %, $$($1_EXCLUDE_FILES_PAT))
- $1_SRCS := $$(filter-out $$($1_EXCLUDE_FILES_PAT), $$($1_SRCS))
- endif
- ifneq ($$($1_INCLUDE_FILES), )
- $1_INCLUDE_FILES_PAT := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_INCLUDE_FILES)))
- $1_SRCS := $$(filter $$($1_INCLUDE_FILES_PAT), $$($1_SRCS))
- endif
- # There can be only a single bin dir root, no need to foreach over the roots.
- $1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX))
- # Now we have a list of all c/c++ files to compile: $$($1_SRCS)
- # and we have a list of all existing object files: $$($1_BINS)
-
- # Prepend the source/bin path to the filter expressions. Then do the filtering.
- ifneq ($$($1_INCLUDES), )
- $1_SRC_INCLUDES := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_INCLUDES))))
- $1_SRCS := $$(filter $$($1_SRC_INCLUDES), $$($1_SRCS))
- endif
- ifneq ($$($1_EXCLUDES), )
- $1_SRC_EXCLUDES := $$(addsuffix /%, $$($1_EXCLUDES))
- $1_SRC_EXCLUDES += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_EXCLUDES))))
- $1_SRCS := $$(filter-out $$($1_SRC_EXCLUDES), $$($1_SRCS))
- endif
-
- $1_SRCS += $$($1_EXTRA_FILES)
-
- ifeq ($$($1_SRCS), )
- $$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
- endif
-
- ifeq ($$($1_TYPE), EXECUTABLE)
- ifeq ($(UBSAN_ENABLED), true)
- # We need to set the default options for UBSan. This needs to be included in every executable.
- # Rather than copy and paste code to everything with a main function, we add an additional
- # source file to every executable that exports __ubsan_default_options.
- ifneq ($$(filter %.cpp %.cc, $$($1_SRCS)), )
- $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.cpp
- else
- $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.c
- endif
- endif
- endif
-
- # Calculate the expected output from compiling the sources
- $1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS)))
- $1_EXPECTED_OBJS := $$(addprefix $$($1_OBJECT_DIR)/, $$($1_EXPECTED_OBJS_FILENAMES))
- # Are there too many object files on disk? Perhaps because some source file was removed?
- $1_SUPERFLOUS_OBJS := $$(sort $$(filter-out $$($1_EXPECTED_OBJS), $$($1_BINS)))
- # Clean out the superfluous object files.
- ifneq ($$($1_SUPERFLUOUS_OBJS), )
- $$(shell $(RM) -f $$($1_SUPERFLUOUS_OBJS))
- endif
- # Sort to remove duplicates and provide a reproducible order on the input files to the linker.
- $1_ALL_OBJS := $$(sort $$($1_EXPECTED_OBJS) $$($1_EXTRA_OBJECT_FILES))
- ifeq ($(STATIC_LIBS), true)
- # Exclude the object files that match with $1_STATIC_LIB_EXCLUDE_OBJS.
- ifneq ($$($1_STATIC_LIB_EXCLUDE_OBJS), )
- $1_ALL_OBJS := $$(call not-containing, $$($1_STATIC_LIB_EXCLUDE_OBJS), $$($1_ALL_OBJS))
+################################################################################
+# Setup the toolchain variables
+define SetupToolchain
+ ifeq ($$($1_TARGET_TYPE), BUILD)
+ $$(call SetIfEmpty, $1_CC, $(BUILD_CC))
+ $$(call SetIfEmpty, $1_CXX, $(BUILD_CXX))
+ $$(call SetIfEmpty, $1_AR, $(BUILD_AR))
+ $$(call SetIfEmpty, $1_LIB, $(BUILD_LIB))
+ $$(call SetIfEmpty, $1_AS, $(BUILD_AS))
+ $$(call SetIfEmpty, $1_OBJCOPY, $(BUILD_OBJCOPY))
+ $$(call SetIfEmpty, $1_STRIP, $(BUILD_STRIP))
+ $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $(BUILD_SYSROOT_CFLAGS))
+ $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $(BUILD_SYSROOT_LDFLAGS))
+ ifeq ($$($1_LINK_TYPE), C++)
+ $$(call SetIfEmpty, $1_LD, $(BUILD_LDCXX))
+ else
+ $$(call SetIfEmpty, $1_LD, $(BUILD_LD))
endif
- endif
-
- # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS, TOOLCHAIN_TYPE and
- # OPENJDK_TARGET_OS plus OPENJDK_TARGET_CPU pair dependent variables for CFLAGS.
- $1_EXTRA_CFLAGS := $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS)) \
- $$($1_CFLAGS_$(TOOLCHAIN_TYPE)) \
- $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU))
-
- ifneq ($(DEBUG_LEVEL), release)
- # Pickup extra debug dependent variables for CFLAGS
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_debug)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_debug)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_debug)
- else
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_release)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_release)
- $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_release)
- endif
- ifeq ($(STATIC_LIBS), true)
- $1_EXTRA_CFLAGS += $$(STATIC_LIBS_CFLAGS)
- endif
-
- # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and/or TOOLCHAIN_TYPE
- # dependent variables for CXXFLAGS.
- $1_EXTRA_CXXFLAGS := $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)) \
- $$($1_CXXFLAGS_$(TOOLCHAIN_TYPE))
-
- ifneq ($(DEBUG_LEVEL), release)
- # Pickup extra debug dependent variables for CXXFLAGS
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_debug)
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_debug)
else
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_release)
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
- $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release)
- endif
- ifeq ($(STATIC_LIBS), true)
- $1_EXTRA_CXXFLAGS += $$(STATIC_LIB_CFLAGS)
- endif
-
- # If no C++ flags are explicitly set, default to using the C flags.
- # After that, we can set additional C++ flags that should not interfere
- # with the mechanism for copying the C flags by default.
- ifeq ($$($1_CXXFLAGS), )
- $1_CXXFLAGS := $$($1_CFLAGS)
- endif
- ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)), )
- $1_EXTRA_CXXFLAGS := $$($1_EXTRA_CFLAGS)
- endif
-
- ifeq ($$($1_COMPILE_WITH_DEBUG_SYMBOLS), true)
- $1_EXTRA_CFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
- $1_EXTRA_CXXFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
- $1_EXTRA_ASFLAGS += $$(ASFLAGS_DEBUG_SYMBOLS)
- endif
-
- # Pass the library name for static JNI library naming
- ifeq ($$($1_TYPE), STATIC_LIBRARY)
- $1_EXTRA_CFLAGS += -DLIBRARY_NAME=$$($1_NAME)
- $1_EXTRA_CXXFLAGS += -DLIBRARY_NAME=$$($1_NAME)
- endif
-
- # Pick up disabled warnings, if possible on this platform.
- ifneq ($(DISABLE_WARNING_PREFIX), )
- $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
- $$(DISABLED_WARNINGS) \
- $$(DISABLED_WARNINGS_C) \
- $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
- $$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)) \
- $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
- $$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
- $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
- $$(DISABLED_WARNINGS) \
- $$(DISABLED_WARNINGS_CXX) \
- $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
- $$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)) \
- $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
- $$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
- endif
-
- # Check if warnings should be considered errors.
- # Pick first binary and toolchain specific, then binary specific, then general setting.
- ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), )
- ifeq ($$($1_WARNINGS_AS_ERRORS), )
- $1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$(WARNINGS_AS_ERRORS)
+ $$(call SetIfEmpty, $1_CC, $(CC))
+ $$(call SetIfEmpty, $1_CXX, $(CXX))
+ $$(call SetIfEmpty, $1_AR, $(AR))
+ $$(call SetIfEmpty, $1_LIB, $(LIB))
+ $$(call SetIfEmpty, $1_AS, $(AS))
+ $$(call SetIfEmpty, $1_MT, $(MT))
+ $$(call SetIfEmpty, $1_RC, $(RC))
+ $$(call SetIfEmpty, $1_OBJCOPY, $(OBJCOPY))
+ $$(call SetIfEmpty, $1_STRIP, $(STRIP))
+ $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $(SYSROOT_CFLAGS))
+ $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $(SYSROOT_LDFLAGS))
+ ifeq ($$($1_LINK_TYPE), C++)
+ $$(call SetIfEmpty, $1_LD, $(LDCXX))
else
- $1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$($1_WARNINGS_AS_ERRORS)
+ $$(call SetIfEmpty, $1_LD, $(LD))
endif
endif
+endef
- ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), true)
- $1_EXTRA_CFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
- $1_EXTRA_CXXFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
- endif
-
- ifeq (NONE, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_NONE)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
- else ifeq (LOW, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_NORM)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
- else ifeq (HIGH, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_HI)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
- else ifeq (HIGHEST, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
- else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
- else ifeq (SIZE, $$($1_OPTIMIZATION))
- $1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
- $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
- else ifneq (, $$($1_OPTIMIZATION))
- $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION))
- endif
-
- $1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker
-
+################################################################################
+# Setup machinery needed by the build system
+define SetupBuildSystemSupport
# Track variable changes for all variables that affect the compilation command
# lines for all object files in this setup. This includes at least all the
# variables used in the call to add_native_source below.
@@ -879,87 +348,19 @@ define SetupNativeCompilationBody
$$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS)
$1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
+endef
- ifneq ($$($1_PRECOMPILED_HEADER), )
- ifeq ($(USE_PRECOMPILED_HEADER), true)
- ifeq ($(TOOLCHAIN_TYPE), microsoft)
- $1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch
- $1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp
- $1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch$(OBJ_SUFFIX)
-
- $$(eval $$(call SetupCompileNativeFile, $1_$$(notdir $$($1_GENERATED_PCH_SRC)), \
- FILE := $$($1_GENERATED_PCH_SRC), \
- BASE := $1, \
- EXTRA_CXXFLAGS := -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \
- ))
-
- $1_USE_PCH_FLAGS := \
- -Fp$$($1_PCH_FILE) -Yu$$(notdir $$($1_PRECOMPILED_HEADER))
-
- $$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ)
-
- # Explicitly add the pch obj file first to ease comparing to old
- # hotspot build.
- $1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS)
-
- $$($1_GENERATED_PCH_SRC):
- $(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@
-
- else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
- ifeq ($(TOOLCHAIN_TYPE), gcc)
- $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch
- $1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled
- else ifeq ($(TOOLCHAIN_TYPE), clang)
- $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch
- $1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE)
- endif
- $1_PCH_DEPS_FILE := $$($1_PCH_FILE).d
- $1_PCH_DEPS_TARGETS_FILE := $$($1_PCH_FILE).d.targets
-
- -include $$($1_PCH_DEPS_FILE)
- -include $$($1_PCH_DEPS_TARGETS_FILE)
-
- $1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
- $$($1_OPT_CFLAGS) -x c++-header -c $(GENDEPS_FLAGS) \
- $$(addsuffix .tmp, $$($1_PCH_DEPS_FILE))
-
- $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
- $$(call LogInfo, Generating precompiled header)
- $$(call MakeDir, $$(@D))
- $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
- $$($1_PCH_COMMAND) $$< -o $$@))
- $$(call fix-deps-file, $$($1_PCH_DEPS_FILE))
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEPS_FILE) \
- > $$($1_PCH_DEPS_TARGETS_FILE)
-
- $$($1_ALL_OBJS): $$($1_PCH_FILE)
-
- # Generate the corresponding compile_commands.json fragment.
- $1_PCH_FILE_JSON := $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
- $$(OUTPUTDIR)/,,$$($1_PCH_FILE))).json
- $1_ALL_OBJS_JSON += $$($1_PCH_FILE_JSON)
-
- $$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
- $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
- $$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE))
- endif
- endif
- endif
-
- # Now call SetupCompileNativeFile for each source file we are going to compile.
- $$(foreach file, $$($1_SRCS), \
- $$(eval $$(call SetupCompileNativeFile, $1_$$(notdir $$(file)),\
- FILE := $$(file), \
- BASE := $1, \
- )) \
- )
-
+################################################################################
+# Have make print information about the library when we start compiling
+define PrintStartInfo
# Setup rule for printing progress info when compiling source files.
# This is a rough heuristic and may not always print accurate information.
# The $1_BUILD_INFO and $1_BUILD_INFO_DEPS variables are used in
# TestFilesCompilation.gmk.
$$(call SetIfEmpty, $1_BUILD_INFO_LOG_MACRO, LogWarn)
$1_BUILD_INFO_DEPS := $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
+ $1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker
+
$$($1_BUILD_INFO): $$($1_BUILD_INFO_DEPS)
ifeq ($$(wildcard $$($1_TARGET)), )
$$(call $$($1_BUILD_INFO_LOG_MACRO), \
@@ -973,47 +374,12 @@ define SetupNativeCompilationBody
$$(if $$(filter %.vardeps, $$?), due to makefile changes))))
endif
$(TOUCH) $$@
+endef
- # On windows we need to create a resource file
- ifeq ($(call isTargetOs, windows), true)
- ifneq ($$($1_VERSIONINFO_RESOURCE), )
- $1_RES := $$($1_OBJECT_DIR)/$$($1_BASENAME).res
- $1_RES_DEPS_FILE := $$($1_RES).d
- $1_RES_DEPS_TARGETS_FILE := $$($1_RES).d.targets
- -include $$($1_RES_DEPS_FILE)
- -include $$($1_RES_DEPS_TARGETS_FILE)
-
- $1_RES_VARDEPS := $$($1_RC) $$($1_RCFLAGS)
- $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
- $$($1_RES).vardeps)
-
- $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
- $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$($1_BASENAME)))
- $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
- $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
- $$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
- $$($1_VERSIONINFO_RESOURCE) 2>&1 ))
- # Windows RC compiler does not support -showIncludes, so we mis-use CL
- # for this. Filter out RC specific arguments that are unknown to CL.
- # For some unknown reason, in this case CL actually outputs the show
- # includes to stderr so need to redirect it to hide the output from the
- # main log.
- $$(call ExecuteWithLog, $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX), \
- $$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \
- $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
- $(CC_OUT_OPTION)$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
- $$($1_VERSIONINFO_RESOURCE)) 2>&1 \
- | $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
- -e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
- $(ECHO) $$($1_RES): \\ > $$($1_RES_DEPS_FILE) ; \
- $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX).log \
- >> $$($1_RES_DEPS_FILE) ; \
- $(ECHO) >> $$($1_RES_DEPS_FILE) ;\
- $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEPS_FILE) \
- > $$($1_RES_DEPS_TARGETS_FILE)
- endif
- endif
-
+################################################################################
+# Setup a library-wide dependency file from individual object file dependency
+# files
+define CreateDependencyFile
# Create a rule to collect all the individual make dependency files into a
# single makefile.
$1_DEPS_FILE := $$($1_OBJECT_DIR)/$1.d
@@ -1031,7 +397,11 @@ define SetupNativeCompilationBody
$(MV) $$@.tmp $$@
$1 += $$($1_DEPS_FILE)
+endef
+################################################################################
+# Import the dependency file into the makefile
+define ImportDependencyFile
# The include must be on the .old file, which represents the state from the
# previous invocation of make. The file being included must not have a rule
# defined for it as otherwise make will think it has to run the rule before
@@ -1041,328 +411,6 @@ define SetupNativeCompilationBody
$1_DEPS_FILE_LOADED := true
-include $$($1_DEPS_FILE).old
endif
-
- ifneq ($(DISABLE_MAPFILES), true)
- $1_REAL_MAPFILE := $$($1_MAPFILE)
- endif
-
- # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and TOOLCHAIN_TYPE
- # dependent variables for LDFLAGS and LIBS, and additionally the pair dependent
- # TOOLCHAIN_TYPE plus OPENJDK_TARGET_OS
- $1_EXTRA_LDFLAGS += $$($1_LDFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LDFLAGS_$(OPENJDK_TARGET_OS)) \
- $$($1_LDFLAGS_$(TOOLCHAIN_TYPE)) $$($1_LDFLAGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
- $1_EXTRA_LIBS += $$($1_LIBS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LIBS_$(OPENJDK_TARGET_OS)) \
- $$($1_LIBS_$(TOOLCHAIN_TYPE)) $$($1_LIBS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
-
- ifneq ($$($1_REAL_MAPFILE), )
- $1_EXTRA_LDFLAGS += $(call SET_SHARED_LIBRARY_MAPFILE,$$($1_REAL_MAPFILE))
- endif
-
- ifneq ($$($1_COPY_DEBUG_SYMBOLS), false)
- $1_COPY_DEBUG_SYMBOLS := $(COPY_DEBUG_SYMBOLS)
- endif
-
- ifneq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), false)
- $1_ZIP_EXTERNAL_DEBUG_SYMBOLS := $(ZIP_EXTERNAL_DEBUG_SYMBOLS)
- endif
-
- ifeq ($$($1_COPY_DEBUG_SYMBOLS), true)
- ifneq ($$($1_DEBUG_SYMBOLS), false)
- $$(call SetIfEmpty, $1_SYMBOLS_DIR, $$($1_OUTPUT_DIR))
- # Only copy debug symbols for dynamic libraries and programs.
- ifneq ($$($1_TYPE), STATIC_LIBRARY)
- # Generate debuginfo files.
- ifeq ($(call isTargetOs, windows), true)
- $1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb" \
- "-map:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).map"
- ifeq ($(SHIP_DEBUG_SYMBOLS), public)
- $1_EXTRA_LDFLAGS += "-pdbstripped:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).stripped.pdb"
- endif
- $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \
- $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map
-
- else ifeq ($(call isTargetOs, linux), true)
- $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
- # Setup the command line creating debuginfo files, to be run after linking.
- # It cannot be run separately since it updates the original target file
- # Creating the debuglink is done in another command rather than all at once
- # so we can run it after strip is called, since strip can sometimes mangle the
- # embedded debuglink, which we want to avoid.
- $1_CREATE_DEBUGINFO_CMDS := \
- $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE)
- $1_CREATE_DEBUGLINK_CMDS := $(CD) $$($1_SYMBOLS_DIR) && \
- $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
-
- else ifeq ($(call isTargetOs, aix), true)
- # AIX does not provide the equivalent of OBJCOPY to extract debug symbols,
- # so we copy the compiled object with symbols to the .debuginfo file, which
- # happens prior to the STRIP_CMD on the original target object file.
- $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
- $1_CREATE_DEBUGINFO_CMDS := $(CP) $$($1_TARGET) $$($1_DEBUGINFO_FILES)
-
- else ifeq ($(call isTargetOs, macosx), true)
- $1_DEBUGINFO_FILES := \
- $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Info.plist \
- $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Resources/DWARF/$$($1_BASENAME)
- $1_CREATE_DEBUGINFO_CMDS := \
- $(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET)
- endif
-
- # Since the link rule creates more than one file that we want to track,
- # we have to use some tricks to get make to cooperate. To properly
- # trigger downstream dependants of $$($1_DEBUGINFO_FILES), we must have
- # a recipe in the rule below. To avoid rerunning the recipe every time
- # have it touch the target. If a debuginfo file is deleted by something
- # external, explicitly delete the TARGET to trigger a rebuild of both.
- ifneq ($$(wildcard $$($1_DEBUGINFO_FILES)), $$($1_DEBUGINFO_FILES))
- $$(call LogDebug, Deleting $$($1_BASENAME) because debuginfo files are missing)
- $$(shell $(RM) $$($1_TARGET))
- endif
- $$($1_DEBUGINFO_FILES): $$($1_TARGET)
- $$(if $$(CORRECT_FUNCTION_IN_RECIPE_EVALUATION), \
- $$(if $$(wildcard $$@), , $$(error $$@ was not created for $$<)) \
- )
- $(TOUCH) $$@
-
- $1 += $$($1_DEBUGINFO_FILES)
-
- ifeq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
- ifeq ($(call isTargetOs, windows), true)
- $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).diz
- else
- $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz
- endif
- $1 += $$($1_DEBUGINFO_ZIP)
-
- # The dependency on TARGET is needed for debuginfo files
- # to be rebuilt properly.
- $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
- $(CD) $$($1_SYMBOLS_DIR) && \
- $(ZIPEXE) -q -r $$@ $$(subst $$($1_SYMBOLS_DIR)/,, $$($1_DEBUGINFO_FILES))
-
- endif
- endif # !STATIC_LIBRARY
- endif # $1_DEBUG_SYMBOLS != false
- endif # COPY_DEBUG_SYMBOLS
-
- # Unless specifically set, stripping should only happen if symbols are also
- # being copied.
- $$(call SetIfEmpty, $1_STRIP_SYMBOLS, $$($1_COPY_DEBUG_SYMBOLS))
-
- ifneq ($$($1_STRIP_SYMBOLS), false)
- ifneq ($$($1_STRIP), )
- # Default to using the global STRIPFLAGS. Allow for overriding with an empty value
- $1_STRIPFLAGS ?= $(STRIPFLAGS)
- $1_STRIP_CMD := $$($1_STRIP) $$($1_STRIPFLAGS) $$($1_TARGET)
- endif
- endif
-
- $1_LD_OBJ_ARG := $$($1_ALL_OBJS)
-
- # If there are many object files, use an @-file...
- ifneq ($$(word 17, $$($1_ALL_OBJS)), )
- $1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt
- ifneq ($(COMPILER_COMMAND_FILE_FLAG), )
- $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST)
- else
- # ...except for toolchains which don't support them.
- $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
- endif
-
- # If we are building static library, 'AR' on macosx/aix may not support @-file.
- ifeq ($$($1_TYPE), STATIC_LIBRARY)
- ifeq ($(call isTargetOs, macosx aix), true)
- $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
- endif
- endif
- endif
-
- # Unfortunately the @-file trick does not work reliably when using clang.
- # Clang does not propagate the @-file parameter to the ld sub process, but
- # instead puts the full content on the command line. At least the llvm ld
- # does not even support an @-file.
- #
- # When linking a large amount of object files, we risk hitting the limit
- # of the command line length even on posix systems if the path length of
- # the output dir is very long due to our use of absolute paths. To
- # mitigate this, use paths relative to the output dir when linking over
- # 500 files with clang and the output dir path is deep.
- ifneq ($$(word 500, $$($1_ALL_OBJS)), )
- ifeq ($$(TOOLCHAIN_TYPE), clang)
- # There is no strlen function in make, but checking path depth is a
- # reasonable approximation.
- ifneq ($$(word 10, $$(subst /, ,$$(OUTPUTDIR))), )
- $1_LINK_OBJS_RELATIVE := true
- $1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUTDIR)/%, %, $$($1_ALL_OBJS))
- endif
- endif
- endif
-
- ifeq ($$($1_TYPE), STATIC_LIBRARY)
- # Include partial linking when building the static library with clang on linux.
- ifeq ($(call isTargetOs, linux), true)
- ifneq ($(findstring $(TOOLCHAIN_TYPE), clang), )
- $1_ENABLE_PARTIAL_LINKING := true
- endif
- endif
-
- $1_VARDEPS := $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) $$($1_LIBS) \
- $$($1_EXTRA_LIBS)
- ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
- $1_VARDEPS += $$($1_LD) $$($1_SYSROOT_LDFLAGS)
- endif
- $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
- $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
-
- # Generating a static library, ie object file archive.
- ifeq ($(STATIC_BUILD), true)
- ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true)
- STATIC_MAPFILE_DEP := $$($1_MAPFILE)
- endif
- endif
-
- $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $$(STATIC_MAPFILE_DEP)
-
- $1_AR_OBJ_ARG := $$($1_LD_OBJ_ARG)
- # With clang on linux, partial linking is enabled and 'AR' takes the output
- # object from the partial linking step.
- ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
- $1_TARGET_RELOCATABLE := $$($1_OBJECT_DIR)/$$($1_PREFIX)$$($1_NAME)_relocatable$(OBJ_SUFFIX)
- $1_AR_OBJ_ARG := $$($1_TARGET_RELOCATABLE)
- endif
-
- $$($1_TARGET): $$($1_TARGET_DEPS)
- ifneq ($$($1_OBJ_FILE_LIST), )
- ifeq ($$($1_LINK_OBJS_RELATIVE), true)
- $$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
- else
- $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
- endif
- endif
- $$(call LogInfo, Building static library $$($1_BASENAME))
- $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
- # Do partial linking.
- ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
- $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_partial_link, \
- $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
- $$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \
- $(LD_OUT_OPTION)$$($1_TARGET_RELOCATABLE) \
- $$($1_LD_OBJ_ARG))
- endif
- $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
- $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
- $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_AR_OBJ_ARG) \
- $$($1_RES))
- ifeq ($(STATIC_BUILD), true)
- ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true)
- $(CP) $$($1_MAPFILE) $$(@D)/$$(basename $$(@F)).symbols
- else
- $(GetSymbols)
- endif
- endif
- else
- # A shared dynamic library or an executable binary has been specified
- ifeq ($$($1_TYPE), LIBRARY)
- # Generating a dynamic library.
- $1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME))
-
- # Create loadmap on AIX. Helps in diagnosing some problems.
- ifneq ($(COMPILER_BINDCMD_FILE_FLAG), )
- $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap
- endif
- endif
-
- ifeq ($(call isTargetOs, windows), true)
- ifeq ($$($1_EMBED_MANIFEST), true)
- $1_EXTRA_LDFLAGS += -manifest:embed
- endif
-
- $1_IMPORT_LIBRARY := $$($1_OBJECT_DIR)/$$($1_NAME).lib
- $1_EXTRA_LDFLAGS += "-implib:$$($1_IMPORT_LIBRARY)"
- ifeq ($$($1_TYPE), LIBRARY)
- # To properly trigger downstream dependants of the import library, just as
- # for debug files, we must have a recipe in the rule. To avoid rerunning
- # the recipe every time have it touch the target. If an import library
- # file is deleted by something external, explicitly delete the target to
- # trigger a rebuild of both.
- ifneq ($$(wildcard $$($1_IMPORT_LIBRARY)), $$($1_IMPORT_LIBRARY))
- $$(call LogDebug, Deleting $$($1_BASENAME) because import library is missing)
- $$(shell $(RM) $$($1_TARGET))
- endif
- $$($1_IMPORT_LIBRARY): $$($1_TARGET)
- $(TOUCH) $$@
-
- $1 += $$($1_IMPORT_LIBRARY)
- endif
- endif
-
- $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
- $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \
- $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \
- $$($1_STRIP_CMD) $$($1_CREATE_DEBUGLINK_CMDS)
- $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
- $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
-
- $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
- $$($1_REAL_MAPFILE) $$($1_VARDEPS_FILE)
-
- $$($1_TARGET): $$($1_TARGET_DEPS)
- ifneq ($$($1_OBJ_FILE_LIST), )
- ifeq ($$($1_LINK_OBJS_RELATIVE), true)
- $$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
- else
- $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
- endif
- endif
- # Keep as much as possible on one execution line for best performance
- # on Windows
- $$(call LogInfo, Linking $$($1_BASENAME))
- $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
- ifeq ($(call isTargetOs, windows), true)
-
- $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
- $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
- $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \
- $$($1_LIBS) $$($1_EXTRA_LIBS)) \
- | $(GREP) -v "^ Creating library .*\.lib and object .*\.exp" || \
- test "$$$$?" = "1" ; \
- $$($1_CREATE_DEBUGINFO_CMDS)
- $$($1_STRIP_CMD)
- $$($1_CREATE_DEBUGLINK_CMDS)
- ifeq ($(call isBuildOsEnv, windows.wsl2), true)
- $$(CHMOD) +x $$($1_TARGET)
- endif
- else
- $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
- $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
- $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
- $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \
- $$($1_LIBS) $$($1_EXTRA_LIBS)) ; \
- $$($1_CREATE_DEBUGINFO_CMDS)
- $$($1_STRIP_CMD)
- $$($1_CREATE_DEBUGLINK_CMDS)
- endif
- ifeq ($(call isTargetOs, windows), true)
- ifneq ($$($1_MANIFEST), )
- $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_NAME).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1
- endif
- endif
- # On macosx, optionally run codesign on every binary.
- # Remove signature explicitly first to avoid warnings if the linker
- # added a default adhoc signature.
- ifeq ($(MACOSX_CODESIGN_MODE), hardened)
- $(CODESIGN) --remove-signature $$@
- $(CODESIGN) -f -s "$(MACOSX_CODESIGN_IDENTITY)" --timestamp --options runtime \
- --entitlements $$(call GetEntitlementsFile, $$@) $$@
- else ifeq ($(MACOSX_CODESIGN_MODE), debug)
- $(CODESIGN) --remove-signature $$@
- $(CODESIGN) -f -s - --entitlements $$(call GetEntitlementsFile, $$@) $$@
- endif
- endif
-
- ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
- $1 := $$($1_ALL_OBJS_JSON)
- endif
endef
endif # _NATIVE_COMPILATION_GMK
diff --git a/make/common/TestFilesCompilation.gmk b/make/common/TestFilesCompilation.gmk
index d97d0e6c697e7..626eb058f0a1b 100644
--- a/make/common/TestFilesCompilation.gmk
+++ b/make/common/TestFilesCompilation.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 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
@@ -103,6 +103,7 @@ define SetupTestFilesCompilationBody
$$(eval $$(call SetupNativeCompilation, BUILD_TEST_$$(name), \
NAME := $$(unprefixed_name), \
TYPE := $$($1_COMPILATION_TYPE), \
+ LINK_TYPE := $(if $$(filter %.cpp, $$(file)), C++, C), \
EXTRA_FILES := $$(file) $$($1_EXTRA_FILES), \
OBJECT_DIR := $$($1_OUTPUT_DIR)/support/$$(name), \
OUTPUT_DIR := $$($1_OUTPUT_DIR)/$$($1_OUTPUT_SUBDIR), \
@@ -113,7 +114,6 @@ define SetupTestFilesCompilationBody
DISABLED_WARNINGS_clang := undef format-nonliteral \
missing-field-initializers sometimes-uninitialized, \
LIBS := $$($1_LIBS_$$(name)), \
- TOOLCHAIN := $(if $$(filter %.cpp, $$(file)), TOOLCHAIN_LINK_CXX, TOOLCHAIN_DEFAULT), \
OPTIMIZATION := $$(if $$($1_OPTIMIZATION_$$(name)),$$($1_OPTIMIZATION_$$(name)),LOW), \
COPY_DEBUG_SYMBOLS := $$($1_COPY_DEBUG_SYMBOLS), \
STRIP_SYMBOLS := $$(if $$($1_STRIP_SYMBOLS_$$(name)),$$($1_STRIP_SYMBOLS_$$(name)),false), \
diff --git a/make/common/native/CompileFile.gmk b/make/common/native/CompileFile.gmk
new file mode 100644
index 0000000000000..a9384fb0cf509
--- /dev/null
+++ b/make/common/native/CompileFile.gmk
@@ -0,0 +1,351 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to compiling a single native source
+# file (C, C++ or Objective-C) into an object file. It also harbours related
+# functionality for generating PCH (precompiled headers) and Windows resource
+# files.
+
+################################################################################
+# Creates a recipe that creates a compile_commands.json fragment. Remove any
+# occurrences of FIXPATH programs from the command to show the actual invocation.
+#
+# Param 1: Name of file to create
+# Param 2: Working directory
+# Param 3: Source file
+# Param 4: Compile command
+################################################################################
+define WriteCompileCommandsFragment
+ $(call LogInfo, Creating compile commands fragment for $(notdir $3))
+ $(call MakeDir, $(dir $1))
+ $(call WriteFile,{ \
+ "directory": "$(strip $(call FixPath, $2))"$(COMMA) \
+ "file": "$(strip $(call FixPath, $3))"$(COMMA) \
+ "command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\
+ $(subst $(FIXPATH),,$(call FixPath, $4)))))" \
+ }$(COMMA), \
+ $1)
+endef
+
+################################################################################
+# Extensions of files handled by this macro.
+NATIVE_SOURCE_EXTENSIONS := %.S %.c %.cpp %.cc %.m %.mm
+
+# Replaces native source extensions with the object file extension in a string.
+# Param 1: the string containing source file names with extensions
+# The surrounding strip is needed to keep additional whitespace out
+define replace_with_obj_extension
+$(strip \
+ $(foreach extension, $(NATIVE_SOURCE_EXTENSIONS), \
+ $(patsubst $(extension),%$(OBJ_SUFFIX), $(filter $(extension), $1))) \
+)
+endef
+
+################################################################################
+# This pattern is used to transform the output of the microsoft CL compiler
+# into a make syntax dependency file (.d)
+WINDOWS_SHOWINCLUDE_SED_PATTERN := \
+ -e '/^Note: including file:/!d' \
+ -e 's|Note: including file: *||' \
+ -e 's|\r||g' \
+ -e 's|\\|/|g' \
+ -e 's|^\([a-zA-Z]\):|$(WINENV_PREFIX)/\1|g' \
+ -e '\|$(TOPDIR)|I !d' \
+ -e 's|$$$$| \\|g' \
+ #
+
+################################################################################
+# This pattern is used to transform a dependency file (.d) to a list
+# of make targets for dependent files (.d.targets)
+DEPENDENCY_TARGET_SED_PATTERN := \
+ -e 's/\#.*//' \
+ -e 's/^[^:]*: *//' \
+ -e 's/ *\\$$$$//' \
+ -e 's/^[ ]*//' \
+ -e '/^$$$$/ d' \
+ -e 's/$$$$/ :/' \
+ #
+
+################################################################################
+# Create the recipe needed to compile a single native source file.
+#
+# Parameter 1 is the name of the rule, based on the name of the library/
+# program being build and the name of the source code file, e.g.
+# BUILD_LIBFOO_fooMain.cpp.
+#
+# Remaining parameters are named arguments:
+# FILE - The full path of the source file to compiler
+# BASE - The name of the rule for the entire binary to build ($1)
+#
+CreateCompiledNativeFile = $(NamedParamsMacroTemplate)
+define CreateCompiledNativeFileBody
+ $1_FILENAME := $$(notdir $$($1_FILE))
+
+ # The target file to be generated.
+ $1_OBJ := $$($$($1_BASE)_OBJECT_DIR)/$$(call replace_with_obj_extension, \
+ $$($1_FILENAME))
+
+ # Generate the corresponding compile_commands.json fragment.
+ $1_OBJ_JSON = $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
+ $$(OUTPUTDIR)/,,$$($1_OBJ))).json
+ $$($1_BASE)_ALL_OBJS_JSON += $$($1_OBJ_JSON)
+
+ # Only continue if this object file hasn't been processed already. This lets
+ # the first found source file override any other with the same name.
+ ifeq ($$($1_OBJ_PROCESSED), )
+ $1_OBJ_PROCESSED := true
+ # This is the definite source file to use for $1_FILENAME.
+ $1_SRC_FILE := $$($1_FILE)
+
+ $$(eval $$(call SetupCompileFileFlags,$1,$$($1_BASE)))
+
+ ifneq ($$(filter %.c, $$($1_FILENAME)), )
+ # Compile as a C file
+ $1_CFLAGS += $$($1_WARNINGS_FLAGS)
+ $1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CFLAGS) \
+ $$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
+ $1_COMPILER := $$($$($1_BASE)_CC)
+ else ifneq ($$(filter %.m, $$($1_FILENAME)), )
+ # Compile as an Objective-C file
+ $1_CFLAGS += $$($1_WARNINGS_FLAGS)
+ $1_FLAGS := -x objective-c $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) \
+ $$($1_BASE_CFLAGS) $$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
+ $1_COMPILER := $$($$($1_BASE)_CC)
+ else ifneq ($$(filter %.S, $$($1_FILENAME)), )
+ # Compile as preprocessed assembler file
+ $1_FLAGS := $(BASIC_ASFLAGS) $$($1_BASE_ASFLAGS)
+ $1_COMPILER := $(AS)
+
+ # gcc or clang assembly files must contain an appropriate relative .file
+ # path for reproducible builds.
+ ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
+ # If no absolute paths allowed, work out relative source file path
+ # for assembly .file substitution, otherwise use full file path
+ ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false)
+ $1_REL_ASM_SRC := $$(call RelativePath, $$($1_FILE), $(WORKSPACE_ROOT))
+ else
+ $1_REL_ASM_SRC := $$($1_FILE)
+ endif
+ $1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
+ -include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
+ endif
+ else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
+ # Compile as a C++ or Objective-C++ file
+ $1_CXXFLAGS += $$($1_WARNINGS_FLAGS)
+ $1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CXXFLAGS) \
+ $$($1_OPT_CXXFLAGS) $$($1_CXXFLAGS) -c
+ $1_COMPILER := $$($$($1_BASE)_CXX)
+ else
+ $$(error Internal error in NativeCompilation.gmk: no compiler for file $$($1_FILENAME))
+ endif
+
+ # And this is the dependency file for this obj file.
+ $1_DEPS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_OBJ))
+ # The dependency target file lists all dependencies as empty targets to
+ # avoid make error "No rule to make target" for removed files
+ $1_DEPS_TARGETS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d.targets,$$($1_OBJ))
+
+ # Only try to load individual dependency information files if the global
+ # file hasn't been loaded (could happen if make was interrupted).
+ ifneq ($$($$($1_BASE)_DEPS_FILE_LOADED), true)
+ # Include previously generated dependency information. (if it exists)
+ -include $$($1_DEPS_FILE)
+ -include $$($1_DEPS_TARGETS_FILE)
+ endif
+
+ ifneq ($$(strip $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)), )
+ $1_VARDEPS := $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_OBJ).vardeps)
+ endif
+
+ $1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \
+ $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE)
+ $1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)
+ # For reproducible builds with gcc and clang ensure random symbol generation is
+ # seeded deterministically
+ ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
+ $1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)"
+ endif
+
+ $$($1_OBJ_JSON): $$($1_OBJ_DEPS)
+ $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
+ $$($1_COMPILER) $$($1_COMPILE_OPTIONS))
+
+ $$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO)
+ $$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME)))
+ $$(call MakeDir, $$(@D))
+ ifneq ($(TOOLCHAIN_TYPE), microsoft)
+ $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
+ $$($1_COMPILER) $$(GENDEPS_FLAGS) \
+ $$(addsuffix .tmp, $$($1_DEPS_FILE)) \
+ $$($1_COMPILE_OPTIONS)))
+ ifneq ($$($1_DEPS_FILE), )
+ $$(call fix-deps-file, $$($1_DEPS_FILE))
+ # Create a dependency target file from the dependency file.
+ # Solution suggested by:
+ # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) \
+ > $$($1_DEPS_TARGETS_FILE)
+ endif
+ else
+ # The Visual Studio compiler lacks a feature for generating make
+ # dependencies, but by setting -showIncludes, all included files are
+ # printed. These are filtered out and parsed into make dependences.
+ #
+ # Keep as much as possible on one execution line for best performance
+ # on Windows. No need to save exit code from compilation since
+ # pipefail is always active on Windows.
+ ifeq ($$(filter %.S, $$($1_FILENAME)), )
+ $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
+ $$($1_COMPILER) -showIncludes $$($1_COMPILE_OPTIONS))) \
+ | $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
+ -e "^$$($1_FILENAME)$$$$" || test "$$$$?" = "1" ; \
+ $(ECHO) $$@: \\ > $$($1_DEPS_FILE) ; \
+ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_OBJ).log \
+ | $(SORT) -u >> $$($1_DEPS_FILE) ; \
+ $(ECHO) >> $$($1_DEPS_FILE) ; \
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) > $$($1_DEPS_TARGETS_FILE)
+ else
+ # For assembler calls just create empty dependency lists
+ $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
+ $$($1_COMPILER) $$($1_FLAGS) \
+ $(CC_OUT_OPTION)$$($1_OBJ) -Ta $$($1_SRC_FILE))) \
+ | $(TR) -d '\r' | $(GREP) -v -e "Assembling:" || test "$$$$?" = "1" ; \
+ $(ECHO) > $$($1_DEPS_FILE) ; \
+ $(ECHO) > $$($1_DEPS_TARGETS_FILE)
+ endif
+ endif
+ endif
+endef
+
+################################################################################
+define CreatePrecompiledHeader
+ ifneq ($$($1_PRECOMPILED_HEADER), )
+ ifeq ($(USE_PRECOMPILED_HEADER), true)
+ ifeq ($(TOOLCHAIN_TYPE), microsoft)
+ $1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch
+ $1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp
+ $1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch$(OBJ_SUFFIX)
+
+ $$(eval $$(call CreateCompiledNativeFile, $1_$$(notdir $$($1_GENERATED_PCH_SRC)), \
+ FILE := $$($1_GENERATED_PCH_SRC), \
+ BASE := $1, \
+ EXTRA_CXXFLAGS := -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \
+ ))
+
+ $1_USE_PCH_FLAGS := \
+ -Fp$$($1_PCH_FILE) -Yu$$(notdir $$($1_PRECOMPILED_HEADER))
+
+ $$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ)
+
+ # Explicitly add the pch obj file first to ease comparing to old
+ # hotspot build.
+ $1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS)
+
+ $$($1_GENERATED_PCH_SRC):
+ $(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@
+
+ else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
+ ifeq ($(TOOLCHAIN_TYPE), gcc)
+ $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch
+ $1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled
+ else ifeq ($(TOOLCHAIN_TYPE), clang)
+ $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch
+ $1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE)
+ endif
+ $1_PCH_DEPS_FILE := $$($1_PCH_FILE).d
+ $1_PCH_DEPS_TARGETS_FILE := $$($1_PCH_FILE).d.targets
+
+ -include $$($1_PCH_DEPS_FILE)
+ -include $$($1_PCH_DEPS_TARGETS_FILE)
+
+ $1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
+ $$($1_OPT_CFLAGS) -x c++-header -c $(GENDEPS_FLAGS) \
+ $$(addsuffix .tmp, $$($1_PCH_DEPS_FILE))
+
+ $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
+ $$(call LogInfo, Generating precompiled header)
+ $$(call MakeDir, $$(@D))
+ $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
+ $$($1_PCH_COMMAND) $$< -o $$@))
+ $$(call fix-deps-file, $$($1_PCH_DEPS_FILE))
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEPS_FILE) \
+ > $$($1_PCH_DEPS_TARGETS_FILE)
+
+ $$($1_ALL_OBJS): $$($1_PCH_FILE)
+
+ # Generate the corresponding compile_commands.json fragment.
+ $1_PCH_FILE_JSON := $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
+ $$(OUTPUTDIR)/,,$$($1_PCH_FILE))).json
+ $1_ALL_OBJS_JSON += $$($1_PCH_FILE_JSON)
+
+ $$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
+ $$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
+ $$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE))
+ endif
+ endif
+ endif
+endef
+
+################################################################################
+define CreateWindowsResourceFile
+ ifneq ($$($1_VERSIONINFO_RESOURCE), )
+ $1_RES := $$($1_OBJECT_DIR)/$$($1_BASENAME).res
+ $1_RES_DEPS_FILE := $$($1_RES).d
+ $1_RES_DEPS_TARGETS_FILE := $$($1_RES).d.targets
+ -include $$($1_RES_DEPS_FILE)
+ -include $$($1_RES_DEPS_TARGETS_FILE)
+
+ $1_RES_VARDEPS := $$($1_RC) $$($1_RCFLAGS)
+ $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
+ $$($1_RES).vardeps)
+
+ $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
+ $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$($1_BASENAME)))
+ $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
+ $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
+ $$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
+ $$($1_VERSIONINFO_RESOURCE) 2>&1 ))
+ # Windows RC compiler does not support -showIncludes, so we mis-use CL
+ # for this. Filter out RC specific arguments that are unknown to CL.
+ # For some unknown reason, in this case CL actually outputs the show
+ # includes to stderr so need to redirect it to hide the output from the
+ # main log.
+ $$(call ExecuteWithLog, $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX), \
+ $$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \
+ $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
+ $(CC_OUT_OPTION)$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
+ $$($1_VERSIONINFO_RESOURCE)) 2>&1 \
+ | $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
+ -e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
+ $(ECHO) $$($1_RES): \\ > $$($1_RES_DEPS_FILE) ; \
+ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX).log \
+ >> $$($1_RES_DEPS_FILE) ; \
+ $(ECHO) >> $$($1_RES_DEPS_FILE) ;\
+ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEPS_FILE) \
+ > $$($1_RES_DEPS_TARGETS_FILE)
+ endif
+endef
diff --git a/make/common/native/DebugSymbols.gmk b/make/common/native/DebugSymbols.gmk
new file mode 100644
index 0000000000000..9f49f5e1d5292
--- /dev/null
+++ b/make/common/native/DebugSymbols.gmk
@@ -0,0 +1,118 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to native debug symbol handling.
+
+################################################################################
+define CreateDebugSymbols
+ ifneq ($$($1_COPY_DEBUG_SYMBOLS), false)
+ $1_COPY_DEBUG_SYMBOLS := $(COPY_DEBUG_SYMBOLS)
+ endif
+
+ ifneq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), false)
+ $1_ZIP_EXTERNAL_DEBUG_SYMBOLS := $(ZIP_EXTERNAL_DEBUG_SYMBOLS)
+ endif
+
+ ifeq ($$($1_COPY_DEBUG_SYMBOLS), true)
+ ifneq ($$($1_DEBUG_SYMBOLS), false)
+ $$(call SetIfEmpty, $1_SYMBOLS_DIR, $$($1_OUTPUT_DIR))
+ # Only copy debug symbols for dynamic libraries and programs.
+ ifneq ($$($1_TYPE), STATIC_LIBRARY)
+ # Generate debuginfo files.
+ ifeq ($(call isTargetOs, windows), true)
+ $1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb" \
+ "-map:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).map"
+ ifeq ($(SHIP_DEBUG_SYMBOLS), public)
+ $1_EXTRA_LDFLAGS += "-pdbstripped:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).stripped.pdb"
+ endif
+ $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \
+ $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map
+
+ else ifeq ($(call isTargetOs, linux), true)
+ $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
+ # Setup the command line creating debuginfo files, to be run after linking.
+ # It cannot be run separately since it updates the original target file
+ # Creating the debuglink is done in another command rather than all at once
+ # so we can run it after strip is called, since strip can sometimes mangle the
+ # embedded debuglink, which we want to avoid.
+ $1_CREATE_DEBUGINFO_CMDS := \
+ $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) && \
+ $$(CHMOD) -x $$($1_DEBUGINFO_FILES)
+ $1_CREATE_DEBUGLINK_CMDS := $(CD) $$($1_SYMBOLS_DIR) && \
+ $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
+
+ else ifeq ($(call isTargetOs, aix), true)
+ # AIX does not provide the equivalent of OBJCOPY to extract debug symbols,
+ # so we copy the compiled object with symbols to the .debuginfo file, which
+ # happens prior to the STRIP_CMD on the original target object file.
+ $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
+ $1_CREATE_DEBUGINFO_CMDS := $(CP) $$($1_TARGET) $$($1_DEBUGINFO_FILES)
+
+ else ifeq ($(call isTargetOs, macosx), true)
+ $1_DEBUGINFO_FILES := \
+ $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Info.plist \
+ $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Resources/DWARF/$$($1_BASENAME)
+ $1_CREATE_DEBUGINFO_CMDS := \
+ $(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET)
+ endif
+
+ # Since the link rule creates more than one file that we want to track,
+ # we have to use some tricks to get make to cooperate. To properly
+ # trigger downstream dependants of $$($1_DEBUGINFO_FILES), we must have
+ # a recipe in the rule below. To avoid rerunning the recipe every time
+ # have it touch the target. If a debuginfo file is deleted by something
+ # external, explicitly delete the TARGET to trigger a rebuild of both.
+ ifneq ($$(wildcard $$($1_DEBUGINFO_FILES)), $$($1_DEBUGINFO_FILES))
+ $$(call LogDebug, Deleting $$($1_BASENAME) because debuginfo files are missing)
+ $$(shell $(RM) $$($1_TARGET))
+ endif
+ $$($1_DEBUGINFO_FILES): $$($1_TARGET)
+ $$(if $$(CORRECT_FUNCTION_IN_RECIPE_EVALUATION), \
+ $$(if $$(wildcard $$@), , $$(error $$@ was not created for $$<)) \
+ )
+ $(TOUCH) $$@
+
+ $1 += $$($1_DEBUGINFO_FILES)
+
+ ifeq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
+ ifeq ($(call isTargetOs, windows), true)
+ $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).diz
+ else
+ $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz
+ endif
+ $1 += $$($1_DEBUGINFO_ZIP)
+
+ # The dependency on TARGET is needed for debuginfo files
+ # to be rebuilt properly.
+ $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
+ $(CD) $$($1_SYMBOLS_DIR) && \
+ $(ZIPEXE) -q -r $$@ $$(subst $$($1_SYMBOLS_DIR)/,, $$($1_DEBUGINFO_FILES))
+
+ endif
+ endif # !STATIC_LIBRARY
+ endif # $1_DEBUG_SYMBOLS != false
+ endif # COPY_DEBUG_SYMBOLS
+endef
diff --git a/make/common/native/Flags.gmk b/make/common/native/Flags.gmk
new file mode 100644
index 0000000000000..213312047a4ff
--- /dev/null
+++ b/make/common/native/Flags.gmk
@@ -0,0 +1,225 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to setting up compiler and linker
+# flags, based on various more abstract sources of compilation description,
+# like optimization level.
+
+################################################################################
+# $1 is the prefix of the file to be compiled
+# $2 is the prefix of the library, i.e. $$($1_BASE)
+define SetupCompileFileFlags
+ ifeq ($$($1_OPTIMIZATION), )
+ $1_OPT_CFLAGS := $$($2_OPT_CFLAGS)
+ $1_OPT_CXXFLAGS := $$($2_OPT_CXXFLAGS)
+ else
+ ifeq ($$($1_OPTIMIZATION), NONE)
+ $1_OPT_CFLAGS := $(C_O_FLAG_NONE)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
+ else ifeq ($$($1_OPTIMIZATION), LOW)
+ $1_OPT_CFLAGS := $(C_O_FLAG_NORM)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
+ else ifeq ($$($1_OPTIMIZATION), HIGH)
+ $1_OPT_CFLAGS := $(C_O_FLAG_HI)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
+ else ifeq ($$($1_OPTIMIZATION), HIGHEST)
+ $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
+ else ifeq ($$($1_OPTIMIZATION), HIGHEST_JVM)
+ $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
+ else ifeq ($$($1_OPTIMIZATION), SIZE)
+ $1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
+ else
+ $$(error Unknown value for file OPTIMIZATION: $$($1_OPTIMIZATION))
+ endif
+ endif
+
+ ifneq ($$($2_PRECOMPILED_HEADER), )
+ ifeq ($$(filter $$($1_FILENAME), $$($2_PRECOMPILED_HEADER_EXCLUDE)), )
+ $1_USE_PCH_FLAGS := $$($2_USE_PCH_FLAGS)
+ endif
+ endif
+
+ ifneq ($(DISABLE_WARNING_PREFIX), )
+ $1_WARNINGS_FLAGS := $$(addprefix $(DISABLE_WARNING_PREFIX), \
+ $$($2_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$$($1_FILENAME)) \
+ $$($2_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)_$$($1_FILENAME)))
+ endif
+
+ $1_BASE_CFLAGS := $$($2_CFLAGS) $$($2_EXTRA_CFLAGS) \
+ $$($2_SYSROOT_CFLAGS)
+ $1_BASE_CXXFLAGS := $$($2_CXXFLAGS) $$($2_EXTRA_CXXFLAGS) \
+ $$($2_SYSROOT_CFLAGS) $$($1_EXTRA_CXXFLAGS)
+ $1_BASE_ASFLAGS := $$($2_ASFLAGS) $$($2_EXTRA_ASFLAGS)
+endef
+
+################################################################################
+define SetupCompilerFlags
+ # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS, TOOLCHAIN_TYPE and
+ # OPENJDK_TARGET_OS plus OPENJDK_TARGET_CPU pair dependent variables for CFLAGS.
+ $1_EXTRA_CFLAGS := $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS)) \
+ $$($1_CFLAGS_$(TOOLCHAIN_TYPE)) \
+ $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU))
+
+ ifneq ($(DEBUG_LEVEL), release)
+ # Pickup extra debug dependent variables for CFLAGS
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_debug)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_debug)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_debug)
+ else
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_release)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_release)
+ $1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_release)
+ endif
+ ifeq ($(STATIC_LIBS), true)
+ $1_EXTRA_CFLAGS += $$(STATIC_LIBS_CFLAGS)
+ endif
+
+ # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and/or TOOLCHAIN_TYPE
+ # dependent variables for CXXFLAGS.
+ $1_EXTRA_CXXFLAGS := $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)) \
+ $$($1_CXXFLAGS_$(TOOLCHAIN_TYPE))
+
+ ifneq ($(DEBUG_LEVEL), release)
+ # Pickup extra debug dependent variables for CXXFLAGS
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_debug)
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_debug)
+ else
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_release)
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
+ $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release)
+ endif
+ ifeq ($(STATIC_LIBS), true)
+ $1_EXTRA_CXXFLAGS += $$(STATIC_LIB_CFLAGS)
+ endif
+
+ # If no C++ flags are explicitly set, default to using the C flags.
+ # After that, we can set additional C++ flags that should not interfere
+ # with the mechanism for copying the C flags by default.
+ ifeq ($$($1_CXXFLAGS), )
+ $1_CXXFLAGS := $$($1_CFLAGS)
+ endif
+ ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)), )
+ $1_EXTRA_CXXFLAGS := $$($1_EXTRA_CFLAGS)
+ endif
+
+ $$(call SetIfEmpty, $1_COMPILE_WITH_DEBUG_SYMBOLS, $$(COMPILE_WITH_DEBUG_SYMBOLS))
+
+ ifeq ($(STATIC_LIBS), true)
+ # For release builds where debug symbols are configured to be moved to
+ # separate debuginfo files, disable debug symbols for static libs instead.
+ # We don't currently support this configuration and we don't want symbol
+ # information in release builds unless explicitly asked to provide it.
+ ifeq ($(DEBUG_LEVEL), release)
+ ifeq ($(COPY_DEBUG_SYMBOLS), true)
+ $1_COMPILE_WITH_DEBUG_SYMBOLS := false
+ endif
+ endif
+ endif
+
+ ifeq ($$($1_COMPILE_WITH_DEBUG_SYMBOLS), true)
+ $1_EXTRA_CFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
+ $1_EXTRA_CXXFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
+ $1_EXTRA_ASFLAGS += $$(ASFLAGS_DEBUG_SYMBOLS)
+ endif
+
+ # Pass the library name for static JNI library naming
+ ifeq ($$($1_TYPE), STATIC_LIBRARY)
+ $1_EXTRA_CFLAGS += -DLIBRARY_NAME=$$($1_NAME)
+ $1_EXTRA_CXXFLAGS += -DLIBRARY_NAME=$$($1_NAME)
+ endif
+
+ # Pick up disabled warnings, if possible on this platform.
+ ifneq ($(DISABLE_WARNING_PREFIX), )
+ $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
+ $$(DISABLED_WARNINGS) \
+ $$(DISABLED_WARNINGS_C) \
+ $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
+ $$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)) \
+ $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
+ $$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
+ $1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
+ $$(DISABLED_WARNINGS) \
+ $$(DISABLED_WARNINGS_CXX) \
+ $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
+ $$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)) \
+ $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
+ $$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
+ endif
+
+ # Check if warnings should be considered errors.
+ # Pick first binary and toolchain specific, then binary specific, then general setting.
+ ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), )
+ ifeq ($$($1_WARNINGS_AS_ERRORS), )
+ $1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$(WARNINGS_AS_ERRORS)
+ else
+ $1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$($1_WARNINGS_AS_ERRORS)
+ endif
+ endif
+
+ ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), true)
+ $1_EXTRA_CFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
+ $1_EXTRA_CXXFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
+ endif
+
+ ifeq (NONE, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_NONE)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
+ else ifeq (LOW, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_NORM)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
+ else ifeq (HIGH, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_HI)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
+ else ifeq (HIGHEST, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
+ else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
+ else ifeq (SIZE, $$($1_OPTIMIZATION))
+ $1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
+ $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
+ else ifneq (, $$($1_OPTIMIZATION))
+ $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION))
+ endif
+endef
+
+################################################################################
+define SetupLinkerFlags
+ # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and TOOLCHAIN_TYPE
+ # dependent variables for LDFLAGS and LIBS, and additionally the pair dependent
+ # TOOLCHAIN_TYPE plus OPENJDK_TARGET_OS
+ $1_EXTRA_LDFLAGS += $$($1_LDFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LDFLAGS_$(OPENJDK_TARGET_OS)) \
+ $$($1_LDFLAGS_$(TOOLCHAIN_TYPE)) $$($1_LDFLAGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
+ $1_EXTRA_LIBS += $$($1_LIBS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LIBS_$(OPENJDK_TARGET_OS)) \
+ $$($1_LIBS_$(TOOLCHAIN_TYPE)) $$($1_LIBS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
+endef
diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk
new file mode 100644
index 0000000000000..fb23152d4fb9b
--- /dev/null
+++ b/make/common/native/Link.gmk
@@ -0,0 +1,182 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to linking a native binary;
+# creating either a dynamic library, a static library or an executable.
+
+################################################################################
+# GetEntitlementsFile
+# Find entitlements file for executable when signing on macosx. If no
+# specialized file is found, returns the default file.
+# This macro might be called from custom makefiles.
+# $1 Executable to find entitlements file for.
+ENTITLEMENTS_DIR := $(TOPDIR)/make/data/macosxsigning
+ifeq ($(MACOSX_CODESIGN_MODE), debug)
+ CODESIGN_PLIST_SUFFIX := -debug
+else
+ CODESIGN_PLIST_SUFFIX :=
+endif
+DEFAULT_ENTITLEMENTS_FILE := $(ENTITLEMENTS_DIR)/default$(CODESIGN_PLIST_SUFFIX).plist
+
+GetEntitlementsFile = \
+ $(foreach f, $(ENTITLEMENTS_DIR)/$(strip $(notdir $1))$(CODESIGN_PLIST_SUFFIX).plist, \
+ $(if $(wildcard $f), $f, $(DEFAULT_ENTITLEMENTS_FILE)) \
+ )
+
+################################################################################
+define SetupLinking
+ # Unless specifically set, stripping should only happen if symbols are also
+ # being copied.
+ $$(call SetIfEmpty, $1_STRIP_SYMBOLS, $$($1_COPY_DEBUG_SYMBOLS))
+
+ ifneq ($$($1_STRIP_SYMBOLS), false)
+ # Default to using the global STRIPFLAGS. Allow for overriding with an
+ # empty value
+ $1_STRIPFLAGS ?= $(STRIPFLAGS)
+ $1_STRIP_CMD := $$($1_STRIP) $$($1_STRIPFLAGS) $$($1_TARGET)
+ endif
+endef
+
+################################################################################
+define CreateLinkedResult
+ ifeq ($$($1_TYPE), STATIC_LIBRARY)
+ $$(eval $$(call CreateStaticLibrary,$1))
+ else
+ $$(eval $$(call CreateDynamicLibraryOrExecutable,$1))
+ endif
+endef
+
+################################################################################
+define CreateStaticLibrary
+ # Include partial linking when building the static library with clang on linux
+ ifeq ($(call isTargetOs, linux), true)
+ ifneq ($(findstring $(TOOLCHAIN_TYPE), clang), )
+ $1_ENABLE_PARTIAL_LINKING := true
+ endif
+ endif
+
+ $1_VARDEPS := $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) $$($1_LIBS) \
+ $$($1_EXTRA_LIBS)
+ ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
+ $1_VARDEPS += $$($1_LD) $$($1_SYSROOT_LDFLAGS)
+ endif
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
+ $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_VARDEPS_FILE)
+
+ $1_AR_OBJ_ARG := $$($1_LD_OBJ_ARG)
+ # With clang on linux, partial linking is enabled and 'AR' takes the output
+ # object from the partial linking step.
+ ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
+ $1_TARGET_RELOCATABLE := $$($1_OBJECT_DIR)/$$($1_PREFIX)$$($1_NAME)_relocatable$(OBJ_SUFFIX)
+ $1_AR_OBJ_ARG := $$($1_TARGET_RELOCATABLE)
+ endif
+
+ $$($1_TARGET): $$($1_TARGET_DEPS)
+ ifneq ($$($1_OBJ_FILE_LIST), )
+ ifeq ($$($1_LINK_OBJS_RELATIVE), true)
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
+ else
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
+ endif
+ endif
+ $$(call LogInfo, Building static library $$($1_BASENAME))
+ $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
+ # Do partial linking.
+ ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
+ $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_partial_link, \
+ $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
+ $$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \
+ -o $$($1_TARGET_RELOCATABLE) \
+ $$($1_LD_OBJ_ARG))
+ endif
+ $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
+ $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
+ $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) -r -cs $$($1_TARGET) \
+ $$($1_AR_OBJ_ARG) $$($1_RES))
+ ifeq ($(STATIC_BUILD), true)
+ $(RM) $$(@D)/$$(basename $$(@F)).symbols; \
+ $(ECHO) "Getting symbols from nm"; \
+ $(NM) $(NMFLAGS) -m $$($1_TARGET) | $(GREP) "__TEXT" | \
+ $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \
+ $(SED) -e 's/.* //' > $$(@D)/$$(basename $$(@F)).symbols
+ endif
+endef
+
+################################################################################
+define CreateDynamicLibraryOrExecutable
+ # A shared dynamic library or an executable binary has been specified
+ ifeq ($$($1_TYPE), LIBRARY)
+ # Generating a dynamic library.
+ $1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME))
+
+ # Create loadmap on AIX. Helps in diagnosing some problems.
+ ifneq ($(COMPILER_BINDCMD_FILE_FLAG), )
+ $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap
+ endif
+ endif
+
+ $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) \
+ $$($1_EXTRA_LDFLAGS) $$($1_LIBS) $$($1_EXTRA_LIBS) \
+ $$($1_CREATE_DEBUGINFO_CMDS) $$($1_STRIP_CMD) $$($1_CREATE_DEBUGLINK_CMDS)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
+ $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_VARDEPS_FILE)
+
+ $$($1_TARGET): $$($1_TARGET_DEPS)
+ ifneq ($$($1_OBJ_FILE_LIST), )
+ ifeq ($$($1_LINK_OBJS_RELATIVE), true)
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
+ else
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
+ endif
+ endif
+ $$(call LogInfo, Linking $$($1_BASENAME))
+ $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
+ $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
+ $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
+ $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+ $$($1_SYSROOT_LDFLAGS) -o $$($1_TARGET) $$($1_LD_OBJ_ARG) \
+ $$($1_LIBS) $$($1_EXTRA_LIBS))
+ $$($1_CREATE_DEBUGINFO_CMDS)
+ $$($1_STRIP_CMD)
+ $$($1_CREATE_DEBUGLINK_CMDS)
+ # On macosx, optionally run codesign on every binary.
+ # Remove signature explicitly first to avoid warnings if the linker
+ # added a default adhoc signature.
+ ifeq ($(MACOSX_CODESIGN_MODE), hardened)
+ $(CODESIGN) --remove-signature $$@
+ $(CODESIGN) -f -s "$(MACOSX_CODESIGN_IDENTITY)" --timestamp \
+ --options runtime --entitlements \
+ $$(call GetEntitlementsFile, $$@) $$@
+ else ifeq ($(MACOSX_CODESIGN_MODE), debug)
+ $(CODESIGN) --remove-signature $$@
+ $(CODESIGN) -f -s - --entitlements \
+ $$(call GetEntitlementsFile, $$@) $$@
+ endif
+endef
diff --git a/make/common/native/LinkMicrosoft.gmk b/make/common/native/LinkMicrosoft.gmk
new file mode 100644
index 0000000000000..f998bf3d117f1
--- /dev/null
+++ b/make/common/native/LinkMicrosoft.gmk
@@ -0,0 +1,112 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to linking a native binary;
+# creating either a dynamic library, a static library or an executable.
+
+################################################################################
+define CreateLinkedResultMicrosoft
+ ifeq ($$($1_TYPE), STATIC_LIBRARY)
+ $$(eval $$(call CreateStaticLibraryMicrosoft,$1))
+ else
+ $$(eval $$(call CreateDynamicLibraryOrExecutableMicrosoft,$1))
+ endif
+endef
+
+################################################################################
+define CreateStaticLibraryMicrosoft
+ $1_VARDEPS := $$($1_LIB) $$(LIBFLAGS) $$($1_LIBFLAGS) $$($1_LIBS) \
+ $$($1_EXTRA_LIBS)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
+ $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
+ ifneq ($$($1_OBJ_FILE_LIST), )
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
+ endif
+ $$(call LogInfo, Building static library $$($1_BASENAME))
+ $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
+ $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
+ $$($1_LIB) -nologo $$(LIBFLAGS) $$($1_LIBFLAGS) -out:$$($1_TARGET) \
+ $$($1_LD_OBJ_ARG) $$($1_RES))
+endef
+
+################################################################################
+define CreateDynamicLibraryOrExecutableMicrosoft
+ ifeq ($$($1_EMBED_MANIFEST), true)
+ $1_EXTRA_LDFLAGS += -manifest:embed
+ endif
+
+ $1_IMPORT_LIBRARY := $$($1_OBJECT_DIR)/$$($1_NAME).lib
+ $1_EXTRA_LDFLAGS += "-implib:$$($1_IMPORT_LIBRARY)"
+
+ ifeq ($$($1_TYPE), LIBRARY)
+ # To properly trigger downstream dependants of the import library, just as
+ # for debug files, we must have a recipe in the rule. To avoid rerunning
+ # the recipe every time have it touch the target. If an import library
+ # file is deleted by something external, explicitly delete the target to
+ # trigger a rebuild of both.
+ ifneq ($$(wildcard $$($1_IMPORT_LIBRARY)), $$($1_IMPORT_LIBRARY))
+ $$(call LogDebug, Deleting $$($1_BASENAME) because import library is missing)
+ $$(shell $(RM) $$($1_TARGET))
+ endif
+ $$($1_IMPORT_LIBRARY): $$($1_TARGET)
+ $(TOUCH) $$@
+
+ $1 += $$($1_IMPORT_LIBRARY)
+ endif
+
+ $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) \
+ $$($1_EXTRA_LDFLAGS) $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \
+ $$($1_MANIFEST_VERSION)
+
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
+ $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
+ $$($1_VARDEPS_FILE)
+
+ $$($1_TARGET): $$($1_TARGET_DEPS)
+ ifneq ($$($1_OBJ_FILE_LIST), )
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
+ endif
+ $$(call LogInfo, Linking $$($1_BASENAME))
+ $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
+ $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
+ $$($1_LD) -nologo $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+ $$($1_SYSROOT_LDFLAGS) -out:$$($1_TARGET) $$($1_LD_OBJ_ARG) \
+ $$($1_RES) $$($1_LIBS) $$($1_EXTRA_LIBS)) \
+ | $(GREP) -v "^ Creating library .*\.lib and object .*\.exp" || \
+ test "$$$$?" = "1"
+ ifeq ($(call isBuildOsEnv, windows.wsl2), true)
+ $$(CHMOD) +x $$($1_TARGET)
+ endif
+ ifneq ($$($1_MANIFEST), )
+ $$($1_MT) -nologo -manifest $$($1_MANIFEST) \
+ -identity:"$$($1_NAME).exe, version=$$($1_MANIFEST_VERSION)" \
+ -outputresource:$$@;#1
+ endif
+endef
diff --git a/make/common/native/Paths.gmk b/make/common/native/Paths.gmk
new file mode 100644
index 0000000000000..67aa61d86e968
--- /dev/null
+++ b/make/common/native/Paths.gmk
@@ -0,0 +1,247 @@
+#
+# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file contains functionality related to handling paths for source files
+# and object files. This is complicated by the fact that we usually, but not
+# always, use absolute instead of relative paths. It is further complicated
+# by the fact that not all tools allow inputting large lists of files as
+# "@-files", which we normally use to avoid hitting command line length limits.
+# Finally this file contains functionality for locating all source code files
+# that should be included in the compilation.
+
+################################################################################
+# When absolute paths are not allowed in the output, and the compiler does not
+# support any options to avoid it, we need to rewrite compile commands to use
+# relative paths. By doing this, the __FILE__ macro will resolve to relative
+# paths. The relevant input paths on the command line are the -I flags and the
+# path to the source file itself.
+#
+# The macro MakeCommandRelative is used to rewrite the command line like this:
+# 'CD $(WORKSPACE_ROOT) && '
+# and changes all paths in cmd to be relative to the workspace root. This only
+# works properly if the build dir is inside the workspace root. If it's not,
+# relative paths are still calculated, but depending on the distance between the
+# dirs, paths in the build dir may end up as essentially absolute anyway.
+#
+# The fix-deps-file macro is used to adjust the contents of the generated make
+# dependency files to contain paths compatible with make.
+#
+REWRITE_PATHS_RELATIVE = false
+ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT)-$(FILE_MACRO_CFLAGS), false-)
+ REWRITE_PATHS_RELATIVE = true
+endif
+
+# CCACHE_BASEDIR needs fix-deps-file as makefiles use absolute filenames for
+# object files while CCACHE_BASEDIR will make ccache relativize all paths for
+# its compiler. The compiler then produces relative dependency files.
+# make does not know a relative and absolute filename is the same so it will
+# ignore such dependencies. This only applies when the OUTPUTDIR is inside
+# the WORKSPACE_ROOT.
+ifneq ($(CCACHE), )
+ ifneq ($(filter $(WORKSPACE_ROOT)/%, $(OUTPUTDIR)), )
+ REWRITE_PATHS_RELATIVE = true
+ endif
+endif
+
+ifeq ($(REWRITE_PATHS_RELATIVE), true)
+ # Need to handle -I flags as both '-Ifoo' and '-I foo'.
+ MakeCommandRelative = \
+ $(CD) $(WORKSPACE_ROOT) && \
+ $(foreach o, $1, \
+ $(if $(filter $(WORKSPACE_ROOT)/% $(OUTPUTDIR)/%, $o), \
+ $(call RelativePath, $o, $(WORKSPACE_ROOT)) \
+ , \
+ $(if $(filter -I$(WORKSPACE_ROOT)/%, $o), \
+ -I$(call RelativePath, $(patsubst -I%, %, $o), $(WORKSPACE_ROOT)) \
+ , \
+ $o \
+ ) \
+ ) \
+ )
+
+ # When compiling with relative paths, the deps file may come out with relative
+ # paths, and that path may start with './'. First remove any leading ./, then
+ # add WORKSPACE_ROOT to any line not starting with /, while allowing for
+ # leading spaces. There may also be multiple entries on the same line, so start
+ # with splitting such lines.
+ # Non GNU sed (BSD on macosx) cannot substitute in literal \n using regex.
+ # Instead use a bash escaped literal newline. To avoid having unmatched quotes
+ # ruin the ability for an editor to properly syntax highlight this file, define
+ # that newline sequence as a separate variable and add the closing quote behind
+ # a comment.
+ sed_newline := \'$$'\n''#'
+ define fix-deps-file
+ $(SED) \
+ -e 's|\([^ ]\) \{1,\}\([^\\:]\)|\1 \\$(sed_newline) \2|g' \
+ $1.tmp \
+ | $(SED) \
+ -e 's|^\([ ]*\)\./|\1|' \
+ -e '/^[ ]*[^/ ]/s|^\([ ]*\)|\1$(WORKSPACE_ROOT)/|' \
+ > $1
+ endef
+else
+ # By default the MakeCommandRelative macro does nothing.
+ MakeCommandRelative = $1
+
+ # No adjustment is needed.
+ define fix-deps-file
+ $(MV) $1.tmp $1
+ endef
+endif
+
+################################################################################
+define SetupSourceFiles
+ $$(foreach d, $$($1_SRC), $$(if $$(wildcard $$d), , \
+ $$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
+
+ $1_SRCS_RAW := $$(call FindFiles, $$($1_SRC))
+ # Order src files according to the order of the src dirs
+ $1_SRCS := $$(foreach d, $$($1_SRC), $$(filter $$d%, $$($1_SRCS_RAW)))
+ $1_SRCS := $$(filter $$(NATIVE_SOURCE_EXTENSIONS), $$($1_SRCS))
+ # Extract the C/C++ files.
+ ifneq ($$($1_EXCLUDE_PATTERNS), )
+ # We must not match the exclude pattern against the src root(s).
+ $1_SRCS_WITHOUT_ROOTS := $$($1_SRCS)
+ $$(foreach i, $$($1_SRC), $$(eval $1_SRCS_WITHOUT_ROOTS := $$(patsubst \
+ $$i/%,%, $$($1_SRCS_WITHOUT_ROOTS))))
+ $1_ALL_EXCLUDE_FILES := $$(call containing, $$($1_EXCLUDE_PATTERNS), \
+ $$($1_SRCS_WITHOUT_ROOTS))
+ endif
+ ifneq ($$($1_EXCLUDE_FILES), )
+ $1_ALL_EXCLUDE_FILES += $$($1_EXCLUDE_FILES)
+ endif
+ ifneq ($$($1_ALL_EXCLUDE_FILES), )
+ $1_EXCLUDE_FILES_PAT := $$($1_ALL_EXCLUDE_FILES) \
+ $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_ALL_EXCLUDE_FILES)))
+ $1_EXCLUDE_FILES_PAT := $$(addprefix %, $$($1_EXCLUDE_FILES_PAT))
+ $1_SRCS := $$(filter-out $$($1_EXCLUDE_FILES_PAT), $$($1_SRCS))
+ endif
+ ifneq ($$($1_INCLUDE_FILES), )
+ $1_INCLUDE_FILES_PAT := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_INCLUDE_FILES)))
+ $1_SRCS := $$(filter $$($1_INCLUDE_FILES_PAT), $$($1_SRCS))
+ endif
+ # Now we have a list of all c/c++ files to compile: $$($1_SRCS)
+
+ # Prepend the source/bin path to the filter expressions. Then do the filtering.
+ ifneq ($$($1_INCLUDES), )
+ $1_SRC_INCLUDES := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_INCLUDES))))
+ $1_SRCS := $$(filter $$($1_SRC_INCLUDES), $$($1_SRCS))
+ endif
+ ifneq ($$($1_EXCLUDES), )
+ $1_SRC_EXCLUDES := $$(addsuffix /%, $$($1_EXCLUDES))
+ $1_SRC_EXCLUDES += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_EXCLUDES))))
+ $1_SRCS := $$(filter-out $$($1_SRC_EXCLUDES), $$($1_SRCS))
+ endif
+
+ $1_SRCS += $$($1_EXTRA_FILES)
+
+ ifeq ($$($1_SRCS), )
+ $$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
+ endif
+
+ ifeq ($$($1_TYPE), EXECUTABLE)
+ ifeq ($(UBSAN_ENABLED), true)
+ # We need to set the default options for UBSan. This needs to be included in every executable.
+ # Rather than copy and paste code to everything with a main function, we add an additional
+ # source file to every executable that exports __ubsan_default_options.
+ ifneq ($$(filter %.cpp %.cc, $$($1_SRCS)), )
+ $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.cpp
+ else
+ $1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.c
+ endif
+ endif
+ endif
+endef
+
+################################################################################
+define SetupOutputFiles
+ # Calculate the expected output from compiling the sources
+ $1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS)))
+ $1_EXPECTED_OBJS := $$(addprefix $$($1_OBJECT_DIR)/, $$($1_EXPECTED_OBJS_FILENAMES))
+ # Sort to remove duplicates and provide a reproducible order on the input files to the linker.
+ $1_ALL_OBJS := $$(sort $$($1_EXPECTED_OBJS) $$($1_EXTRA_OBJECT_FILES))
+ ifeq ($(STATIC_LIBS), true)
+ # Exclude the object files that match with $1_STATIC_LIB_EXCLUDE_OBJS.
+ ifneq ($$($1_STATIC_LIB_EXCLUDE_OBJS), )
+ $1_ALL_OBJS := $$(call not-containing, $$($1_STATIC_LIB_EXCLUDE_OBJS), $$($1_ALL_OBJS))
+ endif
+ endif
+endef
+
+################################################################################
+define RemoveSuperfluousOutputFiles
+ # Are there too many object files on disk? Perhaps because some source file was removed?
+ $1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX))
+ $1_SUPERFLOUS_OBJS := $$(sort $$(filter-out $$($1_EXPECTED_OBJS), $$($1_BINS)))
+ # Clean out the superfluous object files.
+ ifneq ($$($1_SUPERFLUOUS_OBJS), )
+ $$(shell $(RM) -f $$($1_SUPERFLUOUS_OBJS))
+ endif
+endef
+
+################################################################################
+define SetupObjectFileList
+ $1_LD_OBJ_ARG := $$($1_ALL_OBJS)
+
+ # If there are many object files, use an @-file...
+ ifneq ($$(word 17, $$($1_ALL_OBJS)), )
+ $1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt
+ ifneq ($(COMPILER_COMMAND_FILE_FLAG), )
+ $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST)
+ else
+ # ...except for toolchains which don't support them.
+ $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
+ endif
+
+ # If we are building static library, 'AR' on macosx/aix may not support @-file.
+ ifeq ($$($1_TYPE), STATIC_LIBRARY)
+ ifeq ($(call isTargetOs, macosx aix), true)
+ $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
+ endif
+ endif
+ endif
+
+ # Unfortunately the @-file trick does not work reliably when using clang.
+ # Clang does not propagate the @-file parameter to the ld sub process, but
+ # instead puts the full content on the command line. At least the llvm ld
+ # does not even support an @-file.
+ #
+ # When linking a large amount of object files, we risk hitting the limit
+ # of the command line length even on posix systems if the path length of
+ # the output dir is very long due to our use of absolute paths. To
+ # mitigate this, use paths relative to the output dir when linking over
+ # 500 files with clang and the output dir path is deep.
+ ifneq ($$(word 500, $$($1_ALL_OBJS)), )
+ ifeq ($$(TOOLCHAIN_TYPE), clang)
+ # There is no strlen function in make, but checking path depth is a
+ # reasonable approximation.
+ ifneq ($$(word 10, $$(subst /, ,$$(OUTPUTDIR))), )
+ $1_LINK_OBJS_RELATIVE := true
+ $1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUTDIR)/%, %, $$($1_ALL_OBJS))
+ endif
+ endif
+ endif
+endef
diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf
index daa191fc70e3d..38e0f563aca75 100644
--- a/make/conf/github-actions.conf
+++ b/make/conf/github-actions.conf
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2023, 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
@@ -36,6 +36,10 @@ MACOS_X64_BOOT_JDK_EXT=tar.gz
MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee13770090416c/35/GPL/openjdk-21_macos-x64_bin.tar.gz
MACOS_X64_BOOT_JDK_SHA256=af32e84c11009f72f783fdcdc9917efc277893988f097e198e2576875d1e88c1
+MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
+MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee13770090416c/35/GPL/openjdk-21_macos-aarch64_bin.tar.gz
+MACOS_AARCH64_BOOT_JDK_SHA256=f12e1e0a2dffc847951598f597c8ee60fb0913932f24b2b09c62cfd2f0f4dfb9
+
WINDOWS_X64_BOOT_JDK_EXT=zip
WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee13770090416c/35/GPL/openjdk-21_windows-x64_bin.zip
WINDOWS_X64_BOOT_JDK_SHA256=5434faaf029e66e7ce6e75770ca384de476750984a7d2881ef7686894c4b4944
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index d8bca3551217b..af164624877a4 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -441,7 +441,7 @@ var getJibProfilesProfiles = function (input, common, data) {
"macosx-x64": {
target_os: "macosx",
target_cpu: "x64",
- dependencies: ["devkit", "gtest", "pandoc"],
+ dependencies: ["devkit", "gtest", "graphviz", "pandoc"],
configure_args: concat(common.configure_args_64bit, "--with-zlib=system",
"--with-macosx-version-max=11.00.00",
"--enable-compatible-cds-alignment",
@@ -453,7 +453,7 @@ var getJibProfilesProfiles = function (input, common, data) {
"macosx-aarch64": {
target_os: "macosx",
target_cpu: "aarch64",
- dependencies: ["devkit", "gtest", "pandoc"],
+ dependencies: ["devkit", "gtest", "graphviz", "pandoc"],
configure_args: concat(common.configure_args_64bit,
"--with-macosx-version-max=11.00.00"),
},
@@ -486,7 +486,7 @@ var getJibProfilesProfiles = function (input, common, data) {
"linux-aarch64": {
target_os: "linux",
target_cpu: "aarch64",
- dependencies: ["devkit", "gtest", "build_devkit", "pandoc"],
+ dependencies: ["devkit", "gtest", "build_devkit", "graphviz", "pandoc"],
configure_args: [
"--with-zlib=system",
"--disable-dtrace",
@@ -1181,12 +1181,6 @@ var getJibProfilesDependencies = function (input, common) {
revision: (input.build_cpu == "x64" ? "Xcode11.3.1-MacOSX10.15+1.2" : devkit_platform_revisions[devkit_platform])
},
- cups: {
- organization: common.organization,
- ext: "tar.gz",
- revision: "1.0118+1.0"
- },
-
jtreg: {
server: "jpg",
product: "jtreg",
@@ -1237,7 +1231,7 @@ var getJibProfilesDependencies = function (input, common) {
graphviz: {
organization: common.organization,
ext: "tar.gz",
- revision: "2.38.0-1+1.1",
+ revision: "9.0.0+1.0",
module: "graphviz-" + input.target_platform,
configure_args: "DOT=" + input.get("graphviz", "install_path") + "/dot",
environment_path: input.get("graphviz", "install_path")
diff --git a/make/data/hotspot-symbols/symbols-aix b/make/data/hotspot-symbols/symbols-aix
deleted file mode 100644
index 1d32104e8a1ed..0000000000000
--- a/make/data/hotspot-symbols/symbols-aix
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (c) 2016, 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-JVM_handle_aix_signal
-numa_error
-numa_warn
diff --git a/make/data/hotspot-symbols/symbols-aix-debug b/make/data/hotspot-symbols/symbols-aix-debug
deleted file mode 100644
index 10887ab2b61fb..0000000000000
--- a/make/data/hotspot-symbols/symbols-aix-debug
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-JVM_AccessVMBooleanFlag
-JVM_AccessVMIntFlag
-JVM_VMBreakPoint
diff --git a/make/data/hotspot-symbols/symbols-linux b/make/data/hotspot-symbols/symbols-linux
deleted file mode 100644
index d1f258297d82d..0000000000000
--- a/make/data/hotspot-symbols/symbols-linux
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (c) 2016, 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-JVM_handle_linux_signal
-JVM_IsUseContainerSupport
-numa_error
-numa_warn
diff --git a/make/data/hotspot-symbols/symbols-macosx b/make/data/hotspot-symbols/symbols-macosx
deleted file mode 100644
index d0243562b67f9..0000000000000
--- a/make/data/hotspot-symbols/symbols-macosx
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-JVM_handle_bsd_signal
diff --git a/make/data/hotspot-symbols/symbols-shared b/make/data/hotspot-symbols/symbols-shared
deleted file mode 100644
index c5b13ef1ee867..0000000000000
--- a/make/data/hotspot-symbols/symbols-shared
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-AsyncGetCallTrace
-jio_fprintf
-jio_printf
-jio_snprintf
-jio_vfprintf
-jio_vsnprintf
-JNI_CreateJavaVM
-JNI_GetCreatedJavaVMs
-JNI_GetDefaultJavaVMInitArgs
-JVM_IsForeignLinkerSupported
-JVM_FindClassFromBootLoader
-JVM_InitAgentProperties
diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix
deleted file mode 100644
index fbb82a11facb7..0000000000000
--- a/make/data/hotspot-symbols/symbols-unix
+++ /dev/null
@@ -1,233 +0,0 @@
-#
-# 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-JVM_ActiveProcessorCount
-JVM_AreNestMates
-JVM_ArrayCopy
-JVM_AssertionStatusDirectives
-JVM_BeforeHalt
-JVM_CallStackWalk
-JVM_Clone
-JVM_ConstantPoolGetClassAt
-JVM_ConstantPoolGetClassAtIfLoaded
-JVM_ConstantPoolGetClassRefIndexAt
-JVM_ConstantPoolGetDoubleAt
-JVM_ConstantPoolGetFieldAt
-JVM_ConstantPoolGetFieldAtIfLoaded
-JVM_ConstantPoolGetFloatAt
-JVM_ConstantPoolGetIntAt
-JVM_ConstantPoolGetLongAt
-JVM_ConstantPoolGetMemberRefInfoAt
-JVM_ConstantPoolGetMethodAt
-JVM_ConstantPoolGetMethodAtIfLoaded
-JVM_ConstantPoolGetNameAndTypeRefIndexAt
-JVM_ConstantPoolGetNameAndTypeRefInfoAt
-JVM_ConstantPoolGetSize
-JVM_ConstantPoolGetStringAt
-JVM_ConstantPoolGetTagAt
-JVM_ConstantPoolGetUTF8At
-JVM_CurrentCarrierThread
-JVM_CurrentThread
-JVM_SetCurrentThread
-JVM_CurrentTimeMillis
-JVM_DefineClass
-JVM_DefineClassWithSource
-JVM_DesiredAssertionStatus
-JVM_DumpAllStacks
-JVM_DumpClassListToFile
-JVM_DumpDynamicArchive
-JVM_DumpThreads
-JVM_ExpandStackFrameInfo
-JVM_FillInStackTrace
-JVM_FindClassFromCaller
-JVM_FindClassFromClass
-JVM_FindLibraryEntry
-JVM_FindLoadedClass
-JVM_FindPrimitiveClass
-JVM_FindSignal
-JVM_FreeMemory
-JVM_GC
-JVM_GetAllThreads
-JVM_GetAndClearReferencePendingList
-JVM_GetArrayElement
-JVM_GetArrayLength
-JVM_GetCallerClass
-JVM_GetClassAccessFlags
-JVM_GetClassAnnotations
-JVM_GetClassConstantPool
-JVM_GetClassContext
-JVM_GetClassCPEntriesCount
-JVM_GetClassCPTypes
-JVM_GetClassDeclaredConstructors
-JVM_GetClassDeclaredFields
-JVM_GetClassDeclaredMethods
-JVM_GetClassFieldsCount
-JVM_GetClassFileVersion
-JVM_GetClassInterfaces
-JVM_GetClassMethodsCount
-JVM_GetClassModifiers
-JVM_GetClassNameUTF
-JVM_GetClassSignature
-JVM_GetClassSigners
-JVM_GetClassTypeAnnotations
-JVM_GetCPClassNameUTF
-JVM_GetCPFieldClassNameUTF
-JVM_GetCPFieldModifiers
-JVM_GetCPFieldNameUTF
-JVM_GetCPFieldSignatureUTF
-JVM_GetCPMethodClassNameUTF
-JVM_GetCPMethodModifiers
-JVM_GetCPMethodNameUTF
-JVM_GetCPMethodSignatureUTF
-JVM_GetDeclaredClasses
-JVM_GetDeclaringClass
-JVM_GetEnclosingMethodInfo
-JVM_GetExtendedNPEMessage
-JVM_GetFieldIxModifiers
-JVM_GetFieldTypeAnnotations
-JVM_GetInheritedAccessControlContext
-JVM_GetManagement
-JVM_GetMethodIxArgsSize
-JVM_GetMethodIxByteCode
-JVM_GetMethodIxByteCodeLength
-JVM_GetMethodIxExceptionIndexes
-JVM_GetMethodIxExceptionsCount
-JVM_GetMethodIxExceptionTableEntry
-JVM_GetMethodIxExceptionTableLength
-JVM_GetMethodIxLocalsCount
-JVM_GetMethodIxMaxStack
-JVM_GetMethodIxModifiers
-JVM_GetMethodIxNameUTF
-JVM_GetMethodIxSignatureUTF
-JVM_GetMethodParameters
-JVM_GetMethodTypeAnnotations
-JVM_GetNanoTimeAdjustment
-JVM_GetNestHost
-JVM_GetNestMembers
-JVM_GetNextThreadIdOffset
-JVM_GetPermittedSubclasses
-JVM_GetPrimitiveArrayElement
-JVM_GetProperties
-JVM_GetProtectionDomain
-JVM_GetRandomSeedForDumping
-JVM_GetRecordComponents
-JVM_GetSimpleBinaryName
-JVM_GetStackAccessControlContext
-JVM_GetSystemPackage
-JVM_GetSystemPackages
-JVM_GetTemporaryDirectory
-JVM_GetVmArguments
-JVM_Halt
-JVM_HasReferencePendingList
-JVM_HoldsLock
-JVM_GetStackTrace
-JVM_IHashCode
-JVM_InitClassName
-JVM_InitStackTraceElement
-JVM_InitStackTraceElementArray
-JVM_InitializeFromArchive
-JVM_InternString
-JVM_Interrupt
-JVM_InvokeMethod
-JVM_IsArrayClass
-JVM_IsCDSDumpingEnabled
-JVM_IsConstructorIx
-JVM_IsDumpingClassList
-JVM_IsFinalizationEnabled
-JVM_IsHiddenClass
-JVM_IsInterface
-JVM_IsPreviewEnabled
-JVM_IsContinuationsSupported
-JVM_IsPrimitiveClass
-JVM_IsRecord
-JVM_IsSameClassPackage
-JVM_IsSharingEnabled
-JVM_IsSupportedJNIVersion
-JVM_IsVMGeneratedMethodIx
-JVM_LatestUserDefinedLoader
-JVM_LoadZipLibrary
-JVM_LoadLibrary
-JVM_LookupDefineClass
-JVM_LookupLambdaProxyClassFromArchive
-JVM_LogLambdaFormInvoker
-JVM_MaxMemory
-JVM_MaxObjectInspectionAge
-JVM_MonitorNotify
-JVM_MonitorNotifyAll
-JVM_MonitorWait
-JVM_MoreStackWalk
-JVM_NanoTime
-JVM_NativePath
-JVM_NewArray
-JVM_NewInstanceFromConstructor
-JVM_NewMultiArray
-JVM_PhantomReferenceRefersTo
-JVM_PrintWarningAtDynamicAgentLoad
-JVM_RaiseSignal
-JVM_RawMonitorCreate
-JVM_RawMonitorDestroy
-JVM_RawMonitorEnter
-JVM_RawMonitorExit
-JVM_ReferenceClear
-JVM_ReferenceRefersTo
-JVM_RegisterContinuationMethods
-JVM_RegisterLambdaProxyClassForArchiving
-JVM_RegisterSignal
-JVM_ReleaseUTF
-JVM_ReportFinalizationComplete
-JVM_SetArrayElement
-JVM_SetClassSigners
-JVM_SetNativeThreadName
-JVM_SetPrimitiveArrayElement
-JVM_SetStackWalkContinuation
-JVM_SetThreadPriority
-JVM_SleepNanos
-JVM_StartThread
-JVM_TotalMemory
-JVM_UnloadLibrary
-JVM_WaitForReferencePendingList
-JVM_Yield
-
-# Module related API's
-JVM_AddModuleExports
-JVM_AddModuleExportsToAll
-JVM_AddModuleExportsToAllUnnamed
-JVM_AddReadsModule
-JVM_DefineArchivedModules
-JVM_DefineModule
-JVM_SetBootLoaderUnnamedModule
-
-# Virtual thread notifications for JVMTI
-JVM_VirtualThreadStart
-JVM_VirtualThreadEnd
-JVM_VirtualThreadMount
-JVM_VirtualThreadUnmount
-JVM_VirtualThreadHideFrames
-JVM_VirtualThreadDisableSuspend
-
-# Scoped values
-JVM_EnsureMaterializedForStackWalk_func
-JVM_FindScopedValueBindings
-JVM_ScopedValueCache
-JVM_SetScopedValueCache
-#
diff --git a/make/data/hotspot-symbols/version-script.txt b/make/data/hotspot-symbols/version-script.txt
new file mode 100644
index 0000000000000..29578bf7cb2e1
--- /dev/null
+++ b/make/data/hotspot-symbols/version-script.txt
@@ -0,0 +1,11 @@
+SUNWprivate_1.1 {
+ global:
+ *;
+
+ local:
+ __bss_start;
+ _edata;
+ _end;
+ _fini;
+ _init;
+};
diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk
index a964045eb5225..5c29ee4db7587 100644
--- a/make/devkit/Tools.gmk
+++ b/make/devkit/Tools.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -548,6 +548,7 @@ $(BUILDDIR)/$(gcc_ver)/Makefile \
$(PATHPRE) $(ENVS) $(GCC_CFG) $(EXTRA_CFLAGS) \
$(CONFIG) \
--with-sysroot=$(SYSROOT) \
+ --with-debug-prefix-map=$(OUTPUT_ROOT)=devkit \
--enable-languages=c,c++ \
--enable-shared \
--disable-nls \
diff --git a/make/devkit/createGraphvizBundle.sh b/make/devkit/createGraphvizBundle.sh
index 290e68c382c4c..1b890838761ba 100644
--- a/make/devkit/createGraphvizBundle.sh
+++ b/make/devkit/createGraphvizBundle.sh
@@ -1,6 +1,6 @@
-#!/bin/bash -e
+#!/bin/bash
#
-# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -26,38 +26,106 @@
# Create a bundle in the current directory, containing what's needed to run
# the 'dot' program from the graphviz suite by the OpenJDK build.
-TMPDIR=`mktemp -d -t graphvizbundle-XXXX`
-trap "rm -rf \"$TMPDIR\"" EXIT
-
-ORIG_DIR=`pwd`
-cd "$TMPDIR"
-GRAPHVIZ_VERSION=2.38.0-1
-PACKAGE_VERSION=1.1
-TARGET_PLATFORM=linux_x64
-BUNDLE_NAME=graphviz-$TARGET_PLATFORM-$GRAPHVIZ_VERSION+$PACKAGE_VERSION.tar.gz
-wget http://www.graphviz.org/pub/graphviz/stable/redhat/el6/x86_64/os/graphviz-$GRAPHVIZ_VERSION.el6.x86_64.rpm
-wget http://www.graphviz.org/pub/graphviz/stable/redhat/el6/x86_64/os/graphviz-libs-$GRAPHVIZ_VERSION.el6.x86_64.rpm
-wget http://www.graphviz.org/pub/graphviz/stable/redhat/el6/x86_64/os/graphviz-plugins-core-$GRAPHVIZ_VERSION.el6.x86_64.rpm
-wget http://www.graphviz.org/pub/graphviz/stable/redhat/el6/x86_64/os/graphviz-plugins-x-$GRAPHVIZ_VERSION.el6.x86_64.rpm
-wget http://public-yum.oracle.com/repo/OracleLinux/OL6/latest/x86_64/getPackage/libtool-ltdl-2.2.6-15.5.el6.x86_64.rpm
-
-mkdir graphviz
-cd graphviz
-for rpm in ../*.rpm; do
- rpm2cpio $rpm | cpio --extract --make-directories
-done
-
-cat > dot << EOF
+set -eux
+
+mydir="$(cd -- $(dirname ${BASH_SOURCE[0]}) && pwd)"
+me="${mydir}/$(basename ${BASH_SOURCE[0]})"
+
+EXPAT_VERSION="2.6.0"
+EXPAT_URL="https://github.com/libexpat/libexpat/releases/download/R_${EXPAT_VERSION//./_}/expat-${EXPAT_VERSION}.tar.gz"
+EXPAT_SHA256="a13447b9aa67d7c860783fdf6820f33ebdea996900d6d8bbc50a628f55f099f7"
+
+GRAPHVIZ_VERSION="9.0.0"
+GRAPHVIZ_URL="https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/${GRAPHVIZ_VERSION}/graphviz-${GRAPHVIZ_VERSION}.tar.xz"
+GRAPHVIZ_SHA256="6c9afda06a732af7658c2619ee713d2545818c3ff19b7b8fd48effcd06d57bf6"
+
+uname_s="$(uname -s)"
+case ${uname_s} in
+ Linux)
+ bundle_os="linux"
+ shacmd="sha256sum --strict --check -"
+ lib_path_var="LD_LIBRARY_PATH"
+ ;;
+ Darwin)
+ bundle_os="macosx"
+ shacmd="shasum -a 256 --strict --check -"
+ lib_path_var="DYLD_LIBRARY_PATH"
+ ;;
+ *)
+ echo "Unknown OS: ${uname_s}"
+ exit 1
+ ;;
+esac
+uname_m="$(uname -m)"
+case ${uname_m} in
+ aarch64|arm64)
+ bundle_cpu="aarch64"
+ ;;
+ x86_64)
+ bundle_cpu="x64"
+ ;;
+esac
+bundle_platform="${bundle_os}_${bundle_cpu}"
+
+build_dir="${mydir}/../../build/graphviz"
+download_dir="${build_dir}/download"
+install_dir="${build_dir}/result/graphviz-${bundle_platform}-${GRAPHVIZ_VERSION}"
+bundle_file="${install_dir}.tar.gz"
+
+expat_dir="${build_dir}/expat"
+expat_src_dir="${expat_dir}/src"
+
+graphviz_dir="${build_dir}/graphviz"
+graphviz_src_dir="${graphviz_dir}/src"
+graphviz_doc_dir="${install_dir}/doc"
+
+mkdir -p "${build_dir}"
+cd "${build_dir}"
+
+download_and_unpack() {
+ local url="$1"
+ local sha256="$2"
+ local file="$3"
+ local dir="$4"
+
+ mkdir -p "$(dirname "${file}")"
+ if [ ! -f "${file}" ]; then
+ curl -L -o "${file}" "${url}"
+ fi
+ echo "${sha256} ${file}" | ${shacmd}
+ if [ ! -d "${dir}" ]; then
+ mkdir -p "${dir}"
+ tar --extract --file "${file}" --directory "${dir}" --strip-components 1
+ fi
+}
+
+download_and_unpack "${EXPAT_URL}" "${EXPAT_SHA256}" "${download_dir}/expat.tar.gz" "${expat_src_dir}"
+download_and_unpack "${GRAPHVIZ_URL}" "${GRAPHVIZ_SHA256}" "${download_dir}/graphviz.tar.gz" "${graphviz_src_dir}"
+
+(
+ cd "${expat_src_dir}"
+ ./configure --prefix="${install_dir}"
+ make -j install
+)
+
+(
+ cd "${graphviz_src_dir}"
+ ./configure --prefix="${install_dir}" EXPAT_CFLAGS="-I${install_dir}/include" EXPAT_LIBS="-L${install_dir}/lib -lexpat"
+ make -j install
+)
+
+cat > "${install_dir}/dot" << EOF
#!/bin/bash
# Get an absolute path to this script
-this_script_dir=\`dirname \$0\`
-this_script_dir=\`cd \$this_script_dir > /dev/null && pwd\`
-export LD_LIBRARY_PATH="\$this_script_dir/usr/lib64:\$LD_LIBRARY_PATH"
-exec \$this_script_dir/usr/bin/dot "\$@"
+this_script_dir="\$(dirname \$0)"
+this_script_dir="\$(cd \${this_script_dir} > /dev/null && pwd)"
+export ${lib_path_var}="\${this_script_dir}/lib:\${this_script_dir}/lib/graphviz"
+exec "\${this_script_dir}/bin/dot" "\$@"
EOF
-chmod +x dot
-export LD_LIBRARY_PATH="$TMPDIR/graphviz/usr/lib64:$LD_LIBRARY_PATH"
+chmod +x "${install_dir}/dot"
# create config file
-./dot -c
-tar -cvzf ../$BUNDLE_NAME *
-cp ../$BUNDLE_NAME "$ORIG_DIR"
+"${install_dir}/dot" -c
+
+cp "${me}" "${install_dir}"
+
+tar --create --gzip --file "${bundle_file}" -C "${install_dir}" .
diff --git a/make/hotspot/gensrc/GensrcAdlc.gmk b/make/hotspot/gensrc/GensrcAdlc.gmk
index 0898d91e1c2a0..f9e09706141fd 100644
--- a/make/hotspot/gensrc/GensrcAdlc.gmk
+++ b/make/hotspot/gensrc/GensrcAdlc.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -45,13 +45,12 @@ ifeq ($(call check-jvm-feature, compiler2), true)
ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX
endif
else ifeq ($(call isBuildOs, windows), true)
- ADLC_LDFLAGS += -nologo
ADLC_CFLAGS := -nologo -EHsc
ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS
endif
# Set the C++ standard
- ADLC_CFLAGS += $(ADLC_LANGSTD_CXXFLAG)
+ ADLC_CFLAGS += $(ADLC_LANGSTD_CXXFLAGS)
# NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to
# hurt.
@@ -72,7 +71,8 @@ ifeq ($(call check-jvm-feature, compiler2), true)
$(eval $(call SetupNativeCompilation, BUILD_ADLC, \
NAME := adlc, \
TYPE := EXECUTABLE, \
- TOOLCHAIN := TOOLCHAIN_BUILD_LINK_CXX, \
+ TARGET_TYPE := BUILD, \
+ LINK_TYPE := C++, \
SRC := $(TOPDIR)/src/hotspot/share/adlc, \
EXTRA_FILES := $(TOPDIR)/src/hotspot/share/opto/opcodes.cpp, \
CFLAGS := $(ADLC_CFLAGS) $(ADLC_CFLAGS_WARNINGS), \
diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk
index 0d17f7a3be562..a50d1ffac9eb4 100644
--- a/make/hotspot/lib/CompileGtest.gmk
+++ b/make/hotspot/lib/CompileGtest.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 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
@@ -50,7 +50,7 @@ endif
$(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \
NAME := gtest, \
TYPE := STATIC_LIBRARY, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OUTPUT_DIR := $(JVM_OUTPUTDIR)/libgtest, \
OBJECT_DIR := $(JVM_OUTPUTDIR)/libgtest/objs, \
SRC := \
@@ -75,25 +75,11 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \
TARGETS += $(BUILD_GTEST_LIBGTEST)
################################################################################
-
-ifeq ($(call isTargetOs, windows), true)
- GTEST_JVM_MAPFILE := $(JVM_MAPFILE)
-else
- GTEST_JVM_MAPFILE := $(JVM_OUTPUTDIR)/gtest/mapfile
-
- $(JVM_OUTPUTDIR)/gtest/symbols: $(JVM_OUTPUTDIR)/symbols
- $(call MakeDir, $(@D))
- ( $(CAT) $< ; echo "runUnitTests" ) > $@
-
- $(GTEST_JVM_MAPFILE): $(JVM_OUTPUTDIR)/gtest/symbols
- $(call create-mapfile)
-endif
-
# Additional disabled warnings are due to code in the test source.
$(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
NAME := jvm, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/objs, \
SRC := $(GTEST_TEST_SRC), \
@@ -123,8 +109,6 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
LIBS_unix := -lgtest, \
LIBS_windows := $(JVM_OUTPUTDIR)/libgtest/gtest.lib, \
OPTIMIZATION := $(JVM_OPTIMIZATION), \
- MAPFILE := $(GTEST_JVM_MAPFILE), \
- USE_MAPFILE_FOR_SYMBOLS := true, \
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
STRIP_SYMBOLS := false, \
@@ -134,14 +118,19 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
$(BUILD_GTEST_LIBJVM) : $(BUILD_GTEST_LIBGTEST)
+ifeq ($(call isTargetOs, windows), true)
+ $(BUILD_GTEST_LIBJVM_TARGET): $(WIN_EXPORT_FILE)
+endif
+
+
TARGETS += $(BUILD_GTEST_LIBJVM)
################################################################################
$(eval $(call SetupJdkExecutable, BUILD_GTEST_LAUNCHER, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
NAME := gtestLauncher, \
TYPE := EXECUTABLE, \
+ LINK_TYPE := C++, \
OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
EXTRA_FILES := $(GTEST_LAUNCHER_SRC), \
OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/launcher-objs, \
diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk
index 8a461e647ab73..69cd80f5171c8 100644
--- a/make/hotspot/lib/CompileJvm.gmk
+++ b/make/hotspot/lib/CompileJvm.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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,7 +33,6 @@ include lib/JvmFlags.gmk
# Setup compilation of the main Hotspot native library (libjvm).
JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm
-JVM_MAPFILE := $(JVM_OUTPUTDIR)/mapfile
################################################################################
# Platform independent setup
@@ -85,7 +84,7 @@ CFLAGS_VM_VERSION := \
DISABLED_WARNINGS_gcc := array-bounds comment delete-non-virtual-dtor \
empty-body implicit-fallthrough int-in-bool-context \
- maybe-uninitialized missing-field-initializers parentheses \
+ maybe-uninitialized missing-field-initializers \
shift-negative-value unknown-pragmas
DISABLED_WARNINGS_clang := sometimes-uninitialized \
@@ -146,12 +145,28 @@ $(call FillFindCache, $(JVM_SRC_DIRS))
# operator new.
LIBJVM_STATIC_EXCLUDE_OBJS := operator_new.o
+ifeq ($(call isTargetOs, windows), true)
+ ifeq ($(STATIC_LIBS), true)
+ WIN_EXPORT_FILE := $(JVM_OUTPUTDIR)/static-win-exports.def
+ else
+ WIN_EXPORT_FILE := $(JVM_OUTPUTDIR)/win-exports.def
+ endif
+
+ JVM_LDFLAGS += -def:$(WIN_EXPORT_FILE)
+endif
+
+ifeq ($(call isTargetOs, linux), true)
+ HOTSPOT_VERSION_SCRIPT := $(TOPDIR)/make/data/hotspot-symbols/version-script.txt
+
+ JVM_LDFLAGS += -Wl,--exclude-libs,ALL -Wl,-version-script=$(HOTSPOT_VERSION_SCRIPT)
+endif
+
################################################################################
# Now set up the actual compilation of the main hotspot native library
$(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
NAME := jvm, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \
SRC := $(JVM_SRC_DIRS), \
EXCLUDES := $(JVM_EXCLUDES), \
@@ -169,6 +184,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
DISABLED_WARNINGS_gcc_jvmciCodeInstaller.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_jvmtiTagMap.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_postaloc.cpp := address, \
+ DISABLED_WARNINGS_gcc_shenandoahLock.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_synchronizer.cpp := stringop-overflow, \
DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang), \
DISABLED_WARNINGS_clang_arguments.cpp := missing-field-initializers, \
@@ -194,8 +210,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
LIBS := $(JVM_LIBS), \
OPTIMIZATION := $(JVM_OPTIMIZATION), \
OBJECT_DIR := $(JVM_OUTPUTDIR)/objs, \
- MAPFILE := $(JVM_MAPFILE), \
- USE_MAPFILE_FOR_SYMBOLS := true, \
STRIPFLAGS := $(JVM_STRIPFLAGS), \
EMBED_MANIFEST := true, \
RC_FILEDESC := $(HOTSPOT_VM_DISTRO) $(OPENJDK_TARGET_CPU_BITS)-Bit $(JVM_VARIANT) VM, \
@@ -204,11 +218,47 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
STATIC_LIB_EXCLUDE_OBJS := $(LIBJVM_STATIC_EXCLUDE_OBJS), \
))
+ifeq ($(call isTargetOs, windows), true)
+ # The following lines create a list of vftable symbols to be filtered out of
+ # the symbol file. Removing this line causes the linker to complain about too
+ # many (> 64K) symbols, so the _guess_ is that this line is here to keep down
+ # the number of exported symbols below that limit.
+ #
+ # Some usages of C++ lambdas require the vftable symbol of classes that use
+ # the lambda type as a template parameter. The usage of those classes won't
+ # link if their vftable symbols are removed. That's why there's an exception
+ # for vftable symbols containing the string 'lambda'.
+ #
+ # A very simple example of a lambda usage that fails if the lambda vftable
+ # symbols are missing in the symbol file:
+ #
+ # #include
+ # std::function f = [](){}
+ FILTER_SYMBOLS_AWK_SCRIPT := \
+ '{ \
+ if ($$7 ~ /\?\?_7.*@@6B@/ && $$7 !~ /type_info/ && $$7 !~ /lambda/) print " " $$7; \
+ }'
+
+ # A more correct solution would be to send BUILD_LIBJVM_ALL_OBJS instead of
+ # cd && *.obj, but this will result in very long command lines, which could be
+ # problematic.
+ $(WIN_EXPORT_FILE): $(BUILD_LIBJVM_ALL_OBJS)
+ $(call LogInfo, Generating list of symbols to export from object files)
+ $(call MakeDir, $(@D))
+ $(ECHO) "EXPORTS" > $@.tmp
+ $(CD) $(BUILD_LIBJVM_OBJECT_DIR) && \
+ $(DUMPBIN) -symbols *$(OBJ_SUFFIX) | $(AWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u >> $@.tmp
+ $(RM) $@
+ $(MV) $@.tmp $@
+
+ $(BUILD_LIBJVM_TARGET): $(WIN_EXPORT_FILE)
+endif
+
# Always recompile abstract_vm_version.cpp if libjvm needs to be relinked. This ensures
# that the internal vm version is updated as it relies on __DATE__ and __TIME__
# macros.
ABSTRACT_VM_VERSION_OBJ := $(JVM_OUTPUTDIR)/objs/abstract_vm_version$(OBJ_SUFFIX)
-$(ABSTRACT_VM_VERSION_OBJ): $(filter-out $(ABSTRACT_VM_VERSION_OBJ) $(JVM_MAPFILE), \
+$(ABSTRACT_VM_VERSION_OBJ): $(filter-out $(ABSTRACT_VM_VERSION_OBJ), \
$(BUILD_LIBJVM_TARGET_DEPS))
ifneq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
@@ -236,11 +286,6 @@ endif
# 1540-1090 : (I) The destructor of "..." might not be called.
# 1540-1639 : (I) The behavior of long type bit fields has changed ...
-# Include mapfile generation. It relies on BUILD_LIBJVM_ALL_OBJS which is only
-# defined after the above call to BUILD_LIBJVM. Mapfile will be generated
-# after all object files are built, but before the jvm library is linked.
-include lib/JvmMapfile.gmk
-
TARGETS += $(BUILD_LIBJVM)
################################################################################
diff --git a/make/hotspot/lib/JvmMapfile.gmk b/make/hotspot/lib/JvmMapfile.gmk
deleted file mode 100644
index b2199e7d17c6f..0000000000000
--- a/make/hotspot/lib/JvmMapfile.gmk
+++ /dev/null
@@ -1,176 +0,0 @@
-#
-# 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-$(eval $(call IncludeCustomExtension, hotspot/lib/JvmMapfile.gmk))
-
-################################################################################
-# Combine a list of static symbols
-
-ifeq ($(call And, $(call isTargetOs, windows) $(call isTargetCpu, x86_64)), false)
- # On Windows x86_64, we should not have any symbols at all, since that
- # results in duplicate warnings from the linker (JDK-8043491).
- SYMBOLS_SRC += $(TOPDIR)/make/data/hotspot-symbols/symbols-shared
-endif
-
-ifeq ($(call isTargetOsType, unix), true)
- SYMBOLS_SRC += $(TOPDIR)/make/data/hotspot-symbols/symbols-unix
-endif
-
-ifneq ($(wildcard $(TOPDIR)/make/data/hotspot-symbols/symbols-$(OPENJDK_TARGET_OS)), )
- SYMBOLS_SRC += $(TOPDIR)/make/data/hotspot-symbols/symbols-$(OPENJDK_TARGET_OS)
-endif
-
-ifneq ($(findstring debug, $(DEBUG_LEVEL)), )
- ifneq ($(wildcard $(TOPDIR)/make/data/hotspot-symbols/symbols-$(OPENJDK_TARGET_OS)-debug), )
- SYMBOLS_SRC += $(TOPDIR)/make/data/hotspot-symbols/symbols-$(OPENJDK_TARGET_OS)-debug
- endif
-endif
-
-################################################################################
-# Create a dynamic list of symbols from the built object files. This is highly
-# platform dependent.
-
-ifeq ($(call isTargetOs, linux), true)
- DUMP_SYMBOLS_CMD := $(NM) $(NMFLAGS) --defined-only *$(OBJ_SUFFIX)
- ifneq ($(FILTER_SYMBOLS_PATTERN), )
- FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|
- endif
- FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM|^UseSharedSpaces$$
- FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^_ZN9Arguments17SharedArchivePathE$$
- FILTER_SYMBOLS_AWK_SCRIPT := \
- '{ \
- if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
- }'
-
-else ifeq ($(call isTargetOs, macosx), true)
- # nm on macosx prints out "warning: nm: no name list" to stderr for
- # files without symbols. Hide this, even at the expense of hiding real errors.
- DUMP_SYMBOLS_CMD := $(NM) $(NMFLAGS) -Uj *$(OBJ_SUFFIX) 2> /dev/null
- ifneq ($(FILTER_SYMBOLS_PATTERN), )
- FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|
- endif
- FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM
- FILTER_SYMBOLS_AWK_SCRIPT := \
- '{ \
- if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \
- }'
-
-# NOTE: The script is from the old build. It is broken and finds no symbols.
-# The script below might be what was intended, but it fails to link with tons
-# of 'cannot export hidden symbol vtable for X'.
-# '{ if ($$1 ~ /^__ZTV/ || $$1 ~ /^_gHotSpotVM/) print substr($$1, 2) }'
-else ifeq ($(call isTargetOs, aix), true)
- # NOTE: The old build had the solution below. This should to be fixed in
- # configure instead.
-
- # On AIX we have to prevent that we pick up the 'nm' version from the GNU binutils
- # which may be installed under /opt/freeware/bin. So better use an absolute path here!
- # NM=/usr/bin/nm
-
- DUMP_SYMBOLS_CMD := $(NM) $(NMFLAGS) -B -C *$(OBJ_SUFFIX)
- FILTER_SYMBOLS_AWK_SCRIPT := \
- '{ \
- if (($$2="d" || $$2="D") && ($$3 ~ /^__vft/ || $$3 ~ /^gHotSpotVM/)) print $$3; \
- if ($$3 ~ /^UseSharedSpaces$$/) print $$3; \
- if ($$3 ~ /^SharedArchivePath__9Arguments$$/) print $$3; \
- }'
-
-else ifeq ($(call isTargetOs, windows), true)
- DUMP_SYMBOLS_CMD := $(DUMPBIN) -symbols *$(OBJ_SUFFIX)
-
- # The following lines create a list of vftable symbols to be filtered out of
- # the mapfile. Removing this line causes the linker to complain about too many
- # (> 64K) symbols, so the _guess_ is that this line is here to keep down the
- # number of exported symbols below that limit.
- #
- # Some usages of C++ lambdas require the vftable symbol of classes that use
- # the lambda type as a template parameter. The usage of those classes won't
- # link if their vftable symbols are removed. That's why there's an exception
- # for vftable symbols containing the string 'lambda'.
- #
- # A very simple example of a lambda usage that fails if the lambda vftable
- # symbols are missing in the mapfile:
- #
- # #include
- # std::function f = [](){}
-
- FILTER_SYMBOLS_AWK_SCRIPT := \
- '{ \
- if ($$7 ~ /\?\?_7.*@@6B@/ && $$7 !~ /type_info/ && $$7 !~ /lambda/) print $$7; \
- }'
-
-else
- $(error Unknown target OS $(OPENJDK_TARGET_OS) in JvmMapfile.gmk)
-endif
-
-# A more correct solution would be to send BUILD_LIBJVM_ALL_OBJS instead of
-# cd && *.o, but this will result in very long command lines, which is
-# problematic on some platforms.
-$(JVM_OUTPUTDIR)/symbols-objects: $(BUILD_LIBJVM_ALL_OBJS)
- $(call LogInfo, Generating symbol list from object files)
- $(CD) $(JVM_OUTPUTDIR)/objs && \
- $(DUMP_SYMBOLS_CMD) | $(AWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@
-
-SYMBOLS_SRC += $(JVM_OUTPUTDIR)/symbols-objects
-
-################################################################################
-# Now concatenate all symbol lists into a single file and remove comments.
-
-$(JVM_OUTPUTDIR)/symbols: $(SYMBOLS_SRC)
- $(SED) -e '/^#/d' $^ > $@
-
-################################################################################
-# Finally convert the symbol list into a platform-specific mapfile
-
-ifeq ($(call isTargetOs, macosx), true)
- # On macosx, we need to add a leading underscore
- define create-mapfile-work
- $(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp
- endef
-else ifeq ($(call isTargetOs, windows), true)
- # On windows, add an 'EXPORTS' header
- define create-mapfile-work
- $(ECHO) "EXPORTS" > $@.tmp
- $(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp
- endef
-else
- # Assume standard linker script
- define create-mapfile-work
- $(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp
- $(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp
- $(PRINTF) " local: \n *; \n }; \n" >> $@.tmp
- endef
-endif
-
-define create-mapfile
- $(call LogInfo, Creating mapfile)
- $(call MakeDir, $(@D))
- $(call create-mapfile-work)
- $(RM) $@
- $(MV) $@.tmp $@
-endef
-
-$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols
- $(call create-mapfile)
diff --git a/make/hotspot/lib/JvmOverrideFiles.gmk b/make/hotspot/lib/JvmOverrideFiles.gmk
index b50d6f8bb36d5..ffb98b9bb9a2b 100644
--- a/make/hotspot/lib/JvmOverrideFiles.gmk
+++ b/make/hotspot/lib/JvmOverrideFiles.gmk
@@ -48,9 +48,6 @@ ifneq ($(FDLIBM_CFLAGS), )
endif
ifeq ($(call isTargetOs, linux), true)
- BUILD_LIBJVM_ostream.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64
- BUILD_LIBJVM_logFileOutput.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64
-
BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := -DNO_PCH $(FDLIBM_CFLAGS) $(LIBJVM_FDLIBM_COPY_OPT_FLAG)
BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := -DNO_PCH $(FDLIBM_CFLAGS) $(LIBJVM_FDLIBM_COPY_OPT_FLAG)
diff --git a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
index d24aee5eee803..921eaeee764da 100644
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -35,6 +35,7 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -132,6 +133,8 @@ public static void main(String ... args) throws Throwable {
String oldDate = String.format("%s%n",
DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ROOT)
.format(new Date()));
+ StandardCharsets.US_ASCII.encode("");
+ StandardCharsets.UTF_8.encode("");
// A selection of trivial and common reflection operations
var instance = HelloClasslist.class.getConstructor().newInstance();
diff --git a/make/modules/java.base/Java.gmk b/make/modules/java.base/Java.gmk
index 8621ff945ccf6..5820c280fe9d1 100644
--- a/make/modules/java.base/Java.gmk
+++ b/make/modules/java.base/Java.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2023, 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
@@ -23,7 +23,11 @@
# questions.
#
-DISABLED_WARNINGS_java += this-escape restricted
+# The base module should be built with all warnings enabled. When a
+# new warning is added to javac, it can be temporarily added to the
+# disabled warnings list.
+#
+# DISABLED_WARNINGS_java +=
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
@@ -37,7 +41,8 @@ EXCLUDE_FILES += \
EXCLUDES += java/lang/doc-files \
java/lang/classfile/snippet-files \
- java/lang/classfile/components/snippet-files
+ java/lang/classfile/components/snippet-files \
+ java/lang/foreign/snippet-files
# Exclude BreakIterator classes that are just used in compile process to generate
# data files and shouldn't go in the product
diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk
index 924cb8aae268b..54050d0798626 100644
--- a/make/modules/java.base/Lib.gmk
+++ b/make/modules/java.base/Lib.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -242,7 +242,7 @@ endif
ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, x86_64)+$(INCLUDE_COMPILER2)+$(filter $(TOOLCHAIN_TYPE), gcc), true+true+true+gcc)
$(eval $(call SetupJdkLibrary, BUILD_LIB_SIMD_SORT, \
NAME := simdsort, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB), \
CXXFLAGS := $(CXXFLAGS_JDKLIB) -std=c++17, \
diff --git a/make/modules/java.base/lib/CoreLibraries.gmk b/make/modules/java.base/lib/CoreLibraries.gmk
index 8904c39449e29..b27013536f8e3 100644
--- a/make/modules/java.base/lib/CoreLibraries.gmk
+++ b/make/modules/java.base/lib/CoreLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -115,7 +115,7 @@ TARGETS += $(BUILD_LIBZIP)
$(eval $(call SetupJdkLibrary, BUILD_LIBJIMAGE, \
NAME := jimage, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB), \
CXXFLAGS := $(CXXFLAGS_JDKLIB), \
diff --git a/make/modules/java.compiler/Java.gmk b/make/modules/java.compiler/Java.gmk
index e2d5ac264b8b6..04f31a9bc66ee 100644
--- a/make/modules/java.compiler/Java.gmk
+++ b/make/modules/java.compiler/Java.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
# questions.
#
+# To the extent technically possible, this module should be built with
+# -Werror and all lint warnings enabled. In particular,
+# DISABLED_WARNINGS_java should not be augmented.
+
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk
index be1ac3f1fb8a2..cb831faebf62c 100644
--- a/make/modules/java.desktop/Lib.gmk
+++ b/make/modules/java.desktop/Lib.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -51,13 +51,14 @@ ifeq ($(call isTargetOs, aix), false)
-DUSE_PLATFORM_MIDI_IN=TRUE \
#
+ LIBJSOUND_LINK_TYPE := C
ifeq ($(call isTargetOs, macosx), true)
- LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
+ LIBJSOUND_LINK_TYPE := C++
endif
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
NAME := jsound, \
- TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \
+ LINK_TYPE := $(LIBJSOUND_LINK_TYPE), \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJSOUND_CFLAGS), \
diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk
index 4d5ff751981ce..aaf98d088fdad 100644
--- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk
+++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -449,7 +449,6 @@ else
LIBFREETYPE_LIBS := -lfreetype
endif
- # gcc_ftobjs.c := maybe-uninitialized required for GCC 7 builds.
$(eval $(call SetupJdkLibrary, BUILD_LIBFREETYPE, \
NAME := freetype, \
OPTIMIZATION := HIGHEST, \
@@ -458,7 +457,6 @@ else
EXTRA_HEADER_DIRS := $(BUILD_LIBFREETYPE_HEADER_DIRS), \
DISABLED_WARNINGS_microsoft := 4267 4244 4996, \
DISABLED_WARNINGS_gcc := dangling-pointer stringop-overflow, \
- DISABLED_WARNINGS_gcc_ftobjs.c := maybe-uninitialized, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
))
@@ -508,8 +506,10 @@ else
# noexcept-type required for GCC 7 builds. Not required for GCC 8+.
# expansion-to-defined required for GCC 9 builds. Not required for GCC 10+.
# maybe-uninitialized required for GCC 8 builds. Not required for GCC 9+.
+ # calloc-transposed-args required for GCC 14 builds. (fixed upstream in Harfbuzz 032c931e1c0cfb20f18e5acb8ba005775242bd92)
HARFBUZZ_DISABLED_WARNINGS_CXX_gcc := class-memaccess noexcept-type \
- expansion-to-defined dangling-reference maybe-uninitialized
+ expansion-to-defined dangling-reference maybe-uninitialized \
+ calloc-transposed-args
HARFBUZZ_DISABLED_WARNINGS_clang := missing-field-initializers range-loop-analysis
HARFBUZZ_DISABLED_WARNINGS_microsoft := 4267 4244
@@ -562,9 +562,9 @@ LIBFONTMANAGER_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS
# libawt_xawt). See JDK-8196516 for details.
$(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
NAME := fontmanager, \
+ LINK_TYPE := C++, \
EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES) \
AccelGlyphCache.c, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \
OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \
diff --git a/make/modules/jdk.compiler/Java.gmk b/make/modules/jdk.compiler/Java.gmk
index 7e6793fc6379b..a2dd4f60fa681 100644
--- a/make/modules/jdk.compiler/Java.gmk
+++ b/make/modules/jdk.compiler/Java.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2023, 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
@@ -23,6 +23,10 @@
# questions.
#
+# To the extent technically possible, this module should be built with
+# -Werror and all lint warnings enabled. In particular,
+# DISABLED_WARNINGS_java should not be augmented.
+
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:-com.sun.tools.*,-jdk.internal.*,sun.tools.serialver.resources.*'
JAVAC_FLAGS += -XDstringConcat=inline
diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk
index d21c969c18813..6d85061583781 100644
--- a/make/modules/jdk.hotspot.agent/Lib.gmk
+++ b/make/modules/jdk.hotspot.agent/Lib.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 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
@@ -27,10 +27,7 @@ include LibCommon.gmk
################################################################################
-ifeq ($(call isTargetOs, linux), true)
- SA_CFLAGS := -D_FILE_OFFSET_BITS=64
-
-else ifeq ($(call isTargetOs, macosx), true)
+ifeq ($(call isTargetOs, macosx), true)
SA_CFLAGS := -D_GNU_SOURCE -mno-omit-leaf-frame-pointer \
-mstack-alignment=16 -fPIC
LIBSA_EXTRA_SRC := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent
@@ -48,16 +45,16 @@ else ifeq ($(call isTargetOs, windows), true)
endif
endif
-SA_TOOLCHAIN := $(TOOLCHAIN_DEFAULT)
+SA_LINK_TYPE := C
ifeq ($(call isTargetOs, linux), true)
- SA_TOOLCHAIN := TOOLCHAIN_LINK_CXX
+ SA_LINK_TYPE := C++
endif
################################################################################
$(eval $(call SetupJdkLibrary, BUILD_LIBSA, \
NAME := saproc, \
- TOOLCHAIN := $(SA_TOOLCHAIN), \
+ LINK_TYPE := $(SA_LINK_TYPE), \
OPTIMIZATION := HIGH, \
DISABLED_WARNINGS_gcc := sign-compare, \
DISABLED_WARNINGS_gcc_ps_core.c := pointer-arith, \
diff --git a/make/modules/jdk.internal.le/Lib.gmk b/make/modules/jdk.internal.le/Lib.gmk
index 75a2446cc5a18..85550e3cc1d8e 100644
--- a/make/modules/jdk.internal.le/Lib.gmk
+++ b/make/modules/jdk.internal.le/Lib.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 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,7 +31,7 @@ ifeq ($(call isTargetOs, linux macosx windows), true)
$(eval $(call SetupJdkLibrary, BUILD_LIBLE, \
NAME := le, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
diff --git a/make/modules/jdk.javadoc/Java.gmk b/make/modules/jdk.javadoc/Java.gmk
index 3035864ecbacb..a8b1f2c117333 100644
--- a/make/modules/jdk.javadoc/Java.gmk
+++ b/make/modules/jdk.javadoc/Java.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, 2023, 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
@@ -23,6 +23,8 @@
# questions.
#
-DISABLED_WARNINGS_java += this-escape
+# To the extent technically possible, this module should be built with
+# -Werror and all lint warnings enabled. In particular,
+# DISABLED_WARNINGS_java should not be augmented.
COPY += .xml .css .svg .js .js.template .png .txt
diff --git a/make/modules/jdk.jpackage/Lib.gmk b/make/modules/jdk.jpackage/Lib.gmk
index 1d3e27e8a6b77..58e40d772e135 100644
--- a/make/modules/jdk.jpackage/Lib.gmk
+++ b/make/modules/jdk.jpackage/Lib.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 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,13 +32,13 @@ include LauncherCommon.gmk
ifeq ($(call isTargetOs, linux), true)
JPACKAGE_APPLAUNCHER_SRC := \
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher)
- JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_DEFAULT
+ JPACKAGE_APPLAUNCHER_LINK_TYPE := C
JPACKAGE_APPLAUNCHER_INCLUDE_FILES := %.c
else
JPACKAGE_APPLAUNCHER_SRC := \
$(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \
$(call FindSrcDirsForComponent, jdk.jpackage, common)
- JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_LINK_CXX
+ JPACKAGE_APPLAUNCHER_LINK_TYPE := C++
endif
@@ -59,11 +59,11 @@ JPACKAGE_APPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC))
# Output app launcher executable in resources dir, and symbols in the object dir
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
NAME := jpackageapplauncher, \
+ LINK_TYPE := $(JPACKAGE_APPLAUNCHER_LINK_TYPE), \
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
INCLUDE_FILES := $(JPACKAGE_APPLAUNCHER_INCLUDE_FILES), \
- TOOLCHAIN := $(JPACKAGE_APPLAUNCHER_TOOLCHAIN), \
OPTIMIZATION := LOW, \
DISABLED_WARNINGS_clang_LinuxPackage.c := format-nonliteral, \
DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \
@@ -103,7 +103,7 @@ ifeq ($(call isTargetOs, linux), true)
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncheraux, \
SRC := $(JPACKAGE_LIBAPPLAUNCHER_SRC), \
EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \
- TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+ LINK_TYPE := C++, \
OPTIMIZATION := LOW, \
DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \
DISABLED_WARNINGS_clang_tstrings.cpp := format-nonliteral, \
@@ -177,10 +177,10 @@ ifeq ($(call isTargetOs, windows), true)
# Build non-console version of launcher
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
NAME := jpackageapplauncherw, \
+ LINK_TYPE := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LINK_TYPE), \
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
- TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh
index a395e0cd850ca..44c700c48957e 100644
--- a/make/scripts/compare.sh
+++ b/make/scripts/compare.sh
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Copyright (c) 2012, 2022, 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
@@ -60,13 +60,15 @@ else
STAT_PRINT_SIZE="-c %s"
fi
-COMPARE_EXCEPTIONS_INCLUDE="$TOPDIR/make/scripts/compare_exceptions.sh.incl"
-if [ ! -e "$COMPARE_EXCEPTIONS_INCLUDE" ]; then
- echo "Error: Cannot locate the exceptions file, it should have been here: $COMPARE_EXCEPTIONS_INCLUDE"
- exit 1
+
+if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
+ # We ship a pdb file inside a published zip. Such files can never be built
+ # reproducibly, so ignore it.
+ ACCEPTED_JARZIP_CONTENTS="/modules_libs/java.security.jgss/w2k_lsa_auth.dll.pdb"
+elif [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
+ # Due to signing, we can never get a byte-by-byte identical build on macOS
+ STRIP_TESTS_BEFORE_COMPARE="true"
fi
-# Include exception definitions
-. "$COMPARE_EXCEPTIONS_INCLUDE"
################################################################################
#
@@ -117,35 +119,6 @@ diff_text() {
TMP=$($DIFF $THIS_FILE $OTHER_FILE)
- if test "x$SUFFIX" = "xclass"; then
- if [ "$NAME" = "SystemModules\$all.class" ] \
- || [ "$NAME" = "SystemModules\$default.class" ]; then
- # The SystemModules\$*.classes are not comparable as they contain the
- # module hashes which would require a whole other level of
- # reproducible builds to get reproducible. There is also random
- # order of map initialization.
- TMP=""
- elif [ "$NAME" = "module-info.class" ]; then
- # The module-info.class have several issues with random ordering of
- # elements in HashSets.
- MODULES_CLASS_FILTER="$SED \
- -e 's/,$//' \
- -e 's/;$//' \
- -e 's/^ *[0-9]*://' \
- -e 's/#[0-9]* */#/' \
- -e 's/ *\/\// \/\//' \
- -e 's/aload *[0-9]*/aload X/' \
- -e 's/ldc_w/ldc /' \
- | $SORT \
- "
- $JAVAP -c -constants -l -p "${OTHER_FILE}" \
- | eval "$MODULES_CLASS_FILTER" > ${OTHER_FILE}.javap &
- $JAVAP -c -constants -l -p "${THIS_FILE}" \
- | eval "$MODULES_CLASS_FILTER" > ${THIS_FILE}.javap &
- wait
- TMP=$($DIFF ${OTHER_FILE}.javap ${THIS_FILE}.javap)
- fi
- fi
if test -n "$TMP"; then
echo Files $OTHER_FILE and $THIS_FILE differ
@@ -312,75 +285,60 @@ compare_file_types() {
}
################################################################################
-# Compare the rest of the files
+# Find all files to compare and separate them into different categories
-compare_general_files() {
+locate_files() {
THIS_DIR=$1
- OTHER_DIR=$2
- WORK_DIR=$3
+ TEMP_DIR=$COMPARE_ROOT/support
+ $MKDIR -p $TEMP_DIR
- GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" \
- ! -name "*.zip" ! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" \
- ! -name "modules" ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
- ! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
- ! -name "*.lib" ! -name "*.jmod" ! -name "*.exe" \
- ! -name "*.obj" ! -name "*.o" ! -name "jspawnhelper" ! -name "*.a" \
- ! -name "*.tar.gz" ! -name "gtestLauncher" \
- ! -name "*.map" \
- | $GREP -v "./bin/" | $SORT | $FILTER)
+ ALL_FILES_PATH=$TEMP_DIR/all_files.txt
+ cd $THIS_DIR && $FIND . -type f | $SORT | $FILTER > $ALL_FILES_PATH
- echo Other files with binary differences...
- for f in $GENERAL_FILES
- do
- # Skip all files in test/*/native
- if [[ "$f" == */native/* ]]; then
- continue
- fi
- if [ -e $OTHER_DIR/$f ]; then
- SUFFIX="${f##*.}"
- if [ "$(basename $f)" = "release" ]; then
- # In release file, ignore differences in source rev numbers
- OTHER_FILE=$WORK_DIR/$f.other
- THIS_FILE=$WORK_DIR/$f.this
- $MKDIR -p $(dirname $OTHER_FILE)
- $MKDIR -p $(dirname $THIS_FILE)
- RELEASE_FILTER="$SED -e 's/SOURCE=".*"/SOURCE=/g'"
- $CAT $OTHER_DIR/$f | eval "$RELEASE_FILTER" > $OTHER_FILE
- $CAT $THIS_DIR/$f | eval "$RELEASE_FILTER" > $THIS_FILE
- elif [ "$SUFFIX" = "svg" ]; then
- # GraphViz has non-determinism when generating svg files
- OTHER_FILE=$WORK_DIR/$f.other
- THIS_FILE=$WORK_DIR/$f.this
- $MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)
- SVG_FILTER="$SED \
- -e 's/edge[0-9][0-9]*/edgeX/g'
- "
- $CAT $OTHER_DIR/$f | eval "$SVG_FILTER" > $OTHER_FILE
- $CAT $THIS_DIR/$f | eval "$SVG_FILTER" > $THIS_FILE
- elif [ "$SUFFIX" = "jar_contents" ]; then
- # The jar_contents files may have some lines in random order
- OTHER_FILE=$WORK_DIR/$f.other
- THIS_FILE=$WORK_DIR/$f.this
- $MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)
- $RM $OTHER_FILE $THIS_FILE
- $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE
- $CAT $THIS_DIR/$f | $SORT > $THIS_FILE
- else
- OTHER_FILE=$OTHER_DIR/$f
- THIS_FILE=$THIS_DIR/$f
- fi
- DIFF_OUT=$($DIFF $OTHER_FILE $THIS_FILE 2>&1)
- if [ -n "$DIFF_OUT" ]; then
- echo $f
- REGRESSIONS=true
- if [ "$SHOW_DIFFS" = "true" ]; then
- echo "$DIFF_OUT"
- fi
- fi
- fi
- done
+ ZIP_FILES_PATH=$TEMP_DIR/zip_files.txt
+ ZIP_FILTER="-e '\.zip$' -e '\.tar.gz$'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $ZIP_FILTER > $ZIP_FILES_PATH
+
+ JMOD_FILES_PATH=$TEMP_DIR/jmod_files.txt
+ JMOD_FILTER="-e '\.jmod$'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $JMOD_FILTER > $JMOD_FILES_PATH
+
+ JAR_FILES_PATH=$TEMP_DIR/jar_files.txt
+ JAR_FILTER="-e '\.jar$' -e '\.war$' -e '/module$'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $JAR_FILTER > $JAR_FILES_PATH
+
+ LIB_FILES_PATH=$TEMP_DIR/lib_files.txt
+ LIB_FILTER="-e '\.dylib$' -e '/lib.*\.so$' -e '\.dll$' -e '\.obj$' -e '\.o$' -e '\.a$' -e '\.cpl$'"
+ # On macos, filter out the dSYM debug symbols files. They are identically named .dylib files that reside
+ # under a *.dSYM directory
+ LIB_EXCLUDE="-e '/lib.*\.dSYM/'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $LIB_FILTER | eval $GREP -v $LIB_EXCLUDE > $LIB_FILES_PATH
+ DEBUG_FILES_PATH=$TEMP_DIR/debug_files.txt
+ DEBUG_FILTER="-e '\.dSYM/' -e '\.debuginfo$' -e '\.diz$' -e '\.pdb$' -e '\.map$'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $DEBUG_FILTER > $DEBUG_FILES_PATH
+ EXEC_FILES_PATH=$TEMP_DIR/exec_files.txt
+ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
+ EXEC_FILTER="-e '\.exe$'"
+ $CAT "$ALL_FILES_PATH" | eval $GREP $EXEC_FILTER > $EXEC_FILES_PATH
+ else
+ # Find all files with the executable bit set
+ cd $THIS_DIR && $FIND . -type f -perm -100 | $SORT | $FILTER > $EXEC_FILES_PATH
+ fi
+
+ OTHER_FILES_PATH=$TEMP_DIR/other_files.txt
+ ACCOUNTED_FILES_PATH=$TEMP_DIR/accounted_files.txt
+ $CAT $ZIP_FILES_PATH $JMOD_FILES_PATH $JAR_FILES_PATH $LIB_FILES_PATH $DEBUG_FILES_PATH $EXEC_FILES_PATH > $ACCOUNTED_FILES_PATH
+ $CAT $ACCOUNTED_FILES_PATH $ALL_FILES_PATH | $SORT | $UNIQ -u > $OTHER_FILES_PATH
+
+ ALL_ZIP_FILES=$($CAT $ZIP_FILES_PATH)
+ ALL_JMOD_FILES=$($CAT $JMOD_FILES_PATH)
+ ALL_JAR_FILES=$($CAT $JAR_FILES_PATH)
+ ALL_LIB_FILES=$($CAT $LIB_FILES_PATH)
+ ALL_DEBUG_FILES=$($CAT $DEBUG_FILES_PATH)
+ ALL_EXEC_FILES=$($CAT $EXEC_FILES_PATH)
+ ALL_OTHER_FILES=$($CAT $OTHER_FILES_PATH)
}
################################################################################
@@ -450,12 +408,14 @@ compare_zip_file() {
if [ -n "$ONLY_OTHER" ]; then
echo " Only OTHER $ZIP_FILE contains:"
echo "$ONLY_OTHER" | sed "s|Only in $OTHER_UNZIPDIR| |"g | sed 's|: |/|g'
+ REGRESSIONS=true
return_value=1
fi
if [ -n "$ONLY_THIS" ]; then
echo " Only THIS $ZIP_FILE contains:"
echo "$ONLY_THIS" | sed "s|Only in $THIS_UNZIPDIR| |"g | sed 's|: |/|g'
+ REGRESSIONS=true
return_value=1
fi
@@ -484,6 +444,7 @@ compare_zip_file() {
done
if [ -s "$WORK_DIR/$ZIP_FILE.diffs" ]; then
+ REGRESSIONS=true
return_value=1
echo " Differing files in $ZIP_FILE"
$CAT $WORK_DIR/$ZIP_FILE.diffs | $GREP 'differ$' | cut -f 2 -d ' ' | \
@@ -508,6 +469,7 @@ compare_zip_file() {
compare_bin_file $THIS_UNZIPDIR $OTHER_UNZIPDIR $WORK_DIR/$ZIP_FILE.bin \
$file
if [ "$?" != "0" ]; then
+ REGRESSIONS=true
return_value=1
fi
done
@@ -547,12 +509,14 @@ compare_jmod_file() {
if [ -n "$ONLY_OTHER" ]; then
echo " Only OTHER $JMOD_FILE contains:"
echo "$ONLY_OTHER" | sed "s|^>| |"g | sed 's|: |/|g'
+ REGRESSIONS=true
return_value=1
fi
if [ -n "$ONLY_THIS" ]; then
echo " Only THIS $JMOD_FILE contains:"
echo "$ONLY_THIS" | sed "s|^<| |"g | sed 's|: |/|g'
+ REGRESSIONS=true
return_value=1
fi
@@ -567,19 +531,18 @@ compare_all_zip_files() {
OTHER_DIR=$2
WORK_DIR=$3
- ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.zip" -o -name "*.tar.gz" \
- | $SORT | $FILTER )
+ locate_files $THIS_DIR
- if [ -n "$ZIPS" ]; then
+ if [ -n "$ALL_ZIP_FILES" ]; then
echo Zip/tar.gz files...
return_value=0
- for f in $ZIPS; do
+ for f in $ALL_ZIP_FILES; do
if [ -f "$OTHER_DIR/$f" ]; then
compare_zip_file $THIS_DIR $OTHER_DIR $WORK_DIR $f
if [ "$?" != "0" ]; then
- return_value=1
REGRESSIONS=true
+ return_value=1
fi
fi
done
@@ -596,18 +559,18 @@ compare_all_jmod_files() {
OTHER_DIR=$2
WORK_DIR=$3
- JMODS=$(cd $THIS_DIR && $FIND . -type f -name "*.jmod" | $SORT | $FILTER )
+ locate_files $THIS_DIR
- if [ -n "$JMODS" ]; then
+ if [ -n "$ALL_JMOD_FILES" ]; then
echo Jmod files...
return_value=0
- for f in $JMODS; do
+ for f in $ALL_JMOD_FILES; do
if [ -f "$OTHER_DIR/$f" ]; then
compare_jmod_file $THIS_DIR $OTHER_DIR $WORK_DIR $f
if [ "$?" != "0" ]; then
- return_value=1
REGRESSIONS=true
+ return_value=1
fi
fi
done
@@ -624,20 +587,18 @@ compare_all_jar_files() {
OTHER_DIR=$2
WORK_DIR=$3
- # TODO filter?
- ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.jar" -o -name "*.war" \
- -o -name "modules" | $SORT | $FILTER)
+ locate_files $THIS_DIR
- if [ -n "$ZIPS" ]; then
+ if [ -n "$ALL_JAR_FILES" ]; then
echo Jar files...
return_value=0
- for f in $ZIPS; do
+ for f in $ALL_JAR_FILES; do
if [ -f "$OTHER_DIR/$f" ]; then
compare_zip_file $THIS_DIR $OTHER_DIR $WORK_DIR $f
if [ "$?" != "0" ]; then
- return_value=1
REGRESSIONS=true
+ return_value=1
fi
fi
done
@@ -699,14 +660,16 @@ compare_bin_file() {
unset _NT_SYMBOL_PATH
if [ "$(uname -o)" = "Cygwin" ]; then
THIS=$(cygpath -msa $THIS)
- OTHER=$(cygpath -msa $OTHER)
+ if [ -n "$OTHER" ]; then
+ OTHER=$(cygpath -msa $OTHER)
+ fi
fi
# Build an _NT_SYMBOL_PATH that contains all known locations for
# pdb files.
PDB_DIRS="$(ls -d \
{$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \
{$OTHER,$THIS}/support/native/jdk.jpackage/* \
- )"
+ 2> /dev/null )"
export _NT_SYMBOL_PATH="$(echo $PDB_DIRS | tr ' ' ';')"
fi
@@ -1047,23 +1010,16 @@ compare_all_libs() {
OTHER_DIR=$2
WORK_DIR=$3
- LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' \
- -o -name '*.dll' -o -name '*.obj' -o -name '*.o' -o -name '*.a' \
- -o -name '*.cpl' \) | $SORT | $FILTER)
-
- # On macos, filter out the dSYM debug symbols files as they are also
- # named *.dylib.
- if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
- LIBS=$(echo "$LIBS" | $GREP -v '\.dSYM/')
- fi
+ locate_files $THIS_DIR
- if [ -n "$LIBS" ]; then
+ if [ -n "$ALL_LIB_FILES" ]; then
echo Libraries...
print_binary_diff_header
- for l in $LIBS; do
+ for l in $ALL_LIB_FILES; do
if [ -f "$OTHER_DIR/$l" ]; then
compare_bin_file $THIS_DIR $OTHER_DIR $WORK_DIR $l
if [ "$?" != "0" ]; then
+ REGRESSIONS=true
return_value=1
fi
fi
@@ -1081,33 +1037,16 @@ compare_all_execs() {
OTHER_DIR=$2
WORK_DIR=$3
- if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
- EXECS=$(cd $THIS_DIR && $FIND . -type f -name '*.exe' | $SORT | $FILTER)
- else
- EXECS=$(cd $THIS_DIR && $FIND . -name db -prune -o -type f -perm -100 \! \
- \( -name '*.so' -o -name '*.dylib' -o -name '*.dll' -o -name '*.cgi' \
- -o -name '*.jar' -o -name '*.diz' -o -name 'jcontrol' -o -name '*.properties' \
- -o -name '*.data' -o -name '*.bfc' -o -name '*.src' -o -name '*.txt' \
- -o -name '*.cfg' -o -name 'meta-index' -o -name '*.properties.ja' \
- -o -name '*.xml' -o -name '*.html' -o -name '*.png' -o -name 'README' \
- -o -name '*.zip' -o -name '*.jimage' -o -name '*.java' -o -name '*.mf' \
- -o -name '*.jpg' -o -name '*.wsdl' -o -name '*.js' -o -name '*.sh' \
- -o -name '*.bat' -o -name '*LICENSE' -o -name '*.d' -o -name '*store' \
- -o -name 'blocked' -o -name '*certs' -o -name '*.ttf' \
- -o -name '*.jfc' -o -name '*.dat' -o -name 'release' -o -name '*.dir'\
- -o -name '*.sym' -o -name '*.idl' -o -name '*.h' -o -name '*.access' \
- -o -name '*.template' -o -name '*.policy' -o -name '*.security' \
- -o -name 'COPYRIGHT' -o -name '*.1' -o -name '*.debuginfo' \
- -o -name 'classlist' \) | $SORT | $FILTER)
- fi
-
- if [ -n "$EXECS" ]; then
+ locate_files $THIS_DIR
+
+ if [ -n "$ALL_EXEC_FILES" ]; then
echo Executables...
print_binary_diff_header
- for e in $EXECS; do
+ for e in $ALL_EXEC_FILES; do
if [ -f "$OTHER_DIR/$e" ]; then
compare_bin_file $THIS_DIR $OTHER_DIR $WORK_DIR $e
if [ "$?" != "0" ]; then
+ REGRESSIONS=true
return_value=1
fi
fi
@@ -1117,6 +1056,95 @@ compare_all_execs() {
return $return_value
}
+################################################################################
+# Compare native debug symbol files
+
+compare_all_debug_files() {
+ THIS_DIR=$1
+ OTHER_DIR=$2
+ WORK_DIR=$3
+
+ locate_files $THIS_DIR
+
+ echo Debug symbol files with binary differences...
+ for f in $ALL_DEBUG_FILES
+ do
+ if [ -e $OTHER_DIR/$f ]; then
+ SUFFIX="${f##*.}"
+ if [ "$SUFFIX" = "pdb" ]; then
+ # pdb files are never reproducible
+ DIFF_OUT=""
+ else
+ OTHER_FILE=$OTHER_DIR/$f
+ THIS_FILE=$THIS_DIR/$f
+ DIFF_OUT=$($DIFF $OTHER_FILE $THIS_FILE 2>&1)
+ fi
+
+ if [ -n "$DIFF_OUT" ]; then
+ echo $f
+ REGRESSIONS=true
+ if [ "$SHOW_DIFFS" = "true" ]; then
+ echo "$DIFF_OUT"
+ fi
+ fi
+ fi
+ done
+}
+
+################################################################################
+# Compare the rest of the files
+
+compare_all_other_files() {
+ THIS_DIR=$1
+ OTHER_DIR=$2
+ WORK_DIR=$3
+
+ locate_files $THIS_DIR
+
+ echo Other files with binary differences...
+ for f in $ALL_OTHER_FILES
+ do
+ # Skip all files in test/*/native
+ if [[ "$f" == */native/* ]]; then
+ continue
+ fi
+ if [ -e $OTHER_DIR/$f ]; then
+ SUFFIX="${f##*.}"
+ if [ "$(basename $f)" = "release" ]; then
+ # In release file, ignore differences in source rev numbers
+ OTHER_FILE=$WORK_DIR/$f.other
+ THIS_FILE=$WORK_DIR/$f.this
+ $MKDIR -p $(dirname $OTHER_FILE)
+ $MKDIR -p $(dirname $THIS_FILE)
+ RELEASE_FILTER="$SED -e 's/SOURCE=".*"/SOURCE=/g'"
+ $CAT $OTHER_DIR/$f | eval "$RELEASE_FILTER" > $OTHER_FILE
+ $CAT $THIS_DIR/$f | eval "$RELEASE_FILTER" > $THIS_FILE
+ elif [ "$SUFFIX" = "jar_contents" ]; then
+ # The jar_contents files are generated by the build and may have
+ # some lines in random order. They are only included for demos,
+ # which they shouldn't really...
+ OTHER_FILE=$WORK_DIR/$f.other
+ THIS_FILE=$WORK_DIR/$f.this
+ $MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)
+ $RM $OTHER_FILE $THIS_FILE
+ $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE
+ $CAT $THIS_DIR/$f | $SORT > $THIS_FILE
+ else
+ OTHER_FILE=$OTHER_DIR/$f
+ THIS_FILE=$THIS_DIR/$f
+ fi
+ DIFF_OUT=$($DIFF $OTHER_FILE $THIS_FILE 2>&1)
+ if [ -n "$DIFF_OUT" ]; then
+ echo $f
+ REGRESSIONS=true
+ if [ "$SHOW_DIFFS" = "true" ]; then
+ echo "$DIFF_OUT"
+ fi
+ fi
+ fi
+ done
+}
+
################################################################################
# Initiate configuration
@@ -1515,22 +1543,31 @@ fi
if [ "$CMP_GENERAL" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
- compare_general_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ compare_all_other_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ echo -n "JDK "
+ compare_all_debug_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
echo -n "JDK Bundle "
- compare_general_files $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
+ compare_all_other_files $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
+ echo -n "JDK Bundle "
+ compare_all_debug_files $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
fi
if [ -n "$THIS_DOCS" ] && [ -n "$OTHER_DOCS" ]; then
echo -n "Docs "
- compare_general_files $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
+ compare_all_other_files $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
+ echo -n "Docs "
+ compare_all_debug_files $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
fi
if [ -n "$THIS_TEST" ] && [ -n "$OTHER_TEST" ]; then
echo -n "Test "
- compare_general_files $THIS_TEST $OTHER_TEST $COMPARE_ROOT/test
+ compare_all_other_files $THIS_TEST $OTHER_TEST $COMPARE_ROOT/test
+ echo -n "Test "
+ compare_all_debug_files $THIS_TEST $OTHER_TEST $COMPARE_ROOT/test
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
- compare_general_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_all_other_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_all_debug_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
fi
diff --git a/make/scripts/compare_exceptions.sh.incl b/make/scripts/compare_exceptions.sh.incl
index cfbfeeb5be4f9..e69de29bb2d1d 100644
--- a/make/scripts/compare_exceptions.sh.incl
+++ b/make/scripts/compare_exceptions.sh.incl
@@ -1,65 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2012, 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# This script is not to be run as stand-alone, it should be included from
-# compare.sh.
-
-##########################################################################################
-# Check that we are run via inclusion from compare.sh and not as stand-alone.
-if [ -z "$COMPARE_EXCEPTIONS_INCLUDE" ]; then
- echo "Error: This script should not be run as stand-alone. It is included by compare.sh"
- exit 1
-fi
-
-##########################################################################################
-# Diff exceptions
-
-if [ "$OPENJDK_TARGET_OS" = "linux" ]; then
- if [ "$USE_PRECOMPILED_HEADER" = "true" ]; then
- ACCEPTED_BIN_DIFF="
- ./lib/server/libjvm.so
- ./hotspot/gtest/server/libjvm.so
- "
- STRIP_BEFORE_COMPARE="
- ./hotspot/gtest/server/libjvm.so
- "
- fi
-elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
- SKIP_BIN_DIFF="true"
- SKIP_FULLDUMP_DIFF="true"
- ACCEPTED_JARZIP_CONTENTS="
- /modules_libs/java.security.jgss/w2k_lsa_auth.dll.pdb
- /modules_libs/java.security.jgss/w2k_lsa_auth.dll.map
- /modules_libs/java.security.jgss/w2k_lsa_auth.dll
- "
-elif [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
- ACCEPTED_BIN_DIFF="
- ./lib/libawt_lwawt.dylib
- ./lib/libosxapp.dylib
- ./lib/libosxui.dylib
- ./lib/server/libjvm.dylib
- ./hotspot/gtest/server/libjvm.dylib
- "
- STRIP_TESTS_BEFORE_COMPARE="true"
-fi
diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk
index 628f385572829..ba502a5612870 100644
--- a/make/test/BuildMicrobenchmark.gmk
+++ b/make/test/BuildMicrobenchmark.gmk
@@ -107,6 +107,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
--add-exports java.base/sun.invoke.util=ALL-UNNAMED \
--add-exports java.base/sun.security.util=ALL-UNNAMED \
--enable-preview \
+ -XDsuppressNotes \
-processor org.openjdk.jmh.generators.BenchmarkProcessor, \
JAVA_FLAGS := \
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
diff --git a/src/demo/share/java2d/J2DBench/Makefile b/src/demo/share/java2d/J2DBench/Makefile
index 04b0818a2c35b..edc4494e131de 100644
--- a/src/demo/share/java2d/J2DBench/Makefile
+++ b/src/demo/share/java2d/J2DBench/Makefile
@@ -29,6 +29,23 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
+
+ifndef SOURCE
+export SOURCE := 7
+endif
+ifndef TARGET
+export TARGET := 7
+endif
+ifndef JAVAC
+export JAVAC := javac
+endif
+ifndef JAVA
+export JAVA := java
+endif
+ifndef JAR
+export JAR := jar
+endif
+
SOURCEPATH=src
CLASSES=build
DIST=dist
@@ -80,18 +97,18 @@ SCM_DIRs = .hg .svn CVS RCS SCCS Codemgr_wsdata deleted_files
all: mkdirs J2DBench.jar J2DAnalyzer.jar
run: mkdirs J2DBench.jar
- java -jar $(DIST)/J2DBench.jar
+ $(JAVA) -jar $(DIST)/J2DBench.jar
analyze: mkdirs J2DAnalyzer.jar
- java -jar $(DIST)/J2DAnalyzer.jar
+ $(JAVA) -jar $(DIST)/J2DAnalyzer.jar
J2DBench.jar: \
$(J2DBENCH_CLASSES) $(J2DBENCH_RESOURCES) \
$(CLASSES)/j2dbench.manifest
- jar cvmf $(CLASSES)/j2dbench.manifest $(DIST)/J2DBench.jar -C $(CLASSES) j2dbench
+ $(JAR) cvmf $(CLASSES)/j2dbench.manifest $(DIST)/J2DBench.jar -C $(CLASSES) j2dbench
J2DAnalyzer.jar: $(J2DANALYZER_CLASSES) $(CLASSES)/j2danalyzer.manifest
- jar cvmf $(CLASSES)/j2danalyzer.manifest \
+ $(JAR) cvmf $(CLASSES)/j2danalyzer.manifest \
$(DIST)/J2DAnalyzer.jar -C $(CLASSES) j2dbench/report
$(CLASSES)/j2dbench/tests/iio/images: $(RESOURCES)/images
@@ -120,7 +137,7 @@ $(CLASSES):
mkdirs: $(DIST) $(CLASSES)
$(CLASSES)/j2dbench/%.class: $(SOURCEPATH)/j2dbench/%.java
- javac -g:none -source 1.7 -target 1.7 -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
+ $(JAVAC) -g:none -source $(SOURCE) -target $(TARGET) -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
clean:
rm -rf $(CLASSES)
diff --git a/src/demo/share/java2d/J2DBench/README b/src/demo/share/java2d/J2DBench/README
index 3b9f25c13f14e..513c984a6555f 100644
--- a/src/demo/share/java2d/J2DBench/README
+++ b/src/demo/share/java2d/J2DBench/README
@@ -23,6 +23,9 @@ The benchmark requires at least jdk1.4 to compile and run. Note that
source/target is set to 1.7 in the makefile and build.xml, because of
support in jdk 14 compiler. To check compatibility with jdk1.4 you can
use "-source 1.4 -target 1.4" options and jdk1.7.
+Yo can use TARGET/SOURCE of makefile and -Dtarget/surce to set them up for your convinience.
+Similarly you can set JAVA/JAVAC/JAR and -Djava/javac to select diffferent java/javac then is on yoru PATH
+Unluckily in ant, you can not set jar, but ant should honor JAVA_HOME
-----------------------------------------------------------------------
How To Compile
diff --git a/src/demo/share/java2d/J2DBench/build.xml b/src/demo/share/java2d/J2DBench/build.xml
index 7b202946cf145..415c315899eac 100644
--- a/src/demo/share/java2d/J2DBench/build.xml
+++ b/src/demo/share/java2d/J2DBench/build.xml
@@ -39,6 +39,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -49,13 +70,14 @@
-
+
@@ -64,6 +86,7 @@
description="run J2DAnalyzer" >
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index f637648b2279c..7b94897eaad61 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -1237,7 +1237,7 @@ source %{
// r27 is not allocatable when compressed oops is on and heapbase is not
// zero, compressed klass pointers doesn't use r27 after JDK-8234794
- if (UseCompressedOops && (CompressedOops::ptrs_base() != NULL)) {
+ if (UseCompressedOops && (CompressedOops::ptrs_base() != nullptr)) {
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
@@ -1581,7 +1581,7 @@ bool needs_releasing_store(const Node *n)
{
// assert n->is_Store();
StoreNode *st = n->as_Store();
- return st->trailing_membar() != NULL;
+ return st->trailing_membar() != nullptr;
}
// predicate controlling translation of CAS
@@ -1593,9 +1593,9 @@ bool needs_acquiring_load_exclusive(const Node *n)
assert(is_CAS(n->Opcode(), true), "expecting a compare and swap");
LoadStoreNode* ldst = n->as_LoadStore();
if (is_CAS(n->Opcode(), false)) {
- assert(ldst->trailing_membar() != NULL, "expected trailing membar");
+ assert(ldst->trailing_membar() != nullptr, "expected trailing membar");
} else {
- return ldst->trailing_membar() != NULL;
+ return ldst->trailing_membar() != nullptr;
}
// so we can just return true here
@@ -1734,7 +1734,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print("mov rscratch1, #%d\n\t", framesize - 2 * wordSize);
st->print("sub sp, sp, rscratch1");
}
- if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (C->stub_function() == nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
st->print("\n\t");
st->print("ldr rscratch1, [guard]\n\t");
st->print("dmb ishld\n\t");
@@ -1783,9 +1783,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ build_frame(framesize);
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
- if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
// Dummy labels for just measuring the code size
Label dummy_slow_path;
Label dummy_continuation;
@@ -2153,12 +2153,12 @@ void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
if (!ra_)
st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx);
else
- implementation(NULL, ra_, false, st);
+ implementation(nullptr, ra_, false, st);
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation(&cbuf, ra_, false, NULL);
+ implementation(&cbuf, ra_, false, nullptr);
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
@@ -2205,14 +2205,14 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
st->print_cr("# MachUEPNode");
if (UseCompressedClassPointers) {
- st->print_cr("\tldrw rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- if (CompressedKlassPointers::shift() != 0) {
- st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
- }
+ st->print_cr("\tldrw rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldrw r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
+ st->print_cr("\tcmpw rscratch1, r10");
} else {
- st->print_cr("\tldr rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldr rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldr r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
+ st->print_cr("\tcmp rscratch1, r10");
}
- st->print_cr("\tcmp r0, rscratch1\t # Inline cache check");
st->print_cr("\tbne, SharedRuntime::_ic_miss_stub");
}
#endif
@@ -2221,14 +2221,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
-
- __ cmp_klass(j_rarg0, rscratch2, rscratch1);
- Label skip;
- // TODO
- // can we avoid this skip and still use a reloc?
- __ br(Assembler::EQ, skip);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(skip);
+ __ ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
@@ -2249,7 +2242,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf)
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -2267,7 +2260,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf)
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -2377,7 +2370,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return MIN2(size, max_size);
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
return Matcher::max_vector_size(bt);
}
@@ -2410,7 +2403,7 @@ MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* generic_opnd,
case Op_VecX: return new vecXOper();
}
ShouldNotReachHere();
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -2582,8 +2575,8 @@ Assembler::Condition to_assembler_cond(BoolTest::mask cond) {
}
// Binary src (Replicate con)
-bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
- if (n == NULL || m == NULL) {
+static bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
+ if (n == nullptr || m == nullptr) {
return false;
}
@@ -2623,8 +2616,8 @@ bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
// (XorV src (Replicate m1))
// (XorVMask src (MaskAll m1))
-bool is_vector_bitwise_not_pattern(Node* n, Node* m) {
- if (n != NULL && m != NULL) {
+static bool is_vector_bitwise_not_pattern(Node* n, Node* m) {
+ if (n != nullptr && m != nullptr) {
return (n->Opcode() == Op_XorV || n->Opcode() == Op_XorVMask) &&
VectorNode::is_all_ones_vector(m);
}
@@ -2736,10 +2729,6 @@ typedef void (MacroAssembler::* mem_vector_insn)(FloatRegister Rt,
{
Address addr = mem2address(opcode, base, index, scale, disp);
if (addr.getMode() == Address::base_plus_offset) {
- /* If we get an out-of-range offset it is a bug in the compiler,
- so we assert here. */
- assert(Address::offset_ok_for_immed(addr.offset(), exact_log2(size_in_memory)),
- "c2 compiler bug");
/* Fix up any out-of-range offsets. */
assert_different_registers(rscratch1, base);
assert_different_registers(rscratch1, reg);
@@ -3430,7 +3419,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL || con == (address)1) {
+ if (con == nullptr || con == (address)1) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -3473,7 +3462,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -3492,7 +3481,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -3675,7 +3664,7 @@ encode %{
Label miss;
C2_MacroAssembler _masm(&cbuf);
__ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg,
- NULL, &miss,
+ nullptr, &miss,
/*set_cond_codes:*/ true);
if ($primary) {
__ mov(result_reg, zr);
@@ -3691,7 +3680,7 @@ encode %{
if (!_method) {
// A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap.
call = __ trampoline_call(Address(addr, relocInfo::runtime_call_type));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3705,7 +3694,7 @@ encode %{
RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
: static_call_Relocation::spec(method_index);
call = __ trampoline_call(Address(addr, rspec));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3715,8 +3704,8 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin());
} else {
// Emit stub for static call
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3735,7 +3724,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
int method_index = resolved_method_index(cbuf);
address call = __ ic_call((address)$meth$$method, method_index);
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3764,7 +3753,7 @@ encode %{
CodeBlob *cb = CodeCache::find_blob(entry);
if (cb) {
address call = __ trampoline_call(Address(entry, relocInfo::runtime_call_type));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -4663,7 +4652,7 @@ operand immP()
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immP0()
%{
predicate(n->get_ptr() == 0);
@@ -4795,7 +4784,7 @@ operand immN()
interface(CONST_INTER);
%}
-// Narrow NULL Pointer Immediate
+// Narrow Null Pointer Immediate
operand immN0()
%{
predicate(n->get_narrowcon() == 0);
@@ -7219,7 +7208,7 @@ instruct loadConP0(iRegPNoSp dst, immP0 con)
match(Set dst con);
ins_cost(INSN_COST);
- format %{ "mov $dst, $con\t# NULL ptr" %}
+ format %{ "mov $dst, $con\t# null pointer" %}
ins_encode(aarch64_enc_mov_p0(dst, con));
@@ -7233,7 +7222,7 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con)
match(Set dst con);
ins_cost(INSN_COST);
- format %{ "mov $dst, $con\t# NULL ptr" %}
+ format %{ "mov $dst, $con\t# null pointer" %}
ins_encode(aarch64_enc_mov_p1(dst, con));
@@ -7275,7 +7264,7 @@ instruct loadConN0(iRegNNoSp dst, immN0 con)
match(Set dst con);
ins_cost(INSN_COST);
- format %{ "mov $dst, $con\t# compressed NULL ptr" %}
+ format %{ "mov $dst, $con\t# compressed null pointer" %}
ins_encode(aarch64_enc_mov_n0(dst, con));
@@ -15256,7 +15245,7 @@ instruct clearArray_reg_reg(iRegL_R11 cnt, iRegP_R10 base, Universe dummy, rFlag
ins_encode %{
address tpc = __ zero_words($base$$Register, $cnt$$Register);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -15277,7 +15266,7 @@ instruct clearArray_imm_reg(immL cnt, iRegP_R10 base, iRegL_R11 temp, Universe d
ins_encode %{
address tpc = __ zero_words($base$$Register, (uint64_t)$cnt$$constant);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -16440,13 +16429,12 @@ instruct branchLoopEnd(cmpOp cmp, rFlagsReg cr, label lbl)
instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);
- // TODO
- // identify correct cost
ins_cost(5 * INSN_COST);
- format %{ "fastlock $object,$box\t! kills $tmp,$tmp2" %}
+ format %{ "fastlock $object,$box\t! kills $tmp,$tmp2,$tmp3" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register, $tmp3$$Register);
@@ -16457,6 +16445,7 @@ instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegP
instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
%{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, TEMP tmp2);
@@ -16470,6 +16459,37 @@ instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRe
ins_pipe(pipe_serial);
%}
+instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
+%{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP tmp, TEMP tmp2);
+
+ ins_cost(5 * INSN_COST);
+ format %{ "fastlock $object,$box\t! kills $tmp,$tmp2" %}
+
+ ins_encode %{
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
+ %}
+
+ ins_pipe(pipe_serial);
+%}
+
+instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
+%{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object box));
+ effect(TEMP tmp, TEMP tmp2);
+
+ ins_cost(5 * INSN_COST);
+ format %{ "fastunlock $object,$box\t! kills $tmp, $tmp2" %}
+
+ ins_encode %{
+ __ fast_unlock_lightweight($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
+ %}
+
+ ins_pipe(pipe_serial);
+%}
// ============================================================================
// Safepoint Instructions
@@ -17104,23 +17124,7 @@ instruct string_equalsL(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ string_equals($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 1);
- %}
- ins_pipe(pipe_class_memory);
-%}
-
-instruct string_equalsU(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
- iRegI_R0 result, rFlagsReg cr)
-%{
- predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
-
- format %{ "String Equals $str1,$str2,$cnt -> $result" %}
- ins_encode %{
- // Count is in 8-bit bytes; non-Compact chars are 16 bits.
- __ string_equals($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 2);
+ $result$$Register, $cnt$$Register);
%}
ins_pipe(pipe_class_memory);
%}
@@ -17142,7 +17146,7 @@ instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
address tpc = __ arrays_equals($ary1$$Register, $ary2$$Register,
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
$result$$Register, $tmp$$Register, 1);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -17167,7 +17171,7 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
address tpc = __ arrays_equals($ary1$$Register, $ary2$$Register,
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
$result$$Register, $tmp$$Register, 2);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -17182,7 +17186,7 @@ instruct count_positives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg
format %{ "count positives byte[] $ary1,$len -> $result" %}
ins_encode %{
address tpc = __ count_positives($ary1$$Register, $len$$Register, $result$$Register);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -17225,7 +17229,7 @@ instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len
address tpc = __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
$vtmp0$$FloatRegister, $vtmp1$$FloatRegister,
$vtmp2$$FloatRegister, $tmp$$Register);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad
index 210efa0b760cd..d611c14f403ab 100644
--- a/src/hotspot/cpu/aarch64/aarch64_vector.ad
+++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2020, 2023, Arm Limited. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -126,7 +126,7 @@ source %{
}
}
- bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+ bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
if (UseSVE == 0) {
// These operations are not profitable to be vectorized on NEON, because no direct
// NEON instructions support them. But the match rule support for them is profitable for
diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
index 3f4ed020f55c5..5c4e13d432f51 100644
--- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
+++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2020, 2023, Arm Limited. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -116,7 +116,7 @@ source %{
}
}
- bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+ bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
if (UseSVE == 0) {
// These operations are not profitable to be vectorized on NEON, because no direct
// NEON instructions support them. But the match rule support for them is profitable for
diff --git a/src/hotspot/cpu/aarch64/ad_encode.m4 b/src/hotspot/cpu/aarch64/ad_encode.m4
index e6c87cf5b0559..4897998d8709e 100644
--- a/src/hotspot/cpu/aarch64/ad_encode.m4
+++ b/src/hotspot/cpu/aarch64/ad_encode.m4
@@ -19,7 +19,7 @@ dnl Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
dnl or visit www.oracle.com if you need additional information or have any
dnl questions.
dnl
-dnl
+dnl
dnl Process this file with m4 ad_encode.m4 to generate the load/store
dnl patterns used in aarch64.ad.
dnl
@@ -90,4 +90,3 @@ STORE(vRegD,strd,Float,,8)
loadStore(_masm, &MacroAssembler::strb, zr, $mem->opcode(),
as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp, 1);
%}
-
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.cpp b/src/hotspot/cpu/aarch64/assembler_aarch64.cpp
index afeb19e906e99..76f88764416e3 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -118,10 +118,6 @@ extern "C" {
else
Disassembler::decode((address)start, (address)start + len);
}
-
- JNIEXPORT void das1(uintptr_t insn) {
- das(insn, 1);
- }
}
#define __ as->
@@ -187,6 +183,26 @@ void Address::lea(MacroAssembler *as, Register r) const {
zrf(Rd, 0);
}
+// This encoding is similar (but not quite identical) to the encoding used
+// by literal ld/st. see JDK-8324123.
+// PRFM does not support writeback or pre/post index.
+void Assembler::prfm(const Address &adr, prfop pfop) {
+ Address::mode mode = adr.getMode();
+ // PRFM does not support pre/post index
+ guarantee((mode != Address::pre) && (mode != Address::post), "prfm does not support pre/post indexing");
+ if (mode == Address::literal) {
+ starti;
+ f(0b11, 31, 30), f(0b011, 29, 27), f(0b000, 26, 24);
+ f(pfop, 4, 0);
+ int64_t offset = (adr.target() - pc()) >> 2;
+ sf(offset, 23, 5);
+ } else {
+ assert((mode == Address::base_plus_offset)
+ || (mode == Address::base_plus_offset_reg), "must be base_plus_offset/base_plus_offset_reg");
+ ld_st2(as_Register(pfop), adr, 0b11, 0b10);
+ }
+}
+
// An "all-purpose" add/subtract immediate, per ARM documentation:
// A "programmer-friendly" assembler may accept a negative immediate
// between -(2^24 -1) and -1 inclusive, causing it to convert a
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
index 187c1209303a3..9c05c36706d50 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
@@ -797,6 +797,8 @@ class Assembler : public AbstractAssembler {
void adrp(Register Rd, const Address &dest, uint64_t &offset) = delete;
+ void prfm(const Address &adr, prfop pfop = PLDL1KEEP);
+
#undef INSN
void add_sub_immediate(Instruction_aarch64 ¤t_insn, Register Rd, Register Rn,
@@ -1574,17 +1576,6 @@ class Assembler : public AbstractAssembler {
#undef INSN
-#define INSN(NAME, size, op) \
- void NAME(const Address &adr, prfop pfop = PLDL1KEEP) { \
- ld_st2(as_Register(pfop), adr, size, op); \
- }
-
- INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with
- // writeback modes, but the assembler
- // doesn't enfore that.
-
-#undef INSN
-
#define INSN(NAME, size, op) \
void NAME(FloatRegister Rt, const Address &adr) { \
ld_st2(as_Register(Rt), adr, size, op, 1); \
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
index b83d618506298..9bd8c6b8e9f88 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
@@ -53,7 +53,6 @@
#endif
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = rscratch2; // where the IC klass is cached
const Register SYNC_header = r0; // synchronization header
const Register SHIFT_count = r0; // where count for shift operations must be
@@ -293,27 +292,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- int start_offset = __ offset();
- __ inline_cache_check(receiver, ic_klass);
-
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- Label dont;
- __ br(Assembler::EQ, dont);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // We align the verified entry point unless the method body
- // (including its inline cache check) will fit in a single 64-byte
- // icache line.
- if (! method()->is_accessor() || __ offset() - start_offset > 4 * 4) {
- // force alignment after the cache check.
- __ align(CodeEntryAlignment);
- }
-
- __ bind(dont);
- return start_offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -1230,7 +1209,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
len,
tmp1,
tmp2,
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
array_element_size(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
@@ -2042,7 +2021,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
__ emit_static_call_stub();
- assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
+ assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size()
<= call_stub_size(), "stub too big");
__ end_a_stub();
}
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
index 43ec189255f9c..ef1b5fe2703e6 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
@@ -71,8 +71,8 @@ friend class ArrayCopyStub;
void deoptimize_trap(CodeEmitInfo *info);
enum {
- // call stub: CompiledStaticCall::to_interp_stub_size() +
- // CompiledStaticCall::to_trampoline_stub_size()
+ // call stub: CompiledDirectCall::to_interp_stub_size() +
+ // CompiledDirectCall::to_trampoline_stub_size()
_call_stub_size = 13 * NativeInstruction::instruction_size,
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
_deopt_handler_size = 7 * NativeInstruction::instruction_size
diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
index 952e060ed212a..fd31d2dde5be1 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -831,18 +831,12 @@ void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
}
break;
case vmIntrinsics::_dlog:
- if (StubRoutines::dlog() != nullptr) {
- __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
- } else {
- __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
- }
+ // Math.log intrinsic is not implemented on AArch64 (see JDK-8210858),
+ // but we can still call the shared runtime.
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
break;
case vmIntrinsics::_dlog10:
- if (StubRoutines::dlog10() != nullptr) {
- __ call_runtime_leaf(StubRoutines::dlog10(), getThreadTemp(), result_reg, cc->args());
- } else {
- __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), getThreadTemp(), result_reg, cc->args());
- }
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), getThreadTemp(), result_reg, cc->args());
break;
case vmIntrinsics::_dpow:
if (StubRoutines::dpow() != nullptr) {
diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
index d3a746178f14e..e48d64d90696c 100644
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -80,12 +80,12 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
br(Assembler::NE, slow_case);
}
- // Load object header
- ldr(hdr, Address(obj, hdr_offset));
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(obj, hdr, temp, rscratch2, slow_case);
} else if (LockingMode == LM_LEGACY) {
Label done;
+ // Load object header
+ ldr(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
orr(hdr, hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
@@ -144,11 +144,6 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
- ldr(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
- // We cannot use tbnz here, the target might be too far away and cannot
- // be encoded.
- tst(hdr, markWord::monitor_value);
- br(Assembler::NE, slow_case);
lightweight_unlock(obj, hdr, temp, rscratch2, slow_case);
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
@@ -193,6 +188,12 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
if (len->is_valid()) {
strw(len, Address(obj, arrayOopDesc::length_offset_in_bytes()));
+ int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
+ if (!is_aligned(base_offset, BytesPerWord)) {
+ assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
+ // Clear gap/first 4 bytes following the length field.
+ strw(zr, Address(obj, base_offset));
+ }
} else if (UseCompressedClassPointers) {
store_klass_gap(obj, zr);
}
@@ -271,7 +272,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
verify_oop(obj);
}
-void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, int f, Register klass, Label& slow_case) {
+void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, int f, Register klass, Label& slow_case) {
assert_different_registers(obj, len, t1, t2, klass);
// determine alignment mask
@@ -284,7 +285,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
const Register arr_size = t2; // okay to be the same
// align object end
- mov(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask);
+ mov(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask);
add(arr_size, arr_size, len, ext::uxtw, f);
andr(arr_size, arr_size, ~MinObjAlignmentInBytesMask);
@@ -292,8 +293,11 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
initialize_header(obj, klass, len, t1, t2);
+ // Align-up to word boundary, because we clear the 4 bytes potentially
+ // following the length field in initialize_header().
+ int base_offset = align_up(base_offset_in_bytes, BytesPerWord);
// clear rest of allocated space
- initialize_body(obj, arr_size, header_size * BytesPerWord, t1, t2);
+ initialize_body(obj, arr_size, base_offset, t1, t2);
if (Compilation::current()->bailed_out()) {
return;
}
@@ -308,17 +312,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
verify_oop(obj);
}
-
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
-
- cmp_klass(receiver, iCache, rscratch1);
-}
-
-
void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp
index 4aa6206aa6073..d210c21d12b8f 100644
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -100,7 +100,7 @@ using MacroAssembler::null_check;
// header_size: size of object header in words
// f : element scale factor
// slow_case : exit to slow case implementation if fast allocation fails
- void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, int f, Register klass, Label& slow_case);
+ void allocate_array(Register obj, Register len, Register t, Register t2, int base_offset_in_bytes, int f, Register klass, Label& slow_case);
int rsp_offset() const { return _rsp_offset; }
void set_rsp_offset(int n) { _rsp_offset = n; }
diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
index d2f4744a04914..63a32e714e365 100644
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
@@ -38,7 +38,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_aarch64.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_aarch64.hpp"
diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
index 7b9784ec47a24..7e3ceb1f02029 100644
--- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, 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
@@ -32,6 +32,7 @@
#include "opto/output.hpp"
#include "opto/subnode.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/globalDefinitions.hpp"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -55,6 +56,7 @@ void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register
Label object_has_monitor;
Label count, no_count;
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr);
// Load markWord from object into displaced_header.
@@ -73,7 +75,8 @@ void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
b(cont);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Set tmp to be (markWord of object | UNLOCK_VALUE).
orr(tmp, disp_hdr, markWord::unlocked_value);
@@ -102,31 +105,26 @@ void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register
ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result
str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
b(cont);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- lightweight_lock(oop, disp_hdr, tmp, tmp3Reg, no_count);
- b(count);
}
// Handle existing monitor.
bind(object_has_monitor);
- // The object's monitor m is unlocked iff m->owner == NULL,
+ // The object's monitor m is unlocked iff m->owner == nullptr,
// otherwise m->owner may contain a thread or a stack address.
//
- // Try to CAS m->owner from NULL to current thread.
+ // Try to CAS m->owner from null to current thread.
add(tmp, disp_hdr, (in_bytes(ObjectMonitor::owner_offset())-markWord::monitor_value));
cmpxchg(tmp, zr, rthread, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, tmp3Reg); // Sets flags for result
- if (LockingMode != LM_LIGHTWEIGHT) {
- // Store a non-null value into the box to avoid looking like a re-entrant
- // lock. The fast-path monitor unlock code checks for
- // markWord::monitor_value so use markWord::unused_mark which has the
- // relevant bit set, and also matches ObjectSynchronizer::enter.
- mov(tmp, (address)markWord::unused_mark().value());
- str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- }
+ // Store a non-null value into the box to avoid looking like a re-entrant
+ // lock. The fast-path monitor unlock code checks for
+ // markWord::monitor_value so use markWord::unused_mark which has the
+ // relevant bit set, and also matches ObjectSynchronizer::enter.
+ mov(tmp, (address)markWord::unused_mark().value());
+ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+
br(Assembler::EQ, cont); // CAS success means locking succeeded
cmp(tmp3Reg, rthread);
@@ -157,6 +155,7 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe
Label object_has_monitor;
Label count, no_count;
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr);
if (LockingMode == LM_LEGACY) {
@@ -175,7 +174,8 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
b(cont);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is is true if we
// see the stack address of the basicLock in the markWord of the
// object.
@@ -183,10 +183,6 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe
cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
/*release*/ true, /*weak*/ false, tmp);
b(cont);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- lightweight_unlock(oop, tmp, box, disp_hdr, no_count);
- b(count);
}
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
@@ -196,19 +192,6 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
add(tmp, tmp, -(int)markWord::monitor_value); // monitor
- if (LockingMode == LM_LIGHTWEIGHT) {
- // If the owner is anonymous, we need to fix it -- in an outline stub.
- Register tmp2 = disp_hdr;
- ldr(tmp2, Address(tmp, ObjectMonitor::owner_offset()));
- // We cannot use tbnz here, the target might be too far away and cannot
- // be encoded.
- tst(tmp2, (uint64_t)ObjectMonitor::ANONYMOUS_OWNER);
- C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2);
- Compile::current()->output()->add_stub(stub);
- br(Assembler::NE, stub->entry());
- bind(stub->continuation());
- }
-
ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
Label notRecursive;
@@ -241,6 +224,262 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe
bind(no_count);
}
+void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register t1,
+ Register t2, Register t3) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert_different_registers(obj, t1, t2, t3);
+
+ // Handle inflated monitor.
+ Label inflated;
+ // Finish fast lock successfully. MUST branch to with flag == EQ
+ Label locked;
+ // Finish fast lock unsuccessfully. MUST branch to with flag == NE
+ Label slow_path;
+
+ if (DiagnoseSyncOnValueBasedClasses != 0) {
+ load_klass(t1, obj);
+ ldrw(t1, Address(t1, Klass::access_flags_offset()));
+ tstw(t1, JVM_ACC_IS_VALUE_BASED_CLASS);
+ br(Assembler::NE, slow_path);
+ }
+
+ const Register t1_mark = t1;
+
+ { // Lightweight locking
+
+ // Push lock to the lock stack and finish successfully. MUST branch to with flag == EQ
+ Label push;
+
+ const Register t2_top = t2;
+ const Register t3_t = t3;
+
+ // Check if lock-stack is full.
+ ldrw(t2_top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ cmpw(t2_top, (unsigned)LockStack::end_offset() - 1);
+ br(Assembler::GT, slow_path);
+
+ // Check if recursive.
+ subw(t3_t, t2_top, oopSize);
+ ldr(t3_t, Address(rthread, t3_t));
+ cmp(obj, t3_t);
+ br(Assembler::EQ, push);
+
+ // Relaxed normal load to check for monitor. Optimization for monitor case.
+ ldr(t1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ tbnz(t1_mark, exact_log2(markWord::monitor_value), inflated);
+
+ // Not inflated
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea");
+
+ // Try to lock. Transition lock-bits 0b01 => 0b00
+ orr(t1_mark, t1_mark, markWord::unlocked_value);
+ eor(t3_t, t1_mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword,
+ /*acquire*/ true, /*release*/ false, /*weak*/ false, noreg);
+ br(Assembler::NE, slow_path);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ str(obj, Address(rthread, t2_top));
+ addw(t2_top, t2_top, oopSize);
+ strw(t2_top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ b(locked);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated);
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register t1_tagged_monitor = t1_mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+ const Register t2_owner_addr = t2;
+ const Register t3_owner = t3;
+
+ // Compute owner address.
+ lea(t2_owner_addr, Address(t1_tagged_monitor, (in_bytes(ObjectMonitor::owner_offset()) - monitor_tag)));
+
+ // CAS owner (null => current thread).
+ cmpxchg(t2_owner_addr, zr, rthread, Assembler::xword, /*acquire*/ true,
+ /*release*/ false, /*weak*/ false, t3_owner);
+ br(Assembler::EQ, locked);
+
+ // Check if recursive.
+ cmp(t3_owner, rthread);
+ br(Assembler::NE, slow_path);
+
+ // Recursive.
+ increment(Address(t1_tagged_monitor, in_bytes(ObjectMonitor::recursions_offset()) - monitor_tag), 1);
+ }
+
+ bind(locked);
+ increment(Address(rthread, JavaThread::held_monitor_count_offset()));
+
+#ifdef ASSERT
+ // Check that locked label is reached with Flags == EQ.
+ Label flag_correct;
+ br(Assembler::EQ, flag_correct);
+ stop("Fast Lock Flag != EQ");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with Flags == NE.
+ br(Assembler::NE, flag_correct);
+ stop("Fast Lock Flag != NE");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of Flags (NE vs EQ) to determine the continuation.
+}
+
+void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register t1, Register t2,
+ Register t3) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert_different_registers(obj, t1, t2, t3);
+
+ // Handle inflated monitor.
+ Label inflated, inflated_load_monitor;
+ // Finish fast unlock successfully. MUST branch to with flag == EQ
+ Label unlocked;
+ // Finish fast unlock unsuccessfully. MUST branch to with flag == NE
+ Label slow_path;
+
+ const Register t1_mark = t1;
+ const Register t2_top = t2;
+ const Register t3_t = t3;
+
+ { // Lightweight unlock
+
+ // Check if obj is top of lock-stack.
+ ldrw(t2_top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ subw(t2_top, t2_top, oopSize);
+ ldr(t3_t, Address(rthread, t2_top));
+ cmp(obj, t3_t);
+ // Top of lock stack was not obj. Must be monitor.
+ br(Assembler::NE, inflated_load_monitor);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(str(zr, Address(rthread, t2_top));)
+ strw(t2_top, Address(rthread, JavaThread::lock_stack_top_offset()));
+
+ // Check if recursive.
+ subw(t3_t, t2_top, oopSize);
+ ldr(t3_t, Address(rthread, t3_t));
+ cmp(obj, t3_t);
+ br(Assembler::EQ, unlocked);
+
+ // Not recursive.
+ // Load Mark.
+ ldr(t1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check header for monitor (0b10).
+ tbnz(t1_mark, exact_log2(markWord::monitor_value), inflated);
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
+ orr(t3_t, t1_mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword,
+ /*acquire*/ false, /*release*/ true, /*weak*/ false, noreg);
+ br(Assembler::EQ, unlocked);
+
+ // Compare and exchange failed.
+ // Restore lock-stack and handle the unlock in runtime.
+ DEBUG_ONLY(str(obj, Address(rthread, t2_top));)
+ addw(t2_top, t2_top, oopSize);
+ str(t2_top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ b(slow_path);
+ }
+
+
+ { // Handle inflated monitor.
+ bind(inflated_load_monitor);
+ ldr(t1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+#ifdef ASSERT
+ tbnz(t1_mark, exact_log2(markWord::monitor_value), inflated);
+ stop("Fast Unlock not monitor");
+#endif
+
+ bind(inflated);
+
+#ifdef ASSERT
+ Label check_done;
+ subw(t2_top, t2_top, oopSize);
+ cmpw(t2_top, in_bytes(JavaThread::lock_stack_base_offset()));
+ br(Assembler::LT, check_done);
+ ldr(t3_t, Address(rthread, t2_top));
+ cmp(obj, t3_t);
+ br(Assembler::NE, inflated);
+ stop("Fast Unlock lock on stack");
+ bind(check_done);
+#endif
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register t1_monitor = t1_mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+
+ // Untag the monitor.
+ sub(t1_monitor, t1_mark, monitor_tag);
+
+ const Register t2_recursions = t2;
+ Label not_recursive;
+
+ // Check if recursive.
+ ldr(t2_recursions, Address(t1_monitor, ObjectMonitor::recursions_offset()));
+ cbz(t2_recursions, not_recursive);
+
+ // Recursive unlock.
+ sub(t2_recursions, t2_recursions, 1u);
+ str(t2_recursions, Address(t1_monitor, ObjectMonitor::recursions_offset()));
+ // Set flag == EQ
+ cmp(t2_recursions, t2_recursions);
+ b(unlocked);
+
+ bind(not_recursive);
+
+ Label release;
+ const Register t2_owner_addr = t2;
+
+ // Compute owner address.
+ lea(t2_owner_addr, Address(t1_monitor, ObjectMonitor::owner_offset()));
+
+ // Check if the entry lists are empty.
+ ldr(rscratch1, Address(t1_monitor, ObjectMonitor::EntryList_offset()));
+ ldr(t3_t, Address(t1_monitor, ObjectMonitor::cxq_offset()));
+ orr(rscratch1, rscratch1, t3_t);
+ cmp(rscratch1, zr);
+ br(Assembler::EQ, release);
+
+ // The owner may be anonymous and we removed the last obj entry in
+ // the lock-stack. This loses the information about the owner.
+ // Write the thread to the owner field so the runtime knows the owner.
+ str(rthread, Address(t2_owner_addr));
+ b(slow_path);
+
+ bind(release);
+ // Set owner to null.
+ // Release to satisfy the JMM
+ stlr(zr, t2_owner_addr);
+ }
+
+ bind(unlocked);
+ decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with Flags == EQ.
+ Label flag_correct;
+ br(Assembler::EQ, flag_correct);
+ stop("Fast Unlock Flag != EQ");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with Flags == NE.
+ br(Assembler::NE, flag_correct);
+ stop("Fast Unlock Flag != NE");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of Flags (NE vs EQ) to determine the continuation.
+}
+
// Search for str1 in str2 and return index or -1
// Clobbers: rscratch1, rscratch2, rflags. May also clobber v0-v1, when icnt1==-1.
void C2_MacroAssembler::string_indexof(Register str2, Register str1,
diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
index dfa7d88cb93fe..1481f975020c9 100644
--- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, 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
@@ -36,9 +36,11 @@
public:
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
- // See full description in macroAssembler_aarch64.cpp.
void fast_lock(Register object, Register box, Register tmp, Register tmp2, Register tmp3);
void fast_unlock(Register object, Register box, Register tmp, Register tmp2);
+ // Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file.
+ void fast_lock_lightweight(Register object, Register t1, Register t2, Register t3);
+ void fast_unlock_lightweight(Register object, Register t1, Register t2, Register t3);
void string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
diff --git a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
index c58ff8828bce6..23c08f11d1a8b 100644
--- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -36,7 +35,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
precond(cbuf.stubs()->start() != badAddress);
precond(cbuf.stubs()->end() != badAddress);
@@ -71,11 +70,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return MacroAssembler::static_call_stub_size();
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// Somewhat pessimistically, we count 3 instructions here (although
// there are only two) because we sometimes emit an alignment nop.
// Trampoline stubs are always word aligned.
@@ -83,21 +82,14 @@ int CompiledStaticCall::to_trampoline_stub_size() {
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
@@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -132,7 +124,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
index d035ab21093da..47b6f1f2f386a 100644
--- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
- * Copyright (c) 2023, 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
@@ -58,7 +58,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
0x7ffc, 0x7ffe, 0x7fff
};
static constexpr int num_immediates = sizeof(immediates) / sizeof(immediates[0]);
- const int start_index = aslr ? os::random() : 0;
+ const int start_index = aslr ? os::next_random((int)os::javaTimeNanos()) : 0;
constexpr int max_tries = 64;
for (int ntry = 0; result == nullptr && ntry < max_tries; ntry ++) {
// As in os::attempt_reserve_memory_between, we alternate between higher and lower
diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp
index c5b2ff8a4c01c..8d0fa8895d15c 100644
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -678,7 +678,7 @@ static void printbc(Method *m, intptr_t bcx) {
printf("%s : %s ==> %s\n", m->name_and_sig_as_C_string(), buf, name);
}
-void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) {
+static void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) {
if (! fp)
return;
diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp
index 42081d422c869..427987da97141 100644
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp
@@ -28,8 +28,8 @@
#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/javaThread.hpp"
diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp
index b26eaa4bfcdd8..293cc6eb0d0c6 100644
--- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp
@@ -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.
* Copyright (c) 2015, 2019, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -117,7 +117,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
"Use prfm hint with specified distance in compiled code." \
"Value -1 means off.") \
range(-1, 4096) \
- product(ccstr, OnSpinWaitInst, "none", DIAGNOSTIC, \
+ product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \
"The instruction to use to implement " \
"java.lang.Thread.onSpinWait()." \
"Options: none, nop, isb, yield.") \
diff --git a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp
deleted file mode 100644
index bd8cfc42600e2..0000000000000
--- a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_aarch64.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return (MacroAssembler::far_branches() ? 6 : 4) * NativeInstruction::instruction_size;
-}
-
-#define __ masm->
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
- // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop");
-
- address start = __ pc();
- Label l;
- __ ldr(rscratch2, l);
- int jump_code_size = __ far_jump(ExternalAddress(entry_point));
- // IC stub code size is not expected to vary depending on target address.
- // We use NOPs to make the [ldr + far_jump + nops + int64] stub size equal to ic_stub_code_size.
- for (int size = NativeInstruction::instruction_size + jump_code_size + 8;
- size < ic_stub_code_size(); size += NativeInstruction::instruction_size) {
- __ nop();
- }
- __ bind(l);
- assert((uintptr_t)__ pc() % wordSize == 0, "");
- __ emit_int64((int64_t)cached_value);
- // Only need to invalidate the 1st two instructions - not the whole ic stub
- ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
- assert(__ pc() - start == ic_stub_code_size(), "must be");
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(code_begin + 4);
- return jump->jump_destination();
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // The word containing the cached value is at the end of this IC buffer
- uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize);
- void* o = (void*)*p;
- return o;
-}
diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
index 3d87fde2b5bcd..7caafc19fbd31 100644
--- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -53,7 +53,7 @@ struct li_pair {
static struct li_pair InverseLITable[LI_TABLE_SIZE];
// comparator to sort entries in the inverse table
-int compare_immediate_pair(const void *i1, const void *i2)
+static int compare_immediate_pair(const void *i1, const void *i2)
{
struct li_pair *li1 = (struct li_pair *)i1;
struct li_pair *li2 = (struct li_pair *)i2;
@@ -142,7 +142,7 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo)
// result
// a bit string containing count copies of input bit string
//
-uint64_t replicate(uint64_t bits, int nbits, int count)
+static uint64_t replicate(uint64_t bits, int nbits, int count)
{
assert(count > 0, "must be");
assert(nbits > 0, "must be");
@@ -231,8 +231,8 @@ uint64_t replicate(uint64_t bits, int nbits, int count)
// For historical reasons the implementation of this function is much
// more convoluted than is really necessary.
-int expandLogicalImmediate(uint32_t immN, uint32_t immr,
- uint32_t imms, uint64_t &bimm)
+static int expandLogicalImmediate(uint32_t immN, uint32_t immr,
+ uint32_t imms, uint64_t &bimm)
{
int len; // ought to be <= 6
uint32_t levels; // 6 bits
@@ -446,4 +446,3 @@ uint32_t encoding_for_fp_immediate(float immediate)
res = (s << 7) | (r << 4) | f;
return res;
}
-
diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
index 69a61e281f352..b5625b7fc6134 100644
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -701,7 +701,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg)
}
if (LockingMode == LM_LIGHTWEIGHT) {
- ldr(tmp, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
lightweight_lock(obj_reg, tmp, tmp2, tmp3, slow_case);
b(count);
} else if (LockingMode == LM_LEGACY) {
@@ -818,22 +817,6 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg)
if (LockingMode == LM_LIGHTWEIGHT) {
Label slow_case;
-
- // Check for non-symmetric locking. This is allowed by the spec and the interpreter
- // must handle it.
- Register tmp = rscratch1;
- // First check for lock-stack underflow.
- ldrw(tmp, Address(rthread, JavaThread::lock_stack_top_offset()));
- cmpw(tmp, (unsigned)LockStack::start_offset());
- br(Assembler::LE, slow_case);
- // Then check if the top of the lock-stack matches the unlocked object.
- subw(tmp, tmp, oopSize);
- ldr(tmp, Address(rthread, tmp));
- cmpoop(tmp, obj_reg);
- br(Assembler::NE, slow_case);
-
- ldr(header_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- tbnz(header_reg, exact_log2(markWord::monitor_value), slow_case);
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
b(count);
bind(slow_case);
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index a3c560b28d3cf..369a50cc01fcc 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -23,12 +23,11 @@
*
*/
-#include
-
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "ci/ciEnv.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/disassembler.hpp"
#include "compiler/oopMap.hpp"
@@ -55,6 +54,7 @@
#include "runtime/jniHandles.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
#ifdef COMPILER1
#include "c1/c1_LIRAssembler.hpp"
@@ -66,6 +66,8 @@
#include "opto/output.hpp"
#endif
+#include
+
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
#else
@@ -390,13 +392,13 @@ static bool offset_for(uint32_t insn1, uint32_t insn2, ptrdiff_t &byte_offset) {
return false;
}
-class Decoder : public RelocActions {
- virtual reloc_insn adrpMem() { return &Decoder::adrpMem_impl; }
- virtual reloc_insn adrpAdd() { return &Decoder::adrpAdd_impl; }
- virtual reloc_insn adrpMovk() { return &Decoder::adrpMovk_impl; }
+class AArch64Decoder : public RelocActions {
+ virtual reloc_insn adrpMem() { return &AArch64Decoder::adrpMem_impl; }
+ virtual reloc_insn adrpAdd() { return &AArch64Decoder::adrpAdd_impl; }
+ virtual reloc_insn adrpMovk() { return &AArch64Decoder::adrpMovk_impl; }
public:
- Decoder(address insn_addr, uint32_t insn) : RelocActions(insn_addr, insn) {}
+ AArch64Decoder(address insn_addr, uint32_t insn) : RelocActions(insn_addr, insn) {}
virtual int loadStore(address insn_addr, address &target) {
intptr_t offset = Instruction_aarch64::sextract(_insn, 23, 5);
@@ -492,7 +494,7 @@ class Decoder : public RelocActions {
};
address MacroAssembler::target_addr_for_insn(address insn_addr, uint32_t insn) {
- Decoder decoder(insn_addr, insn);
+ AArch64Decoder decoder(insn_addr, insn);
address target;
decoder.run(insn_addr, target);
return target;
@@ -965,7 +967,7 @@ int MacroAssembler::max_trampoline_stub_size() {
}
void MacroAssembler::emit_static_call_stub() {
- // CompiledDirectStaticCall::set_to_interpreted knows the
+ // CompiledDirectCall::set_to_interpreted knows the
// exact layout of this stub.
isb();
@@ -995,10 +997,51 @@ address MacroAssembler::ic_call(address entry, jint method_index) {
// address const_ptr = long_constant((jlong)Universe::non_oop_word());
// uintptr_t offset;
// ldr_constant(rscratch2, const_ptr);
- movptr(rscratch2, (uintptr_t)Universe::non_oop_word());
+ movptr(rscratch2, (intptr_t)Universe::non_oop_word());
return trampoline_call(Address(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ if (target_needs_far_branch(CAST_FROM_FN_PTR(address, SharedRuntime::get_ic_miss_stub()))) {
+ return NativeInstruction::instruction_size * 7;
+ } else {
+ return NativeInstruction::instruction_size * 5;
+ }
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = j_rarg0;
+ Register data = rscratch2;
+ Register tmp1 = rscratch1;
+ Register tmp2 = r10;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ ldrw(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ cmpw(tmp1, tmp2);
+ } else {
+ ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldr(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ cmp(tmp1, tmp2);
+ }
+
+ Label dont;
+ br(Assembler::EQ, dont);
+ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ bind(dont);
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
+}
+
// Implementation of call_VM versions
void MacroAssembler::call_VM(Register oop_result,
@@ -1100,7 +1143,14 @@ void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thr
}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) nop();
+ align(modulus, offset());
+}
+
+// Ensure that the code at target bytes offset from the current offset() is aligned
+// according to modulus.
+void MacroAssembler::align(int modulus, int target) {
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) nop();
}
void MacroAssembler::post_call_nop() {
@@ -1197,7 +1247,7 @@ 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
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - 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.
@@ -4258,108 +4308,117 @@ void MacroAssembler::kernel_crc32_common_fold_using_crypto_pmull(Register crc, R
}
add(table, table, table_offset);
+ // Registers v0..v7 are used as data registers.
+ // Registers v16..v31 are used as tmp registers.
sub(buf, buf, 0x10);
- ldrq(v1, Address(buf, 0x10));
- ldrq(v2, Address(buf, 0x20));
- ldrq(v3, Address(buf, 0x30));
- ldrq(v4, Address(buf, 0x40));
- ldrq(v5, Address(buf, 0x50));
- ldrq(v6, Address(buf, 0x60));
- ldrq(v7, Address(buf, 0x70));
- ldrq(v8, Address(pre(buf, 0x80)));
-
- movi(v25, T4S, 0);
- mov(v25, S, 0, crc);
- eor(v1, T16B, v1, v25);
-
- ldrq(v0, Address(table));
+ ldrq(v0, Address(buf, 0x10));
+ ldrq(v1, Address(buf, 0x20));
+ ldrq(v2, Address(buf, 0x30));
+ ldrq(v3, Address(buf, 0x40));
+ ldrq(v4, Address(buf, 0x50));
+ ldrq(v5, Address(buf, 0x60));
+ ldrq(v6, Address(buf, 0x70));
+ ldrq(v7, Address(pre(buf, 0x80)));
+
+ movi(v31, T4S, 0);
+ mov(v31, S, 0, crc);
+ eor(v0, T16B, v0, v31);
+
+ // Register v16 contains constants from the crc table.
+ ldrq(v16, Address(table));
b(CRC_by128_loop);
align(OptoLoopAlignment);
BIND(CRC_by128_loop);
- pmull (v9, T1Q, v1, v0, T1D);
- pmull2(v10, T1Q, v1, v0, T2D);
- ldrq(v1, Address(buf, 0x10));
- eor3(v1, T16B, v9, v10, v1);
-
- pmull (v11, T1Q, v2, v0, T1D);
- pmull2(v12, T1Q, v2, v0, T2D);
- ldrq(v2, Address(buf, 0x20));
- eor3(v2, T16B, v11, v12, v2);
-
- pmull (v13, T1Q, v3, v0, T1D);
- pmull2(v14, T1Q, v3, v0, T2D);
- ldrq(v3, Address(buf, 0x30));
- eor3(v3, T16B, v13, v14, v3);
-
- pmull (v15, T1Q, v4, v0, T1D);
- pmull2(v16, T1Q, v4, v0, T2D);
- ldrq(v4, Address(buf, 0x40));
- eor3(v4, T16B, v15, v16, v4);
-
- pmull (v17, T1Q, v5, v0, T1D);
- pmull2(v18, T1Q, v5, v0, T2D);
- ldrq(v5, Address(buf, 0x50));
- eor3(v5, T16B, v17, v18, v5);
-
- pmull (v19, T1Q, v6, v0, T1D);
- pmull2(v20, T1Q, v6, v0, T2D);
- ldrq(v6, Address(buf, 0x60));
- eor3(v6, T16B, v19, v20, v6);
-
- pmull (v21, T1Q, v7, v0, T1D);
- pmull2(v22, T1Q, v7, v0, T2D);
- ldrq(v7, Address(buf, 0x70));
- eor3(v7, T16B, v21, v22, v7);
-
- pmull (v23, T1Q, v8, v0, T1D);
- pmull2(v24, T1Q, v8, v0, T2D);
- ldrq(v8, Address(pre(buf, 0x80)));
- eor3(v8, T16B, v23, v24, v8);
+ pmull (v17, T1Q, v0, v16, T1D);
+ pmull2(v18, T1Q, v0, v16, T2D);
+ ldrq(v0, Address(buf, 0x10));
+ eor3(v0, T16B, v17, v18, v0);
+
+ pmull (v19, T1Q, v1, v16, T1D);
+ pmull2(v20, T1Q, v1, v16, T2D);
+ ldrq(v1, Address(buf, 0x20));
+ eor3(v1, T16B, v19, v20, v1);
+
+ pmull (v21, T1Q, v2, v16, T1D);
+ pmull2(v22, T1Q, v2, v16, T2D);
+ ldrq(v2, Address(buf, 0x30));
+ eor3(v2, T16B, v21, v22, v2);
+
+ pmull (v23, T1Q, v3, v16, T1D);
+ pmull2(v24, T1Q, v3, v16, T2D);
+ ldrq(v3, Address(buf, 0x40));
+ eor3(v3, T16B, v23, v24, v3);
+
+ pmull (v25, T1Q, v4, v16, T1D);
+ pmull2(v26, T1Q, v4, v16, T2D);
+ ldrq(v4, Address(buf, 0x50));
+ eor3(v4, T16B, v25, v26, v4);
+
+ pmull (v27, T1Q, v5, v16, T1D);
+ pmull2(v28, T1Q, v5, v16, T2D);
+ ldrq(v5, Address(buf, 0x60));
+ eor3(v5, T16B, v27, v28, v5);
+
+ pmull (v29, T1Q, v6, v16, T1D);
+ pmull2(v30, T1Q, v6, v16, T2D);
+ ldrq(v6, Address(buf, 0x70));
+ eor3(v6, T16B, v29, v30, v6);
+
+ // Reuse registers v23, v24.
+ // Using them won't block the first instruction of the next iteration.
+ pmull (v23, T1Q, v7, v16, T1D);
+ pmull2(v24, T1Q, v7, v16, T2D);
+ ldrq(v7, Address(pre(buf, 0x80)));
+ eor3(v7, T16B, v23, v24, v7);
subs(len, len, 0x80);
br(Assembler::GE, CRC_by128_loop);
// fold into 512 bits
- ldrq(v0, Address(table, 0x10));
+ // Use v31 for constants because v16 can be still in use.
+ ldrq(v31, Address(table, 0x10));
- pmull (v10, T1Q, v1, v0, T1D);
- pmull2(v11, T1Q, v1, v0, T2D);
- eor3(v1, T16B, v10, v11, v5);
+ pmull (v17, T1Q, v0, v31, T1D);
+ pmull2(v18, T1Q, v0, v31, T2D);
+ eor3(v0, T16B, v17, v18, v4);
- pmull (v12, T1Q, v2, v0, T1D);
- pmull2(v13, T1Q, v2, v0, T2D);
- eor3(v2, T16B, v12, v13, v6);
+ pmull (v19, T1Q, v1, v31, T1D);
+ pmull2(v20, T1Q, v1, v31, T2D);
+ eor3(v1, T16B, v19, v20, v5);
- pmull (v14, T1Q, v3, v0, T1D);
- pmull2(v15, T1Q, v3, v0, T2D);
- eor3(v3, T16B, v14, v15, v7);
+ pmull (v21, T1Q, v2, v31, T1D);
+ pmull2(v22, T1Q, v2, v31, T2D);
+ eor3(v2, T16B, v21, v22, v6);
- pmull (v16, T1Q, v4, v0, T1D);
- pmull2(v17, T1Q, v4, v0, T2D);
- eor3(v4, T16B, v16, v17, v8);
+ pmull (v23, T1Q, v3, v31, T1D);
+ pmull2(v24, T1Q, v3, v31, T2D);
+ eor3(v3, T16B, v23, v24, v7);
// fold into 128 bits
- ldrq(v5, Address(table, 0x20));
- pmull (v10, T1Q, v1, v5, T1D);
- pmull2(v11, T1Q, v1, v5, T2D);
- eor3(v4, T16B, v4, v10, v11);
-
- ldrq(v6, Address(table, 0x30));
- pmull (v12, T1Q, v2, v6, T1D);
- pmull2(v13, T1Q, v2, v6, T2D);
- eor3(v4, T16B, v4, v12, v13);
-
- ldrq(v7, Address(table, 0x40));
- pmull (v14, T1Q, v3, v7, T1D);
- pmull2(v15, T1Q, v3, v7, T2D);
- eor3(v1, T16B, v4, v14, v15);
+ // Use v17 for constants because v31 can be still in use.
+ ldrq(v17, Address(table, 0x20));
+ pmull (v25, T1Q, v0, v17, T1D);
+ pmull2(v26, T1Q, v0, v17, T2D);
+ eor3(v3, T16B, v3, v25, v26);
+
+ // Use v18 for constants because v17 can be still in use.
+ ldrq(v18, Address(table, 0x30));
+ pmull (v27, T1Q, v1, v18, T1D);
+ pmull2(v28, T1Q, v1, v18, T2D);
+ eor3(v3, T16B, v3, v27, v28);
+
+ // Use v19 for constants because v18 can be still in use.
+ ldrq(v19, Address(table, 0x40));
+ pmull (v29, T1Q, v2, v19, T1D);
+ pmull2(v30, T1Q, v2, v19, T2D);
+ eor3(v0, T16B, v3, v29, v30);
add(len, len, 0x80);
add(buf, buf, 0x10);
- mov(tmp0, v1, D, 0);
- mov(tmp1, v1, D, 1);
+ mov(tmp0, v0, D, 0);
+ mov(tmp1, v0, D, 1);
}
SkipIfEqual::SkipIfEqual(
@@ -5339,28 +5398,25 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
// For Strings we're passed the address of the first characters in a1
// and a2 and the length in cnt1.
-// elem_size is the element size in bytes: either 1 or 2.
// There are two implementations. For arrays >= 8 bytes, all
// comparisons (including the final one, which may overlap) are
// performed 8 bytes at a time. For strings < 8 bytes, we compare a
// halfword, then a short, and then a byte.
void MacroAssembler::string_equals(Register a1, Register a2,
- Register result, Register cnt1, int elem_size)
+ Register result, Register cnt1)
{
Label SAME, DONE, SHORT, NEXT_WORD;
Register tmp1 = rscratch1;
Register tmp2 = rscratch2;
Register cnt2 = tmp2; // cnt2 only used in array length compare
- assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte");
assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
#ifndef PRODUCT
{
- const char kind = (elem_size == 2) ? 'U' : 'L';
char comment[64];
- snprintf(comment, sizeof comment, "{string_equals%c", kind);
+ snprintf(comment, sizeof comment, "{string_equalsL");
BLOCK_COMMENT(comment);
}
#endif
@@ -5408,14 +5464,12 @@ void MacroAssembler::string_equals(Register a1, Register a2,
cbnzw(tmp1, DONE);
}
bind(TAIL01);
- if (elem_size == 1) { // Only needed when comparing 1-byte elements
- tbz(cnt1, 0, SAME); // 0-1 bytes left.
+ tbz(cnt1, 0, SAME); // 0-1 bytes left.
{
- ldrb(tmp1, a1);
- ldrb(tmp2, a2);
- eorw(tmp1, tmp1, tmp2);
- cbnzw(tmp1, DONE);
- }
+ ldrb(tmp1, a1);
+ ldrb(tmp2, a2);
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
}
// Arrays are equal.
bind(SAME);
@@ -6328,97 +6382,122 @@ void MacroAssembler::double_move(VMRegPair src, VMRegPair dst, Register tmp) {
}
// Implements lightweight-locking.
-// Branches to slow upon failure to lock the object, with ZF cleared.
-// Falls through upon success with ZF set.
//
// - obj: the object to be locked
-// - hdr: the header, already loaded from obj, will be destroyed
-// - t1, t2: temporary registers, will be destroyed
-void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register t1, Register t2, Label& slow) {
+// - t1, t2, t3: temporary registers, will be destroyed
+// - slow: branched to if locking fails, absolute offset may larger than 32KB (imm14 encoding).
+void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, Register t3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr, t1, t2, rscratch1);
-
- // Check if we would have space on lock-stack for the object.
- ldrw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
- cmpw(t1, (unsigned)LockStack::end_offset() - 1);
- br(Assembler::GT, slow);
-
- // Load (object->mark() | 1) into hdr
- orr(hdr, hdr, markWord::unlocked_value);
- // Clear lock-bits, into t2
- eor(t2, hdr, markWord::unlocked_value);
- // Try to swing header from unlocked to locked
- // Clobbers rscratch1 when UseLSE is false
- cmpxchg(/*addr*/ obj, /*expected*/ hdr, /*new*/ t2, Assembler::xword,
- /*acquire*/ true, /*release*/ true, /*weak*/ false, t1);
+ assert_different_registers(obj, t1, t2, t3, rscratch1);
+
+ Label push;
+ const Register top = t1;
+ const Register mark = t2;
+ const Register t = t3;
+
+ // Preload the markWord. It is important that this is the first
+ // instruction emitted as it is part of C1's null check semantics.
+ ldr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check if the lock-stack is full.
+ ldrw(top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ cmpw(top, (unsigned)LockStack::end_offset());
+ br(Assembler::GE, slow);
+
+ // Check for recursion.
+ subw(t, top, oopSize);
+ ldr(t, Address(rthread, t));
+ cmp(obj, t);
+ br(Assembler::EQ, push);
+
+ // Check header for monitor (0b10).
+ tst(mark, markWord::monitor_value);
+ br(Assembler::NE, slow);
+
+ // Try to lock. Transition lock bits 0b01 => 0b00
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
+ orr(mark, mark, markWord::unlocked_value);
+ eor(t, mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword,
+ /*acquire*/ true, /*release*/ false, /*weak*/ false, noreg);
br(Assembler::NE, slow);
- // After successful lock, push object on lock-stack
- ldrw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
- str(obj, Address(rthread, t1));
- addw(t1, t1, oopSize);
- strw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ str(obj, Address(rthread, top));
+ addw(top, top, oopSize);
+ strw(top, Address(rthread, JavaThread::lock_stack_top_offset()));
}
// Implements lightweight-unlocking.
-// Branches to slow upon failure, with ZF cleared.
-// Falls through upon success, with ZF set.
//
// - obj: the object to be unlocked
-// - hdr: the (pre-loaded) header of the object
-// - t1, t2: temporary registers
-void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register t1, Register t2, Label& slow) {
+// - t1, t2, t3: temporary registers
+// - slow: branched to if unlocking fails, absolute offset may larger than 32KB (imm14 encoding).
+void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2, Register t3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr, t1, t2, rscratch1);
+ // cmpxchg clobbers rscratch1.
+ assert_different_registers(obj, t1, t2, t3, rscratch1);
#ifdef ASSERT
{
- // The following checks rely on the fact that LockStack is only ever modified by
- // its owning thread, even if the lock got inflated concurrently; removal of LockStack
- // entries after inflation will happen delayed in that case.
-
// Check for lock-stack underflow.
Label stack_ok;
ldrw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
cmpw(t1, (unsigned)LockStack::start_offset());
- br(Assembler::GT, stack_ok);
+ br(Assembler::GE, stack_ok);
STOP("Lock-stack underflow");
bind(stack_ok);
}
- {
- // Check if the top of the lock-stack matches the unlocked object.
- Label tos_ok;
- subw(t1, t1, oopSize);
- ldr(t1, Address(rthread, t1));
- cmpoop(t1, obj);
- br(Assembler::EQ, tos_ok);
- STOP("Top of lock-stack does not match the unlocked object");
- bind(tos_ok);
- }
- {
- // Check that hdr is fast-locked.
- Label hdr_ok;
- tst(hdr, markWord::lock_mask_in_place);
- br(Assembler::EQ, hdr_ok);
- STOP("Header is not fast-locked");
- bind(hdr_ok);
- }
#endif
- // Load the new header (unlocked) into t1
- orr(t1, hdr, markWord::unlocked_value);
+ Label unlocked, push_and_slow;
+ const Register top = t1;
+ const Register mark = t2;
+ const Register t = t3;
- // Try to swing header from locked to unlocked
- // Clobbers rscratch1 when UseLSE is false
- cmpxchg(obj, hdr, t1, Assembler::xword,
- /*acquire*/ true, /*release*/ true, /*weak*/ false, t2);
+ // Check if obj is top of lock-stack.
+ ldrw(top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ subw(top, top, oopSize);
+ ldr(t, Address(rthread, top));
+ cmp(obj, t);
br(Assembler::NE, slow);
- // After successful unlock, pop object from lock-stack
- ldrw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
- subw(t1, t1, oopSize);
+ // Pop lock-stack.
+ DEBUG_ONLY(str(zr, Address(rthread, top));)
+ strw(top, Address(rthread, JavaThread::lock_stack_top_offset()));
+
+ // Check if recursive.
+ subw(t, top, oopSize);
+ ldr(t, Address(rthread, t));
+ cmp(obj, t);
+ br(Assembler::EQ, unlocked);
+
+ // Not recursive. Check header for monitor (0b10).
+ ldr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ tbnz(mark, log2i_exact(markWord::monitor_value), push_and_slow);
+
#ifdef ASSERT
- str(zr, Address(rthread, t1));
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ tbz(mark, log2i_exact(markWord::unlocked_value), not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
#endif
- strw(t1, Address(rthread, JavaThread::lock_stack_top_offset()));
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
+ orr(t, mark, markWord::unlocked_value);
+ cmpxchg(obj, mark, t, Assembler::xword,
+ /*acquire*/ false, /*release*/ true, /*weak*/ false, noreg);
+ br(Assembler::EQ, unlocked);
+
+ bind(push_and_slow);
+ // Restore lock-stack and handle the unlock in runtime.
+ DEBUG_ONLY(str(obj, Address(rthread, top));)
+ addw(top, top, oopSize);
+ strw(top, Address(rthread, JavaThread::lock_stack_top_offset()));
+ b(slow);
+
+ bind(unlocked);
}
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
index 84931c409cfe9..dad7ec4d4975e 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -720,6 +720,7 @@ class MacroAssembler: public Assembler {
// Alignment
void align(int modulus);
+ void align(int modulus, int target);
// nop
void post_call_nop();
@@ -1247,6 +1248,8 @@ class MacroAssembler: public Assembler {
// Emit the CompiledIC call idiom
address ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment);
public:
@@ -1399,8 +1402,7 @@ class MacroAssembler: public Assembler {
address arrays_equals(Register a1, Register a2, Register result, Register cnt1,
Register tmp1, Register tmp2, Register tmp3, int elem_size);
- void string_equals(Register a1, Register a2, Register result, Register cnt1,
- int elem_size);
+ void string_equals(Register a1, Register a2, Register result, Register cnt1);
void fill_words(Register base, Register cnt, Register value);
address zero_words(Register base, uint64_t cnt);
@@ -1425,11 +1427,6 @@ class MacroAssembler: public Assembler {
FloatRegister vtmp2, FloatRegister vtmp3,
FloatRegister vtmp4, FloatRegister vtmp5);
- void fast_log(FloatRegister vtmp0, FloatRegister vtmp1, FloatRegister vtmp2,
- FloatRegister vtmp3, FloatRegister vtmp4, FloatRegister vtmp5,
- FloatRegister tmpC1, FloatRegister tmpC2, FloatRegister tmpC3,
- FloatRegister tmpC4, Register tmp1, Register tmp2,
- Register tmp3, Register tmp4, Register tmp5);
void generate_dsin_dcos(bool isCos, address npio2_hw, address two_over_pi,
address pio2, address dsin_coef, address dcos_coef);
private:
@@ -1605,8 +1602,8 @@ class MacroAssembler: public Assembler {
// Code for java.lang.Thread::onSpinWait() intrinsic.
void spin_wait();
- void lightweight_lock(Register obj, Register hdr, Register t1, Register t2, Label& slow);
- void lightweight_unlock(Register obj, Register hdr, Register t1, Register t2, Label& slow);
+ void lightweight_lock(Register obj, Register t1, Register t2, Register t3, Label& slow);
+ void lightweight_unlock(Register obj, Register t1, Register t2, Register t3, Label& slow);
private:
// Check the current thread doesn't need a cross modify fence.
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp
deleted file mode 100644
index 45772ff1afd63..0000000000000
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/* Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT)
- * Copyright (c) 2016, 2021, Intel Corporation. All rights reserved.
- * Intel Math Library (LIBM) Source Code
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.hpp"
-#include "asm/assembler.inline.hpp"
-#include "macroAssembler_aarch64.hpp"
-
-// Algorithm idea is taken from x86 hotspot intrinsic and adapted for AARCH64.
-//
-// For mathematical background please refer to the following literature:
-//
-// Tang, Ping-Tak Peter.
-// Table-driven implementation of the logarithm function
-// in IEEE floating-point arithmetic.
-// ACM Transactions on Mathematical Software (TOMS) 16, no. 4, 1990: 378-400.
-
-/******************************************************************************/
-// ALGORITHM DESCRIPTION - LOG()
-// ---------------------
-//
-// x=2^k * mx, mx in [1,2)
-//
-// Get B~1/mx based on the output of frecpe instruction (B0)
-// B = int((B0*2^7+0.5))/2^7
-//
-// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
-//
-// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
-// p(r) is a degree 7 polynomial
-// -log(B) read from data table (high, low parts)
-// Result is formed from high and low parts
-//
-// Special cases:
-// 1. log(NaN) = quiet NaN
-// 2. log(+INF) = that INF
-// 3. log(0) = -INF
-// 4. log(1) = +0
-// 5. log(x) = NaN if x < -0, including -INF
-//
-/******************************************************************************/
-
-// Table with p(r) polynomial coefficients
-// and table representation of logarithm values (hi and low parts)
-ATTRIBUTE_ALIGNED(64) juint _L_tbl[] =
-{
- // coefficients of p(r) polynomial:
- // _coeff[]
- 0x00000000UL, 0xbfd00000UL, // C1_0 = -0.25
- 0x92492492UL, 0x3fc24924UL, // C1_1 = 0.14285714285714285
- 0x55555555UL, 0x3fd55555UL, // C2_0 = 0.3333333333333333
- 0x3d6fb175UL, 0xbfc5555eUL, // C2_1 = -0.16666772842235003
- 0x00000000UL, 0xbfe00000UL, // C3_0 = -0.5
- 0x9999999aUL, 0x3fc99999UL, // C3_1 = 0.2
- // _log2[]
- 0xfefa3800UL, 0x3fa62e42UL, // C4_0 = 0.043321698784993146
- 0x93c76730UL, 0x3ceef357UL, // C4_1 = 3.436201886692732e-15
- // _L_tbl[] with logarithm values (hi and low parts)
- 0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
- 0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
- 0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
- 0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
- 0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
- 0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
- 0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
- 0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
- 0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
- 0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
- 0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
- 0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
- 0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
- 0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
- 0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
- 0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
- 0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
- 0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
- 0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
- 0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
- 0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
- 0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
- 0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
- 0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
- 0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
- 0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
- 0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
- 0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
- 0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
- 0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
- 0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
- 0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
- 0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
- 0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
- 0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
- 0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
- 0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
- 0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
- 0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
- 0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
- 0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
- 0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
- 0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
- 0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
- 0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
- 0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
- 0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
- 0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
- 0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
- 0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
- 0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
- 0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
- 0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
- 0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
- 0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
- 0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
- 0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
- 0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
- 0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
- 0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
- 0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
- 0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
- 0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
- 0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
- 0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
- 0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
- 0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
- 0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
- 0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
- 0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
- 0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
- 0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
- 0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
- 0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
- 0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
- 0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
- 0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
- 0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
- 0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
- 0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
- 0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
- 0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
- 0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
- 0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
- 0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
- 0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
- 0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
- 0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
- 0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
- 0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
- 0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
- 0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
- 0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
- 0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
- 0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
- 0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
- 0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
- 0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
- 0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
- 0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
- 0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
- 0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
- 0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
- 0x80000000UL
-};
-
-// BEGIN dlog PSEUDO CODE:
-// double dlog(double X) {
-// // p(r) polynomial coefficients initialized from _L_tbl table
-// double C1_0 = _L_tbl[0];
-// double C1_1 = _L_tbl[1];
-// double C2_0 = _L_tbl[2];
-// double C2_1 = _L_tbl[3];
-// double C3_0 = _L_tbl[4];
-// double C3_1 = _L_tbl[5];
-// double C4_0 = _L_tbl[6];
-// double C4_1 = _L_tbl[7];
-// // NOTE: operations with coefficients above are mostly vectorized in assembly
-// // Check corner cases first
-// if (X == 1.0d || AS_LONG_BITS(X) + 0x0010000000000000 <= 0x0010000000000000) {
-// // NOTE: AS_LONG_BITS(X) + 0x0010000000000000 <= 0x0010000000000000 means
-// // that X < 0 or X >= 0x7FF0000000000000 (0x7FF* is NaN or INF)
-// if (X < 0 || X is NaN) return NaN;
-// if (X == 1.0d) return 0.0d;
-// if (X == 0.0d) return -INFINITY;
-// if (X is INFINITY) return INFINITY;
-// }
-// // double representation is 2^exponent * mantissa
-// // split X into two multipliers: 2^exponent and 1.0 * mantissa
-// // pseudo function: zeroExponent(X) return value of X with exponent == 0
-// float vtmp5 = 1/(float)(zeroExponent(X)); // reciprocal estimate
-// // pseudo function: HI16(X) returns high 16 bits of double value
-// int hiWord = HI16(X);
-// double vtmp1 = (double) 0x77F0 << 48 | mantissa(X);
-// hiWord -= 16;
-// if (AS_LONG_BITS(hiWord) > 0x8000) {
-// // SMALL_VALUE branch
-// vtmp0 = vtmp1 = vtmp0 * AS_DOUBLE_BITS(0x47F0000000000000);
-// hiWord = HI16(vtmp1);
-// vtmp0 = AS_DOUBLE_BITS(AS_LONG_BITS(vtmp0) |= 0x3FF0000000000000);
-// vtmp5 = (double) (1/(float)vtmp0);
-// vtmp1 <<= 12;
-// vtmp1 >>= 12;
-// }
-// // MAIN branch
-// double vtmp3 = AS_LONG_BITS(vtmp1) & 0xffffe00000000000; // hi part
-// int intB0 = AS_INT_BITS(vtmp5) + 0x8000;
-// double vtmp0 = AS_DOUBLE_BITS(0xffffe00000000000 & (intB0<<29));
-// int index = (intB0 >> 16) && 0xFF;
-// double hiTableValue = _L_tbl[8+index]; // vtmp2[0]
-// double lowTableValue = _L_tbl[16+index]; // vtmp2[1]
-// vtmp5 = AS_DOUBLE_BITS(hiWord & 0x7FF0 - 0x3FE0); // 0x3FE = 1023 << 4
-// vtmp1 -= vtmp3; // low part
-// vtmp3 = vtmp3*vtmp0 - 1.0;
-// hiTableValue += C4_0 * vtmp5;
-// lowTableValue += C4_1 * vtmp5;
-// double r = vtmp1 * vtmp0 + vtmp3; // r = B*mx-1.0, computed in hi and low parts
-// vtmp0 = hiTableValue + r;
-// hiTableValue -= vtmp0;
-// double r2 = r*r;
-// double r3 = r2*r;
-// double p7 = C3_0*r2 + C2_0*r3 + C1_0*r2*r2 + C3_1*r3*r2 + C2_1*r3*r3
-// + C1_1*r3*r2*r2; // degree 7 polynomial
-// return p7 + (vtmp0 + ((r + hiTableValue) + lowTableValue));
-// }
-//
-// END dlog PSEUDO CODE
-
-
-// Generate log(X). X passed in register v0. Return log(X) into v0.
-// Generator parameters: 10 temporary FPU registers and temporary general
-// purpose registers
-void MacroAssembler::fast_log(FloatRegister vtmp0, FloatRegister vtmp1,
- FloatRegister vtmp2, FloatRegister vtmp3,
- FloatRegister vtmp4, FloatRegister vtmp5,
- FloatRegister C1, FloatRegister C2,
- FloatRegister C3, FloatRegister C4,
- Register tmp1, Register tmp2, Register tmp3,
- Register tmp4, Register tmp5) {
- Label DONE, CHECK_CORNER_CASES, SMALL_VALUE, MAIN,
- CHECKED_CORNER_CASES, RETURN_MINF_OR_NAN;
- const int64_t INF_OR_NAN_PREFIX = 0x7FF0;
- const int64_t MINF_OR_MNAN_PREFIX = 0xFFF0;
- const int64_t ONE_PREFIX = 0x3FF0;
- movz(tmp2, ONE_PREFIX, 48);
- movz(tmp4, 0x0010, 48);
- fmovd(rscratch1, v0); // rscratch1 = AS_LONG_BITS(X)
- lea(rscratch2, ExternalAddress((address)_L_tbl));
- movz(tmp5, 0x7F);
- add(tmp1, rscratch1, tmp4);
- cmp(tmp2, rscratch1);
- lsr(tmp3, rscratch1, 29);
- ccmp(tmp1, tmp4, 0b1101 /* LE */, NE);
- bfm(tmp3, tmp5, 41, 8);
- fmovs(vtmp5, tmp3);
- // Load coefficients from table. All coefficients are organized to be
- // in specific order, because load below will load it in vectors to be used
- // later in vector instructions. Load will be performed in parallel while
- // branches are taken. C1 will contain vector of {C1_0, C1_1}, C2 =
- // {C2_0, C2_1}, C3 = {C3_0, C3_1}, C4 = {C4_0, C4_1}
- ld1(C1, C2, C3, C4, T2D, post(rscratch2, 64));
- br(LE, CHECK_CORNER_CASES);
- bind(CHECKED_CORNER_CASES);
- // all corner cases are handled
- frecpe(vtmp5, vtmp5, S); // vtmp5 ~= 1/vtmp5
- lsr(tmp2, rscratch1, 48);
- movz(tmp4, 0x77f0, 48);
- fmovd(vtmp4, 1.0);
- movz(tmp1, INF_OR_NAN_PREFIX, 48);
- bfm(tmp4, rscratch1, 0, 51); // tmp4 = 0x77F0 << 48 | mantissa(X)
- // vtmp1 = AS_DOUBLE_BITS(0x77F0 << 48 | mantissa(X)) == mx
- fmovd(vtmp1, tmp4);
- subw(tmp2, tmp2, 16);
- subs(zr, tmp2, 0x8000);
- br(GE, SMALL_VALUE);
- bind(MAIN);
- fmovs(tmp3, vtmp5); // int intB0 = AS_INT_BITS(B);
- mov(tmp5, 0x3FE0);
- uint64_t mask = UCONST64(0xffffe00000000000);
- mov(rscratch1, mask);
- andr(tmp2, tmp2, tmp1, LSR, 48); // hiWord & 0x7FF0
- sub(tmp2, tmp2, tmp5); // tmp2 = hiWord & 0x7FF0 - 0x3FE0
- scvtfwd(vtmp5, tmp2); // vtmp5 = (double)tmp2;
- addw(tmp3, tmp3, 0x8000); // tmp3 = B
- andr(tmp4, tmp4, rscratch1); // tmp4 == hi_part(mx)
- andr(rscratch1, rscratch1, tmp3, LSL, 29); // rscratch1 = hi_part(B)
- ubfm(tmp3, tmp3, 16, 23); // int index = (intB0 >> 16) && 0xFF
- ldrq(vtmp2, Address(rscratch2, tmp3, Address::lsl(4))); // vtmp2 = _L_tbl[index]
- // AS_LONG_BITS(vtmp1) & 0xffffe00000000000 // hi_part(mx)
- fmovd(vtmp3, tmp4);
- fmovd(vtmp0, rscratch1); // vtmp0 = hi_part(B)
- fsubd(vtmp1, vtmp1, vtmp3); // vtmp1 -= vtmp3; // low_part(mx)
- fnmsub(vtmp3, vtmp3, vtmp0, vtmp4); // vtmp3 = vtmp3*vtmp0 - vtmp4
- fmlavs(vtmp2, T2D, C4, vtmp5, 0); // vtmp2 += {C4} * vtmp5
- // vtmp1 = r = vtmp1 * vtmp0 + vtmp3 == low_part(mx) * hi_part(B) + (hi_part(mx)*hi_part(B) - 1.0)
- fmaddd(vtmp1, vtmp1, vtmp0, vtmp3);
- ins(vtmp5, D, vtmp2, 0, 1); // vtmp5 = vtmp2[1];
- faddd(vtmp0, vtmp2, vtmp1); // vtmp0 = vtmp2 + vtmp1
- fmlavs(C3, T2D, C2, vtmp1, 0); // {C3} += {C2}*vtmp1
- fsubd(vtmp2, vtmp2, vtmp0); // vtmp2 -= vtmp0
- fmuld(vtmp3, vtmp1, vtmp1); // vtmp3 = vtmp1*vtmp1
- faddd(C4, vtmp1, vtmp2); // C4[0] = vtmp1 + vtmp2
- fmlavs(C3, T2D, C1, vtmp3, 0); // {C3} += {C1}*vtmp3
- faddd(C4, C4, vtmp5); // C4 += vtmp5
- fmuld(vtmp4, vtmp3, vtmp1); // vtmp4 = vtmp3*vtmp1
- faddd(vtmp0, vtmp0, C4); // vtmp0 += C4
- fmlavs(C3, T2D, vtmp4, C3, 1); // {C3} += {vtmp4}*C3[1]
- fmaddd(vtmp0, C3, vtmp3, vtmp0); // vtmp0 = C3 * vtmp3 + vtmp0
- ret(lr);
-
- block_comment("if (AS_LONG_BITS(hiWord) > 0x8000)"); {
- bind(SMALL_VALUE);
- movz(tmp2, 0x47F0, 48);
- fmovd(vtmp1, tmp2);
- fmuld(vtmp0, vtmp1, v0);
- fmovd(vtmp1, vtmp0);
- umov(tmp2, vtmp1, S, 3);
- orr(vtmp0, T16B, vtmp0, vtmp4);
- ushr(vtmp5, T2D, vtmp0, 27);
- ushr(vtmp5, T4S, vtmp5, 2);
- frecpe(vtmp5, vtmp5, S);
- shl(vtmp1, T2D, vtmp1, 12);
- ushr(vtmp1, T2D, vtmp1, 12);
- b(MAIN);
- }
-
- block_comment("Corner cases"); {
- bind(RETURN_MINF_OR_NAN);
- movz(tmp1, MINF_OR_MNAN_PREFIX, 48);
- orr(rscratch1, rscratch1, tmp1);
- fmovd(v0, rscratch1);
- ret(lr);
- bind(CHECK_CORNER_CASES);
- movz(tmp1, INF_OR_NAN_PREFIX, 48);
- cmp(rscratch1, zr);
- br(LE, RETURN_MINF_OR_NAN);
- cmp(rscratch1, tmp1);
- br(GE, DONE);
- cmp(rscratch1, tmp2);
- br(NE, CHECKED_CORNER_CASES);
- fmovd(v0, 0.0);
- }
- bind(DONE);
- ret(lr);
-}
diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
index a12caa3daeefb..192a0d1ac1c9e 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/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
index 8694734c751c6..97a10afde7ab2 100644
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -30,7 +30,6 @@
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -39,7 +38,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_aarch64.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -740,9 +738,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
-
- Register holder = rscratch2;
+ Register data = rscratch2;
Register receiver = j_rarg0;
Register tmp = r10; // A call-clobbered register not used for arg passing
@@ -757,17 +753,12 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ block_comment("c2i_unverified_entry {");
- __ load_klass(rscratch1, receiver);
- __ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ cmp(rscratch1, tmp);
- __ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ br(Assembler::EQ, ok);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- __ bind(ok);
// Method might have been compiled since the call site was patched to
// interpreted; if that is the case treat it as a miss so we can get
// the call site corrected.
+ __ ic_check(1 /* end_alignment */);
+ __ ldr(rmethod, Address(data, CompiledICData::speculated_method_offset()));
+
__ ldr(rscratch1, Address(rmethod, in_bytes(Method::code_offset())));
__ cbz(rscratch1, skip_fixup);
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
@@ -1118,7 +1109,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ b(exit);
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1183,7 +1174,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
}
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1391,6 +1382,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
in_ByteSize(-1),
oop_maps,
exception_offset);
+ if (nm == nullptr) return nm;
if (method->is_continuation_enter_intrinsic()) {
ContinuationEntry::set_enter_code(nm, interpreted_entry_offset);
} else if (method->is_continuation_yield_intrinsic()) {
@@ -1538,25 +1530,15 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// restoring them except rfp. rfp is the only callee save register
// as far as the interpreter and the compiler(s) are concerned.
-
- const Register ic_reg = rscratch2;
const Register receiver = j_rarg0;
- Label hit;
Label exception_pending;
- assert_different_registers(ic_reg, receiver, rscratch1);
+ assert_different_registers(receiver, rscratch1);
__ verify_oop(receiver);
- __ cmp_klass(receiver, ic_reg, rscratch1);
- __ br(Assembler::EQ, hit);
-
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ __ ic_check(8 /* end_alignment */);
// Verified entry point must be aligned
- __ align(8);
-
- __ bind(hit);
-
int vep_offset = ((intptr_t)__ pc()) - start;
// If we have to make this method not-entrant we'll overwrite its
@@ -1814,7 +1796,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ br(Assembler::NE, slow_path_lock);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- __ ldr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ lightweight_lock(obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
}
__ bind(count);
@@ -1957,8 +1938,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "");
- __ ldr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ tbnz(old_hdr, exact_log2(markWord::monitor_value), slow_path_unlock);
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
__ decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
}
diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
index 97ca90ac76454..46a7d79626749 100644
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2022, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -5327,19 +5327,6 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
- address generate_dlog() {
- __ align(CodeEntryAlignment);
- StubCodeMark mark(this, "StubRoutines", "dlog");
- address entry = __ pc();
- FloatRegister vtmp0 = v0, vtmp1 = v1, vtmp2 = v2, vtmp3 = v3, vtmp4 = v4,
- vtmp5 = v5, tmpC1 = v16, tmpC2 = v17, tmpC3 = v18, tmpC4 = v19;
- Register tmp1 = r0, tmp2 = r1, tmp3 = r2, tmp4 = r3, tmp5 = r4;
- __ fast_log(vtmp0, vtmp1, vtmp2, vtmp3, vtmp4, vtmp5, tmpC1, tmpC2, tmpC3,
- tmpC4, tmp1, tmp2, tmp3, tmp4, tmp5);
- return entry;
- }
-
-
// code for comparing 16 characters of strings with Latin1 and Utf16 encoding
void compare_string_16_x_LU(Register tmpL, Register tmpU, Label &DIFF1,
Label &DIFF2) {
@@ -5487,6 +5474,32 @@ class StubGenerator: public StubCodeGenerator {
return entry;
}
+ // r0 = input (float16)
+ // v0 = result (float)
+ // v1 = temporary float register
+ address generate_float16ToFloat() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "float16ToFloat");
+ address entry = __ pc();
+ BLOCK_COMMENT("Entry:");
+ __ flt16_to_flt(v0, r0, v1);
+ __ ret(lr);
+ return entry;
+ }
+
+ // v0 = input (float)
+ // r0 = result (float16)
+ // v1 = temporary float register
+ address generate_floatToFloat16() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "floatToFloat16");
+ address entry = __ pc();
+ BLOCK_COMMENT("Entry:");
+ __ flt_to_flt16(r0, v0, v1);
+ __ ret(lr);
+ return entry;
+ }
+
address generate_method_entry_barrier() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier");
@@ -8333,11 +8346,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
- // Disabled until JDK-8210858 is fixed
- // if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dlog)) {
- // StubRoutines::_dlog = generate_dlog();
- // }
-
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) {
StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false);
}
@@ -8345,6 +8353,12 @@ class StubGenerator: public StubCodeGenerator {
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
}
+
+ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_float16ToFloat) &&
+ vmIntrinsics::is_intrinsic_available(vmIntrinsics::_floatToFloat16)) {
+ StubRoutines::_hf2f = generate_float16ToFloat();
+ StubRoutines::_f2hf = generate_floatToFloat16();
+ }
}
void generate_continuation_stubs() {
diff --git a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp
index 14e9764457508..28ec07815be5c 100644
--- a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp
@@ -245,9 +245,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
__ mov_metadata(rmethod, entry);
__ str(rmethod, Address(rthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
+ __ push_cont_fastpath(rthread);
+
__ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset()));
__ blr(rscratch1);
+ __ pop_cont_fastpath(rthread);
+
// return value shuffle
if (!needs_return_buffer) {
#ifdef ASSERT
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
index f7fe2f7dec81a..18f310c746cd4 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
@@ -143,11 +143,19 @@ void VM_Version::initialize() {
}
}
- // Ampere CPUs: Ampere-1 and Ampere-1A
- if (_cpu == CPU_AMPERE && ((_model == CPU_MODEL_AMPERE_1) || (_model == CPU_MODEL_AMPERE_1A))) {
+ // Ampere CPUs
+ if (_cpu == CPU_AMPERE && ((_model == CPU_MODEL_AMPERE_1) ||
+ (_model == CPU_MODEL_AMPERE_1A) ||
+ (_model == CPU_MODEL_AMPERE_1B))) {
if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
}
+ if (FLAG_IS_DEFAULT(OnSpinWaitInst)) {
+ FLAG_SET_DEFAULT(OnSpinWaitInst, "isb");
+ }
+ if (FLAG_IS_DEFAULT(OnSpinWaitInstCount)) {
+ FLAG_SET_DEFAULT(OnSpinWaitInstCount, 2);
+ }
}
// ThunderX
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
index 4b2e5cc5a4ddd..6883dc0d93e16 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -110,7 +110,8 @@ enum Ampere_CPU_Model {
CPU_MODEL_ALTRA = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
CPU_MODEL_ALTRAMAX = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
CPU_MODEL_AMPERE_1 = 0xac3, /* CPU implementer is CPU_AMPERE */
- CPU_MODEL_AMPERE_1A = 0xac4 /* CPU implementer is CPU_AMPERE */
+ CPU_MODEL_AMPERE_1A = 0xac4, /* CPU implementer is CPU_AMPERE */
+ CPU_MODEL_AMPERE_1B = 0xac5 /* AMPERE_1B core Implements ARMv8.7 with CSSC, MTE, SM3/SM4 extensions */
};
#define CPU_FEATURE_FLAGS(decl) \
@@ -168,6 +169,7 @@ enum Ampere_CPU_Model {
// Aarch64 supports fast class initialization checks
static bool supports_fast_class_init_checks() { return true; }
constexpr static bool supports_stack_watermark_barrier() { return true; }
+ constexpr static bool supports_recursive_lightweight_locking() { return true; }
static void get_compatible_board(char *buf, int buflen);
diff --git a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
index 6e345c96ce20c..2bb53d16a3c97 100644
--- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
@@ -26,10 +26,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_aarch64.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -168,22 +168,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// Entry arguments:
- // rscratch2: CompiledICHolder
+ // rscratch2: CompiledICData
// j_rarg0: Receiver
// This stub is called from compiled code which has no callee-saved registers,
// 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 holder_klass_reg = r16; // declaring interface klass (DEFC)
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;
+ const Register icdata_reg = rscratch2;
Label L_no_such_interface;
- __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ ldr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ ldr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
start_pc = __ pc();
@@ -197,7 +197,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
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 estimate = 144;
const ptrdiff_t codesize = __ pc() - start_pc;
slop_delta = (int)(estimate - codesize);
slop_bytes += slop_delta;
diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad
index e31ad91613a1a..1a833b08c4cf4 100644
--- a/src/hotspot/cpu/arm/arm.ad
+++ b/src/hotspot/cpu/arm/arm.ad
@@ -195,7 +195,7 @@ void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, Reloc
assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
- assert(target != NULL, "need real address");
+ assert(target != nullptr, "need real address");
int ret_addr_offset = -1;
if (rspec.type() == relocInfo::runtime_call_type) {
@@ -290,7 +290,7 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize);
}
- if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (C->stub_function() == nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
st->print("ldr t0, [guard]\n\t");
st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t");
st->print("cmp t0, t1\n\t");
@@ -332,7 +332,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ sub_slow(SP, SP, framesize);
}
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->nmethod_entry_barrier(&_masm);
}
@@ -454,7 +454,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
return size; // Self copy, no move
#ifdef TODO
- if (bottom_type()->isa_vect() != NULL) {
+ if (bottom_type()->isa_vect() != nullptr) {
}
#endif
@@ -804,16 +804,16 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
#ifndef PRODUCT
void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
- implementation( NULL, ra_, false, st );
+ implementation(nullptr, ra_, false, st );
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation( &cbuf, ra_, false, NULL );
+ implementation( &cbuf, ra_, false, nullptr );
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation( NULL, ra_, true, NULL );
+ return implementation( nullptr, ra_, true, nullptr );
}
//=============================================================================
@@ -869,12 +869,7 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
#define R_RTEMP "R_R12"
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("\nUEP:");
- if (UseCompressedClassPointers) {
- st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
- st->print_cr("\tdecode_klass " R_RTEMP);
- } else {
- st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
- }
+ st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
st->print_cr("\tCMP " R_RTEMP ",R_R8" );
st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub");
}
@@ -882,13 +877,7 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
C2_MacroAssembler _masm(&cbuf);
- Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode());
- assert(iCache == Ricklass, "should be");
- Register receiver = R0;
-
- __ load_klass(Rtemp, receiver);
- __ cmp(Rtemp, iCache);
- __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
+ __ ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
@@ -903,7 +892,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -926,7 +915,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1002,7 +991,7 @@ bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
-bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
return match_rule_supported_vector(opcode, vlen, bt);
}
@@ -1026,11 +1015,11 @@ bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
}
const RegMask* Matcher::predicate_reg_mask(void) {
- return NULL;
+ return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
- return NULL;
+ return nullptr;
}
// Vector calling convention not yet implemented.
@@ -1074,7 +1063,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return 8/type2aelembytes(bt);
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
return Matcher::max_vector_size(bt);
}
@@ -1094,7 +1083,7 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
ShouldNotReachHere(); // generic vector operands not supported
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -1241,8 +1230,8 @@ encode %{
emit_call_reloc(cbuf, as_MachCall(), $meth, rspec);
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -1987,7 +1976,7 @@ operand immNKlass()
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immN0()
%{
predicate(n->get_narrowcon() == 0);
diff --git a/src/hotspot/cpu/arm/arm_32.ad b/src/hotspot/cpu/arm/arm_32.ad
index affe5a816fcaf..dd7d6f491dad4 100644
--- a/src/hotspot/cpu/arm/arm_32.ad
+++ b/src/hotspot/cpu/arm/arm_32.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2008, 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
@@ -431,7 +431,7 @@ OptoRegPair c2::return_value(int ideal_reg) {
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
- bool far = (_method == NULL) ? maybe_far_call(this) : !cache_reachable();
+ bool far = (_method == nullptr) ? maybe_far_call(this) : !cache_reachable();
return ((far ? 3 : 1) + (_method_handle_invoke ? 1 : 0)) *
NativeInstruction::instruction_size;
}
diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
index 999309c02258d..688790f07e548 100644
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
@@ -161,10 +161,7 @@ void LIR_Assembler::osr_entry() {
int LIR_Assembler::check_icache() {
- Register receiver = LIR_Assembler::receiverOpr()->as_register();
- int offset = __ offset();
- __ inline_cache_check(receiver, Ricklass);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -971,7 +968,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
op->tmp1()->as_register(),
op->tmp2()->as_register(),
op->tmp3()->as_register(),
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
type2aelembytes(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
@@ -1950,7 +1947,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
// If not a single instruction, NativeMovConstReg::next_instruction_address()
// must jump over the whole following ldr_literal.
- // (See CompiledStaticCall::set_to_interpreted())
+ // (See CompiledDirectCall::set_to_interpreted())
#ifdef ASSERT
address ldr_site = __ pc();
#endif
diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
index c09e54e0e57ad..d9d042bb2e4e7 100644
--- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
@@ -43,16 +43,6 @@
// arm [macro]assembler) and used with care in the other C1 specific
// files.
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- Label verified;
- load_klass(Rtemp, receiver);
- cmp(Rtemp, iCache);
- b(verified, eq); // jump over alignment no-ops
- jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type);
- align(CodeEntryAlignment);
- bind(verified);
-}
-
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
assert((frame_size_in_bytes % StackAlignmentInBytes) == 0, "frame size should be aligned");
diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
index 62faa6170833b..9862a074a687f 100644
--- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
@@ -37,7 +37,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_arm.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_arm.hpp"
diff --git a/src/hotspot/cpu/arm/compiledIC_arm.cpp b/src/hotspot/cpu/arm/compiledIC_arm.cpp
index 2d4187b7d6c6a..71389d2353d66 100644
--- a/src/hotspot/cpu/arm/compiledIC_arm.cpp
+++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
@@ -37,7 +36,7 @@
#if COMPILER2_OR_JVMCI
#define __ _masm.
// emit call stub, compiled java to interpreter
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
// set (empty), R9
@@ -59,7 +58,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
InlinedMetadata object_literal(nullptr);
// single instruction, see NativeMovConstReg::next_instruction_address() in
- // CompiledStaticCall::set_to_interpreted()
+ // CompiledDirectCall::set_to_interpreted()
__ ldr_literal(Rmethod, object_literal);
__ set_inst_mark(); // Who uses this?
@@ -87,32 +86,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
#undef __
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call
}
#endif // COMPILER2_OR_JVMCI
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// ARM doesn't use trampolines.
return 0;
}
// size of C2 call stub, compiled java to interpreter
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 8 * NativeInstruction::instruction_size;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -128,7 +120,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -144,7 +136,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp
index 3aa71dca8cbf0..6d724c750aa34 100644
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp
@@ -29,8 +29,8 @@
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/sharedRuntime.hpp"
diff --git a/src/hotspot/cpu/arm/icBuffer_arm.cpp b/src/hotspot/cpu/arm/icBuffer_arm.cpp
deleted file mode 100644
index e3a1c148ec6a0..0000000000000
--- a/src/hotspot/cpu/arm/icBuffer_arm.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_arm.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm->
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return (4 * Assembler::InstructionSize);
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
-
- InlinedAddress oop_literal((address) cached_value);
- __ ldr_literal(Ricklass, oop_literal);
- // FIXME: OK to remove reloc here?
- __ patchable_jump(entry_point, relocInfo::runtime_call_type, Rtemp);
- __ bind_literal(oop_literal);
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- address jump_address;
- jump_address = code_begin + NativeInstruction::instruction_size;
- NativeJump* jump = nativeJump_at(jump_address);
- return jump->jump_destination();
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin);
- return (void*)move->data();
-}
-
-#undef __
diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp
index b827e69d02233..99d619bddb55a 100644
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp
@@ -28,6 +28,7 @@
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.hpp"
#include "ci/ciEnv.hpp"
+#include "code/compiledIC.hpp"
#include "code/nativeInst.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
@@ -297,11 +298,13 @@ Address MacroAssembler::receiver_argument_address(Register params_base, Register
return Address(tmp, -Interpreter::stackElementSize);
}
+void MacroAssembler::align(int modulus, int target) {
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) nop();
+}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) {
- nop();
- }
+ align(modulus, offset());
}
int MacroAssembler::set_last_Java_frame(Register last_java_sp,
@@ -1860,3 +1863,31 @@ void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2,
// Fallthrough: success
}
+
+int MacroAssembler::ic_check_size() {
+ return NativeInstruction::instruction_size * 7;
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = j_rarg0;
+ Register tmp1 = R4;
+ Register tmp2 = R5;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldr(tmp2, Address(Ricklass, CompiledICData::speculated_klass_offset()));
+ cmp(tmp1, tmp2);
+
+ Label dont;
+ b(dont, eq);
+ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type);
+ bind(dont);
+ return uep_offset;
+}
diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp
index d9e49ab986c3a..691c8fa70ee8b 100644
--- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp
@@ -221,6 +221,7 @@ class MacroAssembler: public Assembler {
inline bool ignore_non_patchable_relocations() { return true; }
void align(int modulus);
+ void align(int modulus, int target);
// Support for VM calls
//
@@ -1077,6 +1078,9 @@ class MacroAssembler: public Assembler {
void safepoint_poll(Register tmp1, Label& slow_path);
void get_polling_page(Register dest);
void read_polling_page(Register dest, relocInfo::relocType rtype);
+
+ static int ic_check_size();
+ int ic_check(int end_alignment);
};
diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
index 23ee01d335264..6a4062f29b3ba 100644
--- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
+++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_arm.hpp"
#include "oops/oop.inline.hpp"
diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
index 7006d7709813a..15b57188730df 100644
--- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
+++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
@@ -385,7 +385,7 @@ class NativeMovConstReg: public NativeInstruction {
}
void set_pc_relative_offset(address addr, address pc);
address next_instruction_address() const {
- // NOTE: CompiledStaticCall::set_to_interpreted() calls this but
+ // NOTE: CompiledDirectCall::set_to_interpreted() calls this but
// are restricted to single-instruction ldr. No need to jump over
// several instructions.
assert(is_ldr_literal(), "Should only use single-instructions load");
diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
index 716c7b7575e9c..3792fab082ba6 100644
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
@@ -24,15 +24,14 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/jniHandles.hpp"
@@ -626,12 +625,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label skip_fixup;
const Register receiver = R0;
const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure
- const Register receiver_klass = R4;
- __ load_klass(receiver_klass, receiver);
- __ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
- __ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
- __ cmp(receiver_klass, holder_klass);
+ __ ic_check(1 /* end_alignment */);
+ __ ldr(Rmethod, Address(Ricklass, CompiledICData::speculated_method_offset()));
__ ldr(Rtemp, Address(Rmethod, Method::code_offset()), eq);
__ cmp(Rtemp, 0, eq);
@@ -819,21 +815,14 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Unverified entry point
address start = __ pc();
- // Inline cache check, same as in C1_MacroAssembler::inline_cache_check()
const Register receiver = R0; // see receiverOpr()
- __ load_klass(Rtemp, receiver);
- __ cmp(Rtemp, Ricklass);
- Label verified;
-
- __ b(verified, eq); // jump over alignment no-ops too
- __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp);
- __ align(CodeEntryAlignment);
+ __ verify_oop(receiver);
+ // Inline cache check
+ __ ic_check(CodeEntryAlignment /* end_alignment */);
// Verified entry point
- __ bind(verified);
int vep_offset = __ pc() - start;
-
if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
// Object.hashCode, System.identityHashCode can pull the hashCode from the header word
// instead of doing a full VM transition once it's been computed.
diff --git a/src/hotspot/cpu/arm/vtableStubs_arm.cpp b/src/hotspot/cpu/arm/vtableStubs_arm.cpp
index 539e288f63fb2..1229b5073f506 100644
--- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp
+++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_arm.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "oops/klass.inline.hpp"
@@ -160,7 +160,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(Rclass, R0);
// Receiver subtype check against REFC.
- __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
+ __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_refc_klass_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, noreg,
// outputs: temp reg1, temp reg2
@@ -171,7 +171,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
start_pc = __ pc();
// Get Method* and entry point for compiler
- __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
+ __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_defc_klass_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, itable_index,
// outputs: temp reg1, temp reg2, temp reg3
diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
index 47b681ce26be4..d78dec964cbb0 100644
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
@@ -451,7 +451,7 @@ inline void Assembler::bcctrl(int boint, int biint, int bhint, relocInfo::relocT
// helper function for b
inline bool Assembler::is_within_range_of_b(address a, address pc) {
- // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file).
+ // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file).
if ((((uint64_t)a) & 0x3) != 0) return false;
const int range = 1 << (29-6); // li field is from bit 6 to bit 29.
@@ -465,7 +465,7 @@ inline bool Assembler::is_within_range_of_b(address a, address pc) {
// helper functions for bcxx.
inline bool Assembler::is_within_range_of_bcxx(address a, address pc) {
- // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file).
+ // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file).
if ((((uint64_t)a) & 0x3) != 0) return false;
const int range = 1 << (29-16); // bd field is from bit 16 to bit 29.
diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
index 1a00c9ad268c7..dc70c73d4b330 100644
--- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
@@ -456,6 +456,9 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
__ extsw(R7_ARG5, length()->as_register());
ce->emit_static_call_stub();
+ if (ce->compilation()->bailed_out()) {
+ return; // CodeCache is full
+ }
bool success = ce->emit_trampoline_stub_for_call(SharedRuntime::get_resolve_static_call_stub());
if (!success) { return; }
diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
index 9913a589683a4..3ae35949b2148 100644
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
@@ -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.
* Copyright (c) 2012, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -77,9 +77,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const {
// we fetch the class of the receiver and compare it with the cached class.
// If they do not match we jump to slow case.
int LIR_Assembler::check_icache() {
- int offset = __ offset();
- __ inline_cache_check(R3_ARG1, R19_inline_cache_reg);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -2300,7 +2298,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
op->tmp1()->as_register(),
op->tmp2()->as_register(),
op->tmp3()->as_register(),
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
type2aelembytes(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
@@ -2862,6 +2860,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
if (info != nullptr) {
add_call_info_here(info);
}
+ assert(__ last_calls_return_pc() == __ pc(), "pcn not at return pc");
__ post_call_nop();
}
diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
index 577dcae25f4bc..219aeaf316d87 100644
--- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -40,29 +40,6 @@
#include "utilities/macros.hpp"
#include "utilities/powerOfTwo.hpp"
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- const Register temp_reg = R12_scratch2;
- Label Lmiss;
-
- verify_oop(receiver, FILE_AND_LINE);
- load_klass_check_null(temp_reg, receiver, &Lmiss);
-
- if (TrapBasedICMissChecks && TrapBasedNullChecks) {
- trap_ic_miss_check(temp_reg, iCache);
- } else {
- Label Lok;
- cmpd(CCR0, temp_reg, iCache);
- beq(CCR0, Lok);
- bind(Lmiss);
- //load_const_optimized(temp_reg, SharedRuntime::get_ic_miss_stub(), R0);
- calculate_address_from_global_toc(temp_reg, SharedRuntime::get_ic_miss_stub(), true, true, false);
- mtctr(temp_reg);
- bctr();
- align(32, 12);
- bind(Lok);
- }
-}
-
void C1_MacroAssembler::explicit_null_check(Register base) {
Unimplemented();
@@ -178,9 +155,6 @@ void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rb
verify_oop(Roop, FILE_AND_LINE);
if (LockingMode == LM_LIGHTWEIGHT) {
- ld(Rmark, oopDesc::mark_offset_in_bytes(), Roop);
- andi_(R0, Rmark, markWord::monitor_value);
- bne(CCR0, slow_int);
lightweight_unlock(Roop, Rmark, slow_int);
} else if (LockingMode == LM_LEGACY) {
// Check if it is still a light weight lock, this is is true if we see
@@ -333,7 +307,7 @@ void C1_MacroAssembler::allocate_array(
Register t1, // temp register
Register t2, // temp register
Register t3, // temp register
- int hdr_size, // object header size in words
+ int base_offset_in_bytes, // elements offset in bytes
int elt_size, // element size in bytes
Register klass, // object klass
Label& slow_case // continuation point if fast allocation fails
@@ -365,7 +339,7 @@ void C1_MacroAssembler::allocate_array(
sldi(t1, len, log2_elt_size);
arr_len_in_bytes = t1;
}
- addi(arr_size, arr_len_in_bytes, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment.
+ addi(arr_size, arr_len_in_bytes, base_offset_in_bytes + MinObjAlignmentInBytesMask); // Add space for header & alignment.
clrrdi(arr_size, arr_size, LogMinObjAlignmentInBytes); // Align array size.
// Allocate space & initialize header.
@@ -375,8 +349,18 @@ void C1_MacroAssembler::allocate_array(
// Initialize body.
const Register base = t2;
const Register index = t3;
- addi(base, obj, hdr_size * wordSize); // compute address of first element
- addi(index, arr_size, -(hdr_size * wordSize)); // compute index = number of bytes to clear
+ addi(base, obj, base_offset_in_bytes); // compute address of first element
+ addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear
+
+ // Zero first 4 bytes, if start offset is not word aligned.
+ if (!is_aligned(base_offset_in_bytes, BytesPerWord)) {
+ assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned");
+ li(t1, 0);
+ stw(t1, 0, base);
+ addi(base, base, BytesPerInt);
+ // Note: initialize_body will align index down, no need to correct it here.
+ }
+
initialize_body(base, index);
if (CURRENT_ENV->dtrace_alloc_probes()) {
diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp
index 5fa19d5fd5dad..ab31431e67d9c 100644
--- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -80,7 +80,7 @@
Register t1, // temp register
Register t2, // temp register
Register t3, // temp register
- int hdr_size, // object header size in words
+ int base_offset_in_bytes, // elements offset in bytes
int elt_size, // element size in bytes
Register klass, // object klass
Label& slow_case // continuation point if fast allocation fails
diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
index 2ba6a6bca4e03..63914c5d1cb93 100644
--- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
@@ -34,7 +34,6 @@
#include "gc/shared/cardTableBarrierSet.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_ppc.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_ppc.hpp"
diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
index d504c71e2b8bc..cc69c0abe361f 100644
--- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
@@ -36,6 +36,17 @@
#endif
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+void C2_MacroAssembler::fast_lock_lightweight(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3) {
+ compiler_fast_lock_lightweight_object(flag, obj, tmp1, tmp2, tmp3);
+}
+
+void C2_MacroAssembler::fast_unlock_lightweight(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3) {
+ compiler_fast_unlock_lightweight_object(flag, obj, tmp1, tmp2, tmp3);
+}
+
// Intrinsics for CompactStrings
// Compress char[] to byte[] by compressing 16 bytes at once.
diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp
index ef4840b08a256..5096810ef9110 100644
--- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp
@@ -28,6 +28,12 @@
// C2_MacroAssembler contains high-level macros for C2
public:
+ // Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file.
+ void fast_lock_lightweight(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3);
+ void fast_unlock_lightweight(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3);
+
// Intrinsics for CompactStrings
// Compress char[] to byte[] by compressing 16 bytes at once.
void string_compress_16(Register src, Register dst, Register cnt,
diff --git a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
index 54f9cfa936797..355ac4815d551 100644
--- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
+++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
@@ -37,7 +36,7 @@
// ----------------------------------------------------------------------------
-// A PPC CompiledDirectStaticCall looks like this:
+// A PPC CompiledDirectCall looks like this:
//
// >>>> consts
//
@@ -79,7 +78,7 @@
const int IC_pos_in_java_to_interp_stub = 8;
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
#ifdef COMPILER2
if (mark == nullptr) {
// Get the mark within main instrs section which is set to the address of the call.
@@ -91,7 +90,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
MacroAssembler _masm(&cbuf);
// Start the stub.
- address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
+ address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size());
if (stub == nullptr) {
return nullptr; // CodeCache is full
}
@@ -135,7 +134,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// FIXME: Assert that the stub can be identified and patched.
// Java_to_interp_stub_size should be good.
- assert((__ offset() - stub_start_offset) <= CompiledStaticCall::to_interp_stub_size(),
+ assert((__ offset() - stub_start_offset) <= CompiledDirectCall::to_interp_stub_size(),
"should be good size");
assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)),
"must not confuse java_to_interp with trampoline stubs");
@@ -153,27 +152,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// Size of java_to_interp stub, this doesn't need to be accurate but it must
// be larger or equal to the real size of the stub.
// Used for optimization in Compile::Shorten_branches.
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 12 * BytesPerInstWord;
}
// Relocation entries for call stub, compiled java to interpreter.
// Used for optimization in Compile::Shorten_branches.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 5;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -188,7 +180,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -204,7 +196,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp b/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
index 23229d0a4c316..c1a98b734dab7 100644
--- a/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
@@ -350,7 +350,7 @@ inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) {
if (is_entry_frame) {
callers_sp = _cont.entryFP();
} else {
- CodeBlob* cb = CodeCache::find_blob(pc);
+ CodeBlob* cb = CodeCache::find_blob_fast(pc);
callers_sp = sp + cb->frame_size();
}
// set the back link
diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp
index 637883986195b..b63789f320d7e 100644
--- a/src/hotspot/cpu/ppc/frame_ppc.cpp
+++ b/src/hotspot/cpu/ppc/frame_ppc.cpp
@@ -136,7 +136,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
// It should be safe to construct the sender though it might not be valid.
- frame sender(sender_sp, sender_pc);
+ frame sender(sender_sp, sender_pc, nullptr /* unextended_sp */, nullptr /* fp */, sender_blob);
// Do we have a valid fp?
address sender_fp = (address) sender.fp();
@@ -196,12 +196,12 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
assert(map->include_argument_oops(), "should be set by clear");
if (jfa->last_Java_pc() != nullptr) {
- frame fr(jfa->last_Java_sp(), jfa->last_Java_pc());
+ frame fr(jfa->last_Java_sp(), jfa->last_Java_pc(), kind::code_blob);
return fr;
}
// Last_java_pc is not set, if we come here from compiled code. The
// constructor retrieves the PC from the stack.
- frame fr(jfa->last_Java_sp());
+ frame fr(jfa->last_Java_sp(), nullptr, kind::code_blob);
return fr;
}
@@ -229,7 +229,7 @@ frame frame::sender_for_upcall_stub_frame(RegisterMap* map) const {
assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
map->clear();
assert(map->include_argument_oops(), "should be set by clear");
- frame fr(jfa->last_Java_sp(), jfa->last_Java_pc());
+ frame fr(jfa->last_Java_sp(), jfa->last_Java_pc(), kind::code_blob);
return fr;
}
@@ -451,7 +451,7 @@ intptr_t *frame::initial_deoptimization_info() {
#ifndef PRODUCT
// This is a generic constructor which is only used by pns() in debug.cpp.
// fp is dropped and gets determined by backlink.
-frame::frame(void* sp, void* fp, void* pc) : frame((intptr_t*)sp, (address)pc) {}
+frame::frame(void* sp, void* fp, void* pc) : frame((intptr_t*)sp, (address)pc, kind::unknown) {}
#endif
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
diff --git a/src/hotspot/cpu/ppc/frame_ppc.hpp b/src/hotspot/cpu/ppc/frame_ppc.hpp
index d2c9927f119ee..0e0c1a388bfc6 100644
--- a/src/hotspot/cpu/ppc/frame_ppc.hpp
+++ b/src/hotspot/cpu/ppc/frame_ppc.hpp
@@ -393,16 +393,26 @@
inline common_abi* own_abi() const { return (common_abi*) _sp; }
inline common_abi* callers_abi() const { return (common_abi*) _fp; }
+ enum class kind {
+ unknown, // The frame's pc is not necessarily in the CodeCache.
+ // CodeCache::find_blob_fast(void* pc) can yield wrong results in this case and must not be used.
+ code_blob, // The frame's pc is known to be in the CodeCache but it is likely not in an nmethod.
+ // CodeCache::find_blob_fast() will be correct but not faster in this case.
+ nmethod // This is likely the frame of a nmethod.
+ // The code cache lookup is optimized based on NativePostCallNops.
+ };
+
private:
// Initialize frame members (_pc and _sp must be given)
- inline void setup();
+ inline void setup(kind knd);
public:
// Constructors
inline frame(intptr_t* sp, intptr_t* fp, address pc);
- inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp = nullptr, intptr_t* fp = nullptr, CodeBlob* cb = nullptr);
+ inline frame(intptr_t* sp, address pc, kind knd = kind::nmethod);
+ inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp, intptr_t* fp = nullptr, CodeBlob* cb = nullptr);
inline frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map);
inline frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map, bool on_heap);
diff --git a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
index 220b9c3241e01..7b1f37a342ffd 100644
--- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
@@ -35,14 +35,14 @@
// Inline functions for ppc64 frames:
// Initialize frame members (_sp must be given)
-inline void frame::setup() {
+inline void frame::setup(kind knd) {
if (_pc == nullptr) {
_pc = (address)own_abi()->lr;
assert(_pc != nullptr, "must have PC");
}
if (_cb == nullptr) {
- _cb = CodeCache::find_blob(_pc);
+ _cb = (knd == kind::nmethod) ? CodeCache::find_blob_fast(_pc) : CodeCache::find_blob(_pc);
}
if (_unextended_sp == nullptr) {
@@ -89,21 +89,27 @@ inline void frame::setup() {
inline frame::frame() : _sp(nullptr), _pc(nullptr), _cb(nullptr), _oop_map(nullptr), _deopt_state(unknown),
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(nullptr), _fp(nullptr) {}
-inline frame::frame(intptr_t* sp) : frame(sp, nullptr) {}
+inline frame::frame(intptr_t* sp) : frame(sp, nullptr, kind::nmethod) {}
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) : frame(sp, pc, nullptr, fp, nullptr) {}
+inline frame::frame(intptr_t* sp, address pc, kind knd)
+ : _sp(sp), _pc(pc), _cb(nullptr), _oop_map(nullptr),
+ _on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(sp), _fp(nullptr) {
+ setup(knd);
+}
+
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp, intptr_t* fp, CodeBlob* cb)
: _sp(sp), _pc(pc), _cb(cb), _oop_map(nullptr),
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(unextended_sp), _fp(fp) {
- setup();
+ setup(kind::nmethod);
}
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map)
: _sp(sp), _pc(pc), _cb(cb), _oop_map(oop_map),
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(unextended_sp), _fp(fp) {
assert(_cb != nullptr, "pc: " INTPTR_FORMAT, p2i(pc));
- setup();
+ setup(kind::nmethod);
}
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb,
@@ -113,7 +119,7 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
// In thaw, non-heap frames use this constructor to pass oop_map. I don't know why.
assert(_on_heap || _cb != nullptr, "these frames are always heap frames");
if (cb != nullptr) {
- setup();
+ setup(kind::nmethod);
}
#ifdef ASSERT
// The following assertion has been disabled because it would sometime trap for Continuation.run,
@@ -300,7 +306,7 @@ inline frame frame::sender_raw(RegisterMap* map) const {
// Must be native-compiled frame, i.e. the marshaling code for native
// methods that exists in the core system.
- return frame(sender_sp(), sender_pc());
+ return frame(sender_sp(), sender_pc(), kind::code_blob);
}
inline frame frame::sender(RegisterMap* map) const {
diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp
index cd2fd355bbb97..ab520162d350e 100644
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp
@@ -30,9 +30,9 @@
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1CardTable.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/sharedRuntime.hpp"
diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp
index ec91e86cd7c9a..44bb03aa6d87d 100644
--- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp
@@ -23,11 +23,10 @@
*
*/
-#include "gc/shared/gcArguments.hpp"
-#include "gc/shared/gc_globals.hpp"
-#include "macroAssembler_ppc.hpp"
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/gcArguments.hpp"
+#include "gc/shared/gc_globals.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
#include "gc/shenandoah/shenandoahForwarding.hpp"
@@ -38,6 +37,7 @@
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
#include "interpreter/interpreter.hpp"
+#include "macroAssembler_ppc.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/globalDefinitions.hpp"
diff --git a/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp
index b83994ee8de94..7db34177d3acf 100644
--- a/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp
@@ -22,8 +22,8 @@
* questions.
*/
-#include "asm/register.hpp"
#include "precompiled.hpp"
+#include "asm/register.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/codeBlob.hpp"
#include "code/vmreg.inline.hpp"
diff --git a/src/hotspot/cpu/ppc/globals_ppc.hpp b/src/hotspot/cpu/ppc/globals_ppc.hpp
index f46ca5db3b7df..a2a94c178fb8b 100644
--- a/src/hotspot/cpu/ppc/globals_ppc.hpp
+++ b/src/hotspot/cpu/ppc/globals_ppc.hpp
@@ -60,7 +60,7 @@ define_pd_global(bool, VMContinuations, true);
// Use large code-entry alignment.
define_pd_global(uintx, CodeCacheSegmentSize, 128);
-define_pd_global(intx, CodeEntryAlignment, 128);
+define_pd_global(intx, CodeEntryAlignment, 64);
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineSmallCode, 1500);
diff --git a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp b/src/hotspot/cpu/ppc/icBuffer_ppc.cpp
deleted file mode 100644
index 4157a5b0fd788..0000000000000
--- a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_ppc.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm.
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return MacroAssembler::load_const_size + MacroAssembler::b64_patchable_size;
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler masm(&code);
- // Note: even though the code contains an embedded metadata, we do not need reloc info
- // because
- // (1) the metadata is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear.
-
- // Load the oop ...
- __ load_const(R19_method, (address) cached_value, R0);
- // ... and jump to entry point.
- __ b64_patchable((address) entry_point, relocInfo::none);
-
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(move->next_instruction_address());
- return jump->jump_destination();
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- void* o = (void*)move->data();
- return o;
-}
-
diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
index 54a31a16c8aa1..94ef1b3c9d2be 100644
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
@@ -970,9 +970,6 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
// markWord displaced_header = obj->mark().set_unlocked();
- // Load markWord from object into header.
- ld(header, oopDesc::mark_offset_in_bytes(), object);
-
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, object);
lwz(tmp, in_bytes(Klass::access_flags_offset()), tmp);
@@ -981,9 +978,11 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
}
if (LockingMode == LM_LIGHTWEIGHT) {
- lightweight_lock(object, /* mark word */ header, tmp, slow_case);
+ lightweight_lock(object, header, tmp, slow_case);
b(count_locking);
} else if (LockingMode == LM_LEGACY) {
+ // Load markWord from object into header.
+ ld(header, oopDesc::mark_offset_in_bytes(), object);
// Set displaced_header to be (markWord of object | UNLOCK_VALUE).
ori(header, header, markWord::unlocked_value);
@@ -1115,22 +1114,6 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) {
ld(object, in_bytes(BasicObjectLock::obj_offset()), monitor);
if (LockingMode == LM_LIGHTWEIGHT) {
- // Check for non-symmetric locking. This is allowed by the spec and the interpreter
- // must handle it.
- Register tmp = current_header;
- // First check for lock-stack underflow.
- lwz(tmp, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
- cmplwi(CCR0, tmp, (unsigned)LockStack::start_offset());
- ble(CCR0, slow_case);
- // Then check if the top of the lock-stack matches the unlocked object.
- addi(tmp, tmp, -oopSize);
- ldx(tmp, tmp, R16_thread);
- cmpd(CCR0, tmp, object);
- bne(CCR0, slow_case);
-
- ld(header, oopDesc::mark_offset_in_bytes(), object);
- andi_(R0, header, markWord::monitor_value);
- bne(CCR0, slow_case);
lightweight_unlock(object, header, slow_case);
} else {
addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes());
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
index 8942199610ebc..b7b5936a58da0 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/barrierSet.hpp"
@@ -37,6 +38,7 @@
#include "oops/klass.inline.hpp"
#include "oops/methodData.hpp"
#include "prims/methodHandles.hpp"
+#include "register_ppc.hpp"
#include "runtime/icache.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/objectMonitor.hpp"
@@ -1187,8 +1189,87 @@ void MacroAssembler::post_call_nop() {
if (!Continuations::enabled()) {
return;
}
+ // We use CMPI/CMPLI instructions to encode post call nops.
+ // Refer to NativePostCallNop for details.
+ relocate(post_call_nop_Relocation::spec());
InlineSkippedInstructionsCounter skipCounter(this);
- nop();
+ Assembler::emit_int32(Assembler::CMPLI_OPCODE | Assembler::opp_u_field(1, 9, 9));
+ assert(is_post_call_nop(*(int*)(pc() - 4)), "post call not not found");
+}
+
+int MacroAssembler::ic_check_size() {
+ bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(),
+ use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks,
+ use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks;
+
+ int num_ins;
+ if (use_fast_receiver_null_check && TrapBasedICMissChecks) {
+ num_ins = 3;
+ if (use_trap_based_null_check) num_ins += 1;
+ } else {
+ num_ins = 7;
+ if (!implicit_null_checks_available) num_ins += 2;
+ }
+ return num_ins * BytesPerInstWord;
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(),
+ use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks,
+ use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks;
+
+ Register receiver = R3_ARG1;
+ Register data = R19_inline_cache_reg;
+ Register tmp1 = R11_scratch1;
+ Register tmp2 = R12_scratch2;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, end_alignment, end_alignment - ic_check_size());
+
+ int uep_offset = offset();
+
+ if (use_fast_receiver_null_check && TrapBasedICMissChecks) {
+ // Fast version which uses SIGTRAP
+
+ if (use_trap_based_null_check) {
+ trap_null_check(receiver);
+ }
+ if (UseCompressedClassPointers) {
+ lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ } else {
+ ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ }
+ ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
+ trap_ic_miss_check(tmp1, tmp2);
+
+ } else {
+ // Slower version which doesn't use SIGTRAP
+
+ // Load stub address using toc (fixed instruction size, unlike load_const_optimized)
+ calculate_address_from_global_toc(tmp1, SharedRuntime::get_ic_miss_stub(),
+ true, true, false); // 2 instructions
+ mtctr(tmp1);
+
+ if (!implicit_null_checks_available) {
+ cmpdi(CCR0, receiver, 0);
+ beqctr(CCR0);
+ }
+ if (UseCompressedClassPointers) {
+ lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ } else {
+ ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ }
+ ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
+ cmpd(CCR0, tmp1, tmp2);
+ bnectr(CCR0);
+ }
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
}
void MacroAssembler::call_VM_base(Register oop_result,
@@ -2179,8 +2260,8 @@ address MacroAssembler::emit_trampoline_stub(int destination_toc_offset,
// "The box" is the space on the stack where we copy the object mark.
void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box,
Register temp, Register displaced_header, Register current_header) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_lock_lightweight");
assert_different_registers(oop, box, temp, displaced_header, current_header);
- assert(LockingMode != LM_LIGHTWEIGHT || flag == CCR0, "bad condition register");
Label object_has_monitor;
Label cas_failed;
Label success, failure;
@@ -2204,7 +2285,8 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
// Set NE to indicate 'failure' -> take slow-path.
crandc(flag, Assembler::equal, flag, Assembler::equal);
b(failure);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Set displaced_header to be (markWord of object | UNLOCK_VALUE).
ori(displaced_header, displaced_header, markWord::unlocked_value);
@@ -2248,10 +2330,6 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
}
beq(CCR0, success);
b(failure);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- lightweight_lock(oop, displaced_header, temp, failure);
- b(success);
}
// Handle existing monitor.
@@ -2269,10 +2347,8 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
MacroAssembler::cmpxchgx_hint_acquire_lock());
- if (LockingMode != LM_LIGHTWEIGHT) {
- // Store a non-null value into the box.
- std(box, BasicLock::displaced_header_offset_in_bytes(), box);
- }
+ // Store a non-null value into the box.
+ std(box, BasicLock::displaced_header_offset_in_bytes(), box);
beq(flag, success);
// Check for recursive locking.
@@ -2294,8 +2370,8 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box,
Register temp, Register displaced_header, Register current_header) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_unlock_lightweight");
assert_different_registers(oop, box, temp, displaced_header, current_header);
- assert(LockingMode != LM_LIGHTWEIGHT || flag == CCR0, "bad condition register");
Label success, failure, object_has_monitor, notRecursive;
if (LockingMode == LM_LEGACY) {
@@ -2317,7 +2393,8 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
// Set NE to indicate 'failure' -> take slow-path.
crandc(flag, Assembler::equal, flag, Assembler::equal);
b(failure);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is is true if we see
// the stack address of the basicLock in the markWord of the object.
// Cmpxchg sets flag to cmpd(current_header, box).
@@ -2332,10 +2409,6 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
&failure);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
b(success);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- lightweight_unlock(oop, current_header, failure);
- b(success);
}
// Handle existing monitor.
@@ -2375,6 +2448,276 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
bind(failure);
}
+void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister flag, Register obj, Register tmp1,
+ Register tmp2, Register tmp3) {
+ assert_different_registers(obj, tmp1, tmp2, tmp3);
+ assert(flag == CCR0, "bad condition register");
+
+ // Handle inflated monitor.
+ Label inflated;
+ // Finish fast lock successfully. MUST reach to with flag == NE
+ Label locked;
+ // Finish fast lock unsuccessfully. MUST branch to with flag == EQ
+ Label slow_path;
+
+ if (DiagnoseSyncOnValueBasedClasses != 0) {
+ load_klass(tmp1, obj);
+ lwz(tmp1, in_bytes(Klass::access_flags_offset()), tmp1);
+ testbitdi(flag, R0, tmp1, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
+ bne(flag, slow_path);
+ }
+
+ const Register mark = tmp1;
+ const Register t = tmp3; // Usage of R0 allowed!
+
+ { // Lightweight locking
+
+ // Push lock to the lock stack and finish successfully. MUST reach to with flag == EQ
+ Label push;
+
+ const Register top = tmp2;
+
+ // Check if lock-stack is full.
+ lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ cmplwi(flag, top, LockStack::end_offset() - 1);
+ bgt(flag, slow_path);
+
+ // The underflow check is elided. The recursive check will always fail
+ // when the lock stack is empty because of the _bad_oop_sentinel field.
+
+ // Check if recursive.
+ subi(t, top, oopSize);
+ ldx(t, R16_thread, t);
+ cmpd(flag, obj, t);
+ beq(flag, push);
+
+ // Check for monitor (0b10) or locked (0b00).
+ ld(mark, oopDesc::mark_offset_in_bytes(), obj);
+ andi_(t, mark, markWord::lock_mask_in_place);
+ cmpldi(flag, t, markWord::unlocked_value);
+ bgt(flag, inflated);
+ bne(flag, slow_path);
+
+ // Not inflated.
+
+ // Try to lock. Transition lock bits 0b00 => 0b01
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea");
+ atomically_flip_locked_state(/* is_unlock */ false, obj, mark, slow_path, MacroAssembler::MemBarAcq);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ stdx(obj, R16_thread, top);
+ addi(top, top, oopSize);
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ b(locked);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated);
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register tagged_monitor = mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+ const Register owner_addr = tmp2;
+
+ // Compute owner address.
+ addi(owner_addr, tagged_monitor, in_bytes(ObjectMonitor::owner_offset()) - monitor_tag);
+
+ // CAS owner (null => current thread).
+ cmpxchgd(/*flag=*/flag,
+ /*current_value=*/t,
+ /*compare_value=*/(intptr_t)0,
+ /*exchange_value=*/R16_thread,
+ /*where=*/owner_addr,
+ MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
+ MacroAssembler::cmpxchgx_hint_acquire_lock());
+ beq(flag, locked);
+
+ // Check if recursive.
+ cmpd(flag, t, R16_thread);
+ bne(flag, slow_path);
+
+ // Recursive.
+ ld(tmp1, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), owner_addr);
+ addi(tmp1, tmp1, 1);
+ std(tmp1, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), owner_addr);
+ }
+
+ bind(locked);
+ inc_held_monitor_count(tmp1);
+
+#ifdef ASSERT
+ // Check that locked label is reached with flag == EQ.
+ Label flag_correct;
+ beq(flag, flag_correct);
+ stop("Fast Lock Flag != EQ");
+#endif
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag == NE.
+ bne(flag, flag_correct);
+ stop("Fast Lock Flag != NE");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (NE vs EQ) to determine the continuation.
+}
+
+void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register obj, Register tmp1,
+ Register tmp2, Register tmp3) {
+ assert_different_registers(obj, tmp1, tmp2, tmp3);
+ assert(flag == CCR0, "bad condition register");
+
+ // Handle inflated monitor.
+ Label inflated, inflated_load_monitor;
+ // Finish fast unlock successfully. MUST reach to with flag == EQ.
+ Label unlocked;
+ // Finish fast unlock unsuccessfully. MUST branch to with flag == NE.
+ Label slow_path;
+
+ const Register mark = tmp1;
+ const Register top = tmp2;
+ const Register t = tmp3;
+
+ { // Lightweight unlock
+ Label push_and_slow;
+
+ // Check if obj is top of lock-stack.
+ lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ subi(top, top, oopSize);
+ ldx(t, R16_thread, top);
+ cmpd(flag, obj, t);
+ // Top of lock stack was not obj. Must be monitor.
+ bne(flag, inflated_load_monitor);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(li(t, 0);)
+ DEBUG_ONLY(stdx(t, R16_thread, top);)
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+
+ // The underflow check is elided. The recursive check will always fail
+ // when the lock stack is empty because of the _bad_oop_sentinel field.
+
+ // Check if recursive.
+ subi(t, top, oopSize);
+ ldx(t, R16_thread, t);
+ cmpd(flag, obj, t);
+ beq(flag, unlocked);
+
+ // Not recursive.
+
+ // Check for monitor (0b10).
+ ld(mark, oopDesc::mark_offset_in_bytes(), obj);
+ andi_(t, mark, markWord::monitor_value);
+ bne(CCR0, inflated);
+
+#ifdef ASSERT
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ andi_(t, mark, markWord::unlocked_value);
+ beq(CCR0, not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
+#endif
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ atomically_flip_locked_state(/* is_unlock */ true, obj, mark, push_and_slow, MacroAssembler::MemBarRel);
+ b(unlocked);
+
+ bind(push_and_slow);
+ // Restore lock-stack and handle the unlock in runtime.
+ DEBUG_ONLY(stdx(obj, R16_thread, top);)
+ addi(top, top, oopSize);
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ b(slow_path);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated_load_monitor);
+ ld(mark, oopDesc::mark_offset_in_bytes(), obj);
+#ifdef ASSERT
+ andi_(t, mark, markWord::monitor_value);
+ bne(CCR0, inflated);
+ stop("Fast Unlock not monitor");
+#endif
+
+ bind(inflated);
+
+#ifdef ASSERT
+ Label check_done;
+ subi(top, top, oopSize);
+ cmplwi(CCR0, top, in_bytes(JavaThread::lock_stack_base_offset()));
+ blt(CCR0, check_done);
+ ldx(t, R16_thread, top);
+ cmpd(flag, obj, t);
+ bne(flag, inflated);
+ stop("Fast Unlock lock on stack");
+ bind(check_done);
+#endif
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register monitor = mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+
+ // Untag the monitor.
+ subi(monitor, mark, monitor_tag);
+
+ const Register recursions = tmp2;
+ Label not_recursive;
+
+ // Check if recursive.
+ ld(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ addic_(recursions, recursions, -1);
+ blt(CCR0, not_recursive);
+
+ // Recursive unlock.
+ std(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ crorc(CCR0, Assembler::equal, CCR0, Assembler::equal);
+ b(unlocked);
+
+ bind(not_recursive);
+
+ Label release_;
+ const Register t2 = tmp2;
+
+ // Check if the entry lists are empty.
+ ld(t, in_bytes(ObjectMonitor::EntryList_offset()), monitor);
+ ld(t2, in_bytes(ObjectMonitor::cxq_offset()), monitor);
+ orr(t, t, t2);
+ cmpdi(flag, t, 0);
+ beq(flag, release_);
+
+ // The owner may be anonymous and we removed the last obj entry in
+ // the lock-stack. This loses the information about the owner.
+ // Write the thread to the owner field so the runtime knows the owner.
+ std(R16_thread, in_bytes(ObjectMonitor::owner_offset()), monitor);
+ b(slow_path);
+
+ bind(release_);
+ // Set owner to null.
+ release();
+ // t contains 0
+ std(t, in_bytes(ObjectMonitor::owner_offset()), monitor);
+ }
+
+ bind(unlocked);
+ dec_held_monitor_count(t);
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with flag == EQ.
+ Label flag_correct;
+ beq(flag, flag_correct);
+ stop("Fast Lock Flag != EQ");
+#endif
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag == NE.
+ bne(flag, flag_correct);
+ stop("Fast Lock Flag != NE");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (NE vs EQ) to determine the continuation.
+}
+
void MacroAssembler::safepoint_poll(Label& slow_path, Register temp, bool at_return, bool in_nmethod) {
ld(temp, in_bytes(JavaThread::polling_word_offset()), R16_thread);
@@ -3994,58 +4337,57 @@ void MacroAssembler::atomically_flip_locked_state(bool is_unlock, Register obj,
}
// Implements lightweight-locking.
-// Branches to slow upon failure to lock the object, with CCR0 NE.
-// Falls through upon success with CCR0 EQ.
//
// - obj: the object to be locked
-// - hdr: the header, already loaded from obj, will be destroyed
-// - t1: temporary register
-void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register t1, Label& slow) {
+// - t1, t2: temporary register
+void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr, t1);
+ assert_different_registers(obj, t1, t2);
+
+ Label push;
+ const Register top = t1;
+ const Register mark = t2;
+ const Register t = R0;
+
+ // Check if the lock-stack is full.
+ lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ cmplwi(CCR0, top, LockStack::end_offset());
+ bge(CCR0, slow);
+
+ // The underflow check is elided. The recursive check will always fail
+ // when the lock stack is empty because of the _bad_oop_sentinel field.
- // Check if we would have space on lock-stack for the object.
- lwz(t1, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
- cmplwi(CCR0, t1, LockStack::end_offset() - 1);
- bgt(CCR0, slow);
+ // Check for recursion.
+ subi(t, top, oopSize);
+ ldx(t, R16_thread, t);
+ cmpd(CCR0, obj, t);
+ beq(CCR0, push);
- // Quick check: Do not reserve cache line for atomic update if not unlocked.
- // (Similar to contention_hint in cmpxchg solutions.)
- xori(R0, hdr, markWord::unlocked_value); // flip unlocked bit
- andi_(R0, R0, markWord::lock_mask_in_place);
- bne(CCR0, slow); // failed if new header doesn't contain locked_value (which is 0)
+ // Check header for monitor (0b10) or locked (0b00).
+ ld(mark, oopDesc::mark_offset_in_bytes(), obj);
+ xori(t, mark, markWord::unlocked_value);
+ andi_(t, t, markWord::lock_mask_in_place);
+ bne(CCR0, slow);
- // Note: We're not publishing anything (like the displaced header in LM_LEGACY)
- // to other threads at this point. Hence, no release barrier, here.
- // (The obj has been written to the BasicObjectLock at obj_offset() within the own thread stack.)
- atomically_flip_locked_state(/* is_unlock */ false, obj, hdr, slow, MacroAssembler::MemBarAcq);
+ // Try to lock. Transition lock bits 0b00 => 0b01
+ atomically_flip_locked_state(/* is_unlock */ false, obj, mark, slow, MacroAssembler::MemBarAcq);
+ bind(push);
// After successful lock, push object on lock-stack
- stdx(obj, t1, R16_thread);
- addi(t1, t1, oopSize);
- stw(t1, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ stdx(obj, R16_thread, top);
+ addi(top, top, oopSize);
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
}
// Implements lightweight-unlocking.
-// Branches to slow upon failure, with CCR0 NE.
-// Falls through upon success, with CCR0 EQ.
//
// - obj: the object to be unlocked
-// - hdr: the (pre-loaded) header of the object, will be destroyed
-void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Label& slow) {
+// - t1: temporary register
+void MacroAssembler::lightweight_unlock(Register obj, Register t1, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr);
+ assert_different_registers(obj, t1);
#ifdef ASSERT
- {
- // Check that hdr is fast-locked.
- Label hdr_ok;
- andi_(R0, hdr, markWord::lock_mask_in_place);
- beq(CCR0, hdr_ok);
- stop("Header is not fast-locked");
- bind(hdr_ok);
- }
- Register t1 = hdr; // Reuse in debug build.
{
// The following checks rely on the fact that LockStack is only ever modified by
// its owning thread, even if the lock got inflated concurrently; removal of LockStack
@@ -4055,32 +4397,67 @@ void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Label& slow)
Label stack_ok;
lwz(t1, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
cmplwi(CCR0, t1, LockStack::start_offset());
- bgt(CCR0, stack_ok);
+ bge(CCR0, stack_ok);
stop("Lock-stack underflow");
bind(stack_ok);
}
- {
- // Check if the top of the lock-stack matches the unlocked object.
- Label tos_ok;
- addi(t1, t1, -oopSize);
- ldx(t1, t1, R16_thread);
- cmpd(CCR0, t1, obj);
- beq(CCR0, tos_ok);
- stop("Top of lock-stack does not match the unlocked object");
- bind(tos_ok);
- }
#endif
- // Release the lock.
- atomically_flip_locked_state(/* is_unlock */ true, obj, hdr, slow, MacroAssembler::MemBarRel);
+ Label unlocked, push_and_slow;
+ const Register top = t1;
+ const Register mark = R0;
+ Register t = R0;
+
+ // Check if obj is top of lock-stack.
+ lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ subi(top, top, oopSize);
+ ldx(t, R16_thread, top);
+ cmpd(CCR0, obj, t);
+ bne(CCR0, slow);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(li(t, 0);)
+ DEBUG_ONLY(stdx(t, R16_thread, top);)
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+
+ // The underflow check is elided. The recursive check will always fail
+ // when the lock stack is empty because of the _bad_oop_sentinel field.
+
+ // Check if recursive.
+ subi(t, top, oopSize);
+ ldx(t, R16_thread, t);
+ cmpd(CCR0, obj, t);
+ beq(CCR0, unlocked);
+
+ // Use top as tmp
+ t = top;
+
+ // Not recursive. Check header for monitor (0b10).
+ ld(mark, oopDesc::mark_offset_in_bytes(), obj);
+ andi_(t, mark, markWord::monitor_value);
+ bne(CCR0, push_and_slow);
- // After successful unlock, pop object from lock-stack
- Register t2 = hdr;
- lwz(t2, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
- addi(t2, t2, -oopSize);
#ifdef ASSERT
- li(R0, 0);
- stdx(R0, t2, R16_thread);
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ andi_(t, mark, markWord::unlocked_value);
+ beq(CCR0, not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
#endif
- stw(t2, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ atomically_flip_locked_state(/* is_unlock */ true, obj, t, push_and_slow, MacroAssembler::MemBarRel);
+ b(unlocked);
+
+ bind(push_and_slow);
+
+ // Restore lock-stack and handle the unlock in runtime.
+ lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ DEBUG_ONLY(stdx(obj, R16_thread, top);)
+ addi(top, top, oopSize);
+ stw(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
+ b(slow);
+
+ bind(unlocked);
}
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
index 52d8e7fa96dec..92db8a86b42ff 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
@@ -367,6 +367,9 @@ class MacroAssembler: public Assembler {
Register toc);
#endif
+ static int ic_check_size();
+ int ic_check(int end_alignment);
+
protected:
// It is imperative that all calls into the VM are handled via the
@@ -417,6 +420,12 @@ class MacroAssembler: public Assembler {
inline void call_stub_and_return_to(Register function_entry, Register return_pc);
void post_call_nop();
+ static bool is_post_call_nop(int instr_bits) {
+ const uint32_t nineth_bit = opp_u_field(1, 9, 9);
+ const uint32_t opcode_mask = 0b111110 << OPCODE_SHIFT;
+ const uint32_t pcn_mask = opcode_mask | nineth_bit;
+ return (instr_bits & pcn_mask) == (Assembler::CMPLI_OPCODE | nineth_bit);
+ }
//
// Java utilities
@@ -606,8 +615,8 @@ class MacroAssembler: public Assembler {
void inc_held_monitor_count(Register tmp);
void dec_held_monitor_count(Register tmp);
void atomically_flip_locked_state(bool is_unlock, Register obj, Register tmp, Label& failed, int semantics);
- void lightweight_lock(Register obj, Register hdr, Register t1, Label& slow);
- void lightweight_unlock(Register obj, Register hdr, Label& slow);
+ void lightweight_lock(Register obj, Register t1, Register t2, Label& slow);
+ void lightweight_unlock(Register obj, Register t1, Label& slow);
// allocation (for C1)
void tlab_allocate(
@@ -628,6 +637,12 @@ class MacroAssembler: public Assembler {
void compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box,
Register tmp1, Register tmp2, Register tmp3);
+ void compiler_fast_lock_lightweight_object(ConditionRegister flag, Register oop, Register tmp1,
+ Register tmp2, Register tmp3);
+
+ void compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register oop, Register tmp1,
+ Register tmp2, Register tmp3);
+
// Check if safepoint requested and if so branch
void safepoint_poll(Label& slow_path, Register temp, bool at_return, bool in_nmethod);
diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp
index 06754ccfdd7d2..e1a41a17d936f 100644
--- a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp
+++ b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp
@@ -429,6 +429,31 @@ void NativePostCallNop::make_deopt() {
NativeDeoptInstruction::insert(addr_at(0));
}
+bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) {
+ int32_t i2, i1;
+ assert(is_aligned(cb_offset, 4), "cb offset alignment does not match instruction alignment");
+ assert(!decode(i1, i2), "already patched");
+
+ cb_offset = cb_offset >> 2;
+ if (((oopmap_slot & ppc_oopmap_slot_mask) != oopmap_slot) || ((cb_offset & ppc_cb_offset_mask) != cb_offset)) {
+ return false; // cannot encode
+ }
+ const uint32_t data = oopmap_slot << ppc_cb_offset_bits | cb_offset;
+ const uint32_t lo_data = data & ppc_data_lo_mask;
+ const uint32_t hi_data = data >> ppc_data_lo_bits;
+ const uint32_t nineth_bit = 1 << (31 - 9);
+ uint32_t instr = Assembler::CMPLI_OPCODE | hi_data << ppc_data_hi_shift | nineth_bit | lo_data;
+ *(uint32_t*)addr_at(0) = instr;
+
+ int32_t oopmap_slot_dec, cb_offset_dec;
+ assert(is_post_call_nop(), "pcn not recognized");
+ assert(decode(oopmap_slot_dec, cb_offset_dec), "encoding failed");
+ assert(oopmap_slot == oopmap_slot_dec, "oopmap slot encoding is wrong");
+ assert((cb_offset << 2) == cb_offset_dec, "cb offset encoding is wrong");
+
+ return true; // encoding succeeded
+}
+
void NativeDeoptInstruction::verify() {
}
diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp
index ec6f5a90a7211..113cedfee7cab 100644
--- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp
+++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp
@@ -51,7 +51,7 @@ class NativeInstruction {
friend class Relocation;
public:
- bool is_nop() const { return Assembler::is_nop(long_at(0)); }
+ bool is_post_call_nop() const { return MacroAssembler::is_post_call_nop(long_at(0)); }
bool is_jump() const { return Assembler::is_b(long_at(0)); } // See NativeGeneralJump.
@@ -506,10 +506,50 @@ class NativeMovRegMem: public NativeInstruction {
};
class NativePostCallNop: public NativeInstruction {
+
+ // We use CMPI/CMPLI to represent Post Call Nops (PCN)
+
+ // Bit |0 5|6 |9 |10|11 |16 31|
+ // +--------------------------------------------------------------+
+ // Field |OPCODE |BF |/ |L |RA |SI |
+ // +--------------------------------------------------------------+
+ // |0 0 1 0 1|DATA HI| 1| DATA LO |
+ // | |4 bits | | 22 bits |
+ //
+ // Bit 9 is always 1 for PCNs to distinguish them from regular CMPI/CMPLI
+ //
+ // Using both, CMPLI (opcode 10 = 0b001010) and CMPI (opcode 11 = 0b001011) for
+ // PCNs allows using bit 5 from the opcode to encode DATA HI.
+
+ enum {
+ ppc_data_lo_bits = 31 - 9,
+ ppc_data_lo_mask = right_n_bits(ppc_data_lo_bits),
+ ppc_data_hi_bits = 9 - 5,
+ ppc_data_hi_shift = ppc_data_lo_bits + 1,
+ ppc_data_hi_mask = right_n_bits(ppc_data_hi_bits) << ppc_data_hi_shift,
+ ppc_data_bits = ppc_data_lo_bits + ppc_data_hi_bits,
+
+ ppc_oopmap_slot_bits = 9,
+ ppc_oopmap_slot_mask = right_n_bits(ppc_oopmap_slot_bits),
+ ppc_cb_offset_bits = ppc_data_bits - ppc_oopmap_slot_bits,
+ ppc_cb_offset_mask = right_n_bits(ppc_cb_offset_bits),
+};
+
public:
- bool check() const { return is_nop(); }
- bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { return false; }
- bool patch(int32_t oopmap_slot, int32_t cb_offset) { return false; }
+ bool check() const { return is_post_call_nop(); }
+ bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const {
+ uint32_t instr_bits = long_at(0);
+ uint32_t data_lo = instr_bits & ppc_data_lo_mask;
+ uint32_t data_hi = (instr_bits & ppc_data_hi_mask) >> 1;
+ uint32_t data = data_hi | data_lo;
+ if (data == 0) {
+ return false; // no data found
+ }
+ cb_offset = (data & ppc_cb_offset_mask) << 2;
+ oopmap_slot = data >> ppc_cb_offset_bits;
+ return true; // decoding succeeded
+ }
+ bool patch(int32_t oopmap_slot, int32_t cb_offset);
void make_deopt();
};
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index be37ff1785b64..1058ae35b76b7 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2012, 2023 SAP SE. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -1026,7 +1026,7 @@ bool followed_by_acquire(const Node *load) {
assert(load->is_Load(), "So far implemented only for loads.");
// Find MemBarAcquire.
- const Node *mba = NULL;
+ const Node *mba = nullptr;
for (DUIterator_Fast imax, i = load->fast_outs(imax); i < imax; i++) {
const Node *out = load->fast_out(i);
if (out->Opcode() == Op_MemBarAcquire) {
@@ -1043,7 +1043,7 @@ bool followed_by_acquire(const Node *load) {
// edge to assure no other operations are in between the two nodes.
//
// So first get the Proj node, mem_proj, to use it to iterate forward.
- Node *mem_proj = NULL;
+ Node *mem_proj = nullptr;
for (DUIterator_Fast imax, i = mba->fast_outs(imax); i < imax; i++) {
mem_proj = mba->fast_out(i); // Runs out of bounds and asserts if Proj not found.
assert(mem_proj->is_Proj(), "only projections here");
@@ -1270,7 +1270,7 @@ source %{
void CallStubImpl::emit_trampoline_stub(C2_MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
address stub = __ emit_trampoline_stub(destination_toc_offset, insts_call_instruction_offset);
- if (stub == NULL) {
+ if (stub == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
}
}
@@ -1305,11 +1305,11 @@ EmitCallOffsets emit_call_with_trampoline_stub(C2_MacroAssembler &_masm, address
offsets.insts_call_instruction_offset = __ offset();
// No entry point given, use the current pc.
- if (entry_point == NULL) entry_point = __ pc();
+ if (entry_point == nullptr) entry_point = __ pc();
// Put the entry point as a constant into the constant pool.
const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none);
- if (entry_point_toc_addr == NULL) {
+ if (entry_point_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return offsets;
}
@@ -1355,8 +1355,8 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, Phase
MachNode *m1 = new loadToc_hiNode();
MachNode *m2 = new loadToc_loNode();
- m1->add_req(NULL);
- m2->add_req(NULL, m1);
+ m1->add_req(nullptr);
+ m2->add_req(nullptr, m1);
m1->_opnds[0] = op_dst;
m2->_opnds[0] = op_dst;
m2->_opnds[1] = op_dst;
@@ -1398,7 +1398,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print("push frame %ld\n\t", -framesize);
}
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
st->print("nmethod entry barrier\n\t");
}
}
@@ -1554,7 +1554,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ std(return_pc, _abi0(lr), callers_sp);
}
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->nmethod_entry_barrier(&_masm, push_frame_temp);
}
@@ -1724,7 +1724,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
if (src_lo == dst_lo && src_hi == dst_hi)
return size; // Self copy, no move.
- if (bottom_type()->isa_vect() != NULL && ideal_reg() == Op_VecX) {
+ if (bottom_type()->isa_vect() != nullptr && ideal_reg() == Op_VecX) {
// Memory->Memory Spill.
if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
int src_offset = ra_->reg2offset(src_lo);
@@ -1910,16 +1910,16 @@ void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
if (!ra_)
st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx);
else
- implementation(NULL, ra_, false, st);
+ implementation(nullptr, ra_, false, st);
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation(&cbuf, ra_, false, NULL);
+ implementation(&cbuf, ra_, false, nullptr);
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation(NULL, ra_, true, NULL);
+ return implementation(nullptr, ra_, true, nullptr);
}
#ifndef PRODUCT
@@ -1978,42 +1978,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
- // Inline_cache contains a klass.
- Register ic_klass = as_Register(Matcher::inline_cache_reg_encode());
- Register receiver_klass = R12_scratch2; // tmp
-
- assert_different_registers(ic_klass, receiver_klass, R11_scratch1, R3_ARG1);
- assert(R11_scratch1 == R11, "need prologue scratch register");
-
- // Check for NULL argument if we don't have implicit null checks.
- if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
- if (TrapBasedNullChecks) {
- __ trap_null_check(R3_ARG1);
- } else {
- Label valid;
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ bne_predict_taken(CCR0, valid);
- // We have a null argument, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ bind(valid);
- }
- }
- // Assume argument is not NULL, load klass from receiver.
- __ load_klass(receiver_klass, R3_ARG1);
-
- if (TrapBasedICMissChecks) {
- __ trap_ic_miss_check(receiver_klass, ic_klass);
- } else {
- Label valid;
- __ cmpd(CCR0, receiver_klass, ic_klass);
- __ beq_predict_taken(CCR0, valid);
- // We have an unexpected klass, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ bind(valid);
- }
-
+ __ ic_check(CodeEntryAlignment);
// Argument is valid and klass is as expected, continue.
}
@@ -2062,7 +2027,10 @@ int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) return 0; // CodeBuffer::expand failed
+ if (base == nullptr) {
+ ciEnv::current()->record_failure("CodeCache is full");
+ return 0; // CodeBuffer::expand failed
+ }
int offset = __ offset();
__ b64_patchable((address)OptoRuntime::exception_blob()->content_begin(),
@@ -2079,7 +2047,10 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) return 0; // CodeBuffer::expand failed
+ if (base == nullptr) {
+ ciEnv::current()->record_failure("CodeCache is full");
+ return 0; // CodeBuffer::expand failed
+ }
int offset = __ offset();
__ bl64_patchable((address)SharedRuntime::deopt_blob()->unpack(),
@@ -2173,7 +2144,7 @@ bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
-bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
return match_rule_supported_vector(opcode, vlen, bt);
}
@@ -2193,11 +2164,11 @@ bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
}
const RegMask* Matcher::predicate_reg_mask(void) {
- return NULL;
+ return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
- return NULL;
+ return nullptr;
}
// Vector calling convention not yet implemented.
@@ -2242,7 +2213,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return max_vector_size(bt); // Same as max.
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
return Matcher::max_vector_size(bt);
}
@@ -2275,7 +2246,7 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
/* TODO: PPC port
// Make a new machine dependent decode node (with its operands).
MachTypeNode *Matcher::make_decode_node() {
- assert(CompressedOops::base() == NULL && CompressedOops::shift() == 0,
+ assert(CompressedOops::base() == nullptr && CompressedOops::shift() == 0,
"This method is only implemented for unscaled cOops mode so far");
MachTypeNode *decode = new decodeN_unscaledNode();
decode->set_opnd_array(0, new iRegPdstOper());
@@ -2286,7 +2257,7 @@ MachTypeNode *Matcher::make_decode_node() {
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
ShouldNotReachHere(); // generic vector operands not supported
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -2545,7 +2516,7 @@ encode %{
// Create a non-oop constant, no relocation needed.
// If it is an IC, it has a virtual_call_Relocation.
const_toc_addr = __ long_constant((jlong)$src$$constant);
- if (const_toc_addr == NULL) {
+ if (const_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -2568,7 +2539,7 @@ encode %{
// Create a non-oop constant, no relocation needed.
// If it is an IC, it has a virtual_call_Relocation.
const_toc_addr = __ long_constant((jlong)$src$$constant);
- if (const_toc_addr == NULL) {
+ if (const_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -2607,8 +2578,8 @@ loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immL
loadConL_loNode *m2 = new loadConL_loNode();
// inputs for new nodes
- m1->add_req(NULL, toc);
- m2->add_req(NULL, m1);
+ m1->add_req(nullptr, toc);
+ m2->add_req(nullptr, m1);
// operands for new nodes
m1->_opnds[0] = new iRegLdstOper(); // dst
@@ -2632,14 +2603,14 @@ loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immL
// Create result.
nodes._large_hi = m1;
nodes._large_lo = m2;
- nodes._small = NULL;
+ nodes._small = nullptr;
nodes._last = nodes._large_lo;
assert(m2->bottom_type()->isa_long(), "must be long");
} else {
loadConLNode *m2 = new loadConLNode();
// inputs for new nodes
- m2->add_req(NULL, toc);
+ m2->add_req(nullptr, toc);
// operands for new nodes
m2->_opnds[0] = new iRegLdstOper(); // dst
@@ -2653,8 +2624,8 @@ loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immL
ra_->set_pair(m2->_idx, reg_second, reg_first);
// Create result.
- nodes._large_hi = NULL;
- nodes._large_lo = NULL;
+ nodes._large_hi = nullptr;
+ nodes._large_lo = nullptr;
nodes._small = m2;
nodes._last = nodes._small;
assert(m2->bottom_type()->isa_long(), "must be long");
@@ -2687,10 +2658,10 @@ loadConLReplicatedNodesTuple loadConLReplicatedNodesTuple_create(Compile *C, Pha
xxspltdNode *m4 = new xxspltdNode();
// inputs for new nodes
- m1->add_req(NULL, toc);
- m2->add_req(NULL, m1);
- m3->add_req(NULL, m2);
- m4->add_req(NULL, m3);
+ m1->add_req(nullptr, toc);
+ m2->add_req(nullptr, m1);
+ m3->add_req(nullptr, m2);
+ m4->add_req(nullptr, m3);
// operands for new nodes
m1->_opnds[0] = new iRegLdstOper(); // dst
@@ -2727,7 +2698,7 @@ loadConLReplicatedNodesTuple loadConLReplicatedNodesTuple_create(Compile *C, Pha
nodes._large_lo = m2;
nodes._moved = m3;
nodes._replicated = m4;
- nodes._small = NULL;
+ nodes._small = nullptr;
nodes._last = nodes._replicated;
assert(m2->bottom_type()->isa_long(), "must be long");
} else {
@@ -2736,7 +2707,7 @@ loadConLReplicatedNodesTuple loadConLReplicatedNodesTuple_create(Compile *C, Pha
xxspltdNode *m4 = new xxspltdNode();
// inputs for new nodes
- m2->add_req(NULL, toc);
+ m2->add_req(nullptr, toc);
// operands for new nodes
m2->_opnds[0] = new iRegLdstOper(); // dst
@@ -2760,8 +2731,8 @@ loadConLReplicatedNodesTuple loadConLReplicatedNodesTuple_create(Compile *C, Pha
ra_->set_pair(m2->_idx, reg_second, reg_first);
// Create result.
- nodes._large_hi = NULL;
- nodes._large_lo = NULL;
+ nodes._large_hi = nullptr;
+ nodes._large_lo = nullptr;
nodes._small = m2;
nodes._moved = m3;
nodes._replicated = m4;
@@ -2801,24 +2772,26 @@ encode %{
intptr_t val = $src$$constant;
relocInfo::relocType constant_reloc = $src->constant_reloc(); // src
address const_toc_addr;
+ RelocationHolder r; // Initializes type to none.
if (constant_reloc == relocInfo::oop_type) {
// Create an oop constant and a corresponding relocation.
- AddressLiteral a = __ allocate_oop_address((jobject)val);
+ AddressLiteral a = __ constant_oop_address((jobject)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
- __ relocate(a.rspec());
+ r = a.rspec();
} else if (constant_reloc == relocInfo::metadata_type) {
+ // Notify OOP recorder (don't need the relocation)
AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
- __ relocate(a.rspec());
} else {
// Create a non-oop constant, no relocation needed.
const_toc_addr = __ long_constant((jlong)$src$$constant);
}
- if (const_toc_addr == NULL) {
+ if (const_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
+ __ relocate(r); // If set above.
// Get the constant's TOC offset.
toc_offset = __ offset_to_method_toc(const_toc_addr);
@@ -2832,24 +2805,26 @@ encode %{
intptr_t val = $src$$constant;
relocInfo::relocType constant_reloc = $src->constant_reloc(); // src
address const_toc_addr;
+ RelocationHolder r; // Initializes type to none.
if (constant_reloc == relocInfo::oop_type) {
// Create an oop constant and a corresponding relocation.
- AddressLiteral a = __ allocate_oop_address((jobject)val);
+ AddressLiteral a = __ constant_oop_address((jobject)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
- __ relocate(a.rspec());
+ r = a.rspec();
} else if (constant_reloc == relocInfo::metadata_type) {
+ // Notify OOP recorder (don't need the relocation)
AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
- __ relocate(a.rspec());
} else { // non-oop pointers, e.g. card mark base, heap top
// Create a non-oop constant, no relocation needed.
const_toc_addr = __ long_constant((jlong)$src$$constant);
}
- if (const_toc_addr == NULL) {
+ if (const_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
+ __ relocate(r); // If set above.
// Get the constant's TOC offset.
const int toc_offset = __ offset_to_method_toc(const_toc_addr);
// Store the toc offset of the constant.
@@ -2870,8 +2845,8 @@ encode %{
loadConP_loNode *m2 = new loadConP_loNode();
// inputs for new nodes
- m1->add_req(NULL, n_toc);
- m2->add_req(NULL, m1);
+ m1->add_req(nullptr, n_toc);
+ m2->add_req(nullptr, m1);
// operands for new nodes
m1->_opnds[0] = new iRegPdstOper(); // dst
@@ -2896,7 +2871,7 @@ encode %{
loadConPNode *m2 = new loadConPNode();
// inputs for new nodes
- m2->add_req(NULL, n_toc);
+ m2->add_req(nullptr, n_toc);
// operands for new nodes
m2->_opnds[0] = new iRegPdstOper(); // dst
@@ -2923,7 +2898,7 @@ encode %{
m2 = new loadConFNode();
}
// inputs for new nodes
- m2->add_req(NULL, n_toc);
+ m2->add_req(nullptr, n_toc);
// operands for new nodes
m2->_opnds[0] = op_dst;
@@ -2947,7 +2922,7 @@ encode %{
m2 = new loadConDNode();
}
// inputs for new nodes
- m2->add_req(NULL, n_toc);
+ m2->add_req(nullptr, n_toc);
// operands for new nodes
m2->_opnds[0] = op_dst;
@@ -3258,9 +3233,9 @@ encode %{
Label d; // dummy
__ bind(d);
Label* p = ($lbl$$label);
- // `p' is `NULL' when this encoding class is used only to
+ // `p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
- Label& l = (NULL == p)? d : *(p);
+ Label& l = (nullptr == p)? d : *(p);
int cc = $cmp$$cmpcode;
int flags_reg = $crx$$reg;
assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding");
@@ -3287,9 +3262,9 @@ encode %{
Label d; // dummy
__ bind(d);
Label* p = ($lbl$$label);
- // `p' is `NULL' when this encoding class is used only to
+ // `p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
- Label& l = (NULL == p)? d : *(p);
+ Label& l = (nullptr == p)? d : *(p);
int cc = $cmp$$cmpcode;
int flags_reg = $crx$$reg;
int bhint = Assembler::bhintNoHint;
@@ -3431,7 +3406,7 @@ encode %{
// Put the entry point as a constant into the constant pool.
const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none);
- if (entry_point_toc_addr == NULL) {
+ if (entry_point_toc_addr == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -3452,8 +3427,8 @@ encode %{
__ bl(__ pc()); // Emits a relocation.
// The stub for call to interpreter.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3470,7 +3445,7 @@ encode %{
// Create a call trampoline stub for the given method.
const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method;
const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none);
- if (entry_point_const == NULL) {
+ if (entry_point_const == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -3479,13 +3454,13 @@ encode %{
if (ra_->C->env()->failing()) { return; } // Code cache may be full.
// Build relocation at call site with ic position as data.
- assert((_load_ic_hi_node != NULL && _load_ic_node == NULL) ||
- (_load_ic_hi_node == NULL && _load_ic_node != NULL),
+ assert((_load_ic_hi_node != nullptr && _load_ic_node == nullptr) ||
+ (_load_ic_hi_node == nullptr && _load_ic_node != nullptr),
"must have one, but can't have both");
- assert((_load_ic_hi_node != NULL && _load_ic_hi_node->_cbuf_insts_offset != -1) ||
- (_load_ic_node != NULL && _load_ic_node->_cbuf_insts_offset != -1),
+ assert((_load_ic_hi_node != nullptr && _load_ic_hi_node->_cbuf_insts_offset != -1) ||
+ (_load_ic_node != nullptr && _load_ic_node->_cbuf_insts_offset != -1),
"must contain instruction offset");
- const int virtual_call_oop_addr_offset = _load_ic_hi_node != NULL
+ const int virtual_call_oop_addr_offset = _load_ic_hi_node != nullptr
? _load_ic_hi_node->_cbuf_insts_offset
: _load_ic_node->_cbuf_insts_offset;
const address virtual_call_oop_addr = __ addr_at(virtual_call_oop_addr_offset);
@@ -3507,7 +3482,7 @@ encode %{
// Create the nodes for loading the IC from the TOC.
loadConLNodesTuple loadConLNodes_IC =
- loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()),
+ loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) Universe::non_oop_word()),
OptoReg::Name(R19_H_num), OptoReg::Name(R19_num));
// Create the call node.
@@ -3625,7 +3600,7 @@ encode %{
const address start_pc = __ pc();
#if defined(ABI_ELFv2)
- address entry= !($meth$$method) ? NULL : (address)$meth$$method;
+ address entry= !($meth$$method) ? nullptr : (address)$meth$$method;
__ call_c(entry, relocInfo::runtime_call_type);
__ post_call_nop();
#else
@@ -3682,13 +3657,13 @@ encode %{
// Create nodes and operands for loading the env pointer.
- if (fd->env() != NULL) {
+ if (fd->env() != nullptr) {
loadConLNodes_Env = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->env()),
OptoReg::Name(R11_H_num), OptoReg::Name(R11_num));
} else {
- loadConLNodes_Env._large_hi = NULL;
- loadConLNodes_Env._large_lo = NULL;
- loadConLNodes_Env._small = NULL;
+ loadConLNodes_Env._large_hi = nullptr;
+ loadConLNodes_Env._large_lo = nullptr;
+ loadConLNodes_Env._small = nullptr;
loadConLNodes_Env._last = new loadConL16Node();
loadConLNodes_Env._last->_opnds[0] = new iRegLdstOper();
loadConLNodes_Env._last->_opnds[1] = new immL16Oper(0);
@@ -3702,7 +3677,7 @@ encode %{
// mtctr node
MachNode *mtctr = new CallLeafDirect_mtctrNode();
- assert(loadConLNodes_Entry._last != NULL, "entry must exist");
+ assert(loadConLNodes_Entry._last != nullptr, "entry must exist");
mtctr->add_req(0, loadConLNodes_Entry._last);
mtctr->_opnds[0] = new iRegLdstOper();
@@ -3722,7 +3697,7 @@ encode %{
call->_guaranteed_safepoint = false;
call->_oop_map = _oop_map;
guarantee(!_jvms, "You must clone the jvms and adapt the offsets by fix_jvms().");
- call->_jvms = NULL;
+ call->_jvms = nullptr;
call->_jvmadj = _jvmadj;
call->_in_rms = _in_rms;
call->_nesting = _nesting;
@@ -3826,7 +3801,7 @@ frame %{
// opcodes. This simplifies the register allocator.
c_return_value %{
assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) ||
- (ideal_reg == Op_RegN && CompressedOops::base() == NULL && CompressedOops::shift() == 0),
+ (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0),
"only return normal values");
// enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL
static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num };
@@ -3837,7 +3812,7 @@ frame %{
// Location of compiled Java return values. Same as C
return_value %{
assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) ||
- (ideal_reg == Op_RegN && CompressedOops::base() == NULL && CompressedOops::shift() == 0),
+ (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0),
"only return normal values");
// enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL
static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num };
@@ -4110,7 +4085,7 @@ operand immN() %{
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immN_0() %{
predicate(n->get_narrowcon() == 0);
match(ConN);
@@ -4682,7 +4657,7 @@ operand iRegN2P(iRegNsrc reg) %{
%}
operand iRegN2P_klass(iRegNsrc reg) %{
- predicate(CompressedKlassPointers::base() == NULL && CompressedKlassPointers::shift() == 0);
+ predicate(CompressedKlassPointers::base() == nullptr && CompressedKlassPointers::shift() == 0);
constraint(ALLOC_IN_RC(bits32_reg_ro));
match(DecodeNKlass reg);
format %{ "$reg" %}
@@ -4751,7 +4726,7 @@ operand indirectNarrow(iRegNsrc reg) %{
%}
operand indirectNarrow_klass(iRegNsrc reg) %{
- predicate(CompressedKlassPointers::base() == NULL && CompressedKlassPointers::shift() == 0);
+ predicate(CompressedKlassPointers::base() == nullptr && CompressedKlassPointers::shift() == 0);
constraint(ALLOC_IN_RC(bits64_reg_ro));
match(DecodeNKlass reg);
op_cost(100);
@@ -4780,7 +4755,7 @@ operand indOffset16Narrow(iRegNsrc reg, immL16 offset) %{
%}
operand indOffset16Narrow_klass(iRegNsrc reg, immL16 offset) %{
- predicate(CompressedKlassPointers::base() == NULL && CompressedKlassPointers::shift() == 0);
+ predicate(CompressedKlassPointers::base() == nullptr && CompressedKlassPointers::shift() == 0);
constraint(ALLOC_IN_RC(bits64_reg_ro));
match(AddP (DecodeNKlass reg) offset);
op_cost(100);
@@ -4809,7 +4784,7 @@ operand indOffset16NarrowAlg4(iRegNsrc reg, immL16Alg4 offset) %{
%}
operand indOffset16NarrowAlg4_klass(iRegNsrc reg, immL16Alg4 offset) %{
- predicate(CompressedKlassPointers::base() == NULL && CompressedKlassPointers::shift() == 0);
+ predicate(CompressedKlassPointers::base() == nullptr && CompressedKlassPointers::shift() == 0);
constraint(ALLOC_IN_RC(bits64_reg_ro));
match(AddP (DecodeNKlass reg) offset);
op_cost(100);
@@ -5544,7 +5519,7 @@ instruct loadN2P_unscaled(iRegPdst dst, memory mem) %{
instruct loadN2P_klass_unscaled(iRegPdst dst, memory mem) %{
match(Set dst (DecodeNKlass (LoadNKlass mem)));
- predicate(CompressedKlassPointers::base() == NULL && CompressedKlassPointers::shift() == 0 &&
+ predicate(CompressedKlassPointers::base() == nullptr && CompressedKlassPointers::shift() == 0 &&
_kids[0]->_leaf->as_Load()->is_unordered());
ins_cost(MEMORY_REF_COST);
@@ -5954,7 +5929,7 @@ instruct loadConL_Ex(iRegLdst dst, immL src) %{
postalloc_expand( postalloc_expand_load_long_constant(dst, src, constanttablebase) );
%}
-// Load NULL as compressed oop.
+// Load nullptr as compressed oop.
instruct loadConN0(iRegNdst dst, immN_0 src) %{
match(Set dst src);
ins_cost(DEFAULT_COST);
@@ -6045,9 +6020,9 @@ instruct loadConN_Ex(iRegNdst dst, immN src) %{
MachNode *m1 = new loadConN_hiNode();
MachNode *m2 = new loadConN_loNode();
MachNode *m3 = new clearMs32bNode();
- m1->add_req(NULL);
- m2->add_req(NULL, m1);
- m3->add_req(NULL, m2);
+ m1->add_req(nullptr);
+ m2->add_req(nullptr, m1);
+ m3->add_req(nullptr, m2);
m1->_opnds[0] = op_dst;
m1->_opnds[1] = op_src;
m2->_opnds[0] = op_dst;
@@ -6123,7 +6098,7 @@ instruct loadConNKlass_Ex(iRegNdst dst, immNKlass src) %{
postalloc_expand %{
// Load high bits into register. Sign extended.
MachNode *m1 = new loadConNKlass_hiNode();
- m1->add_req(NULL);
+ m1->add_req(nullptr);
m1->_opnds[0] = op_dst;
m1->_opnds[1] = op_src;
ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
@@ -6133,7 +6108,7 @@ instruct loadConNKlass_Ex(iRegNdst dst, immNKlass src) %{
if (!Assembler::is_uimm((jlong)CompressedKlassPointers::encode((Klass *)op_src->constant()), 31)) {
// Value might be 1-extended. Mask out these bits.
m2 = new loadConNKlass_maskNode();
- m2->add_req(NULL, m1);
+ m2->add_req(nullptr, m1);
m2->_opnds[0] = op_dst;
m2->_opnds[1] = op_src;
m2->_opnds[2] = op_dst;
@@ -6142,7 +6117,7 @@ instruct loadConNKlass_Ex(iRegNdst dst, immNKlass src) %{
}
MachNode *m3 = new loadConNKlass_loNode();
- m3->add_req(NULL, m2);
+ m3->add_req(nullptr, m2);
m3->_opnds[0] = op_dst;
m3->_opnds[1] = op_src;
m3->_opnds[2] = op_dst;
@@ -6243,7 +6218,7 @@ instruct loadConF(regF dst, immF src, iRegLdst toc) %{
size(4);
ins_encode %{
address float_address = __ float_constant($src$$constant);
- if (float_address == NULL) {
+ if (float_address == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -6267,7 +6242,7 @@ instruct loadConFComp(regF dst, immF src, iRegLdst toc) %{
FloatRegister Rdst = $dst$$FloatRegister;
Register Rtoc = $toc$$Register;
address float_address = __ float_constant($src$$constant);
- if (float_address == NULL) {
+ if (float_address == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -6305,7 +6280,7 @@ instruct loadConD(regD dst, immD src, iRegLdst toc) %{
size(4);
ins_encode %{
address float_address = __ double_constant($src$$constant);
- if (float_address == NULL) {
+ if (float_address == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -6330,7 +6305,7 @@ instruct loadConDComp(regD dst, immD src, iRegLdst toc) %{
FloatRegister Rdst = $dst$$FloatRegister;
Register Rtoc = $toc$$Register;
address float_address = __ double_constant($src$$constant);
- if (float_address == NULL) {
+ if (float_address == nullptr) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
@@ -6632,7 +6607,7 @@ instruct cond_sub_base(iRegNdst dst, flagsRegSrc crx, iRegPsrc src1) %{
predicate(false);
format %{ "BEQ $crx, done\n\t"
- "SUB $dst, $src1, heapbase \t// encode: subtract base if != NULL\n"
+ "SUB $dst, $src1, heapbase \t// encode: subtract base if != nullptr\n"
"done:" %}
ins_encode %{
Label done;
@@ -6701,7 +6676,7 @@ instruct encodeP_not_null_base_null(iRegNdst dst, iRegPsrc src) %{
predicate(CompressedOops::shift() != 0 &&
CompressedOops::base() ==0);
- format %{ "SRDI $dst, $src, #3 \t// encodeP, $src != NULL" %}
+ format %{ "SRDI $dst, $src, #3 \t// encodeP, $src != nullptr" %}
size(4);
ins_encode %{
__ srdi($dst$$Register, $src$$Register, CompressedOops::shift() & 0x3f);
@@ -6762,7 +6737,7 @@ instruct cond_add_base(iRegPdst dst, flagsRegSrc crx, iRegPsrc src) %{
predicate(false);
format %{ "BEQ $crx, done\n\t"
- "ADD $dst, $src, heapbase \t// DecodeN: add oop base if $src != NULL\n"
+ "ADD $dst, $src, heapbase \t// DecodeN: add oop base if $src != nullptr\n"
"done:" %}
ins_encode %{
Label done;
@@ -6850,7 +6825,7 @@ instruct decodeN_Disjoint_notNull_Ex(iRegPdst dst, iRegNsrc src) %{
"RLDIMI $dst, $src, shift, 32-shift \t// decode with disjoint base" %}
postalloc_expand %{
loadBaseNode *n1 = new loadBaseNode();
- n1->add_req(NULL);
+ n1->add_req(nullptr);
n1->_opnds[0] = op_dst;
decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
@@ -6882,7 +6857,7 @@ instruct decodeN_Disjoint_isel_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
format %{ "DecodeN $dst, $src \t// decode with disjoint base using isel" %}
postalloc_expand %{
loadBaseNode *n1 = new loadBaseNode();
- n1->add_req(NULL);
+ n1->add_req(nullptr);
n1->_opnds[0] = op_dst;
cmpN_reg_imm0Node *n_compare = new cmpN_reg_imm0Node();
@@ -6929,7 +6904,7 @@ instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
CompressedOops::base() != 0);
ins_cost(2 * DEFAULT_COST);
- format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %}
+ format %{ "DecodeN $dst, $src \t// $src != nullptr, postalloc expanded" %}
postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src));
%}
@@ -7086,7 +7061,7 @@ instruct decodeNKlass_notNull_addBase_Ex(iRegPdst dst, iRegLsrc base, iRegNsrc s
//effect(kill src); // We need a register for the immediate result after shifting.
predicate(false);
- format %{ "DecodeNKlass $dst = $base + ($src << 3) \t// $src != NULL, postalloc expanded" %}
+ format %{ "DecodeNKlass $dst = $base + ($src << 3) \t// $src != nullptr, postalloc expanded" %}
postalloc_expand %{
decodeNKlass_add_baseNode *n1 = new decodeNKlass_add_baseNode();
n1->add_req(n_region, n_base, n_src);
@@ -7115,7 +7090,7 @@ instruct decodeNKlass_notNull_addBase_ExEx(iRegPdst dst, iRegNsrc src) %{
// predicate(CompressedKlassPointers::shift() != 0 &&
// CompressedKlassPointers::base() != 0);
- //format %{ "DecodeNKlass $dst, $src \t// $src != NULL, expanded" %}
+ //format %{ "DecodeNKlass $dst, $src \t// $src != nullptr, expanded" %}
ins_cost(DEFAULT_COST*2); // Don't count constant.
expand %{
@@ -7602,7 +7577,7 @@ instruct compareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- $res$$Register, NULL, true);
+ $res$$Register, nullptr, true);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
@@ -7621,7 +7596,7 @@ instruct compareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- $res$$Register, NULL, true);
+ $res$$Register, nullptr, true);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
@@ -7815,7 +7790,7 @@ instruct weakCompareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iReg
// value is never passed to caller.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone,
- MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, NULL, true, /*weak*/ true);
+ MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
%}
ins_pipe(pipe_class_default);
%}
@@ -7831,7 +7806,7 @@ instruct weakCompareAndSwapL_acq_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr,
// value is never passed to caller.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
- MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, NULL, true, /*weak*/ true);
+ MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
%}
ins_pipe(pipe_class_default);
%}
@@ -7845,7 +7820,7 @@ instruct weakCompareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iReg
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone,
- MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, NULL, true, /*weak*/ true);
+ MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
%}
ins_pipe(pipe_class_default);
%}
@@ -7861,7 +7836,7 @@ instruct weakCompareAndSwapP_acq_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr,
// value is never passed to caller.
__ cmpxchgd(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
- MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, NULL, true, /*weak*/ true);
+ MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
%}
ins_pipe(pipe_class_default);
%}
@@ -8081,7 +8056,7 @@ instruct compareAndExchangeL_regP_regL_regL(iRegLdst res, iRegPdst mem_ptr, iReg
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- noreg, NULL, true);
+ noreg, nullptr, true);
%}
ins_pipe(pipe_class_default);
%}
@@ -8095,7 +8070,7 @@ instruct compareAndExchangeL_acq_regP_regL_regL(iRegLdst res, iRegPdst mem_ptr,
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- noreg, NULL, true);
+ noreg, nullptr, true);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
@@ -8116,7 +8091,7 @@ instruct compareAndExchangeP_regP_regP_regP(iRegPdst res, iRegPdst mem_ptr, iReg
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- noreg, NULL, true);
+ noreg, nullptr, true);
%}
ins_pipe(pipe_class_default);
%}
@@ -8131,7 +8106,7 @@ instruct compareAndExchangeP_acq_regP_regP_regP(iRegPdst res, iRegPdst mem_ptr,
// CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
__ cmpxchgd(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
- noreg, NULL, true);
+ noreg, nullptr, true);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ isync();
} else {
@@ -12043,9 +12018,9 @@ instruct branch(label labl) %{
Label d; // dummy
__ bind(d);
Label* p = $labl$$label;
- // `p' is `NULL' when this encoding class is used only to
+ // `p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
- Label& l = (NULL == p)? d : *(p);
+ Label& l = (nullptr == p)? d : *(p);
__ b(l);
%}
ins_pipe(pipe_class_default);
@@ -12139,7 +12114,7 @@ instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P supe
format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %}
ins_encode %{
__ check_klass_subtype_slow_path($subklass$$Register, $superklass$$Register, $tmp_arrayptr$$Register,
- $tmp_klass$$Register, NULL, $result$$Register);
+ $tmp_klass$$Register, nullptr, $result$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -12147,6 +12122,7 @@ instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P supe
// inlined locking and unlocking
instruct cmpFastLock(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set crx (FastLock oop box));
effect(TEMP tmp1, TEMP tmp2);
@@ -12162,6 +12138,7 @@ instruct cmpFastLock(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1,
%}
instruct cmpFastUnlock(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set crx (FastUnlock oop box));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3);
@@ -12176,6 +12153,38 @@ instruct cmpFastUnlock(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp
ins_pipe(pipe_class_compare);
%}
+instruct cmpFastLockLightweight(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set crx (FastLock oop box));
+ effect(TEMP tmp1, TEMP tmp2);
+
+ format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2" %}
+ ins_encode %{
+ __ fast_lock_lightweight($crx$$CondRegister, $oop$$Register, $box$$Register,
+ $tmp1$$Register, $tmp2$$Register, /*tmp3*/ R0);
+ // If locking was successful, crx should indicate 'EQ'.
+ // The compiler generates a branch to the runtime call to
+ // _complete_monitor_locking_Java for the case where crx is 'NE'.
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
+instruct cmpFastUnlockLightweight(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set crx (FastUnlock oop box));
+ effect(TEMP tmp1, TEMP tmp2, TEMP tmp3);
+
+ format %{ "FASTUNLOCK $oop, $box, $tmp1, $tmp2" %}
+ ins_encode %{
+ __ fast_unlock_lightweight($crx$$CondRegister, $oop$$Register, $box$$Register,
+ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
+ // If unlocking was successful, crx should indicate 'EQ'.
+ // The compiler generates a branch to the runtime call to
+ // _complete_monitor_unlocking_Java for the case where crx is 'NE'.
+ %}
+ ins_pipe(pipe_class_compare);
+%}
+
// Align address.
instruct align_addr(iRegPdst dst, iRegPsrc src, immLnegpow2 mask) %{
match(Set dst (CastX2P (AndL (CastP2X src) mask)));
@@ -12318,21 +12327,6 @@ instruct string_equalsL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst
ins_pipe(pipe_class_default);
%}
-instruct string_equalsU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst result,
- iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{
- predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp, KILL ctr, KILL cr0);
- ins_cost(300);
- format %{ "String Equals char[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %}
- ins_encode %{
- __ array_equals(false, $str1$$Register, $str2$$Register,
- $cnt$$Register, $tmp$$Register,
- $result$$Register, false /* byte */);
- %}
- ins_pipe(pipe_class_default);
-%}
-
instruct array_equalsB(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result,
iRegIdst tmp1, iRegIdst tmp2, regCTR ctr, flagsRegCR0 cr0, flagsRegCR0 cr1) %{
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
@@ -12670,7 +12664,7 @@ instruct indexOf_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRe
ins_encode %{
__ string_indexof($result$$Register,
$haystack$$Register, $haycnt$$Register,
- $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $needle$$Register, nullptr, $needlecnt$$Register, 0, // needlecnt not constant.
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UU);
%}
ins_pipe(pipe_class_compare);
@@ -12691,7 +12685,7 @@ instruct indexOf_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRe
ins_encode %{
__ string_indexof($result$$Register,
$haystack$$Register, $haycnt$$Register,
- $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $needle$$Register, nullptr, $needlecnt$$Register, 0, // needlecnt not constant.
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_compare);
@@ -12712,7 +12706,7 @@ instruct indexOf_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iR
ins_encode %{
__ string_indexof($result$$Register,
$haystack$$Register, $haycnt$$Register,
- $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant.
+ $needle$$Register, nullptr, $needlecnt$$Register, 0, // needlecnt not constant.
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_compare);
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index 3382df355da79..66b19794b057e 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/debugInfoRec.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "frame_ppc.hpp"
#include "compiler/oopMap.hpp"
@@ -35,7 +34,6 @@
#include "interpreter/interpreter.hpp"
#include "interpreter/interp_masm.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/continuation.hpp"
@@ -1174,8 +1172,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
BLOCK_COMMENT("c2i unverified entry");
c2i_unverified_entry = __ pc();
- // inline_cache contains a compiledICHolder
- const Register ic = R19_method;
+ // inline_cache contains a CompiledICData
+ const Register ic = R19_inline_cache_reg;
const Register ic_klass = R11_scratch1;
const Register receiver_klass = R12_scratch2;
const Register code = R21_tmp1;
@@ -1186,45 +1184,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label call_interpreter;
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
- "klass offset should reach into any page");
- // Check for null argument if we don't have implicit null checks.
- if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
- if (TrapBasedNullChecks) {
- __ trap_null_check(R3_ARG1);
- } else {
- Label valid;
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ bne_predict_taken(CCR0, valid);
- // We have a null argument, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ BIND(valid);
- }
- }
- // Assume argument is not null, load klass from receiver.
- __ load_klass(receiver_klass, R3_ARG1);
-
- __ ld(ic_klass, CompiledICHolder::holder_klass_offset(), ic);
-
- if (TrapBasedICMissChecks) {
- __ trap_ic_miss_check(receiver_klass, ic_klass);
- } else {
- Label valid;
- __ cmpd(CCR0, receiver_klass, ic_klass);
- __ beq_predict_taken(CCR0, valid);
- // We have an unexpected klass, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ BIND(valid);
- }
-
+ __ ic_check(4 /* end_alignment */);
+ __ ld(R19_method, CompiledICData::speculated_method_offset(), ic);
// Argument is valid and klass is as expected, continue.
- // Extract method from inline cache, verified entry point needs it.
- __ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic);
- assert(R19_method == ic, "the inline cache register is dead here");
-
__ ld(code, method_(code));
__ cmpdi(CCR0, code, 0);
__ ld(ientry, method_(interpreter_entry)); // preloaded
@@ -1798,7 +1761,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// static stub for the call above
CodeBuffer* cbuf = masm->code_section()->outer();
- stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, c2i_call_pc);
+ stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, c2i_call_pc);
guarantee(stub != nullptr, "no space for static stub");
}
@@ -1891,7 +1854,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// static stub for the call above
CodeBuffer* cbuf = masm->code_section()->outer();
- stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, call_pc);
+ stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, call_pc);
guarantee(stub != nullptr, "no space for static stub");
}
@@ -2039,6 +2002,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
in_ByteSize(-1),
oop_maps,
exception_offset);
+ if (nm == nullptr) return nm;
if (method->is_continuation_enter_intrinsic()) {
ContinuationEntry::set_enter_code(nm, interpreted_entry_offset);
} else if (method->is_continuation_yield_intrinsic()) {
@@ -2187,7 +2151,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
intptr_t frame_done_pc;
intptr_t oopmap_pc;
- Label ic_miss;
Label handle_pending_exception;
Register r_callers_sp = R21;
@@ -2211,19 +2174,9 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Check ic: object class == cached class?
if (!method_is_static) {
- Register ic = R19_inline_cache_reg;
- Register receiver_klass = r_temp_1;
-
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ beq(CCR0, ic_miss);
- __ verify_oop(R3_ARG1, FILE_AND_LINE);
- __ load_klass(receiver_klass, R3_ARG1);
-
- __ cmpd(CCR0, receiver_klass, ic);
- __ bne(CCR0, ic_miss);
+ __ ic_check(4 /* end_alignment */);
}
-
// Generate the Verified Entry Point (VEP).
// --------------------------------------------------------------------------
vep_start_pc = (intptr_t)__ pc();
@@ -2403,8 +2356,13 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ addi(r_box, R1_SP, lock_offset);
// Try fastpath for locking.
- // fast_lock kills r_temp_1, r_temp_2, r_temp_3.
- __ compiler_fast_lock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
+ if (LockingMode == LM_LIGHTWEIGHT) {
+ // fast_lock kills r_temp_1, r_temp_2, r_temp_3.
+ __ compiler_fast_lock_lightweight_object(CCR0, r_oop, r_temp_1, r_temp_2, r_temp_3);
+ } else {
+ // fast_lock kills r_temp_1, r_temp_2, r_temp_3.
+ __ compiler_fast_lock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
+ }
__ beq(CCR0, locked);
// None of the above fast optimizations worked so we have to get into the
@@ -2614,7 +2572,11 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ addi(r_box, R1_SP, lock_offset);
// Try fastpath for unlocking.
- __ compiler_fast_unlock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
+ if (LockingMode == LM_LIGHTWEIGHT) {
+ __ compiler_fast_unlock_lightweight_object(CCR0, r_oop, r_temp_1, r_temp_2, r_temp_3);
+ } else {
+ __ compiler_fast_unlock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
+ }
__ beq(CCR0, done);
// Save and restore any potential method result value around the unlocking operation.
@@ -2703,16 +2665,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ b64_patchable((address)StubRoutines::forward_exception_entry(),
relocInfo::runtime_call_type);
- // Handler for a cache miss (out-of-line).
- // --------------------------------------------------------------------------
-
- if (!method_is_static) {
- __ bind(ic_miss);
-
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- }
-
// Done.
// --------------------------------------------------------------------------
diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp
index e26f03f52d802..094757ad3e16c 100644
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp
@@ -3643,8 +3643,6 @@ class StubGenerator: public StubCodeGenerator {
#define VALID_B64 0x80
#define VB64(x) (VALID_B64 | x)
-#define VEC_ALIGN __attribute__ ((aligned(16)))
-
#define BLK_OFFSETOF(x) (offsetof(constant_block, x))
// In little-endian mode, the lxv instruction loads the element at EA into
@@ -3681,7 +3679,7 @@ class StubGenerator: public StubCodeGenerator {
unsigned char pack_permute_val[16];
} constant_block;
- static const constant_block VEC_ALIGN const_block = {
+ alignas(16) static const constant_block const_block = {
.offsetLUT_val = {
ARRAY_TO_LXV_ORDER(
@@ -4263,7 +4261,7 @@ class StubGenerator: public StubCodeGenerator {
unsigned char base64_48_63_URL_val[16];
} constant_block;
- static const constant_block VEC_ALIGN const_block = {
+ alignas(16) static const constant_block const_block = {
.expand_permute_val = {
ARRAY_TO_LXV_ORDER(
0, 4, 5, 6,
diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
index 84ecfc4f934e7..86353aefb36ef 100644
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -3803,16 +3803,15 @@ void TemplateTable::_new() {
__ sldi(Roffset, Rindex, LogBytesPerWord);
__ load_resolved_klass_at_offset(Rcpool, Roffset, RinstanceKlass);
- // Make sure klass is fully initialized and get instance_size.
- __ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass);
+ // Make sure klass is initialized.
+ assert(VM_Version::supports_fast_class_init_checks(), "Optimization requires support for fast class initialization checks");
+ __ clinit_barrier(RinstanceKlass, R16_thread, nullptr /*L_fast_path*/, &Lslow_case);
+
__ lwz(Rinstance_size, in_bytes(Klass::layout_helper_offset()), RinstanceKlass);
- __ cmpdi(CCR1, Rscratch, InstanceKlass::fully_initialized);
// Make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class.
__ andi_(R0, Rinstance_size, Klass::_lh_instance_slow_path_bit); // slow path bit equals 0?
-
- __ crnand(CCR0, Assembler::equal, CCR1, Assembler::equal); // slow path bit set or not fully initialized?
- __ beq(CCR0, Lslow_case);
+ __ bne(CCR0, Lslow_case);
// --------------------------------------------------------------------------
// Fast case:
diff --git a/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp
index a1c8f46ce2d57..b60fd4f16d163 100644
--- a/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp
+++ b/src/hotspot/cpu/ppc/upcallLinker_ppc.cpp
@@ -243,10 +243,14 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
__ load_const_optimized(R19_method, (intptr_t)entry);
__ std(R19_method, in_bytes(JavaThread::callee_target_offset()), R16_thread);
+ __ push_cont_fastpath();
+
__ ld(call_target_address, in_bytes(Method::from_compiled_offset()), R19_method);
__ mtctr(call_target_address);
__ bctrl();
+ __ pop_cont_fastpath();
+
// return value shuffle
if (!needs_return_buffer) {
// CallArranger can pick a return type that goes in the same reg for both CCs.
diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp
index a5831ef1590ad..0efde131277b2 100644
--- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp
@@ -94,6 +94,7 @@ class VM_Version: public Abstract_VM_Version {
// PPC64 supports fast class initialization checks
static bool supports_fast_class_init_checks() { return true; }
constexpr static bool supports_stack_watermark_barrier() { return true; }
+ constexpr static bool supports_recursive_lightweight_locking() { return true; }
static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
// CPU instruction support
diff --git a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
index fe4eb3df8f12f..28ba04d833bed 100644
--- a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_ppc.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
@@ -181,13 +181,13 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass_check_null(rcvr_klass, R3_ARG1);
// Receiver subtype check against REFC.
- __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
+ __ ld(interface, CompiledICData::itable_refc_klass_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, noreg,
R0, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ false);
// Get Method* and entrypoint for compiler
- __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
+ __ ld(interface, CompiledICData::itable_defc_klass_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, itable_index,
R19_method, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ true);
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp
index f44840d9f8cc7..38804ff2ed6a8 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp
@@ -815,6 +815,8 @@ enum operand_size { int8, int16, int32, uint32, int64 };
INSN(fsqrt_s, 0b1010011, 0b00000, 0b0101100);
INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101);
+ INSN(fcvt_s_h, 0b1010011, 0b00010, 0b0100000);
+ INSN(fcvt_h_s, 0b1010011, 0b00000, 0b0100010);
INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000);
INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001);
#undef INSN
@@ -1071,6 +1073,7 @@ enum operand_size { int8, int16, int32, uint32, int64 };
emit(insn); \
}
+ INSN(fmv_h_x, 0b1010011, 0b000, 0b00000, 0b1111010);
INSN(fmv_w_x, 0b1010011, 0b000, 0b00000, 0b1111000);
INSN(fmv_d_x, 0b1010011, 0b000, 0b00000, 0b1111001);
@@ -1108,8 +1111,10 @@ enum fclass_mask {
emit(insn); \
}
+ INSN(fclass_h, 0b1010011, 0b001, 0b00000, 0b1110010);
INSN(fclass_s, 0b1010011, 0b001, 0b00000, 0b1110000);
INSN(fclass_d, 0b1010011, 0b001, 0b00000, 0b1110001);
+ INSN(fmv_x_h, 0b1010011, 0b000, 0b00000, 0b1110010);
INSN(fmv_x_w, 0b1010011, 0b000, 0b00000, 0b1110000);
INSN(fmv_x_d, 0b1010011, 0b000, 0b00000, 0b1110001);
@@ -2651,7 +2656,7 @@ enum Nf {
}
bool do_compress_zcb(Register reg1 = noreg, Register reg2 = noreg) const {
- return do_compress() && VM_Version::ext_Zcb.enabled() &&
+ return do_compress() && UseZcb &&
(reg1 == noreg || reg1->is_compressed_valid()) && (reg2 == noreg || reg2->is_compressed_valid());
}
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
index 0bbf3771a04bc..5d0fa3fad3cec 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
@@ -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.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -51,7 +51,6 @@
#endif
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = t1; // where the IC klass is cached
const Register SYNC_header = x10; // synchronization header
const Register SHIFT_count = x10; // where count for shift operations must be
@@ -265,26 +264,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- int start_offset = __ offset();
- Label dont;
- __ inline_cache_check(receiver, ic_klass, dont);
-
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // We align the verified entry point unless the method body
- // (including its inline cache check) will fit in a single 64-byte
- // icache line.
- if (!method()->is_accessor() || __ offset() - start_offset > 4 * 4) {
- // force alignment after the cache check.
- __ align(CodeEntryAlignment);
- }
-
- __ bind(dont);
- return start_offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::jobject2reg(jobject o, Register reg) {
@@ -1040,7 +1020,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
len,
tmp1,
tmp2,
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
array_element_size(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
@@ -1398,7 +1378,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
__ emit_static_call_stub();
- assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
+ assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size()
<= call_stub_size(), "stub too big");
__ end_a_stub();
}
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
index b088498e6fc08..ce23213776c08 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
@@ -68,7 +68,7 @@ friend class ArrayCopyStub;
enum {
// See emit_static_call_stub for detail
- // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address)
+ // CompiledDirectCall::to_interp_stub_size() (14) + CompiledDirectCall::to_trampoline_stub_size() (1 + 3 + address)
_call_stub_size = 14 * NativeInstruction::instruction_size +
(NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size),
// See emit_exception_handler for detail
diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
index 6c1dce0de1598..f4c05b9efd651 100644
--- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -69,13 +69,12 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
bnez(temp, slow_case, true /* is_far */);
}
- // Load object header
- ld(hdr, Address(obj, hdr_offset));
-
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(obj, hdr, temp, t1, slow_case);
} else if (LockingMode == LM_LEGACY) {
Label done;
+ // Load object header
+ ld(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
ori(hdr, hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
@@ -134,9 +133,6 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
- ld(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
- test_bit(temp, hdr, exact_log2(markWord::monitor_value));
- bnez(temp, slow_case, /* is_far */ true);
lightweight_unlock(obj, hdr, temp, t1, slow_case);
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
@@ -280,7 +276,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
verify_oop(obj);
}
-void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case) {
+void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int base_offset_in_bytes, int f, Register klass, Label& slow_case) {
assert_different_registers(obj, len, tmp1, tmp2, klass);
// determine alignment mask
@@ -292,7 +288,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1
const Register arr_size = tmp2; // okay to be the same
// align object end
- mv(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask);
+ mv(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask);
shadd(arr_size, len, arr_size, t0, f);
andi(arr_size, arr_size, ~(uint)MinObjAlignmentInBytesMask);
@@ -300,9 +296,20 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1
initialize_header(obj, klass, len, tmp1, tmp2);
+ // Clear leading 4 bytes, if necessary.
+ // TODO: This could perhaps go into initialize_body() and also clear the leading 4 bytes
+ // for non-array objects, thereby replacing the klass-gap clearing code in initialize_header().
+ int base_offset = base_offset_in_bytes;
+ if (!is_aligned(base_offset, BytesPerWord)) {
+ assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
+ sw(zr, Address(obj, base_offset));
+ base_offset += BytesPerInt;
+ }
+ assert(is_aligned(base_offset, BytesPerWord), "must be word-aligned");
+
// clear rest of allocated space
const Register len_zero = len;
- initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
+ initialize_body(obj, arr_size, base_offset, len_zero);
membar(MacroAssembler::StoreStore);
@@ -314,15 +321,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1
verify_oop(obj);
}
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache, Label &L) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
- assert_different_registers(receiver, iCache, t0, t2);
- cmp_klass(receiver, iCache, t0, t2 /* call-clobbered t2 as a tmp */, L);
-}
-
void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp
index b737a438511c8..2d7f8d7485d4f 100644
--- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -101,7 +101,7 @@ using MacroAssembler::null_check;
// header_size: size of object header in words
// f : element scale factor
// slow_case : exit to slow case implementation if fast allocation fails
- void allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case);
+ void allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int base_offset_in_bytes, int f, Register klass, Label& slow_case);
int rsp_offset() const { return _rsp_offset; }
diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
index b76163a30841d..9fa8939837a85 100644
--- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
@@ -37,7 +37,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_riscv.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_riscv.hpp"
diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
index 711eb2100912b..767d4111e76a6 100644
--- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -32,6 +32,7 @@
#include "opto/output.hpp"
#include "opto/subnode.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/globalDefinitions.hpp"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -51,30 +52,35 @@ void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg,
Register box = boxReg;
Register disp_hdr = tmp1Reg;
Register tmp = tmp2Reg;
- Label cont;
Label object_has_monitor;
- Label count, no_count;
+ // Finish fast lock successfully. MUST branch to with flag == 0
+ Label locked;
+ // Finish fast lock unsuccessfully. slow_path MUST branch to with flag != 0
+ Label slow_path;
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr, flag, tmp3Reg, t0);
+ mv(flag, 1);
+
// Load markWord from object into displaced_header.
ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
if (DiagnoseSyncOnValueBasedClasses != 0) {
- load_klass(flag, oop);
- lwu(flag, Address(flag, Klass::access_flags_offset()));
- test_bit(flag, flag, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
- bnez(flag, cont, true /* is_far */);
+ load_klass(tmp, oop);
+ lwu(tmp, Address(tmp, Klass::access_flags_offset()));
+ test_bit(tmp, tmp, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
+ bnez(tmp, slow_path);
}
// Check for existing monitor
- test_bit(t0, disp_hdr, exact_log2(markWord::monitor_value));
- bnez(t0, object_has_monitor);
+ test_bit(tmp, disp_hdr, exact_log2(markWord::monitor_value));
+ bnez(tmp, object_has_monitor);
if (LockingMode == LM_MONITOR) {
- mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow-path
- j(cont);
- } else if (LockingMode == LM_LEGACY) {
+ j(slow_path);
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Set tmp to be (markWord of object | UNLOCK_VALUE).
ori(tmp, disp_hdr, markWord::unlocked_value);
@@ -84,77 +90,72 @@ void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg,
// Compare object markWord with an unlocked value (tmp) and if
// equal exchange the stack address of our box with object markWord.
// On failure disp_hdr contains the possibly locked markWord.
- cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq,
- Assembler::rl, /*result*/disp_hdr);
- mv(flag, zr);
- beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas
+ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64,
+ Assembler::aq, Assembler::rl, /*result*/disp_hdr);
+ beq(disp_hdr, tmp, locked);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// If the compare-and-exchange succeeded, then we found an unlocked
- // object, will have now locked it will continue at label cont
+ // object, will have now locked it will continue at label locked
// We did not see an unlocked object so try the fast recursive case.
// Check if the owner is self by comparing the value in the
// markWord of object (disp_hdr) with the stack pointer.
sub(disp_hdr, disp_hdr, sp);
mv(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markWord::lock_mask_in_place));
- // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont,
+ // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto label locked,
// hence we can store 0 as the displaced header in the box, which indicates that it is a
// recursive lock.
andr(tmp/*==0?*/, disp_hdr, tmp);
sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- mv(flag, tmp); // we can use the value of tmp as the result here
- j(cont);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "");
- Label slow;
- lightweight_lock(oop, disp_hdr, tmp, tmp3Reg, slow);
-
- // Indicate success on completion.
- mv(flag, zr);
- j(count);
- bind(slow);
- mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow-path
- j(no_count);
+ beqz(tmp, locked);
+ j(slow_path);
}
// Handle existing monitor.
bind(object_has_monitor);
- // The object's monitor m is unlocked iff m->owner == NULL,
+ // The object's monitor m is unlocked iff m->owner == nullptr,
// otherwise m->owner may contain a thread or a stack address.
//
- // Try to CAS m->owner from NULL to current thread.
+ // Try to CAS m->owner from null to current thread.
add(tmp, disp_hdr, (in_bytes(ObjectMonitor::owner_offset()) - markWord::monitor_value));
- cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq,
- Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected)
-
- if (LockingMode != LM_LIGHTWEIGHT) {
- // Store a non-null value into the box to avoid looking like a re-entrant
- // lock. The fast-path monitor unlock code checks for
- // markWord::monitor_value so use markWord::unused_mark which has the
- // relevant bit set, and also matches ObjectSynchronizer::slow_enter.
- mv(tmp, (address)markWord::unused_mark().value());
- sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- }
+ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64,
+ Assembler::aq, Assembler::rl, /*result*/tmp3Reg); // cas succeeds if tmp3Reg == zr(expected)
+
+ // Store a non-null value into the box to avoid looking like a re-entrant
+ // lock. The fast-path monitor unlock code checks for
+ // markWord::monitor_value so use markWord::unused_mark which has the
+ // relevant bit set, and also matches ObjectSynchronizer::slow_enter.
+ mv(tmp, (address)markWord::unused_mark().value());
+ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- beqz(flag, cont); // CAS success means locking succeeded
+ beqz(tmp3Reg, locked); // CAS success means locking succeeded
- bne(flag, xthread, cont); // Check for recursive locking
+ bne(tmp3Reg, xthread, slow_path); // Check for recursive locking
// Recursive lock case
- mv(flag, zr);
- increment(Address(disp_hdr, in_bytes(ObjectMonitor::recursions_offset()) - markWord::monitor_value), 1, t0, tmp);
+ increment(Address(disp_hdr, in_bytes(ObjectMonitor::recursions_offset()) - markWord::monitor_value), 1, tmp2Reg, tmp3Reg);
- bind(cont);
- // zero flag indicates success
- // non-zero flag indicates failure
- bnez(flag, no_count);
+ bind(locked);
+ mv(flag, zr);
+ increment(Address(xthread, JavaThread::held_monitor_count_offset()), 1, tmp2Reg, tmp3Reg);
- bind(count);
- increment(Address(xthread, JavaThread::held_monitor_count_offset()), 1, t0, tmp);
+#ifdef ASSERT
+ // Check that locked label is reached with flag == 0.
+ Label flag_correct;
+ beqz(flag, flag_correct);
+ stop("Fast Lock Flag != 0");
+#endif
- bind(no_count);
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag != 0.
+ bnez(flag, flag_correct);
+ stop("Fast Lock Flag == 0");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (0 vs !0) to determine the continuation.
}
void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
@@ -165,19 +166,23 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
Register box = boxReg;
Register disp_hdr = tmp1Reg;
Register tmp = tmp2Reg;
- Label cont;
Label object_has_monitor;
- Label count, no_count;
+ // Finish fast lock successfully. MUST branch to with flag == 0
+ Label unlocked;
+ // Finish fast lock unsuccessfully. slow_path MUST branch to with flag != 0
+ Label slow_path;
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr, flag, t0);
+ mv(flag, 1);
+
if (LockingMode == LM_LEGACY) {
// Find the lock address and load the displaced header from the stack.
ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// If the displaced header is 0, we have a recursive unlock.
- mv(flag, disp_hdr);
- beqz(disp_hdr, cont);
+ beqz(disp_hdr, unlocked);
}
// Handle existing monitor.
@@ -186,28 +191,17 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
bnez(t0, object_has_monitor);
if (LockingMode == LM_MONITOR) {
- mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow path
- j(cont);
- } else if (LockingMode == LM_LEGACY) {
+ j(slow_path);
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is true if we
// see the stack address of the basicLock in the markWord of the
// object.
- cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed,
- Assembler::rl, /*result*/tmp);
- xorr(flag, box, tmp); // box == tmp if cas succeeds
- j(cont);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "");
- Label slow;
- lightweight_unlock(oop, tmp, box, disp_hdr, slow);
-
- // Indicate success on completion.
- mv(flag, zr);
- j(count);
- bind(slow);
- mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow path
- j(no_count);
+ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64,
+ Assembler::relaxed, Assembler::rl, /*result*/tmp);
+ beq(box, tmp, unlocked); // box == tmp if cas succeeds
+ j(slow_path);
}
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
@@ -217,17 +211,6 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
add(tmp, tmp, -(int)markWord::monitor_value); // monitor
- if (LockingMode == LM_LIGHTWEIGHT) {
- // If the owner is anonymous, we need to fix it -- in an outline stub.
- Register tmp2 = disp_hdr;
- ld(tmp2, Address(tmp, ObjectMonitor::owner_offset()));
- test_bit(t0, tmp2, exact_log2(ObjectMonitor::ANONYMOUS_OWNER));
- C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2);
- Compile::current()->output()->add_stub(stub);
- bnez(t0, stub->entry(), /* is_far */ true);
- bind(stub->continuation());
- }
-
ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
Label notRecursive;
@@ -236,28 +219,304 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
// Recursive lock
addi(disp_hdr, disp_hdr, -1);
sd(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
- mv(flag, zr);
- j(cont);
+ j(unlocked);
bind(notRecursive);
- ld(flag, Address(tmp, ObjectMonitor::EntryList_offset()));
+ ld(t0, Address(tmp, ObjectMonitor::EntryList_offset()));
ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset()));
- orr(flag, flag, disp_hdr); // Will be 0 if both are 0.
- bnez(flag, cont);
+ orr(t0, t0, disp_hdr); // Will be 0 if both are 0.
+ bnez(t0, slow_path);
+
// need a release store here
la(tmp, Address(tmp, ObjectMonitor::owner_offset()));
membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
sd(zr, Address(tmp)); // set unowned
- bind(cont);
- // zero flag indicates success
- // non-zero flag indicates failure
- bnez(flag, no_count);
+ bind(unlocked);
+ mv(flag, zr);
+ decrement(Address(xthread, JavaThread::held_monitor_count_offset()), 1, tmp1Reg, tmp2Reg);
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with flag == 0.
+ Label flag_correct;
+ beqz(flag, flag_correct);
+ stop("Fast Lock Flag != 0");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag != 0.
+ bnez(flag, flag_correct);
+ stop("Fast Lock Flag == 0");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (0 vs !0) to determine the continuation.
+}
+
+void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register tmp1, Register tmp2, Register tmp3) {
+ // Flag register, zero for success; non-zero for failure.
+ Register flag = t1;
+
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert_different_registers(obj, tmp1, tmp2, tmp3, flag, t0);
- bind(count);
- decrement(Address(xthread, JavaThread::held_monitor_count_offset()), 1, t0, tmp);
+ mv(flag, 1);
- bind(no_count);
+ // Handle inflated monitor.
+ Label inflated;
+ // Finish fast lock successfully. MUST branch to with flag == 0
+ Label locked;
+ // Finish fast lock unsuccessfully. slow_path MUST branch to with flag != 0
+ Label slow_path;
+
+ if (DiagnoseSyncOnValueBasedClasses != 0) {
+ load_klass(tmp1, obj);
+ lwu(tmp1, Address(tmp1, Klass::access_flags_offset()));
+ test_bit(tmp1, tmp1, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
+ bnez(tmp1, slow_path);
+ }
+
+ const Register tmp1_mark = tmp1;
+
+ { // Lightweight locking
+
+ // Push lock to the lock stack and finish successfully. MUST branch to with flag == 0
+ Label push;
+
+ const Register tmp2_top = tmp2;
+ const Register tmp3_t = tmp3;
+
+ // Check if lock-stack is full.
+ lwu(tmp2_top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ mv(tmp3_t, (unsigned)LockStack::end_offset());
+ bge(tmp2_top, tmp3_t, slow_path);
+
+ // Check if recursive.
+ add(tmp3_t, xthread, tmp2_top);
+ ld(tmp3_t, Address(tmp3_t, -oopSize));
+ beq(obj, tmp3_t, push);
+
+ // Relaxed normal load to check for monitor. Optimization for monitor case.
+ ld(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value));
+ bnez(tmp3_t, inflated);
+
+ // Not inflated
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a la");
+
+ // Try to lock. Transition lock-bits 0b01 => 0b00
+ ori(tmp1_mark, tmp1_mark, markWord::unlocked_value);
+ xori(tmp3_t, tmp1_mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ tmp1_mark, /*new*/ tmp3_t, Assembler::int64,
+ /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ tmp3_t);
+ bne(tmp1_mark, tmp3_t, slow_path);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ add(tmp3_t, xthread, tmp2_top);
+ sd(obj, Address(tmp3_t));
+ addw(tmp2_top, tmp2_top, oopSize);
+ sw(tmp2_top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ j(locked);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated);
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register tmp1_tagged_monitor = tmp1_mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+ const Register tmp2_owner_addr = tmp2;
+ const Register tmp3_owner = tmp3;
+
+ // Compute owner address.
+ la(tmp2_owner_addr, Address(tmp1_tagged_monitor, (in_bytes(ObjectMonitor::owner_offset()) - monitor_tag)));
+
+ // CAS owner (null => current thread).
+ cmpxchg(/*addr*/ tmp2_owner_addr, /*expected*/ zr, /*new*/ xthread, Assembler::int64,
+ /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ tmp3_owner);
+ beqz(tmp3_owner, locked);
+
+ // Check if recursive.
+ bne(tmp3_owner, xthread, slow_path);
+
+ // Recursive.
+ increment(Address(tmp1_tagged_monitor, in_bytes(ObjectMonitor::recursions_offset()) - monitor_tag), 1, tmp2, tmp3);
+ }
+
+ bind(locked);
+ mv(flag, zr);
+ increment(Address(xthread, JavaThread::held_monitor_count_offset()), 1, tmp2, tmp3);
+
+#ifdef ASSERT
+ // Check that locked label is reached with flag == 0.
+ Label flag_correct;
+ beqz(flag, flag_correct);
+ stop("Fast Lock Flag != 0");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag != 0.
+ bnez(flag, flag_correct);
+ stop("Fast Lock Flag == 0");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (0 vs !0) to determine the continuation.
+}
+
+void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register tmp1, Register tmp2,
+ Register tmp3) {
+ // Flag register, zero for success; non-zero for failure.
+ Register flag = t1;
+
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert_different_registers(obj, tmp1, tmp2, tmp3, flag, t0);
+
+ mv(flag, 1);
+
+ // Handle inflated monitor.
+ Label inflated, inflated_load_monitor;
+ // Finish fast unlock successfully. unlocked MUST branch to with flag == 0
+ Label unlocked;
+ // Finish fast unlock unsuccessfully. MUST branch to with flag != 0
+ Label slow_path;
+
+ const Register tmp1_mark = tmp1;
+ const Register tmp2_top = tmp2;
+ const Register tmp3_t = tmp3;
+
+ { // Lightweight unlock
+
+ // Check if obj is top of lock-stack.
+ lwu(tmp2_top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ subw(tmp2_top, tmp2_top, oopSize);
+ add(tmp3_t, xthread, tmp2_top);
+ ld(tmp3_t, Address(tmp3_t));
+ // Top of lock stack was not obj. Must be monitor.
+ bne(obj, tmp3_t, inflated_load_monitor);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(add(tmp3_t, xthread, tmp2_top);)
+ DEBUG_ONLY(sd(zr, Address(tmp3_t));)
+ sw(tmp2_top, Address(xthread, JavaThread::lock_stack_top_offset()));
+
+ // Check if recursive.
+ add(tmp3_t, xthread, tmp2_top);
+ ld(tmp3_t, Address(tmp3_t, -oopSize));
+ beq(obj, tmp3_t, unlocked);
+
+ // Not recursive.
+ // Load Mark.
+ ld(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check header for monitor (0b10).
+ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value));
+ bnez(tmp3_t, inflated);
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
+ ori(tmp3_t, tmp1_mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ tmp1_mark, /*new*/ tmp3_t, Assembler::int64,
+ /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, /*result*/ tmp3_t);
+ beq(tmp1_mark, tmp3_t, unlocked);
+
+ // Compare and exchange failed.
+ // Restore lock-stack and handle the unlock in runtime.
+ DEBUG_ONLY(add(tmp3_t, xthread, tmp2_top);)
+ DEBUG_ONLY(sd(obj, Address(tmp3_t));)
+ addw(tmp2_top, tmp2_top, oopSize);
+ sd(tmp2_top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ j(slow_path);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated_load_monitor);
+ ld(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+#ifdef ASSERT
+ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value));
+ bnez(tmp3_t, inflated);
+ stop("Fast Unlock not monitor");
+#endif
+
+ bind(inflated);
+
+#ifdef ASSERT
+ Label check_done;
+ subw(tmp2_top, tmp2_top, oopSize);
+ mv(tmp3_t, in_bytes(JavaThread::lock_stack_base_offset()));
+ blt(tmp2_top, tmp3_t, check_done);
+ add(tmp3_t, xthread, tmp2_top);
+ ld(tmp3_t, Address(tmp3_t));
+ bne(obj, tmp3_t, inflated);
+ stop("Fast Unlock lock on stack");
+ bind(check_done);
+#endif
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register tmp1_monitor = tmp1_mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+
+ // Untag the monitor.
+ sub(tmp1_monitor, tmp1_mark, monitor_tag);
+
+ const Register tmp2_recursions = tmp2;
+ Label not_recursive;
+
+ // Check if recursive.
+ ld(tmp2_recursions, Address(tmp1_monitor, ObjectMonitor::recursions_offset()));
+ beqz(tmp2_recursions, not_recursive);
+
+ // Recursive unlock.
+ addi(tmp2_recursions, tmp2_recursions, -1);
+ sd(tmp2_recursions, Address(tmp1_monitor, ObjectMonitor::recursions_offset()));
+ j(unlocked);
+
+ bind(not_recursive);
+
+ Label release;
+ const Register tmp2_owner_addr = tmp2;
+
+ // Compute owner address.
+ la(tmp2_owner_addr, Address(tmp1_monitor, ObjectMonitor::owner_offset()));
+
+ // Check if the entry lists are empty.
+ ld(t0, Address(tmp1_monitor, ObjectMonitor::EntryList_offset()));
+ ld(tmp3_t, Address(tmp1_monitor, ObjectMonitor::cxq_offset()));
+ orr(t0, t0, tmp3_t);
+ beqz(t0, release);
+
+ // The owner may be anonymous and we removed the last obj entry in
+ // the lock-stack. This loses the information about the owner.
+ // Write the thread to the owner field so the runtime knows the owner.
+ sd(xthread, Address(tmp2_owner_addr));
+ j(slow_path);
+
+ bind(release);
+ // Set owner to null.
+ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
+ sd(zr, Address(tmp2_owner_addr));
+ }
+
+ bind(unlocked);
+ mv(flag, zr);
+ decrement(Address(xthread, JavaThread::held_monitor_count_offset()), 1, tmp2, tmp3);
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with flag == 0.
+ Label flag_correct;
+ beqz(flag, flag_correct);
+ stop("Fast Lock Flag != 0");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with flag != 0.
+ bnez(flag, flag_correct);
+ stop("Fast Lock Flag == 0");
+ bind(flag_correct);
+#endif
+ // C2 uses the value of flag (0 vs !0) to determine the continuation.
}
// short string
@@ -1358,7 +1617,6 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
// For Strings we're passed the address of the first characters in a1
// and a2 and the length in cnt1.
-// elem_size is the element size in bytes: either 1 or 2.
// There are two implementations. For arrays >= 8 bytes, all
// comparisons (for hw supporting unaligned access: including the final one,
// which may overlap) are performed 8 bytes at a time.
@@ -1367,13 +1625,12 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
// halfword, then a short, and then a byte.
void C2_MacroAssembler::string_equals(Register a1, Register a2,
- Register result, Register cnt1, int elem_size)
+ Register result, Register cnt1)
{
Label SAME, DONE, SHORT, NEXT_WORD;
Register tmp1 = t0;
Register tmp2 = t1;
- assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte");
assert_different_registers(a1, a2, result, cnt1, tmp1, tmp2);
BLOCK_COMMENT("string_equals {");
@@ -1439,15 +1696,13 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2,
}
bind(TAIL01);
- if (elem_size == 1) { // Only needed when comparing 1-byte elements
- // 0-1 bytes left.
- test_bit(tmp1, cnt1, 0);
- beqz(tmp1, SAME);
- {
- lbu(tmp1, Address(a1, 0));
- lbu(tmp2, Address(a2, 0));
- bne(tmp1, tmp2, DONE);
- }
+ // 0-1 bytes left.
+ test_bit(tmp1, cnt1, 0);
+ beqz(tmp1, SAME);
+ {
+ lbu(tmp1, Address(a1, 0));
+ lbu(tmp2, Address(a2, 0));
+ bne(tmp1, tmp2, DONE);
}
// Arrays are equal.
@@ -1783,6 +2038,95 @@ void C2_MacroAssembler::signum_fp(FloatRegister dst, FloatRegister one, bool is_
bind(done);
}
+static void float16_to_float_slow_path(C2_MacroAssembler& masm, C2GeneralStub& stub) {
+#define __ masm.
+ FloatRegister dst = stub.data<0>();
+ Register src = stub.data<1>();
+ Register tmp = stub.data<2>();
+ __ bind(stub.entry());
+
+ // following instructions mainly focus on NaN, as riscv does not handle
+ // NaN well with fcvt, but the code also works for Inf at the same time.
+
+ // construct a NaN in 32 bits from the NaN in 16 bits,
+ // we need the payloads of non-canonical NaNs to be preserved.
+ __ mv(tmp, 0x7f800000);
+ // sign-bit was already set via sign-extension if necessary.
+ __ slli(t0, src, 13);
+ __ orr(tmp, t0, tmp);
+ __ fmv_w_x(dst, tmp);
+
+ __ j(stub.continuation());
+#undef __
+}
+
+// j.l.Float.float16ToFloat
+void C2_MacroAssembler::float16_to_float(FloatRegister dst, Register src, Register tmp) {
+ auto stub = C2CodeStub::make(dst, src, tmp, 20, float16_to_float_slow_path);
+
+ // in riscv, NaN needs a special process as fcvt does not work in that case.
+ // in riscv, Inf does not need a special process as fcvt can handle it correctly.
+ // but we consider to get the slow path to process NaN and Inf at the same time,
+ // as both of them are rare cases, and if we try to get the slow path to handle
+ // only NaN case it would sacrifise the performance for normal cases,
+ // i.e. non-NaN and non-Inf cases.
+
+ // check whether it's a NaN or +/- Inf.
+ mv(t0, 0x7c00);
+ andr(tmp, src, t0);
+ // jump to stub processing NaN and Inf cases.
+ beq(t0, tmp, stub->entry());
+
+ // non-NaN or non-Inf cases, just use built-in instructions.
+ fmv_h_x(dst, src);
+ fcvt_s_h(dst, dst);
+
+ bind(stub->continuation());
+}
+
+static void float_to_float16_slow_path(C2_MacroAssembler& masm, C2GeneralStub& stub) {
+#define __ masm.
+ Register dst = stub.data<0>();
+ FloatRegister src = stub.data<1>();
+ Register tmp = stub.data<2>();
+ __ bind(stub.entry());
+
+ __ fmv_x_w(dst, src);
+
+ // preserve the payloads of non-canonical NaNs.
+ __ srai(dst, dst, 13);
+ // preserve the sign bit.
+ __ srai(tmp, dst, 13);
+ __ slli(tmp, tmp, 10);
+ __ mv(t0, 0x3ff);
+ __ orr(tmp, tmp, t0);
+
+ // get the result by merging sign bit and payloads of preserved non-canonical NaNs.
+ __ andr(dst, dst, tmp);
+
+ __ j(stub.continuation());
+#undef __
+}
+
+// j.l.Float.floatToFloat16
+void C2_MacroAssembler::float_to_float16(Register dst, FloatRegister src, FloatRegister ftmp, Register xtmp) {
+ auto stub = C2CodeStub::make(dst, src, xtmp, 130, float_to_float16_slow_path);
+
+ // in riscv, NaN needs a special process as fcvt does not work in that case.
+
+ // check whether it's a NaN.
+ // replace fclass with feq as performance optimization.
+ feq_s(t0, src, src);
+ // jump to stub processing NaN cases.
+ beqz(t0, stub->entry());
+
+ // non-NaN cases, just use built-in instructions.
+ fcvt_h_s(ftmp, src);
+ fmv_x_h(dst, ftmp);
+
+ bind(stub->continuation());
+}
+
void C2_MacroAssembler::signum_fp_v(VectorRegister dst, VectorRegister one, BasicType bt, int vlen) {
vsetvli_helper(bt, vlen);
@@ -1896,7 +2240,7 @@ void C2_MacroAssembler::element_compare(Register a1, Register a2, Register resul
mv(result, true);
}
-void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register result, Register cnt, int elem_size) {
+void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register result, Register cnt) {
Label DONE;
Register tmp1 = t0;
Register tmp2 = t1;
@@ -1905,11 +2249,7 @@ void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register resul
mv(result, false);
- if (elem_size == 2) {
- srli(cnt, cnt, 1);
- }
-
- element_compare(a1, a2, result, cnt, tmp1, tmp2, v2, v4, v2, elem_size == 1, DONE);
+ element_compare(a1, a2, result, cnt, tmp1, tmp2, v2, v4, v2, true, DONE);
bind(DONE);
BLOCK_COMMENT("} string_equals_v");
diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
index 4940ce5fe9e94..25ba66387f18a 100644
--- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
@@ -44,9 +44,11 @@
public:
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
- // See full description in macroAssembler_riscv.cpp.
void fast_lock(Register object, Register box, Register tmp1, Register tmp2, Register tmp3);
void fast_unlock(Register object, Register box, Register tmp1, Register tmp2);
+ // Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file.
+ void fast_lock_lightweight(Register object, Register tmp1, Register tmp2, Register tmp3);
+ void fast_unlock_lightweight(Register object, Register tmp1, Register tmp2, Register tmp3);
void string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
@@ -92,8 +94,7 @@
void arrays_hashcode_elload(Register dst, Address src, BasicType eltype);
void string_equals(Register r1, Register r2,
- Register result, Register cnt1,
- int elem_size);
+ Register result, Register cnt1);
// refer to conditional_branches and float_conditional_branches
static const int bool_test_bits = 3;
@@ -172,8 +173,12 @@
void signum_fp(FloatRegister dst, FloatRegister one, bool is_double);
+ void float16_to_float(FloatRegister dst, Register src, Register tmp);
+ void float_to_float16(Register dst, FloatRegister src, FloatRegister ftmp, Register xtmp);
+
void signum_fp_v(VectorRegister dst, VectorRegister one, BasicType bt, int vlen);
+
// intrinsic methods implemented by rvv instructions
// compress bits, i.e. j.l.Integer/Long::compress.
@@ -184,8 +189,7 @@
void expand_bits_l_v(Register dst, Register src, Register mask);
void string_equals_v(Register r1, Register r2,
- Register result, Register cnt1,
- int elem_size);
+ Register result, Register cnt1);
void arrays_equals_v(Register r1, Register r2,
Register result, Register cnt1,
diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
index e29dee56de8d8..fdb2bcb06ff97 100644
--- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
@@ -27,7 +27,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -37,7 +36,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
precond(cbuf.stubs()->start() != badAddress);
precond(cbuf.stubs()->end() != badAddress);
// Stub is fixed up when the corresponding call is converted from
@@ -69,11 +68,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return MacroAssembler::static_call_stub_size();
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// Somewhat pessimistically, we count 4 instructions here (although
// there are only 3) because we sometimes emit an alignment nop.
// Trampoline stubs are always word aligned.
@@ -81,21 +80,14 @@ int CompiledStaticCall::to_trampoline_stub_size() {
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub);
@@ -112,7 +104,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -129,7 +121,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp
index 5d0b0fb472934..fa7df32d7e944 100644
--- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp
@@ -29,8 +29,8 @@
#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/javaThread.hpp"
diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp
index e368bbdc9141f..68cd51ece5f70 100644
--- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp
+++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp
@@ -50,6 +50,9 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY
+// auipc useable for all cc -> cc calls and jumps
+#define CODE_CACHE_SIZE_LIMIT ((2*G)-(2*K))
+
// The expected size in bytes of a cache line.
#define DEFAULT_CACHE_LINE_SIZE 64
diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp
index aa95cebec14cd..8461948752bae 100644
--- a/src/hotspot/cpu/riscv/globals_riscv.hpp
+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp
@@ -105,7 +105,9 @@ define_pd_global(intx, InlineSmallCode, 1000);
product(bool, UseZba, false, "Use Zba instructions") \
product(bool, UseZbb, false, "Use Zbb instructions") \
product(bool, UseZbs, false, "Use Zbs instructions") \
+ product(bool, UseZfh, false, "Use Zfh instructions") \
product(bool, UseZacas, false, EXPERIMENTAL, "Use Zacas instructions") \
+ product(bool, UseZcb, false, EXPERIMENTAL, "Use Zcb instructions") \
product(bool, UseZic64b, false, EXPERIMENTAL, "Use Zic64b instructions") \
product(bool, UseZicbom, false, EXPERIMENTAL, "Use Zicbom instructions") \
product(bool, UseZicbop, false, EXPERIMENTAL, "Use Zicbop instructions") \
diff --git a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp
deleted file mode 100644
index ab904817816fc..0000000000000
--- a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
- * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_riscv.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // 6: auipc + ld + auipc + jalr + address(2 * instruction_size)
- return 6 * NativeInstruction::instruction_size;
-}
-
-#define __ masm->
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- assert_cond(code_begin != nullptr && entry_point != nullptr);
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // Note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
-
- address start = __ pc();
- Label l;
- __ ld(t1, l);
- __ far_jump(ExternalAddress(entry_point));
- __ align(wordSize);
- __ bind(l);
- __ emit_int64((intptr_t)cached_value);
- // Only need to invalidate the 1st two instructions - not the whole ic stub
- ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
- assert(__ pc() - start == ic_stub_code_size(), "must be");
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(move->next_instruction_address());
- return jump->jump_destination();
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // The word containing the cached value is at the end of this IC buffer
- uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize);
- void* o = (void*)*p;
- return o;
-}
diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
index 19d665bd421d0..497918e6c05c6 100644
--- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
@@ -763,7 +763,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg)
}
if (LockingMode == LM_LIGHTWEIGHT) {
- ld(tmp, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
lightweight_lock(obj_reg, tmp, tmp2, tmp3, slow_case);
j(count);
} else if (LockingMode == LM_LEGACY) {
@@ -860,24 +859,6 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg)
if (LockingMode == LM_LIGHTWEIGHT) {
Label slow_case;
-
- // Check for non-symmetric locking. This is allowed by the spec and the interpreter
- // must handle it.
- Register tmp1 = t0;
- Register tmp2 = header_reg;
- // First check for lock-stack underflow.
- lwu(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
- mv(tmp2, (unsigned)LockStack::start_offset());
- ble(tmp1, tmp2, slow_case);
- // Then check if the top of the lock-stack matches the unlocked object.
- subw(tmp1, tmp1, oopSize);
- add(tmp1, xthread, tmp1);
- ld(tmp1, Address(tmp1, 0));
- bne(tmp1, obj_reg, slow_case);
-
- ld(header_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- test_bit(t0, header_reg, exact_log2(markWord::monitor_value));
- bnez(t0, slow_case);
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
j(count);
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
index ce336c16aa718..4459356d3b132 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
@@ -27,6 +27,7 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -48,6 +49,7 @@
#include "runtime/jniHandles.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
#ifdef COMPILER2
#include "opto/compile.hpp"
@@ -634,8 +636,8 @@ void MacroAssembler::unimplemented(const char* what) {
}
void MacroAssembler::emit_static_call_stub() {
- IncompressibleRegion ir(this); // Fixed length: see CompiledStaticCall::to_interp_stub_size().
- // CompiledDirectStaticCall::set_to_interpreted knows the
+ IncompressibleRegion ir(this); // Fixed length: see CompiledDirectCall::to_interp_stub_size().
+ // CompiledDirectCall::set_to_interpreted knows the
// exact layout of this stub.
mov_metadata(xmethod, (Metadata*)nullptr);
@@ -2542,7 +2544,7 @@ 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
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - 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.
@@ -3542,6 +3544,48 @@ address MacroAssembler::ic_call(address entry, jint method_index) {
return trampoline_call(Address(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ // No compressed
+ return (NativeInstruction::instruction_size * (2 /* 2 loads */ + 1 /* branch */)) +
+ far_branch_size();
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ IncompressibleRegion ir(this);
+ Register receiver = j_rarg0;
+ Register data = t1;
+
+ Register tmp1 = t0; // t0 always scratch
+ // t2 is saved on call, thus should have been saved before this check.
+ // Hence we can clobber it.
+ Register tmp2 = t2;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, ic_check_size());
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ lwu(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ lwu(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ } else {
+ ld(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ld(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ }
+
+ Label ic_hit;
+ beq(tmp1, tmp2, ic_hit);
+ // Note, far_jump is not fixed size.
+ // Is this ever generates a movptr alignment/size will be off.
+ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ bind(ic_hit);
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point.");
+ return uep_offset;
+}
+
// Emit a trampoline stub for a call to a target which is too far away.
//
// code sequences:
@@ -4999,98 +5043,124 @@ void MacroAssembler::test_bit(Register Rd, Register Rs, uint32_t bit_pos) {
}
// Implements lightweight-locking.
-// Branches to slow upon failure to lock the object.
-// Falls through upon success.
//
// - obj: the object to be locked
-// - hdr: the header, already loaded from obj, will be destroyed
-// - tmp1, tmp2: temporary registers, will be destroyed
-void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register tmp1, Register tmp2, Label& slow) {
+// - tmp1, tmp2, tmp3: temporary registers, will be destroyed
+// - slow: branched to if locking fails
+void MacroAssembler::lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr, tmp1, tmp2, t0);
-
- // Check if we would have space on lock-stack for the object.
- lwu(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
- mv(tmp2, (unsigned)LockStack::end_offset());
- bge(tmp1, tmp2, slow, /* is_far */ true);
-
- // Load (object->mark() | 1) into hdr
- ori(hdr, hdr, markWord::unlocked_value);
- // Clear lock-bits, into tmp2
- xori(tmp2, hdr, markWord::unlocked_value);
-
- // Try to swing header from unlocked to locked
- Label success;
- cmpxchgptr(hdr, tmp2, obj, tmp1, success, &slow);
- bind(success);
-
- // After successful lock, push object on lock-stack
- lwu(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
- add(tmp2, xthread, tmp1);
- sd(obj, Address(tmp2, 0));
- addw(tmp1, tmp1, oopSize);
- sw(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
+ assert_different_registers(obj, tmp1, tmp2, tmp3, t0);
+
+ Label push;
+ const Register top = tmp1;
+ const Register mark = tmp2;
+ const Register t = tmp3;
+
+ // Preload the markWord. It is important that this is the first
+ // instruction emitted as it is part of C1's null check semantics.
+ ld(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check if the lock-stack is full.
+ lwu(top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ mv(t, (unsigned)LockStack::end_offset());
+ bge(top, t, slow, /* is_far */ true);
+
+ // Check for recursion.
+ add(t, xthread, top);
+ ld(t, Address(t, -oopSize));
+ beq(obj, t, push);
+
+ // Check header for monitor (0b10).
+ test_bit(t, mark, exact_log2(markWord::monitor_value));
+ bnez(t, slow, /* is_far */ true);
+
+ // Try to lock. Transition lock-bits 0b01 => 0b00
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a la");
+ ori(mark, mark, markWord::unlocked_value);
+ xori(t, mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::int64,
+ /*acquire*/ Assembler::aq, /*release*/ Assembler::relaxed, /*result*/ t);
+ bne(mark, t, slow, /* is_far */ true);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ add(t, xthread, top);
+ sd(obj, Address(t));
+ addw(top, top, oopSize);
+ sw(top, Address(xthread, JavaThread::lock_stack_top_offset()));
}
// Implements ligthweight-unlocking.
-// Branches to slow upon failure.
-// Falls through upon success.
//
// - obj: the object to be unlocked
-// - hdr: the (pre-loaded) header of the object
-// - tmp1, tmp2: temporary registers
-void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register tmp1, Register tmp2, Label& slow) {
+// - tmp1, tmp2, tmp3: temporary registers
+// - slow: branched to if unlocking fails
+void MacroAssembler::lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, hdr, tmp1, tmp2, t0);
+ assert_different_registers(obj, tmp1, tmp2, tmp3, t0);
#ifdef ASSERT
{
- // The following checks rely on the fact that LockStack is only ever modified by
- // its owning thread, even if the lock got inflated concurrently; removal of LockStack
- // entries after inflation will happen delayed in that case.
-
// Check for lock-stack underflow.
Label stack_ok;
lwu(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
mv(tmp2, (unsigned)LockStack::start_offset());
- bgt(tmp1, tmp2, stack_ok);
+ bge(tmp1, tmp2, stack_ok);
STOP("Lock-stack underflow");
bind(stack_ok);
}
- {
- // Check if the top of the lock-stack matches the unlocked object.
- Label tos_ok;
- subw(tmp1, tmp1, oopSize);
- add(tmp1, xthread, tmp1);
- ld(tmp1, Address(tmp1, 0));
- beq(tmp1, obj, tos_ok);
- STOP("Top of lock-stack does not match the unlocked object");
- bind(tos_ok);
- }
- {
- // Check that hdr is fast-locked.
- Label hdr_ok;
- andi(tmp1, hdr, markWord::lock_mask_in_place);
- beqz(tmp1, hdr_ok);
- STOP("Header is not fast-locked");
- bind(hdr_ok);
- }
#endif
- // Load the new header (unlocked) into tmp1
- ori(tmp1, hdr, markWord::unlocked_value);
+ Label unlocked, push_and_slow;
+ const Register top = tmp1;
+ const Register mark = tmp2;
+ const Register t = tmp3;
+
+ // Check if obj is top of lock-stack.
+ lwu(top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ subw(top, top, oopSize);
+ add(t, xthread, top);
+ ld(t, Address(t));
+ bne(obj, t, slow, /* is_far */ true);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(add(t, xthread, top);)
+ DEBUG_ONLY(sd(zr, Address(t));)
+ sw(top, Address(xthread, JavaThread::lock_stack_top_offset()));
+
+ // Check if recursive.
+ add(t, xthread, top);
+ ld(t, Address(t, -oopSize));
+ beq(obj, t, unlocked);
+
+ // Not recursive. Check header for monitor (0b10).
+ ld(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ test_bit(t, mark, exact_log2(markWord::monitor_value));
+ bnez(t, push_and_slow);
- // Try to swing header from locked to unlocked
- Label success;
- cmpxchgptr(hdr, tmp1, obj, tmp2, success, &slow);
- bind(success);
-
- // After successful unlock, pop object from lock-stack
- lwu(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
- subw(tmp1, tmp1, oopSize);
#ifdef ASSERT
- add(tmp2, xthread, tmp1);
- sd(zr, Address(tmp2, 0));
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ test_bit(t, mark, exact_log2(markWord::unlocked_value));
+ beqz(t, not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
#endif
- sw(tmp1, Address(xthread, JavaThread::lock_stack_top_offset()));
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
+ ori(t, mark, markWord::unlocked_value);
+ cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::int64,
+ /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, /*result*/ t);
+ beq(mark, t, unlocked);
+
+ bind(push_and_slow);
+ // Restore lock-stack and handle the unlock in runtime.
+ DEBUG_ONLY(add(t, xthread, top);)
+ DEBUG_ONLY(sd(obj, Address(t));)
+ addw(top, top, oopSize);
+ sw(top, Address(xthread, JavaThread::lock_stack_top_offset()));
+ j(slow);
+
+ bind(unlocked);
}
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
index d283654e6e179..75c0f9ba30596 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
@@ -1193,7 +1193,10 @@ class MacroAssembler: public Assembler {
//
// Return: the call PC or null if CodeCache is full.
address trampoline_call(Address entry);
+
address ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment = NativeInstruction::instruction_size);
// Support for memory inc/dec
// n.b. increment/decrement calls with an Address destination will
@@ -1516,8 +1519,8 @@ class MacroAssembler: public Assembler {
void store_conditional(Register dst, Register new_val, Register addr, enum operand_size size, Assembler::Aqrl release);
public:
- void lightweight_lock(Register obj, Register hdr, Register tmp1, Register tmp2, Label& slow);
- void lightweight_unlock(Register obj, Register hdr, Register tmp1, Register tmp2, Label& slow);
+ void lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow);
+ void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow);
};
#ifdef ASSERT
diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
index c29ac1a04fae1..c4048f66e0d3e 100644
--- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
@@ -27,7 +27,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "code/compiledIC.hpp"
-#include "memory/resourceArea.hpp"
#include "nativeInst_riscv.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
@@ -157,7 +156,6 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
CompiledICLocker::is_safe(addr_at(0)),
"concurrent code patching");
- ResourceMark rm;
address addr_call = addr_at(0);
assert(NativeCall::is_call_at(addr_call), "unexpected code at call site");
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index 7e1291f49d74c..86d0ad7a05929 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
// Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -1196,13 +1196,13 @@ bool is_CAS(int opcode, bool maybe_volatile)
// returns true if CAS needs to use an acquiring load otherwise false
bool needs_acquiring_load_reserved(const Node *n)
{
- assert(n != NULL && is_CAS(n->Opcode(), true), "expecting a compare and swap");
+ assert(n != nullptr && is_CAS(n->Opcode(), true), "expecting a compare and swap");
LoadStoreNode* ldst = n->as_LoadStore();
- if (n != NULL && is_CAS(n->Opcode(), false)) {
- assert(ldst != NULL && ldst->trailing_membar() != NULL, "expected trailing membar");
+ if (n != nullptr && is_CAS(n->Opcode(), false)) {
+ assert(ldst != nullptr && ldst->trailing_membar() != nullptr, "expected trailing membar");
} else {
- return ldst != NULL && ldst->trailing_membar() != NULL;
+ return ldst != nullptr && ldst->trailing_membar() != nullptr;
}
// so we can just return true here
return true;
@@ -1247,7 +1247,7 @@ int MachCallRuntimeNode::ret_addr_offset() {
// sd(t1, Address(sp, wordSize)) -> sd
// jalr(t0) -> jalr
CodeBlob *cb = CodeCache::find_blob(_entry_point);
- if (cb != NULL) {
+ if (cb != nullptr) {
return 1 * NativeInstruction::instruction_size;
} else {
return 11 * NativeInstruction::instruction_size;
@@ -1286,7 +1286,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
#ifndef PRODUCT
void MachBreakpointNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
- assert_cond(st != NULL);
+ assert_cond(st != nullptr);
st->print("BREAKPOINT");
}
#endif
@@ -1342,14 +1342,14 @@ uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
#ifndef PRODUCT
void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
- assert_cond(st != NULL);
+ assert_cond(st != nullptr);
st->print("-- \t// MachConstantBaseNode (empty encoding)");
}
#endif
#ifndef PRODUCT
void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
- assert_cond(st != NULL && ra_ != NULL);
+ assert_cond(st != nullptr && ra_ != nullptr);
Compile* C = ra_->C;
int framesize = C->output()->frame_slots() << LogBytesPerInt;
@@ -1363,7 +1363,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); }
st->print("sub sp, sp, #%d\n\t", framesize);
- if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (C->stub_function() == nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
st->print("ld t0, [guard]\n\t");
st->print("membar LoadLoad\n\t");
st->print("ld t1, [xthread, #thread_disarmed_guard_value_offset]\n\t");
@@ -1377,7 +1377,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
#endif
void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
Compile* C = ra_->C;
C2_MacroAssembler _masm(&cbuf);
@@ -1392,7 +1392,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ nop(); // 4 bytes
}
- assert_cond(C != NULL);
+ assert_cond(C != nullptr);
if (C->clinit_barrier_on_entry()) {
assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
@@ -1412,9 +1412,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ build_frame(framesize);
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
- if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
// Dummy labels for just measuring the code size
Label dummy_slow_path;
Label dummy_continuation;
@@ -1451,7 +1451,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
uint MachPrologNode::size(PhaseRegAlloc* ra_) const
{
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
return MachNode::size(ra_); // too many variables; just compute it
// the hard way
}
@@ -1465,9 +1465,9 @@ int MachPrologNode::reloc() const
#ifndef PRODUCT
void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
- assert_cond(st != NULL && ra_ != NULL);
+ assert_cond(st != nullptr && ra_ != nullptr);
Compile* C = ra_->C;
- assert_cond(C != NULL);
+ assert_cond(C != nullptr);
int framesize = C->output()->frame_size_in_bytes();
st->print("# pop frame %d\n\t", framesize);
@@ -1491,10 +1491,10 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
#endif
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
Compile* C = ra_->C;
C2_MacroAssembler _masm(&cbuf);
- assert_cond(C != NULL);
+ assert_cond(C != nullptr);
int framesize = C->output()->frame_size_in_bytes();
__ remove_frame(framesize);
@@ -1517,7 +1517,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
}
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
// Variable size. Determine dynamically.
return MachNode::size(ra_);
}
@@ -1568,7 +1568,7 @@ static enum RC rc_class(OptoReg::Name reg) {
}
uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream *st) const {
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
Compile* C = ra_->C;
// Get registers to move.
@@ -1599,7 +1599,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
int src_offset = ra_->reg2offset(src_lo);
int dst_offset = ra_->reg2offset(dst_lo);
- if (bottom_type()->isa_vect() != NULL) {
+ if (bottom_type()->isa_vect() != nullptr) {
uint ireg = ideal_reg();
if (ireg == Op_VecA && cbuf) {
C2_MacroAssembler _masm(cbuf);
@@ -1640,7 +1640,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
ShouldNotReachHere();
}
}
- } else if (cbuf != NULL) {
+ } else if (cbuf != nullptr) {
C2_MacroAssembler _masm(cbuf);
switch (src_lo_rc) {
case rc_int:
@@ -1711,7 +1711,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
}
}
- if (st != NULL) {
+ if (st != nullptr) {
st->print("spill ");
if (src_lo_rc == rc_stack) {
st->print("[sp, #%d] -> ", src_offset);
@@ -1745,16 +1745,16 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
#ifndef PRODUCT
void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
- if (ra_ == NULL) {
+ if (ra_ == nullptr) {
st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx);
} else {
- implementation(NULL, ra_, false, st);
+ implementation(nullptr, ra_, false, st);
}
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation(&cbuf, ra_, false, NULL);
+ implementation(&cbuf, ra_, false, nullptr);
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
@@ -1765,7 +1765,7 @@ uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
#ifndef PRODUCT
void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
- assert_cond(ra_ != NULL && st != NULL);
+ assert_cond(ra_ != nullptr && st != nullptr);
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
int reg = ra_->get_reg_first(this);
st->print("add %s, sp, #%d\t# box lock",
@@ -1777,7 +1777,7 @@ void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
C2_MacroAssembler _masm(&cbuf);
Assembler::IncompressibleRegion ir(&_masm); // Fixed length: see BoxLockNode::size()
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
int reg = ra_->get_encode(this);
@@ -1805,17 +1805,16 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
#ifndef PRODUCT
void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
- assert_cond(st != NULL);
+ assert_cond(st != nullptr);
st->print_cr("# MachUEPNode");
if (UseCompressedClassPointers) {
- st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- if (CompressedKlassPointers::shift() != 0) {
- st->print_cr("\tdecode_klass_not_null t0, t0");
- }
+ st->print_cr("\tlwu t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tlwu t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
} else {
- st->print_cr("\tld t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tld t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tld t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
}
- st->print_cr("\tbeq t0, t1, ic_hit");
+ st->print_cr("\tbeq t0, t2, ic_hit");
st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check");
st->print_cr("\tic_hit:");
}
@@ -1825,20 +1824,16 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
+ __ ic_check(CodeEntryAlignment);
- Label skip;
- __ cmp_klass(j_rarg0, t1, t0, t2 /* call-clobbered t2 as a tmp */, skip);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(skip);
-
- // These NOPs are critical so that verified entry point is properly
- // 4 bytes aligned for patching by NativeJump::patch_verified_entry()
- __ align(NativeInstruction::instruction_size);
+ // Verified entry point must be properly 4 bytes aligned for patching by NativeJump::patch_verified_entry().
+ // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
+ assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
{
- assert_cond(ra_ != NULL);
+ assert_cond(ra_ != nullptr);
return MachNode::size(ra_);
}
@@ -1855,7 +1850,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf)
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1873,7 +1868,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf)
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1932,6 +1927,10 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_FmaVF:
case Op_FmaVD:
return UseFMA;
+
+ case Op_ConvHF2F:
+ case Op_ConvF2HF:
+ return UseZfh;
}
return true; // Per default match rules are supported.
@@ -2013,7 +2012,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return MIN2(size, max_size);
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
return Matcher::max_vector_size(bt);
}
@@ -2034,7 +2033,7 @@ int Matcher::scalable_vector_reg_size(const BasicType bt) {
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
ShouldNotReachHere(); // generic vector operands not supported
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -2137,10 +2136,10 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
}
bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
- assert_cond(addp != NULL);
+ assert_cond(addp != nullptr);
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
Node* u = addp->fast_out(i);
- if (u != NULL && u->is_Mem()) {
+ if (u != nullptr && u->is_Mem()) {
int opsize = u->as_Mem()->memory_size();
assert(opsize > 0, "unexpected memory operand size");
if (u->as_Mem()->memory_size() != (1 << shift)) {
@@ -2153,7 +2152,7 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
// Should the Matcher clone input 'm' of node 'n'?
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
- assert_cond(m != NULL);
+ assert_cond(m != nullptr);
if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
mstack.push(m, Visit); // m = ShiftCntV
return true;
@@ -2212,7 +2211,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL || con == (address)1) {
+ if (con == nullptr || con == (address)1) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -2242,7 +2241,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -2261,7 +2260,7 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Register dst_reg = as_Register($dst$$reg);
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
relocInfo::relocType rtype = $src->constant_reloc();
@@ -2347,7 +2346,7 @@ encode %{
Label done;
C2_MacroAssembler _masm(&cbuf);
__ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg,
- NULL, &miss);
+ nullptr, &miss);
if ($primary) {
__ mv(result_reg, zr);
} else {
@@ -2368,12 +2367,12 @@ encode %{
Assembler::IncompressibleRegion ir(&_masm); // Fixed length: see ret_addr_offset
address addr = (address)$meth$$method;
- address call = NULL;
- assert_cond(addr != NULL);
+ address call = nullptr;
+ assert_cond(addr != nullptr);
if (!_method) {
// A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap.
call = __ trampoline_call(Address(addr, relocInfo::runtime_call_type));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2387,7 +2386,7 @@ encode %{
RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
: static_call_Relocation::spec(method_index);
call = __ trampoline_call(Address(addr, rspec));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2398,8 +2397,8 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin());
} else {
// Emit stub for static call
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2414,7 +2413,7 @@ encode %{
Assembler::IncompressibleRegion ir(&_masm); // Fixed length: see ret_addr_offset
int method_index = resolved_method_index(cbuf);
address call = __ ic_call((address)$meth$$method, method_index);
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2440,9 +2439,9 @@ encode %{
// which loads the absolute address into a register.
address entry = (address)$meth$$method;
CodeBlob *cb = CodeCache::find_blob(entry);
- if (cb != NULL) {
+ if (cb != nullptr) {
address call = __ trampoline_call(Address(entry, relocInfo::runtime_call_type));
- if (call == NULL) {
+ if (call == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2890,7 +2889,7 @@ operand immP()
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immP0()
%{
predicate(n->get_ptr() == 0);
@@ -3011,7 +3010,7 @@ operand immN()
interface(CONST_INTER);
%}
-// Narrow NULL Pointer Immediate
+// Narrow Null Pointer Immediate
operand immN0()
%{
predicate(n->get_narrowcon() == 0);
@@ -4889,7 +4888,7 @@ instruct loadConP0(iRegPNoSp dst, immP0 con)
match(Set dst con);
ins_cost(ALU_COST);
- format %{ "mv $dst, $con\t# NULL ptr, #@loadConP0" %}
+ format %{ "mv $dst, $con\t# null pointer, #@loadConP0" %}
ins_encode(riscv_enc_mov_zero(dst));
@@ -4940,7 +4939,7 @@ instruct loadConN0(iRegNNoSp dst, immN0 con)
match(Set dst con);
ins_cost(ALU_COST);
- format %{ "mv $dst, $con\t# compressed NULL ptr, #@loadConN0" %}
+ format %{ "mv $dst, $con\t# compressed null pointer, #@loadConN0" %}
ins_encode(riscv_enc_mov_zero(dst));
@@ -8275,6 +8274,32 @@ instruct convD2F_reg(fRegF dst, fRegD src) %{
ins_pipe(fp_d2f);
%}
+// single <-> half precision
+
+instruct convHF2F_reg_reg(fRegF dst, iRegINoSp src, iRegINoSp tmp) %{
+ match(Set dst (ConvHF2F src));
+ effect(TEMP tmp);
+ format %{ "fmv.h.x $dst, $src\t# move source from $src to $dst\n\t"
+ "fcvt.s.h $dst, $dst\t# convert half to single precision"
+ %}
+ ins_encode %{
+ __ float16_to_float($dst$$FloatRegister, $src$$Register, $tmp$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct convF2HF_reg_reg(iRegINoSp dst, fRegF src, fRegF ftmp, iRegINoSp xtmp) %{
+ match(Set dst (ConvF2HF src));
+ effect(TEMP_DEF dst, TEMP ftmp, TEMP xtmp);
+ format %{ "fcvt.h.s $ftmp, $src\t# convert single precision to half\n\t"
+ "fmv.x.h $dst, $ftmp\t# move result from $ftmp to $dst"
+ %}
+ ins_encode %{
+ __ float_to_float16($dst$$Register, $src$$FloatRegister, $ftmp$$FloatRegister, $xtmp$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// float <-> int
instruct convF2I_reg_reg(iRegINoSp dst, fRegF src) %{
@@ -10308,7 +10333,7 @@ instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, iRegP_R30 tmp1,
ins_encode %{
address tpc = __ zero_words($base$$Register, $cnt$$Register);
- if (tpc == NULL) {
+ if (tpc == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -10345,23 +10370,7 @@ instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt,
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ string_equals($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 1);
- %}
- ins_pipe(pipe_class_memory);
-%}
-
-instruct string_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt,
- iRegI_R10 result, rFlagsReg cr)
-%{
- predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
-
- format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %}
- ins_encode %{
- // Count is in 8-bit bytes; non-Compact chars are 16 bits.
- __ string_equals($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 2);
+ $result$$Register, $cnt$$Register);
%}
ins_pipe(pipe_class_memory);
%}
@@ -10460,10 +10469,11 @@ instruct tlsLoadP(javaThread_RegP dst)
// using t1 as the 'flag' register to bridge the BoolNode producers and consumers
instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3);
- ins_cost(LOAD_COST * 2 + STORE_COST * 3 + ALU_COST * 6 + BRANCH_COST * 3);
+ ins_cost(10 * DEFAULT_COST);
format %{ "fastlock $object,$box\t! kills $tmp1,$tmp2,$tmp3, #@cmpFastLock" %}
ins_encode %{
@@ -10476,10 +10486,11 @@ instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iReg
// using t1 as the 'flag' register to bridge the BoolNode producers and consumers
instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2)
%{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp1, TEMP tmp2);
- ins_cost(LOAD_COST * 2 + STORE_COST + ALU_COST * 2 + BRANCH_COST * 4);
+ ins_cost(10 * DEFAULT_COST);
format %{ "fastunlock $object,$box\t! kills $tmp1, $tmp2, #@cmpFastUnlock" %}
ins_encode %{
@@ -10489,6 +10500,38 @@ instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iR
ins_pipe(pipe_serial);
%}
+instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP_R10 box, iRegPNoSp tmp1, iRegPNoSp tmp2)
+%{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP tmp1, TEMP tmp2, USE_KILL box);
+
+ ins_cost(10 * DEFAULT_COST);
+ format %{ "fastlock $object,$box\t! kills $box,$tmp1,$tmp2 #@cmpFastLockLightweight" %}
+
+ ins_encode %{
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register);
+ %}
+
+ ins_pipe(pipe_serial);
+%}
+
+instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP_R10 box, iRegPNoSp tmp1, iRegPNoSp tmp2)
+%{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object box));
+ effect(TEMP tmp1, TEMP tmp2, USE_KILL box);
+
+ ins_cost(10 * DEFAULT_COST);
+ format %{ "fastunlock $object,$box\t! kills $box,$tmp1,$tmp2, #@cmpFastUnlockLightweight" %}
+
+ ins_encode %{
+ __ fast_unlock_lightweight($object$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register);
+ %}
+
+ ins_pipe(pipe_serial);
+%}
+
// Tail Call; Jump from runtime stub to Java code.
// Also known as an 'interprocedural jump'.
// Target of jump will eventually return to caller.
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index c163325fc815f..d07f4dc7c9a2c 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2020, 2023, Arm Limited. All rights reserved.
// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -46,7 +46,7 @@ source %{
}
}
- bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+ bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
return match_rule_supported_vector(opcode, vlen, bt);
}
@@ -2614,24 +2614,7 @@ instruct vstring_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt,
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ string_equals_v($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 1);
- %}
- ins_pipe(pipe_class_memory);
-%}
-
-instruct vstring_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt,
- iRegI_R10 result, vReg_V2 v2,
- vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, rFlagsReg cr)
-%{
- predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v2, TEMP v3, TEMP v4, TEMP v5, KILL cr);
-
- format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %}
- ins_encode %{
- // Count is in 8-bit bytes; non-Compact chars are 16 bits.
- __ string_equals_v($str1$$Register, $str2$$Register,
- $result$$Register, $cnt$$Register, 2);
+ $result$$Register, $cnt$$Register);
%}
ins_pipe(pipe_class_memory);
%}
@@ -3217,7 +3200,7 @@ instruct vcvtBtoX(vReg dst, vReg src) %{
__ csrwi(CSR_FRM, C2_MacroAssembler::rne);
__ vfcvt_f_x_v(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg));
} else {
- __ integer_extend_v(as_VectorRegister($dst$$reg), bt,
+ __ integer_extend_v(as_VectorRegister($dst$$reg), bt,
Matcher::vector_length(this), as_VectorRegister($src$$reg), T_BYTE);
}
%}
diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
index 01fe307bc27c3..5945f9d5fe2ab 100644
--- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
@@ -29,7 +29,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -38,7 +37,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_riscv.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -622,10 +620,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
-
- const Register holder = t1;
const Register receiver = j_rarg0;
+ const Register data = t1;
const Register tmp = t2; // A call-clobbered register not used for arg passing
// -------------------------------------------------------------------------
@@ -639,16 +635,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ block_comment("c2i_unverified_entry {");
- __ load_klass(t0, receiver, tmp);
- __ ld(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ ld(xmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ beq(t0, tmp, ok);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(ok);
- // Method might have been compiled since the call site was patched to
- // interpreted; if that is the case treat it as a miss so we can get
- // the call site corrected.
+ __ ic_check();
+ __ ld(xmethod, Address(data, CompiledICData::speculated_method_offset()));
+
__ ld(t0, Address(xmethod, in_bytes(Method::code_offset())));
__ beqz(t0, skip_fixup);
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
@@ -985,7 +975,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ j(exit);
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1051,7 +1041,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
}
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1271,6 +1261,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
in_ByteSize(-1),
oop_maps,
exception_offset);
+ if (nm == nullptr) return nm;
if (method->is_continuation_enter_intrinsic()) {
ContinuationEntry::set_enter_code(nm, interpreted_entry_offset);
} else if (method->is_continuation_yield_intrinsic()) {
@@ -1424,19 +1415,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register ic_reg = t1;
const Register receiver = j_rarg0;
- Label hit;
- Label exception_pending;
-
__ verify_oop(receiver);
- assert_different_registers(ic_reg, receiver, t0, t2);
- __ cmp_klass(receiver, ic_reg, t0, t2 /* call-clobbered t2 as a tmp */, hit);
-
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // Verified entry point must be aligned
- __ align(8);
+ assert_different_registers(receiver, t0, t1);
- __ bind(hit);
+ __ ic_check();
int vep_offset = ((intptr_t)__ pc()) - start;
@@ -1697,8 +1679,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ sd(swap_reg, Address(lock_reg, mark_word_offset));
__ bnez(swap_reg, slow_path_lock);
} else {
- assert(LockingMode == LM_LIGHTWEIGHT, "");
- __ ld(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
__ lightweight_lock(obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
}
@@ -1824,9 +1805,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ decrement(Address(xthread, JavaThread::held_monitor_count_offset()));
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "");
- __ ld(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ test_bit(t0, old_hdr, exact_log2(markWord::monitor_value));
- __ bnez(t0, slow_path_unlock);
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
__ decrement(Address(xthread, JavaThread::held_monitor_count_offset()));
}
@@ -1871,6 +1849,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ leave();
// Any exception pending?
+ Label exception_pending;
__ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset())));
__ bnez(t0, exception_pending);
diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
index 4bd33d08f8928..bbdafb922cc46 100644
--- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
@@ -4809,6 +4809,348 @@ class StubGenerator: public StubCodeGenerator {
return (address) start;
}
+
+ // ------------------------ SHA-1 intrinsic ------------------------
+
+ // K't =
+ // 5a827999, 0 <= t <= 19
+ // 6ed9eba1, 20 <= t <= 39
+ // 8f1bbcdc, 40 <= t <= 59
+ // ca62c1d6, 60 <= t <= 79
+ void sha1_prepare_k(Register cur_k, int round) {
+ assert(round >= 0 && round < 80, "must be");
+
+ static const int64_t ks[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
+ if ((round % 20) == 0) {
+ __ mv(cur_k, ks[round/20]);
+ }
+ }
+
+ // W't =
+ // M't, 0 <= t <= 15
+ // ROTL'1(W't-3 ^ W't-8 ^ W't-14 ^ W't-16), 16 <= t <= 79
+ void sha1_prepare_w(Register cur_w, Register ws[], Register buf, int round) {
+ assert(round >= 0 && round < 80, "must be");
+
+ if (round < 16) {
+ // in the first 16 rounds, in ws[], every register contains 2 W't, e.g.
+ // in ws[0], high part contains W't-0, low part contains W't-1,
+ // in ws[1], high part contains W't-2, low part contains W't-3,
+ // ...
+ // in ws[7], high part contains W't-14, low part contains W't-15.
+
+ if ((round % 2) == 0) {
+ __ ld(ws[round/2], Address(buf, (round/2) * 8));
+ // reverse bytes, as SHA-1 is defined in big-endian.
+ __ revb(ws[round/2], ws[round/2]);
+ __ srli(cur_w, ws[round/2], 32);
+ } else {
+ __ mv(cur_w, ws[round/2]);
+ }
+
+ return;
+ }
+
+ if ((round % 2) == 0) {
+ int idx = 16;
+ // W't = ROTL'1(W't-3 ^ W't-8 ^ W't-14 ^ W't-16), 16 <= t <= 79
+ __ srli(t1, ws[(idx-8)/2], 32);
+ __ xorr(t0, ws[(idx-3)/2], t1);
+
+ __ srli(t1, ws[(idx-14)/2], 32);
+ __ srli(cur_w, ws[(idx-16)/2], 32);
+ __ xorr(cur_w, cur_w, t1);
+
+ __ xorr(cur_w, cur_w, t0);
+ __ rolw_imm(cur_w, cur_w, 1, t0);
+
+ // copy the cur_w value to ws[8].
+ // now, valid w't values are at:
+ // w0: ws[0]'s lower 32 bits
+ // w1 ~ w14: ws[1] ~ ws[7]
+ // w15: ws[8]'s higher 32 bits
+ __ slli(ws[idx/2], cur_w, 32);
+
+ return;
+ }
+
+ int idx = 17;
+ // W't = ROTL'1(W't-3 ^ W't-8 ^ W't-14 ^ W't-16), 16 <= t <= 79
+ __ srli(t1, ws[(idx-3)/2], 32);
+ __ xorr(t0, t1, ws[(idx-8)/2]);
+
+ __ xorr(cur_w, ws[(idx-16)/2], ws[(idx-14)/2]);
+
+ __ xorr(cur_w, cur_w, t0);
+ __ rolw_imm(cur_w, cur_w, 1, t0);
+
+ // copy the cur_w value to ws[8]
+ __ zero_extend(cur_w, cur_w, 32);
+ __ orr(ws[idx/2], ws[idx/2], cur_w);
+
+ // shift the w't registers, so they start from ws[0] again.
+ // now, valid w't values are at:
+ // w0 ~ w15: ws[0] ~ ws[7]
+ Register ws_0 = ws[0];
+ for (int i = 0; i < 16/2; i++) {
+ ws[i] = ws[i+1];
+ }
+ ws[8] = ws_0;
+ }
+
+ // f't(x, y, z) =
+ // Ch(x, y, z) = (x & y) ^ (~x & z) , 0 <= t <= 19
+ // Parity(x, y, z) = x ^ y ^ z , 20 <= t <= 39
+ // Maj(x, y, z) = (x & y) ^ (x & z) ^ (y & z) , 40 <= t <= 59
+ // Parity(x, y, z) = x ^ y ^ z , 60 <= t <= 79
+ void sha1_f(Register dst, Register x, Register y, Register z, int round) {
+ assert(round >= 0 && round < 80, "must be");
+ assert_different_registers(dst, x, y, z, t0, t1);
+
+ if (round < 20) {
+ // (x & y) ^ (~x & z)
+ __ andr(t0, x, y);
+ __ andn(dst, z, x);
+ __ xorr(dst, dst, t0);
+ } else if (round >= 40 && round < 60) {
+ // (x & y) ^ (x & z) ^ (y & z)
+ __ andr(t0, x, y);
+ __ andr(t1, x, z);
+ __ andr(dst, y, z);
+ __ xorr(dst, dst, t0);
+ __ xorr(dst, dst, t1);
+ } else {
+ // x ^ y ^ z
+ __ xorr(dst, x, y);
+ __ xorr(dst, dst, z);
+ }
+ }
+
+ // T = ROTL'5(a) + f't(b, c, d) + e + K't + W't
+ // e = d
+ // d = c
+ // c = ROTL'30(b)
+ // b = a
+ // a = T
+ void sha1_process_round(Register a, Register b, Register c, Register d, Register e,
+ Register cur_k, Register cur_w, Register tmp, int round) {
+ assert(round >= 0 && round < 80, "must be");
+ assert_different_registers(a, b, c, d, e, cur_w, cur_k, tmp, t0);
+
+ // T = ROTL'5(a) + f't(b, c, d) + e + K't + W't
+
+ // cur_w will be recalculated at the beginning of each round,
+ // so, we can reuse it as a temp register here.
+ Register tmp2 = cur_w;
+
+ // reuse e as a temporary register, as we will mv new value into it later
+ Register tmp3 = e;
+ __ add(tmp2, cur_k, tmp2);
+ __ add(tmp3, tmp3, tmp2);
+ __ rolw_imm(tmp2, a, 5, t0);
+
+ sha1_f(tmp, b, c, d, round);
+
+ __ add(tmp2, tmp2, tmp);
+ __ add(tmp2, tmp2, tmp3);
+
+ // e = d
+ // d = c
+ // c = ROTL'30(b)
+ // b = a
+ // a = T
+ __ mv(e, d);
+ __ mv(d, c);
+
+ __ rolw_imm(c, b, 30);
+ __ mv(b, a);
+ __ mv(a, tmp2);
+ }
+
+ // H(i)0 = a + H(i-1)0
+ // H(i)1 = b + H(i-1)1
+ // H(i)2 = c + H(i-1)2
+ // H(i)3 = d + H(i-1)3
+ // H(i)4 = e + H(i-1)4
+ void sha1_calculate_im_hash(Register a, Register b, Register c, Register d, Register e,
+ Register prev_ab, Register prev_cd, Register prev_e) {
+ assert_different_registers(a, b, c, d, e, prev_ab, prev_cd, prev_e);
+
+ __ add(a, a, prev_ab);
+ __ srli(prev_ab, prev_ab, 32);
+ __ add(b, b, prev_ab);
+
+ __ add(c, c, prev_cd);
+ __ srli(prev_cd, prev_cd, 32);
+ __ add(d, d, prev_cd);
+
+ __ add(e, e, prev_e);
+ }
+
+ void sha1_preserve_prev_abcde(Register a, Register b, Register c, Register d, Register e,
+ Register prev_ab, Register prev_cd, Register prev_e) {
+ assert_different_registers(a, b, c, d, e, prev_ab, prev_cd, prev_e, t0);
+
+ __ slli(t0, b, 32);
+ __ zero_extend(prev_ab, a, 32);
+ __ orr(prev_ab, prev_ab, t0);
+
+ __ slli(t0, d, 32);
+ __ zero_extend(prev_cd, c, 32);
+ __ orr(prev_cd, prev_cd, t0);
+
+ __ mv(prev_e, e);
+ }
+
+ // Intrinsic for:
+ // void sun.security.provider.SHA.implCompress0(byte[] buf, int ofs)
+ // void sun.security.provider.DigestBase.implCompressMultiBlock0(byte[] b, int ofs, int limit)
+ //
+ // Arguments:
+ //
+ // Inputs:
+ // c_rarg0: byte[] src array + offset
+ // c_rarg1: int[] SHA.state
+ // - - - - - - below are only for implCompressMultiBlock0 - - - - - -
+ // c_rarg2: int offset
+ // c_rarg3: int limit
+ //
+ // Outputs:
+ // - - - - - - below are only for implCompressMultiBlock0 - - - - - -
+ // c_rarg0: int offset, when (multi_block == true)
+ //
+ address generate_sha1_implCompress(bool multi_block, const char *name) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", name);
+
+ address start = __ pc();
+ __ enter();
+
+ RegSet saved_regs = RegSet::range(x18, x27);
+ if (multi_block) {
+ // use x9 as src below.
+ saved_regs += RegSet::of(x9);
+ }
+ __ push_reg(saved_regs, sp);
+
+ // c_rarg0 - c_rarg3: x10 - x13
+ Register buf = c_rarg0;
+ Register state = c_rarg1;
+ Register offset = c_rarg2;
+ Register limit = c_rarg3;
+ // use src to contain the original start point of the array.
+ Register src = x9;
+
+ if (multi_block) {
+ __ sub(limit, limit, offset);
+ __ add(limit, limit, buf);
+ __ sub(src, buf, offset);
+ }
+
+ // [args-reg]: x14 - x17
+ // [temp-reg]: x28 - x31
+ // [saved-reg]: x18 - x27
+
+ // h0/1/2/3/4
+ const Register a = x14, b = x15, c = x16, d = x17, e = x28;
+ // w0, w1, ... w15
+ // put two adjecent w's in one register:
+ // one at high word part, another at low word part
+ // at different round (even or odd), w't value reside in different items in ws[].
+ // w0 ~ w15, either reside in
+ // ws[0] ~ ws[7], where
+ // w0 at higher 32 bits of ws[0],
+ // w1 at lower 32 bits of ws[0],
+ // ...
+ // w14 at higher 32 bits of ws[7],
+ // w15 at lower 32 bits of ws[7].
+ // or, reside in
+ // w0: ws[0]'s lower 32 bits
+ // w1 ~ w14: ws[1] ~ ws[7]
+ // w15: ws[8]'s higher 32 bits
+ Register ws[9] = {x29, x30, x31, x18,
+ x19, x20, x21, x22,
+ x23}; // auxiliary register for calculating w's value
+ // current k't's value
+ const Register cur_k = x24;
+ // current w't's value
+ const Register cur_w = x25;
+ // values of a, b, c, d, e in the previous round
+ const Register prev_ab = x26, prev_cd = x27;
+ const Register prev_e = offset; // reuse offset/c_rarg2
+
+ // load 5 words state into a, b, c, d, e.
+ //
+ // To minimize the number of memory operations, we apply following
+ // optimization: read the states (a/b/c/d) of 4-byte values in pairs,
+ // with a single ld, and split them into 2 registers.
+ //
+ // And, as the core algorithm of SHA-1 works on 32-bits words, so
+ // in the following code, it does not care about the content of
+ // higher 32-bits in a/b/c/d/e. Based on this observation,
+ // we can apply further optimization, which is to just ignore the
+ // higher 32-bits in a/c/e, rather than set the higher
+ // 32-bits of a/c/e to zero explicitly with extra instructions.
+ __ ld(a, Address(state, 0));
+ __ srli(b, a, 32);
+ __ ld(c, Address(state, 8));
+ __ srli(d, c, 32);
+ __ lw(e, Address(state, 16));
+
+ Label L_sha1_loop;
+ if (multi_block) {
+ __ BIND(L_sha1_loop);
+ }
+
+ sha1_preserve_prev_abcde(a, b, c, d, e, prev_ab, prev_cd, prev_e);
+
+ for (int round = 0; round < 80; round++) {
+ // prepare K't value
+ sha1_prepare_k(cur_k, round);
+
+ // prepare W't value
+ sha1_prepare_w(cur_w, ws, buf, round);
+
+ // one round process
+ sha1_process_round(a, b, c, d, e, cur_k, cur_w, t2, round);
+ }
+
+ // compute the intermediate hash value
+ sha1_calculate_im_hash(a, b, c, d, e, prev_ab, prev_cd, prev_e);
+
+ if (multi_block) {
+ int64_t block_bytes = 16 * 4;
+ __ addi(buf, buf, block_bytes);
+
+ __ bge(limit, buf, L_sha1_loop, true);
+ }
+
+ // store back the state.
+ __ zero_extend(a, a, 32);
+ __ slli(b, b, 32);
+ __ orr(a, a, b);
+ __ sd(a, Address(state, 0));
+ __ zero_extend(c, c, 32);
+ __ slli(d, d, 32);
+ __ orr(c, c, d);
+ __ sd(c, Address(state, 8));
+ __ sw(e, Address(state, 16));
+
+ // return offset
+ if (multi_block) {
+ __ sub(c_rarg0, buf, src);
+ }
+
+ __ pop_reg(saved_regs, sp);
+
+ __ leave();
+ __ ret();
+
+ return (address) start;
+ }
+
+
+
#ifdef COMPILER2
static const int64_t right_2_bits = right_n_bits(2);
@@ -5273,6 +5615,11 @@ static const int64_t right_3_bits = right_n_bits(3);
StubRoutines::_chacha20Block = generate_chacha20Block();
}
+ if (UseSHA1Intrinsics) {
+ StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress");
+ StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB");
+ }
+
#endif // COMPILER2_OR_JVMCI
}
diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp
index 7c604e8c11cc2..90a7e0967b240 100644
--- a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp
+++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp
@@ -39,7 +39,7 @@ enum platform_dependent_constants {
// simply increase sizes if too small (assembler will crash if too small)
_initial_stubs_code_size = 10000,
_continuation_stubs_code_size = 2000,
- _compiler_stubs_code_size = 15000 ZGC_ONLY(+5000),
+ _compiler_stubs_code_size = 25000 ZGC_ONLY(+5000),
_final_stubs_code_size = 20000 ZGC_ONLY(+10000)
};
diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
index 73b4d1e28ccef..58f57f32b2f65 100644
--- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
@@ -3547,11 +3547,10 @@ void TemplateTable::_new() {
// get InstanceKlass
__ load_resolved_klass_at_offset(x14, x13, x14, t0);
- // make sure klass is initialized & doesn't have finalizer
- // make sure klass is fully initialized
- __ lbu(t0, Address(x14, InstanceKlass::init_state_offset()));
- __ sub(t1, t0, (u1)InstanceKlass::fully_initialized);
- __ bnez(t1, slow_case);
+ // make sure klass is initialized
+ assert(VM_Version::supports_fast_class_init_checks(),
+ "Optimization requires support for fast class initialization checks");
+ __ clinit_barrier(x14, t0, nullptr /*L_fast_path*/, &slow_case);
// get instance_size in InstanceKlass (scaled to a count of bytes)
__ lwu(x13, Address(x14, Klass::layout_helper_offset()));
diff --git a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp
index 142d9d636938d..8a6557dde93a1 100644
--- a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp
+++ b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp
@@ -267,9 +267,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
__ mov_metadata(xmethod, entry);
__ sd(xmethod, Address(xthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
+ __ push_cont_fastpath(xthread);
+
__ ld(t0, Address(xmethod, Method::from_compiled_offset()));
__ jalr(t0);
+ __ pop_cont_fastpath(xthread);
+
// return value shuffle
if (!needs_return_buffer) {
#ifdef ASSERT
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
index 9a72b8d75a136..e1711dc5592f9 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
@@ -81,6 +81,9 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseZbs)) {
FLAG_SET_DEFAULT(UseZbs, true);
}
+ if (FLAG_IS_DEFAULT(UseZfh)) {
+ FLAG_SET_DEFAULT(UseZfh, true);
+ }
if (FLAG_IS_DEFAULT(UseZic64b)) {
FLAG_SET_DEFAULT(UseZic64b, true);
}
@@ -146,16 +149,6 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
}
- if (UseSHA1Intrinsics) {
- warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
- FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
- }
-
- if (UseSHA3Intrinsics) {
- warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU.");
- FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
- }
-
if (UseCRC32Intrinsics) {
warning("CRC32 intrinsics are not available on this CPU.");
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
@@ -257,11 +250,8 @@ void VM_Version::initialize() {
// NOTE: Make sure codes dependent on UseRVV are put after c2_initialize(),
// as there are extra checks inside it which could disable UseRVV
// in some situations.
- if (UseZvkn && !UseRVV) {
- FLAG_SET_DEFAULT(UseZvkn, false);
- warning("Cannot enable Zvkn on cpu without RVV support.");
- }
+ // ChaCha20
if (UseRVV) {
if (FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) {
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, true);
@@ -273,29 +263,65 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
}
- if (!UseZvkn && UseSHA) {
- warning("SHA instructions are not available on this CPU");
- FLAG_SET_DEFAULT(UseSHA, false);
- } else if (UseZvkn && FLAG_IS_DEFAULT(UseSHA)) {
+ // SHA's
+ if (FLAG_IS_DEFAULT(UseSHA)) {
FLAG_SET_DEFAULT(UseSHA, true);
}
- if (!UseSHA) {
+ // SHA-1, no RVV required though.
+ if (UseSHA) {
+ if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
+ }
+ } else if (UseSHA1Intrinsics) {
+ warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
+ FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+ }
+
+ // UseZvkn (depends on RVV) and SHA-2.
+ if (UseZvkn && !UseRVV) {
+ FLAG_SET_DEFAULT(UseZvkn, false);
+ warning("Cannot enable Zvkn on cpu without RVV support.");
+ }
+ // SHA-2, depends on Zvkn.
+ if (UseSHA) {
+ if (UseZvkn) {
+ if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
+ }
+ if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
+ }
+ } else {
+ if (UseSHA256Intrinsics) {
+ warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU, UseZvkn needed.");
+ FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+ }
+ if (UseSHA512Intrinsics) {
+ warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU, UseZvkn needed.");
+ FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
+ }
+ }
+ } else {
if (UseSHA256Intrinsics) {
- warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU, UseZvkn needed.");
+ warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU, as UseSHA disabled.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
if (UseSHA512Intrinsics) {
- warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU, UseZvkn needed.");
+ warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU, as UseSHA disabled.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
- } else {
- if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
- FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
- }
- if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
- FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
- }
+ }
+
+ // SHA-3
+ if (UseSHA3Intrinsics) {
+ warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU.");
+ FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
+ }
+
+ // UseSHA
+ if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA3Intrinsics || UseSHA512Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA, false);
}
}
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp
index 1ea853284ff15..e6f79cd6379d0 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp
@@ -105,6 +105,8 @@ class VM_Version : public Abstract_VM_Version {
// Zbc Carry-less multiplication
// Zbs Single-bit instructions
//
+ // Zfh Half-Precision Floating-Point instructions
+ //
// Zicsr Control and Status Register (CSR) Instructions
// Zifencei Instruction-Fetch Fence
// Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space.
@@ -142,7 +144,8 @@ class VM_Version : public Abstract_VM_Version {
decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
- decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
+ decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
+ decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
@@ -214,6 +217,8 @@ class VM_Version : public Abstract_VM_Version {
constexpr static bool supports_stack_watermark_barrier() { return true; }
+ constexpr static bool supports_recursive_lightweight_locking() { return true; }
+
static bool supports_on_spin_wait() { return UseZihintpause; }
// RISCV64 supports fast class initialization checks
diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
index 9d08796681f3f..5d945dbc32309 100644
--- a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
@@ -27,10 +27,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_riscv.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -171,22 +171,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// Entry arguments:
- // t1: CompiledICHolder
+ // t1: CompiledICData
// j_rarg0: Receiver
// This stub is called from compiled code which has no callee-saved registers,
// so all registers except arguments are free at this point.
const Register recv_klass_reg = x18;
- const Register holder_klass_reg = x19; // declaring interface klass (DECC)
+ const Register holder_klass_reg = x19; // declaring interface klass (DEFC)
const Register resolved_klass_reg = x30; // resolved interface klass (REFC)
const Register temp_reg = x28;
const Register temp_reg2 = x29;
- const Register icholder_reg = t1;
+ const Register icdata_reg = t1;
Label L_no_such_interface;
- __ ld(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ ld(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ ld(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ ld(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
start_pc = __ pc();
diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp
index 9bb143001b944..91cc7e611bfd1 100644
--- a/src/hotspot/cpu/s390/assembler_s390.hpp
+++ b/src/hotspot/cpu/s390/assembler_s390.hpp
@@ -107,7 +107,7 @@ class RelAddr {
static bool is_in_range_of_RelAddr(address target, address pc, bool shortForm) {
// Guard against illegal branch targets, e.g. -1. Occurrences in
- // CompiledStaticCall and ad-file. Do not assert (it's a test
+ // CompiledDirectCall and ad-file. Do not assert (it's a test
// function!). Just return false in case of illegal operands.
if ((((uint64_t)target) & 0x0001L) != 0) return false;
if ((((uint64_t)pc) & 0x0001L) != 0) return false;
diff --git a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
index 200f7ee978dcb..b7f1d3605681a 100644
--- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -428,6 +428,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
"must be aligned");
ce->emit_static_call_stub();
+ CHECK_BAILOUT();
// Prepend each BRASL with a nop.
__ relocate(relocInfo::static_call_type);
diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
index 542ade8ed0ec3..503440a5fcc01 100644
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -76,10 +76,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const {
// We fetch the class of the receiver and compare it with the cached class.
// If they do not match we jump to the slow case.
int LIR_Assembler::check_icache() {
- Register receiver = receiverOpr()->as_register();
- int offset = __ offset();
- __ inline_cache_check(receiver, Z_inline_cache);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -2385,7 +2382,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
op->len()->as_register(),
op->tmp1()->as_register(),
op->tmp2()->as_register(),
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
type2aelembytes(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
@@ -2480,23 +2477,30 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
assert_different_registers(obj, k_RInfo, klass_RInfo);
if (op->should_profile()) {
+ Register mdo = klass_RInfo;
+ metadata2reg(md->constant_encoding(), mdo);
NearLabel not_null;
__ compareU64_and_branch(obj, (intptr_t) 0, Assembler::bcondNotEqual, not_null);
// Object is null; update MDO and exit.
- Register mdo = klass_RInfo;
- metadata2reg(md->constant_encoding(), mdo);
Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
__ or2mem_8(data_addr, header_bits);
__ branch_optimized(Assembler::bcondAlways, *obj_is_null);
__ bind(not_null);
+
+ NearLabel update_done;
+ Register recv = k_RInfo;
+ __ load_klass(recv, obj);
+ type_profile_helper(mdo, md, data, recv, Rtmp1, &update_done);
+ Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
+ __ add2mem_64(counter_addr, DataLayout::counter_increment, Rtmp1);
+ __ bind(update_done);
} else {
__ compareU64_and_branch(obj, (intptr_t) 0, Assembler::bcondEqual, *obj_is_null);
}
- NearLabel profile_cast_failure, profile_cast_success;
- Label *failure_target = op->should_profile() ? &profile_cast_failure : failure;
- Label *success_target = op->should_profile() ? &profile_cast_success : success;
+ Label *failure_target = failure;
+ Label *success_target = success;
// Patching may screw with our temporaries,
// so let's do it before loading the class.
@@ -2536,28 +2540,12 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
store_parameter(klass_RInfo, 0); // sub
store_parameter(k_RInfo, 1); // super
emit_call_c(a); // Sets condition code 0 for match (2 otherwise).
- CHECK_BAILOUT2(profile_cast_failure, profile_cast_success);
__ branch_optimized(Assembler::bcondNotEqual, *failure_target);
// Fall through to success case.
}
}
- if (op->should_profile()) {
- Register mdo = klass_RInfo, recv = k_RInfo;
- assert_different_registers(obj, mdo, recv);
- __ bind(profile_cast_success);
- metadata2reg(md->constant_encoding(), mdo);
- __ load_klass(recv, obj);
- type_profile_helper(mdo, md, data, recv, Rtmp1, success);
- __ branch_optimized(Assembler::bcondAlways, *success);
-
- __ bind(profile_cast_failure);
- metadata2reg(md->constant_encoding(), mdo);
- __ add2mem_64(Address(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())), -(int)DataLayout::counter_increment, Rtmp1);
- __ branch_optimized(Assembler::bcondAlways, *failure);
- } else {
- __ branch_optimized(Assembler::bcondAlways, *success);
- }
+ __ branch_optimized(Assembler::bcondAlways, *success);
}
void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
@@ -2587,21 +2575,29 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
assert(data != nullptr, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
}
- NearLabel profile_cast_success, profile_cast_failure, done;
- Label *success_target = op->should_profile() ? &profile_cast_success : &done;
- Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry();
+ NearLabel done;
+ Label *success_target = &done;
+ Label *failure_target = stub->entry();
if (op->should_profile()) {
+ Register mdo = klass_RInfo;
+ metadata2reg(md->constant_encoding(), mdo);
NearLabel not_null;
__ compareU64_and_branch(value, (intptr_t) 0, Assembler::bcondNotEqual, not_null);
// Object is null; update MDO and exit.
- Register mdo = klass_RInfo;
- metadata2reg(md->constant_encoding(), mdo);
Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
__ or2mem_8(data_addr, header_bits);
__ branch_optimized(Assembler::bcondAlways, done);
__ bind(not_null);
+
+ NearLabel update_done;
+ Register recv = k_RInfo;
+ __ load_klass(recv, value);
+ type_profile_helper(mdo, md, data, recv, Rtmp1, &update_done);
+ Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
+ __ add2mem_64(counter_addr, DataLayout::counter_increment, Rtmp1);
+ __ bind(update_done);
} else {
__ compareU64_and_branch(value, (intptr_t) 0, Assembler::bcondEqual, done);
}
@@ -2619,25 +2615,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
store_parameter(klass_RInfo, 0); // sub
store_parameter(k_RInfo, 1); // super
emit_call_c(a); // Sets condition code 0 for match (2 otherwise).
- CHECK_BAILOUT3(profile_cast_success, profile_cast_failure, done);
__ branch_optimized(Assembler::bcondNotEqual, *failure_target);
// Fall through to success case.
- if (op->should_profile()) {
- Register mdo = klass_RInfo, recv = k_RInfo;
- assert_different_registers(value, mdo, recv);
- __ bind(profile_cast_success);
- metadata2reg(md->constant_encoding(), mdo);
- __ load_klass(recv, value);
- type_profile_helper(mdo, md, data, recv, Rtmp1, &done);
- __ branch_optimized(Assembler::bcondAlways, done);
-
- __ bind(profile_cast_failure);
- metadata2reg(md->constant_encoding(), mdo);
- __ add2mem_64(Address(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())), -(int)DataLayout::counter_increment, Rtmp1);
- __ branch_optimized(Assembler::bcondAlways, *stub->entry());
- }
-
__ bind(done);
} else {
if (code == lir_checkcast) {
diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
index 229216ef20d44..c8815f3a729a4 100644
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
@@ -45,7 +45,7 @@
}
enum {
- _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledStaticCall::emit_to_interp_stub.
+ _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledDirectCall::emit_to_interp_stub.
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
_deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64)
};
diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
index 40edca6559aa4..58bdcee5d5f8f 100644
--- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -40,31 +40,6 @@
#include "runtime/stubRoutines.hpp"
#include "utilities/macros.hpp"
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- Label ic_miss, ic_hit;
- verify_oop(receiver, FILE_AND_LINE);
- int klass_offset = oopDesc::klass_offset_in_bytes();
-
- if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) {
- if (VM_Version::has_CompareBranch()) {
- z_cgij(receiver, 0, Assembler::bcondEqual, ic_miss);
- } else {
- z_ltgr(receiver, receiver);
- z_bre(ic_miss);
- }
- }
-
- compare_klass_ptr(iCache, klass_offset, receiver, false);
- z_bre(ic_hit);
-
- // If icache check fails, then jump to runtime routine.
- // Note: RECEIVER must still contain the receiver!
- load_const_optimized(Z_R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub()));
- z_br(Z_R1_scratch);
- align(CodeEntryAlignment);
- bind(ic_hit);
-}
-
void C1_MacroAssembler::explicit_null_check(Register base) {
ShouldNotCallThis(); // unused
}
@@ -296,7 +271,7 @@ void C1_MacroAssembler::allocate_array(
Register len, // array length
Register t1, // temp register
Register t2, // temp register
- int hdr_size, // object header size in words
+ int base_offset_in_bytes, // elements offset in bytes
int elt_size, // element size in bytes
Register klass, // object klass
Label& slow_case // Continuation point if fast allocation fails.
@@ -322,8 +297,8 @@ void C1_MacroAssembler::allocate_array(
case 8: z_sllg(arr_size, len, 3); break;
default: ShouldNotReachHere();
}
- add2reg(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment.
- z_nill(arr_size, (~MinObjAlignmentInBytesMask) & 0xffff); // Align array size.
+ add2reg(arr_size, base_offset_in_bytes + MinObjAlignmentInBytesMask); // Add space for header & alignment.
+ z_nill(arr_size, (~MinObjAlignmentInBytesMask) & 0xffff); // Align array size.
try_allocate(obj, arr_size, 0, t1, slow_case);
@@ -333,9 +308,9 @@ void C1_MacroAssembler::allocate_array(
Label done;
Register object_fields = t1;
Register Rzero = Z_R1_scratch;
- z_aghi(arr_size, -(hdr_size * BytesPerWord));
+ z_aghi(arr_size, -base_offset_in_bytes);
z_bre(done); // Jump if size of fields is zero.
- z_la(object_fields, hdr_size * BytesPerWord, obj);
+ z_la(object_fields, base_offset_in_bytes, obj);
z_xgr(Rzero, Rzero);
initialize_body(object_fields, arr_size, Rzero);
bind(done);
diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp
index 7a4f76af1546e..c77258509e1a5 100644
--- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -86,7 +86,7 @@
Register len, // array length
Register t1, // temp register
Register t2, // temp register
- int hdr_size, // object header size in words
+ int base_offset_in_bytes, // elements offset in bytes
int elt_size, // element size in bytes
Register klass, // object klass
Label& slow_case // Continuation point if fast allocation fails.
diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
index 257148827be4e..decb3a1cafc31 100644
--- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
@@ -35,7 +35,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_s390.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_s390.hpp"
diff --git a/src/hotspot/cpu/s390/compiledIC_s390.cpp b/src/hotspot/cpu/s390/compiledIC_s390.cpp
index 7ea90c1de7c69..3adcfbc85f185 100644
--- a/src/hotspot/cpu/s390/compiledIC_s390.cpp
+++ b/src/hotspot/cpu/s390/compiledIC_s390.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
@@ -40,7 +39,7 @@
#undef __
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
#ifdef COMPILER2
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
@@ -54,7 +53,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// That's why we must use the macroassembler to generate a stub.
MacroAssembler _masm(&cbuf);
- address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
+ address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size());
if (stub == nullptr) {
return nullptr; // CodeBuffer::expand failed.
}
@@ -81,27 +80,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 2 * MacroAssembler::load_const_from_toc_size() +
2; // branch
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 5; // 4 in emit_java_to_interp + 1 in Java_Static_Call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -131,7 +123,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp
index 3ed99f68c475c..8ce9305a865e5 100644
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp
@@ -31,9 +31,9 @@
#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1SATBMarkQueueSet.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/sharedRuntime.hpp"
diff --git a/src/hotspot/cpu/s390/icBuffer_s390.cpp b/src/hotspot/cpu/s390/icBuffer_s390.cpp
deleted file mode 100644
index 0dc936d6fad0c..0000000000000
--- a/src/hotspot/cpu/s390/icBuffer_s390.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_s390.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm.
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return MacroAssembler::load_const_size() + Assembler::z_brul_size();
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_oop, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler masm(&code);
- // Note: even though the code contains an embedded oop, we do not need reloc info
- // because
- // (1) the oop is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear.
-
- // Load the oop,
- __ load_const(Z_method, (address) cached_oop); // inline cache reg = Z_method
- // and do a tail-call (pc-relative).
- __ z_brul((address) entry_point);
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object.
- return MacroAssembler::get_target_addr_pcrel(move->next_instruction_address());
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object.
- return (void*)move->data();
-}
diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp
index ea691342b2397..9ee38c619f0b0 100644
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -447,9 +447,6 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// Do the check.
check_klass_subtype(Rsub_klass, Rsuper_klass, Rtmp1, Rtmp2, ok_is_subtype);
-
- // Profile the failure of the check.
- profile_typecheck_failed(Rtmp1, Rtmp2);
}
// Pop topmost element from stack. It just disappears.
@@ -1425,7 +1422,7 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
}
// Record the receiver type.
- record_klass_in_profile(receiver, mdp, reg2, true);
+ record_klass_in_profile(receiver, mdp, reg2);
bind(skip_receiver_profile);
// The method data pointer needs to be updated to reflect the new target.
@@ -1448,11 +1445,9 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
void InterpreterMacroAssembler::record_klass_in_profile_helper(
Register receiver, Register mdp,
Register reg2, int start_row,
- Label& done, bool is_virtual_call) {
+ Label& done) {
if (TypeProfileWidth == 0) {
- if (is_virtual_call) {
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
- }
+ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
return;
}
@@ -1487,23 +1482,19 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
z_ltgr(reg2, reg2);
if (start_row == last_row) {
// The only thing left to do is handle the null case.
- if (is_virtual_call) {
- z_brz(found_null);
- // Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polymorphic case.
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
- z_bru(done);
- bind(found_null);
- } else {
- z_brnz(done);
- }
+ z_brz(found_null);
+ // Receiver did not match any saved receiver and there is no empty row for it.
+ // Increment total counter to indicate polymorphic case.
+ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+ z_bru(done);
+ bind(found_null);
break;
}
// Since null is rare, make it be the branch-taken case.
z_brz(found_null);
// Put all the "Case 3" tests here.
- record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
+ record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done);
// Found a null. Keep searching for a matching receiver,
// but remember that this is an empty (unused) slot.
@@ -1550,12 +1541,11 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
// done:
void InterpreterMacroAssembler::record_klass_in_profile(Register receiver,
- Register mdp, Register reg2,
- bool is_virtual_call) {
+ Register mdp, Register reg2) {
assert(ProfileInterpreter, "must be profiling");
Label done;
- record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call);
+ record_klass_in_profile_helper(receiver, mdp, reg2, 0, done);
bind (done);
}
@@ -1615,24 +1605,6 @@ void InterpreterMacroAssembler::profile_null_seen(Register mdp) {
}
}
-void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp, Register tmp) {
- if (ProfileInterpreter && TypeProfileCasts) {
- Label profile_continue;
-
- // If no method data exists, go to profile_continue.
- test_method_data_pointer(mdp, profile_continue);
-
- int count_offset = in_bytes(CounterData::count_offset());
- // Back up the address, since we have already bumped the mdp.
- count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
-
- // *Decrement* the counter. We expect to see zero or small negatives.
- increment_mdp_data_at(mdp, count_offset, tmp, true);
-
- bind (profile_continue);
- }
-}
-
void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) {
if (ProfileInterpreter) {
Label profile_continue;
@@ -1646,7 +1618,7 @@ void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass,
mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
// Record the object type.
- record_klass_in_profile(klass, mdp, reg2, false);
+ record_klass_in_profile(klass, mdp, reg2);
}
update_mdp_by_constant(mdp, mdp_delta);
diff --git a/src/hotspot/cpu/s390/interp_masm_s390.hpp b/src/hotspot/cpu/s390/interp_masm_s390.hpp
index 56abe295876aa..f94473b1700b7 100644
--- a/src/hotspot/cpu/s390/interp_masm_s390.hpp
+++ b/src/hotspot/cpu/s390/interp_masm_s390.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -281,10 +281,10 @@ class InterpreterMacroAssembler: public MacroAssembler {
Label& not_equal_continue);
void record_klass_in_profile(Register receiver, Register mdp,
- Register reg2, bool is_virtual_call);
+ Register reg2);
void record_klass_in_profile_helper(Register receiver, Register mdp,
Register reg2, int start_row,
- Label& done, bool is_virtual_call);
+ Label& done);
void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
void update_mdp_by_offset(Register mdp_in, Register dataidx, int offset_of_disp);
@@ -301,7 +301,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
void profile_ret(Register return_bci, Register mdp);
void profile_null_seen(Register mdp);
void profile_typecheck(Register mdp, Register klass, Register scratch);
- void profile_typecheck_failed(Register mdp, Register tmp);
void profile_switch_default(Register mdp);
void profile_switch_case(Register index_in_scratch, Register mdp,
Register scratch1, Register scratch2);
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
index d95a0b3a3c5bd..0226d494c8958 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -1097,7 +1098,13 @@ void MacroAssembler::clear_mem(const Address& addr, unsigned int size) {
}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) z_nop();
+ align(modulus, offset());
+}
+
+void MacroAssembler::align(int modulus, int target) {
+ assert(((modulus % 2 == 0) && (target % 2 == 0)), "needs to be even");
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) z_nop();
}
// Special version for non-relocateable code if required alignment
@@ -2150,6 +2157,45 @@ void MacroAssembler::call_VM_leaf_base(address entry_point) {
call_VM_leaf_base(entry_point, allow_relocation);
}
+int MacroAssembler::ic_check_size() {
+ return 30 + (ImplicitNullChecks ? 0 : 6);
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register R2_receiver = Z_ARG1;
+ Register R0_scratch = Z_R0_scratch;
+ Register R1_scratch = Z_R1_scratch;
+ Register R9_data = Z_inline_cache;
+ Label success, failure;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+ if (!ImplicitNullChecks) {
+ z_cgij(R2_receiver, 0, Assembler::bcondEqual, failure);
+ }
+
+ if (UseCompressedClassPointers) {
+ z_llgf(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes()));
+ } else {
+ z_lg(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes()));
+ }
+ z_cg(R1_scratch, Address(R9_data, in_bytes(CompiledICData::speculated_klass_offset())));
+ z_bre(success);
+
+ bind(failure);
+ load_const(R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub()));
+ z_br(R1_scratch);
+ bind(success);
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point, offset() = %d, end_alignment = %d", offset(), end_alignment);
+ return uep_offset;
+}
+
void MacroAssembler::call_VM_base(Register oop_result,
Register last_java_sp,
address entry_point,
@@ -3744,7 +3790,7 @@ void MacroAssembler::compare_klass_ptr(Register Rop1, int64_t disp, Register Rba
Register current = Rop1;
Label done;
- if (maybenull) { // null ptr must be preserved!
+ if (maybenull) { // null pointer must be preserved!
z_ltgr(Z_R0, current);
z_bre(done);
current = Z_R0;
@@ -3883,7 +3929,7 @@ void MacroAssembler::compare_heap_oop(Register Rop1, Address mem, bool maybenull
Label done;
int pow2_offset = get_oop_base_complement(Z_R1, ((uint64_t)(intptr_t)base));
- if (maybenull) { // null ptr must be preserved!
+ if (maybenull) { // null pointer must be preserved!
z_ltgr(Z_R0, Rop1);
z_bre(done);
}
@@ -4123,7 +4169,7 @@ void MacroAssembler::oop_decoder(Register Rdst, Register Rsrc, bool maybenull, R
Label done;
// Rsrc contains a narrow oop. Thus we are sure the leftmost bits will never be set.
- if (maybenull) { // null ptr must be preserved!
+ if (maybenull) { // null pointer must be preserved!
z_slag(Rdst, Rsrc, oop_shift); // Arithmetic shift sets the condition code.
z_bre(done);
} else {
@@ -4185,7 +4231,7 @@ void MacroAssembler::oop_decoder(Register Rdst, Register Rsrc, bool maybenull, R
// Scale oop and check for null.
// Rsrc contains a narrow oop. Thus we are sure the leftmost bits will never be set.
- if (maybenull) { // null ptr must be preserved!
+ if (maybenull) { // null pointer must be preserved!
z_slag(Rdst_tmp, Rsrc, oop_shift); // Arithmetic shift sets the condition code.
z_bre(done);
} else {
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
index bf14b42e2d1b3..924583abdf563 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
@@ -257,6 +257,7 @@ class MacroAssembler: public Assembler {
// nop padding
void align(int modulus);
+ void align(int modulus, int target);
void align_address(int modulus);
//
@@ -566,6 +567,9 @@ class MacroAssembler: public Assembler {
// Get the pc where the last call will return to. Returns _last_calls_return_pc.
inline address last_calls_return_pc();
+ static int ic_check_size();
+ int ic_check(int end_alignment);
+
private:
static bool is_call_far_patchable_variant0_at(address instruction_addr); // Dynamic TOC: load target addr from CP and call.
static bool is_call_far_patchable_variant2_at(address instruction_addr); // PC-relative call, prefixed with NOPs.
diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad
index 9f4e182a9e4b7..5fcb885cdc3ab 100644
--- a/src/hotspot/cpu/s390/s390.ad
+++ b/src/hotspot/cpu/s390/s390.ad
@@ -1,6 +1,6 @@
//
-// Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
-// Copyright (c) 2017, 2022 SAP SE. All rights reserved.
+// Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2017, 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
@@ -740,7 +740,7 @@ int emit_call_reloc(C2_MacroAssembler &_masm, intptr_t entry_point, relocInfo::r
if (rtype == relocInfo::runtime_call_w_cp_type) {
assert((__ offset() & 2) == 0, "misaligned emit_call_reloc");
address call_addr = __ call_c_opt((address)entry_point);
- if (call_addr == NULL) {
+ if (call_addr == nullptr) {
Compile::current()->env()->record_out_of_memory_failure();
return -1;
}
@@ -835,7 +835,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print_cr("push_frame %d", (int)-framesize);
st->print("\t");
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
st->print("nmethod entry barrier\n\t");
}
}
@@ -890,7 +890,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
}
- if (C->stub_function() == NULL) {
+ if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->nmethod_entry_barrier(&_masm);
}
@@ -1056,7 +1056,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
bool src12 = Immediate::is_uimm12(src_offset);
bool dst12 = Immediate::is_uimm12(dst_offset);
- const char *mnemo = NULL;
+ const char *mnemo = nullptr;
unsigned long opc = 0;
// Memory->Memory Spill. Use Z_R0 to hold the value.
@@ -1199,7 +1199,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
#if !defined(PRODUCT)
void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
if (ra_ && ra_->node_regs_max_index() > 0) {
- implementation(NULL, ra_, false, os);
+ implementation(nullptr, ra_, false, os);
} else {
if (req() == 2 && in(1)) {
os->print("N%d = N%d\n", _idx, in(1)->_idx);
@@ -1217,11 +1217,11 @@ void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation(&cbuf, ra_, false, NULL);
+ implementation(&cbuf, ra_, false, nullptr);
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation(NULL, ra_, true, NULL);
+ return implementation(nullptr, ra_, true, nullptr);
}
//=============================================================================
@@ -1341,51 +1341,9 @@ void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
#endif
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
+ // This is Unverified Entry Point
C2_MacroAssembler _masm(&cbuf);
- const int ic_miss_offset = 2;
-
- // Inline_cache contains a klass.
- Register ic_klass = as_Register(Matcher::inline_cache_reg_encode());
- // ARG1 is the receiver oop.
- Register R2_receiver = Z_ARG1;
- int klass_offset = oopDesc::klass_offset_in_bytes();
- AddressLiteral icmiss(SharedRuntime::get_ic_miss_stub());
- Register R1_ic_miss_stub_addr = Z_R1_scratch;
-
- // Null check of receiver.
- // This is the null check of the receiver that actually should be
- // done in the caller. It's here because in case of implicit null
- // checks we get it for free.
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
- "second word in oop should not require explicit null check.");
- if (!ImplicitNullChecks) {
- Label valid;
- if (VM_Version::has_CompareBranch()) {
- __ z_cgij(R2_receiver, 0, Assembler::bcondNotEqual, valid);
- } else {
- __ z_ltgr(R2_receiver, R2_receiver);
- __ z_bre(valid);
- }
- // The ic_miss_stub will handle the null pointer exception.
- __ load_const_optimized(R1_ic_miss_stub_addr, icmiss);
- __ z_br(R1_ic_miss_stub_addr);
- __ bind(valid);
- }
-
- // Check whether this method is the proper implementation for the class of
- // the receiver (ic miss check).
- {
- Label valid;
- // Compare cached class against klass from receiver.
- // This also does an implicit null check!
- __ compare_klass_ptr(ic_klass, klass_offset, R2_receiver, false);
- __ z_bre(valid);
- // The inline cache points to the wrong method. Call the
- // ic_miss_stub to find the proper method.
- __ load_const_optimized(R1_ic_miss_stub_addr, icmiss);
- __ z_br(R1_ic_miss_stub_addr);
- __ bind(valid);
- }
+ __ ic_check(CodeEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
@@ -1446,7 +1404,8 @@ int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) {
+ if (base == nullptr) {
+ ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1467,7 +1426,8 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) {
+ if (base == nullptr) {
+ ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1513,7 +1473,7 @@ bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
-bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
return match_rule_supported_vector(opcode, vlen, bt);
}
@@ -1533,11 +1493,11 @@ bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
}
const RegMask* Matcher::predicate_reg_mask(void) {
- return NULL;
+ return nullptr;
}
const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) {
- return NULL;
+ return nullptr;
}
// Vector calling convention not yet implemented.
@@ -1574,7 +1534,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return max_vector_size(bt); // Same as max.
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
return Matcher::max_vector_size(bt);
}
@@ -1602,7 +1562,7 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
ShouldNotReachHere(); // generic vector operands not supported
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -1948,12 +1908,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
__ z_brul(l);
%}
@@ -1961,12 +1921,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
__ z_bru(l);
%}
@@ -1974,12 +1934,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
__ z_brcl((Assembler::branch_condition)$cmp$$cmpcode, l);
%}
@@ -1987,12 +1947,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
__ z_brc((Assembler::branch_condition)$cmp$$cmpcode, l);
%}
@@ -2000,12 +1960,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
Assembler::branch_condition cc = (Assembler::branch_condition)$cmp$$cmpcode;
unsigned long instr = $primary;
if (instr == CRJ_ZOPC) {
@@ -2024,12 +1984,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
unsigned long instr = $primary;
if (instr == CR_ZOPC) {
@@ -2050,12 +2010,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
Assembler::branch_condition cc = (Assembler::branch_condition)$cmp$$cmpcode;
unsigned long instr = $primary;
@@ -2075,12 +2035,12 @@ encode %{
C2_MacroAssembler _masm(&cbuf);
Label* p = $lbl$$label;
- // 'p' is `NULL' when this encoding class is used only to
+ // 'p' is `nullptr' when this encoding class is used only to
// determine the size of the encoded instruction.
// Use a bound dummy label in that case.
Label d;
__ bind(d);
- Label& l = (NULL == p) ? d : *(p);
+ Label& l = (nullptr == p) ? d : *(p);
unsigned long instr = $primary;
if (instr == CHI_ZOPC) {
@@ -2112,7 +2072,7 @@ encode %{
assert((__ offset() & 2) == 0, "misaligned z_enc_java_to_runtime_call");
address call_addr = __ call_c_opt((address)$meth$$method);
- if (call_addr == NULL) {
+ if (call_addr == nullptr) {
Compile::current()->env()->record_out_of_memory_failure();
return;
}
@@ -2143,11 +2103,11 @@ encode %{
static_call_Relocation::spec(method_index));
}
}
- assert(__ inst_mark() != NULL, "emit_call_reloc must set_inst_mark()");
+ assert(__ inst_mark() != nullptr, "emit_call_reloc must set_inst_mark()");
if (_method) { // Emit stub for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2162,7 +2122,7 @@ encode %{
int vtable_index = this->_vtable_index;
if (vtable_index == -4) {
Register ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
- address virtual_call_oop_addr = NULL;
+ address virtual_call_oop_addr = nullptr;
AddressLiteral empty_ic((address) Universe::non_oop_word());
virtual_call_oop_addr = __ pc();
@@ -2929,7 +2889,7 @@ operand immP8() %{
// POINTER specific values
//-----------------------------------
-// Pointer Immediate: NULL
+// Pointer Immediate: nullptr
operand immP0() %{
predicate(n->get_ptr() == 0);
match(ConP);
@@ -2966,7 +2926,7 @@ operand immN8() %{
interface(CONST_INTER);
%}
-// Narrow NULL Pointer Immediate
+// Narrow Null Pointer Immediate
operand immN0() %{
predicate(n->get_narrowcon() == 0);
match(ConN);
@@ -3383,7 +3343,7 @@ operand inline_cache_regP(iRegP reg) %{
// Operands to remove register moves in unscaled mode.
// Match read/write registers with an EncodeP node if neither shift nor add are required.
operand iRegP2N(iRegP reg) %{
- predicate(CompressedOops::shift() == 0 && _leaf->as_EncodeP()->in(0) == NULL);
+ predicate(CompressedOops::shift() == 0 && _leaf->as_EncodeP()->in(0) == nullptr);
constraint(ALLOC_IN_RC(z_memory_ptr_reg));
match(EncodeP reg);
format %{ "$reg" %}
@@ -3391,8 +3351,8 @@ operand iRegP2N(iRegP reg) %{
%}
operand iRegN2P(iRegN reg) %{
- predicate(CompressedOops::base() == NULL && CompressedOops::shift() == 0 &&
- _leaf->as_DecodeN()->in(0) == NULL);
+ predicate(CompressedOops::base() == nullptr && CompressedOops::shift() == 0 &&
+ _leaf->as_DecodeN()->in(0) == nullptr);
constraint(ALLOC_IN_RC(z_memory_ptr_reg));
match(DecodeN reg);
format %{ "$reg" %}
@@ -4236,7 +4196,7 @@ instruct loadConL_pcrelTOC(iRegL dst, immL src) %{
format %{ "LGRL $dst,[pcrelTOC]\t # load long $src from table" %}
ins_encode %{
address long_address = __ long_constant($src$$constant);
- if (long_address == NULL) {
+ if (long_address == nullptr) {
Compile::current()->env()->record_out_of_memory_failure();
return;
}
@@ -4292,14 +4252,14 @@ instruct loadConP_pcrelTOC(iRegP dst, immP src) %{
} else if (constant_reloc == relocInfo::metadata_type) {
AddressLiteral a = __ constant_metadata_address((Metadata *)$src$$constant);
address const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
- if (const_toc_addr == NULL) {
+ if (const_toc_addr == nullptr) {
Compile::current()->env()->record_out_of_memory_failure();
return;
}
__ load_long_pcrelative($dst$$Register, const_toc_addr);
} else { // Non-oop pointers, e.g. card mark base, heap top.
address long_address = __ long_constant((jlong)$src$$constant);
- if (long_address == NULL) {
+ if (long_address == nullptr) {
Compile::current()->env()->record_out_of_memory_failure();
return;
}
@@ -4314,7 +4274,7 @@ instruct loadConP0(iRegP dst, immP0 src, flagsReg cr) %{
match(Set dst src);
effect(KILL cr);
size(4);
- format %{ "XGR $dst,$dst\t # NULL ptr" %}
+ format %{ "XGR $dst,$dst\t # null pointer" %}
opcode(XGR_ZOPC);
ins_encode(z_rreform(dst, dst));
ins_pipe(pipe_class_dummy);
@@ -4660,7 +4620,7 @@ instruct loadConNKlass(iRegN dst, immNKlass src) %{
instruct decodeLoadN(iRegP dst, memory mem) %{
match(Set dst (DecodeN (LoadN mem)));
- predicate(false && (CompressedOops::base()==NULL)&&(CompressedOops::shift()==0));
+ predicate(false && (CompressedOops::base()==nullptr)&&(CompressedOops::shift()==0));
ins_cost(MEMORY_REF_COST);
size(Z_DISP3_SIZE);
format %{ "DecodeLoadN $dst,$mem\t # (cOop Load+Decode)" %}
@@ -4671,7 +4631,7 @@ instruct decodeLoadN(iRegP dst, memory mem) %{
instruct decodeLoadNKlass(iRegP dst, memory mem) %{
match(Set dst (DecodeNKlass (LoadNKlass mem)));
- predicate(false && (CompressedKlassPointers::base()==NULL)&&(CompressedKlassPointers::shift()==0));
+ predicate(false && (CompressedKlassPointers::base()==nullptr)&&(CompressedKlassPointers::shift()==0));
ins_cost(MEMORY_REF_COST);
size(Z_DISP3_SIZE);
format %{ "DecodeLoadNKlass $dst,$mem\t # (load/decode NKlass)" %}
@@ -4699,7 +4659,7 @@ instruct decodeLoadConNKlass(iRegP dst, immNKlass src) %{
instruct decodeN(iRegP dst, iRegN src, flagsReg cr) %{
match(Set dst (DecodeN src));
effect(KILL cr);
- predicate(CompressedOops::base() == NULL || !ExpandLoadingBaseDecode);
+ predicate(CompressedOops::base() == nullptr || !ExpandLoadingBaseDecode);
ins_cost(MEMORY_REF_COST+3 * DEFAULT_COST + BRANCH_COST);
// TODO: s390 port size(VARIABLE_SIZE);
format %{ "decodeN $dst,$src\t # (decode cOop)" %}
@@ -4723,7 +4683,7 @@ instruct decodeN_NN(iRegP dst, iRegN src, flagsReg cr) %{
effect(KILL cr);
predicate((n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull ||
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
- (CompressedOops::base()== NULL || !ExpandLoadingBaseDecode_NN));
+ (CompressedOops::base()== nullptr || !ExpandLoadingBaseDecode_NN));
ins_cost(MEMORY_REF_COST+2 * DEFAULT_COST);
// TODO: s390 port size(VARIABLE_SIZE);
format %{ "decodeN $dst,$src\t # (decode cOop NN)" %}
@@ -4749,7 +4709,7 @@ instruct decodeN_NN(iRegP dst, iRegN src, flagsReg cr) %{
effect(KILL cr);
predicate(false);
// TODO: s390 port size(VARIABLE_SIZE);
- format %{ "decodeN $dst = ($src == 0) ? NULL : ($src << 3) + $base + pow2_offset\t # (decode cOop)" %}
+ format %{ "decodeN $dst = ($src == 0) ? nullptr : ($src << 3) + $base + pow2_offset\t # (decode cOop)" %}
ins_encode %{
__ oop_decoder($dst$$Register, $src$$Register, true, $base$$Register,
(jlong)MacroAssembler::get_oop_base_pow2_offset((uint64_t)(intptr_t)CompressedOops::base()));
@@ -4774,7 +4734,7 @@ instruct decodeN_NN(iRegP dst, iRegN src, flagsReg cr) %{
// Decoder for heapbased mode peeling off loading the base.
instruct decodeN_Ex(iRegP dst, iRegN src, flagsReg cr) %{
match(Set dst (DecodeN src));
- predicate(CompressedOops::base() != NULL && ExpandLoadingBaseDecode);
+ predicate(CompressedOops::base() != nullptr && ExpandLoadingBaseDecode);
ins_cost(MEMORY_REF_COST+3 * DEFAULT_COST + BRANCH_COST);
// TODO: s390 port size(VARIABLE_SIZE);
expand %{
@@ -4790,7 +4750,7 @@ instruct decodeN_NN_Ex(iRegP dst, iRegN src, flagsReg cr) %{
match(Set dst (DecodeN src));
predicate((n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull ||
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
- CompressedOops::base() != NULL && ExpandLoadingBaseDecode_NN);
+ CompressedOops::base() != nullptr && ExpandLoadingBaseDecode_NN);
ins_cost(MEMORY_REF_COST+2 * DEFAULT_COST);
// TODO: s390 port size(VARIABLE_SIZE);
expand %{
@@ -6069,7 +6029,7 @@ instruct addP_reg_reg_imm12(iRegP dst, memoryRegP src1, iRegL src2, uimmL12 con)
instruct addP_regN_reg_imm12(iRegP dst, iRegP_N2P src1, iRegL src2, uimmL12 con) %{
match(Set dst (AddP (AddP src1 src2) con));
- predicate( PreferLAoverADD && CompressedOops::base() == NULL && CompressedOops::shift() == 0);
+ predicate( PreferLAoverADD && CompressedOops::base() == nullptr && CompressedOops::shift() == 0);
ins_cost(DEFAULT_COST_LOW);
size(4);
format %{ "LA $dst,$con($src1,$src2)\t # ptr d12(x,b)" %}
@@ -6091,7 +6051,7 @@ instruct addP_reg_reg_imm20(iRegP dst, memoryRegP src1, iRegL src2, immL20 con)
instruct addP_regN_reg_imm20(iRegP dst, iRegP_N2P src1, iRegL src2, immL20 con) %{
match(Set dst (AddP (AddP src1 src2) con));
- predicate( PreferLAoverADD && CompressedOops::base() == NULL && CompressedOops::shift() == 0);
+ predicate( PreferLAoverADD && CompressedOops::base() == nullptr && CompressedOops::shift() == 0);
ins_cost(DEFAULT_COST);
// TODO: s390 port size(FIXED_SIZE);
format %{ "LAY $dst,$con($src1,$src2)\t # ptr d20(x,b)" %}
@@ -8427,7 +8387,7 @@ instruct compP_reg_imm0(flagsReg cr, iRegP_N2P op1, immP0 op2) %{
// Don't use LTGFR which performs sign extend.
instruct compP_decode_reg_imm0(flagsReg cr, iRegN op1, immP0 op2) %{
match(Set cr (CmpP (DecodeN op1) op2));
- predicate(CompressedOops::base() == NULL && CompressedOops::shift() == 0);
+ predicate(CompressedOops::base() == nullptr && CompressedOops::shift() == 0);
ins_cost(DEFAULT_COST_LOW);
size(2);
format %{ "LTR $op1, $op1\t # ptr" %}
@@ -9843,24 +9803,10 @@ instruct string_equalsL(iRegP str1, iRegP str2, iRegI cnt, iRegI result, roddReg
ins_pipe(pipe_class_dummy);
%}
-instruct string_equalsU(iRegP str1, iRegP str2, iRegI cnt, iRegI result, roddRegL oddReg, revenRegL evenReg, flagsReg cr) %{
- match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP oddReg, TEMP evenReg, KILL cr); // R0, R1 are killed, too.
- predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU || ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::none);
- ins_cost(300);
- format %{ "String Equals char[] $str1,$str2,$cnt -> $result" %}
- ins_encode %{
- __ array_equals(false, $str1$$Register, $str2$$Register,
- $cnt$$Register, $oddReg$$Register, $evenReg$$Register,
- $result$$Register, false /* byte */);
- %}
- ins_pipe(pipe_class_dummy);
-%}
-
instruct string_equals_imm(iRegP str1, iRegP str2, uimmI8 cnt, iRegI result, flagsReg cr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
effect(KILL cr); // R0 is killed, too.
- predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL || ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
+ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL);
ins_cost(100);
format %{ "String Equals byte[] $str1,$str2,$cnt -> $result" %}
ins_encode %{
diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
index ed1795cfa339f..11e1e617d8e3a 100644
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
@@ -26,8 +26,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shared/gcLocker.hpp"
@@ -35,7 +35,6 @@
#include "interpreter/interp_masm.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_s390.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "registerSaver_s390.hpp"
@@ -1500,17 +1499,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
unsigned int wrapper_FrameDone;
unsigned int wrapper_CRegsSet;
Label handle_pending_exception;
- Label ic_miss;
//---------------------------------------------------------------------
// Unverified entry point (UEP)
//---------------------------------------------------------------------
- wrapper_UEPStart = __ offset();
// check ic: object class <-> cached class
- if (!method_is_static) __ nmethod_UEP(ic_miss);
- // Fill with nops (alignment of verified entry point).
- __ align(CodeEntryAlignment);
+ if (!method_is_static) {
+ wrapper_UEPStart = __ ic_check(CodeEntryAlignment /* end_alignment */);
+ }
//---------------------------------------------------------------------
// Verified entry point (VEP)
@@ -2026,13 +2023,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ restore_return_pc();
__ z_br(Z_R1_scratch);
- //---------------------------------------------------------------------
- // Handler for a cache miss (out-of-line)
- //---------------------------------------------------------------------
- __ call_ic_miss_handler(ic_miss, 0x77, 0, Z_R1_scratch);
__ flush();
-
-
//////////////////////////////////////////////////////////////////////
// end of code generation
//////////////////////////////////////////////////////////////////////
@@ -2318,9 +2309,6 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label skip_fixup;
{
Label ic_miss;
- const int klass_offset = oopDesc::klass_offset_in_bytes();
- const int holder_klass_offset = in_bytes(CompiledICHolder::holder_klass_offset());
- const int holder_metadata_offset = in_bytes(CompiledICHolder::holder_metadata_offset());
// Out-of-line call to ic_miss handler.
__ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch);
@@ -2329,27 +2317,11 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ align(CodeEntryAlignment);
c2i_unverified_entry = __ pc();
- // Check the pointers.
- if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) {
- __ z_ltgr(Z_ARG1, Z_ARG1);
- __ z_bre(ic_miss);
- }
- __ verify_oop(Z_ARG1, FILE_AND_LINE);
-
- // Check ic: object class <-> cached class
- // Compress cached class for comparison. That's more efficient.
- if (UseCompressedClassPointers) {
- __ z_lg(Z_R11, holder_klass_offset, Z_method); // Z_R11 is overwritten a few instructions down anyway.
- __ compare_klass_ptr(Z_R11, klass_offset, Z_ARG1, false); // Cached class can't be zero.
- } else {
- __ z_clc(klass_offset, sizeof(void *)-1, Z_ARG1, holder_klass_offset, Z_method);
- }
- __ z_brne(ic_miss); // Cache miss: call runtime to handle this.
-
+ __ ic_check(2);
+ __ z_lg(Z_method, Address(Z_inline_cache, CompiledICData::speculated_method_offset()));
// This def MUST MATCH code in gen_c2i_adapter!
const Register code = Z_R11;
- __ z_lg(Z_method, holder_metadata_offset, Z_method);
__ load_and_test_long(Z_R0, method_(code));
__ z_brne(ic_miss); // Cache miss: call runtime to handle this.
diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp
index 62d62a9842f83..02b9405ad31d5 100644
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -2868,7 +2868,7 @@ void TemplateTable::jvmti_post_field_mod(Register cache,
__ z_lgr(fieldEntry, cache);
if (is_static) {
- // Life is simple. NULL the object pointer.
+ // Life is simple. Null the object pointer.
__ clear_reg(obj, true, false); // Don't set CC.
} else {
// Life is harder. The stack holds the value on top, followed by
@@ -3914,20 +3914,15 @@ void TemplateTable::_new() {
__ z_cli(0, tmp, JVM_CONSTANT_Class);
__ z_brne(slow_case);
- __ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset.
+ __ z_sllg(offset, offset, LogBytesPerWord); // Convert to offset.
// Get InstanceKlass.
Register iklass = cpool;
__ load_resolved_klass_at_offset(cpool, offset, iklass);
- // Make sure klass is initialized & doesn't have finalizer.
- // Make sure klass is fully initialized.
- const int state_offset = in_bytes(InstanceKlass::init_state_offset());
- if (Immediate::is_uimm12(state_offset)) {
- __ z_cli(state_offset, iklass, InstanceKlass::fully_initialized);
- } else {
- __ z_cliy(state_offset, iklass, InstanceKlass::fully_initialized);
- }
- __ z_brne(slow_case);
+ // make sure klass is initialized
+ assert(VM_Version::supports_fast_class_init_checks(),
+ "Optimization requires support for fast class initialization checks");
+ __ clinit_barrier(iklass, Z_thread, nullptr /*L_fast_path*/, &slow_case);
// Get instance_size in InstanceKlass (scaled to a count of bytes).
Register Rsize = offset;
diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp
index 93d5b11c473d1..7ac60a10ae7f8 100644
--- a/src/hotspot/cpu/s390/vm_version_s390.hpp
+++ b/src/hotspot/cpu/s390/vm_version_s390.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2022 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -567,7 +567,6 @@ class VM_Version: public Abstract_VM_Version {
static unsigned long z_SIGSEGV();
static void initialize_cpu_information(void);
- static bool profile_all_receivers_at_type_check() { return false; }
};
#endif // CPU_S390_VM_VERSION_S390_HPP
diff --git a/src/hotspot/cpu/s390/vtableStubs_s390.cpp b/src/hotspot/cpu/s390/vtableStubs_s390.cpp
index 5a79369ceab47..573c23d796708 100644
--- a/src/hotspot/cpu/s390/vtableStubs_s390.cpp
+++ b/src/hotspot/cpu/s390/vtableStubs_s390.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2023 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
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_s390.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
@@ -197,12 +197,12 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(rcvr_klass, Z_ARG1);
// Receiver subtype check against REFC.
- __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset()));
+ __ z_lg(interface, Address(Z_method, CompiledICData::itable_refc_klass_offset()));
__ lookup_interface_method(rcvr_klass, interface, noreg,
noreg, Z_R1, no_such_interface, /*return_method=*/ false);
// Get Method* and entrypoint for compiler
- __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset()));
+ __ z_lg(interface, Address(Z_method, CompiledICData::itable_defc_klass_offset()));
__ lookup_interface_method(rcvr_klass, interface, itable_index,
Z_method, Z_R1, no_such_interface, /*return_method=*/ true);
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 63d6ec9b00f1b..9482537d84f90 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -1089,7 +1089,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
break;
case 0x62: // EVEX_4bytes
- assert(VM_Version::supports_evex(), "shouldn't have EVEX prefix");
+ assert(VM_Version::cpu_supports_evex(), "shouldn't have EVEX prefix");
assert(ip == inst+1, "no prefixes allowed");
// no EVEX collisions, all instructions that have 0x62 opcodes
// have EVEX versions and are subopcodes of 0x66
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index 7b907218f3516..8b512fac6bc05 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -816,8 +816,8 @@ class Assembler : public AbstractAssembler {
void check_relocation(RelocationHolder const& rspec, int format);
#endif
- void emit_data(jint data, relocInfo::relocType rtype, int format);
- void emit_data(jint data, RelocationHolder const& rspec, int format);
+ void emit_data(jint data, relocInfo::relocType rtype, int format = 0);
+ void emit_data(jint data, RelocationHolder const& rspec, int format = 0);
void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
index ff0726840d30a..c279e3073af87 100644
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
@@ -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
@@ -72,7 +72,6 @@ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jl
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = rax; // where the IC klass is cached
const Register SYNC_header = rax; // synchronization header
const Register SHIFT_count = rcx; // where count for shift operations must be
@@ -336,23 +335,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- const bool do_post_padding = VerifyOops || UseCompressedClassPointers;
- if (!do_post_padding) {
- // insert some nops so that the verified entry point is aligned on CodeEntryAlignment
- __ align(CodeEntryAlignment, __ offset() + ic_cmp_size);
- }
- int offset = __ offset();
- __ inline_cache_check(receiver, IC_Klass);
- assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct");
- if (do_post_padding) {
- // force alignment after the cache check.
- // It's been verified to be aligned if !VerifyOops
- __ align(CodeEntryAlignment);
- }
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -1635,7 +1618,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
len,
tmp1,
tmp2,
- arrayOopDesc::header_size(op->type()),
+ arrayOopDesc::base_offset_in_bytes(op->type()),
array_element_size(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
index b6a27abf0f37e..7088cf33cf646 100644
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, 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
@@ -1207,9 +1207,10 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
__ move(result_reg, result);
}
+#ifndef _LP64
// _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f
// _i2b, _i2c, _i2s
-LIR_Opr fixed_register_for(BasicType type) {
+static LIR_Opr fixed_register_for(BasicType type) {
switch (type) {
case T_FLOAT: return FrameMap::fpu0_float_opr;
case T_DOUBLE: return FrameMap::fpu0_double_opr;
@@ -1218,6 +1219,7 @@ LIR_Opr fixed_register_for(BasicType type) {
default: ShouldNotReachHere(); return LIR_OprFact::illegalOpr;
}
}
+#endif
void LIRGenerator::do_Convert(Convert* x) {
#ifdef _LP64
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
index 78361a305aeeb..caca3a1528261 100644
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_Runtime1.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -34,10 +35,12 @@
#include "oops/arrayOop.hpp"
#include "oops/markWord.hpp"
#include "runtime/basicLock.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
+#include "utilities/globalDefinitions.hpp"
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
@@ -60,9 +63,6 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
jcc(Assembler::notZero, slow_case);
}
- // Load object header
- movptr(hdr, Address(obj, hdr_offset));
-
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
const Register thread = r15_thread;
@@ -73,6 +73,8 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
lightweight_lock(obj, hdr, thread, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
Label done;
+ // Load object header
+ movptr(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
orptr(hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
@@ -134,9 +136,14 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
- movptr(disp_hdr, Address(obj, hdr_offset));
- andptr(disp_hdr, ~(int32_t)markWord::lock_mask_in_place);
- lightweight_unlock(obj, disp_hdr, hdr, slow_case);
+#ifdef _LP64
+ lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case);
+#else
+ // This relies on the implementation of lightweight_unlock being able to handle
+ // that the reg_rax and thread Register parameters may alias each other.
+ get_thread(disp_hdr);
+ lightweight_unlock(obj, disp_hdr, disp_hdr, hdr, slow_case);
+#endif
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
@@ -179,6 +186,15 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
if (len->is_valid()) {
movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
+#ifdef _LP64
+ int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
+ if (!is_aligned(base_offset, BytesPerWord)) {
+ assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
+ // Clear gap/first 4 bytes following the length field.
+ xorl(t1, t1);
+ movl(Address(obj, base_offset), t1);
+ }
+#endif
}
#ifdef _LP64
else if (UseCompressedClassPointers) {
@@ -262,7 +278,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
verify_oop(obj);
}
-void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case) {
+void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case) {
assert(obj == rax, "obj must be in rax, for cmpxchg");
assert_different_registers(obj, len, t1, t2, klass);
@@ -275,7 +291,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
const Register arr_size = t2; // okay to be the same
// align object end
- movptr(arr_size, header_size * BytesPerWord + MinObjAlignmentInBytesMask);
+ movptr(arr_size, base_offset_in_bytes + MinObjAlignmentInBytesMask);
lea(arr_size, Address(arr_size, len, f));
andptr(arr_size, ~MinObjAlignmentInBytesMask);
@@ -285,7 +301,10 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
// clear rest of allocated space
const Register len_zero = len;
- initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
+ // Align-up to word boundary, because we clear the 4 bytes potentially
+ // following the length field in initialize_header().
+ int base_offset = align_up(base_offset_in_bytes, BytesPerWord);
+ initialize_body(obj, arr_size, base_offset, len_zero);
if (CURRENT_ENV->dtrace_alloc_probes()) {
assert(obj == rax, "must be");
@@ -295,30 +314,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
verify_oop(obj);
}
-
-
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
- int start_offset = offset();
-
- if (UseCompressedClassPointers) {
- load_klass(rscratch1, receiver, rscratch2);
- cmpptr(rscratch1, iCache);
- } else {
- cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
- }
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- jump_cc(Assembler::notEqual,
- RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- assert(UseCompressedClassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
-}
-
-
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp
index b3593feb05640..ae340e64fb737 100644
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -89,7 +89,7 @@
// header_size: size of object header in words
// f : element scale factor
// slow_case : exit to slow case implementation if fast allocation fails
- void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case);
+ void allocate_array(Register obj, Register len, Register t, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case);
int rsp_offset() const { return _rsp_offset; }
void set_rsp_offset(int n) { _rsp_offset = n; }
diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
index 8b56f464f2739..2c24c0c2cfb17 100644
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
@@ -38,7 +38,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_x86.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_x86.hpp"
diff --git a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
index b9b4e8af02c5f..6dc8d14064ad2 100644
--- a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, 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
@@ -73,26 +73,74 @@ void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) {
__ jmp(continuation(), false /* maybe_short */);
}
-#ifdef _LP64
-int C2HandleAnonOMOwnerStub::max_size() const {
- // Max size of stub has been determined by testing with 0, in which case
- // C2CodeStubList::emit() will throw an assertion and report the actual size that
- // is needed.
- return DEBUG_ONLY(36) NOT_DEBUG(21);
+int C2FastUnlockLightweightStub::max_size() const {
+ return 128;
}
-void C2HandleAnonOMOwnerStub::emit(C2_MacroAssembler& masm) {
- __ bind(entry());
- Register mon = monitor();
- Register t = tmp();
- __ movptr(Address(mon, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), r15_thread);
- __ subl(Address(r15_thread, JavaThread::lock_stack_top_offset()), oopSize);
+void C2FastUnlockLightweightStub::emit(C2_MacroAssembler& masm) {
+ assert(_t == rax, "must be");
+
+ Label restore_held_monitor_count_and_slow_path;
+
+ { // Restore lock-stack and handle the unlock in runtime.
+
+ __ bind(_push_and_slow_path);
#ifdef ASSERT
- __ movl(t, Address(r15_thread, JavaThread::lock_stack_top_offset()));
- __ movptr(Address(r15_thread, t), 0);
+ // The obj was only cleared in debug.
+ __ movl(_t, Address(_thread, JavaThread::lock_stack_top_offset()));
+ __ movptr(Address(_thread, _t), _obj);
#endif
- __ jmp(continuation());
-}
+ __ addl(Address(_thread, JavaThread::lock_stack_top_offset()), oopSize);
+ }
+
+ { // Restore held monitor count and slow path.
+
+ __ bind(restore_held_monitor_count_and_slow_path);
+ // Restore held monitor count.
+ __ increment(Address(_thread, JavaThread::held_monitor_count_offset()));
+ // increment will always result in ZF = 0 (no overflows).
+ __ jmp(slow_path_continuation());
+ }
+
+ { // Handle monitor medium path.
+
+ __ bind(_check_successor);
+
+ Label fix_zf_and_unlocked;
+ const Register monitor = _mark;
+
+#ifndef _LP64
+ __ jmpb(restore_held_monitor_count_and_slow_path);
+#else // _LP64
+ // successor null check.
+ __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD);
+ __ jccb(Assembler::equal, restore_held_monitor_count_and_slow_path);
+
+ // Release lock.
+ __ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+
+ // Fence.
+ // Instead of MFENCE we use a dummy locked add of 0 to the top-of-stack.
+ __ lock(); __ addl(Address(rsp, 0), 0);
+
+ // Recheck successor.
+ __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD);
+ // Observed a successor after the release -> fence we have handed off the monitor
+ __ jccb(Assembler::notEqual, fix_zf_and_unlocked);
+
+ // Try to relock, if it fails the monitor has been handed over
+ // TODO: Caveat, this may fail due to deflation, which does
+ // not handle the monitor handoff. Currently only works
+ // due to the responsible thread.
+ __ xorptr(rax, rax);
+ __ lock(); __ cmpxchgptr(_thread, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
+ __ jccb (Assembler::equal, restore_held_monitor_count_and_slow_path);
#endif
+ __ bind(fix_zf_and_unlocked);
+ __ xorl(rax, rax);
+ __ jmp(unlocked_continuation());
+ }
+}
+
#undef __
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 3817c38f4ba3b..b6ecde62af655 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -33,9 +33,13 @@
#include "opto/output.hpp"
#include "opto/opcodes.hpp"
#include "opto/subnode.hpp"
+#include "runtime/globals.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/powerOfTwo.hpp"
+#include "utilities/sizes.hpp"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -554,6 +558,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data,
bool use_rtm, bool profile_rtm) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
// Ensure the register assignments are disjoint
assert(tmpReg == rax, "");
@@ -605,7 +610,8 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
if (LockingMode == LM_MONITOR) {
// Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0.
testptr(objReg, objReg);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Attempt stack-locking ...
orptr (tmpReg, markWord::unlocked_value);
movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS
@@ -620,10 +626,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
// Next instruction set ZFlag == 1 (Success) if difference is less then one page.
andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - (int)os::vm_page_size())) );
movptr(Address(boxReg, 0), tmpReg);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "");
- lightweight_lock(objReg, tmpReg, thread, scrReg, NO_COUNT);
- jmp(COUNT);
}
jmp(DONE_LABEL);
@@ -754,6 +756,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
// Xcheck:jni is enabled.
void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert(boxReg == rax, "");
assert_different_registers(objReg, boxReg, tmpReg);
@@ -784,23 +787,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
}
// It's inflated.
- if (LockingMode == LM_LIGHTWEIGHT) {
- // If the owner is ANONYMOUS, we need to fix it - in an outline stub.
- testb(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t) ObjectMonitor::ANONYMOUS_OWNER);
-#ifdef _LP64
- if (!Compile::current()->output()->in_scratch_emit_size()) {
- C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmpReg, boxReg);
- Compile::current()->output()->add_stub(stub);
- jcc(Assembler::notEqual, stub->entry());
- bind(stub->continuation());
- } else
-#endif
- {
- // We can't easily implement this optimization on 32 bit because we don't have a thread register.
- // Call the slow-path instead.
- jcc(Assembler::notEqual, NO_COUNT);
- }
- }
#if INCLUDE_RTM_OPT
if (use_rtm) {
@@ -922,19 +908,14 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
jmpb (DONE_LABEL);
#endif
- if (LockingMode != LM_MONITOR) {
+ if (LockingMode == LM_LEGACY) {
bind (Stacked);
- if (LockingMode == LM_LIGHTWEIGHT) {
- mov(boxReg, tmpReg);
- lightweight_unlock(objReg, boxReg, tmpReg, NO_COUNT);
- jmp(COUNT);
- } else if (LockingMode == LM_LEGACY) {
- movptr(tmpReg, Address (boxReg, 0)); // re-fetch
- lock();
- cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box
- }
+ movptr(tmpReg, Address (boxReg, 0)); // re-fetch
+ lock();
+ cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box
// Intentional fall-thru into DONE_LABEL
}
+
bind(DONE_LABEL);
// ZFlag == 1 count in fast path
@@ -955,6 +936,247 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
bind(NO_COUNT);
}
+void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register rax_reg,
+ Register t, Register thread) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert(rax_reg == rax, "Used for CAS");
+ assert_different_registers(obj, box, rax_reg, t, thread);
+
+ // Handle inflated monitor.
+ Label inflated;
+ // Finish fast lock successfully. ZF value is irrelevant.
+ Label locked;
+ // Finish fast lock unsuccessfully. MUST jump with ZF == 0
+ Label slow_path;
+
+ if (DiagnoseSyncOnValueBasedClasses != 0) {
+ load_klass(rax_reg, obj, t);
+ movl(rax_reg, Address(rax_reg, Klass::access_flags_offset()));
+ testl(rax_reg, JVM_ACC_IS_VALUE_BASED_CLASS);
+ jcc(Assembler::notZero, slow_path);
+ }
+
+ const Register mark = t;
+
+ { // Lightweight Lock
+
+ Label push;
+
+ const Register top = box;
+
+ // Load the mark.
+ movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Prefetch top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Check for monitor (0b10).
+ testptr(mark, markWord::monitor_value);
+ jcc(Assembler::notZero, inflated);
+
+ // Check if lock-stack is full.
+ cmpl(top, LockStack::end_offset() - 1);
+ jcc(Assembler::greater, slow_path);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ jccb(Assembler::equal, push);
+
+ // Try to lock. Transition lock bits 0b01 => 0b00
+ movptr(rax_reg, mark);
+ orptr(rax_reg, markWord::unlocked_value);
+ andptr(mark, ~(int32_t)markWord::unlocked_value);
+ lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, slow_path);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ movptr(Address(thread, top), obj);
+ addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+ jmpb(locked);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated);
+
+ const Register tagged_monitor = mark;
+
+ // CAS owner (null => current thread).
+ xorptr(rax_reg, rax_reg);
+ lock(); cmpxchgptr(thread, Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
+ jccb(Assembler::equal, locked);
+
+ // Check if recursive.
+ cmpptr(thread, rax_reg);
+ jccb(Assembler::notEqual, slow_path);
+
+ // Recursive.
+ increment(Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ }
+
+ bind(locked);
+ increment(Address(thread, JavaThread::held_monitor_count_offset()));
+ // Set ZF = 1
+ xorl(rax_reg, rax_reg);
+
+#ifdef ASSERT
+ // Check that locked label is reached with ZF set.
+ Label zf_correct;
+ jccb(Assembler::zero, zf_correct);
+ stop("Fast Lock ZF != 1");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with ZF not set.
+ jccb(Assembler::notZero, zf_correct);
+ stop("Fast Lock ZF != 0");
+ bind(zf_correct);
+#endif
+ // C2 uses the value of ZF to determine the continuation.
+}
+
+void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert(reg_rax == rax, "Used for CAS");
+ assert_different_registers(obj, reg_rax, t);
+
+ // Handle inflated monitor.
+ Label inflated, inflated_check_lock_stack;
+ // Finish fast unlock successfully. MUST jump with ZF == 1
+ Label unlocked;
+
+ // Assume success.
+ decrement(Address(thread, JavaThread::held_monitor_count_offset()));
+
+ const Register mark = t;
+ const Register top = reg_rax;
+
+ Label dummy;
+ C2FastUnlockLightweightStub* stub = nullptr;
+
+ if (!Compile::current()->output()->in_scratch_emit_size()) {
+ stub = new (Compile::current()->comp_arena()) C2FastUnlockLightweightStub(obj, mark, reg_rax, thread);
+ Compile::current()->output()->add_stub(stub);
+ }
+
+ Label& push_and_slow_path = stub == nullptr ? dummy : stub->push_and_slow_path();
+ Label& check_successor = stub == nullptr ? dummy : stub->check_successor();
+
+ { // Lightweight Unlock
+
+ // Load top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Prefetch mark.
+ movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check if obj is top of lock-stack.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ // Top of lock stack was not obj. Must be monitor.
+ jcc(Assembler::notEqual, inflated_check_lock_stack);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);)
+ subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize));
+ jcc(Assembler::equal, unlocked);
+
+ // We elide the monitor check, let the CAS fail instead.
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ movptr(reg_rax, mark);
+ andptr(reg_rax, ~(int32_t)markWord::lock_mask);
+ orptr(mark, markWord::unlocked_value);
+ lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, push_and_slow_path);
+ jmp(unlocked);
+ }
+
+
+ { // Handle inflated monitor.
+ bind(inflated_check_lock_stack);
+#ifdef ASSERT
+ Label check_done;
+ subl(top, oopSize);
+ cmpl(top, in_bytes(JavaThread::lock_stack_base_offset()));
+ jcc(Assembler::below, check_done);
+ cmpptr(obj, Address(thread, top));
+ jccb(Assembler::notEqual, inflated_check_lock_stack);
+ stop("Fast Unlock lock on stack");
+ bind(check_done);
+ testptr(mark, markWord::monitor_value);
+ jccb(Assembler::notZero, inflated);
+ stop("Fast Unlock not monitor");
+#endif
+
+ bind(inflated);
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register monitor = mark;
+
+#ifndef _LP64
+ // Check if recursive.
+ xorptr(reg_rax, reg_rax);
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Check if the entry lists are empty.
+ movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Release lock.
+ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+#else // _LP64
+ Label recursive;
+
+ // Check if recursive.
+ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 0);
+ jccb(Assembler::notEqual, recursive);
+
+ // Check if the entry lists are empty.
+ movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Release lock.
+ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+ jmpb(unlocked);
+
+ // Recursive unlock.
+ bind(recursive);
+ decrement(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ xorl(t, t);
+#endif
+ }
+
+ bind(unlocked);
+ if (stub != nullptr) {
+ bind(stub->unlocked_continuation());
+ }
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with ZF set.
+ Label zf_correct;
+ jccb(Assembler::zero, zf_correct);
+ stop("Fast Unlock ZF != 1");
+#endif
+
+ if (stub != nullptr) {
+ bind(stub->slow_path_continuation());
+ }
+#ifdef ASSERT
+ // Check that stub->continuation() label is reached with ZF not set.
+ jccb(Assembler::notZero, zf_correct);
+ stop("Fast Unlock ZF != 0");
+ bind(zf_correct);
+#endif
+ // C2 uses the value of ZF to determine the continuation.
+}
+
//-------------------------------------------------------------------------------------------
// Generic instructions support for use in .ad files C2 code generation
@@ -5282,6 +5504,42 @@ void C2_MacroAssembler::vector_mask_compress(KRegister dst, KRegister src, Regis
kmov(dst, rtmp2);
}
+#ifdef _LP64
+void C2_MacroAssembler::vector_compress_expand_avx2(int opcode, XMMRegister dst, XMMRegister src,
+ XMMRegister mask, Register rtmp, Register rscratch,
+ XMMRegister permv, XMMRegister xtmp, BasicType bt,
+ int vec_enc) {
+ assert(type2aelembytes(bt) >= 4, "");
+ assert(opcode == Op_CompressV || opcode == Op_ExpandV, "");
+ address compress_perm_table = nullptr;
+ address expand_perm_table = nullptr;
+ if (type2aelembytes(bt) == 8) {
+ compress_perm_table = StubRoutines::x86::compress_perm_table64();
+ expand_perm_table = StubRoutines::x86::expand_perm_table64();
+ vmovmskpd(rtmp, mask, vec_enc);
+ } else {
+ compress_perm_table = StubRoutines::x86::compress_perm_table32();
+ expand_perm_table = StubRoutines::x86::expand_perm_table32();
+ vmovmskps(rtmp, mask, vec_enc);
+ }
+ shlq(rtmp, 5); // for 32 byte permute row.
+ if (opcode == Op_CompressV) {
+ lea(rscratch, ExternalAddress(compress_perm_table));
+ } else {
+ lea(rscratch, ExternalAddress(expand_perm_table));
+ }
+ addptr(rtmp, rscratch);
+ vmovdqu(permv, Address(rtmp));
+ vpermps(dst, permv, src, Assembler::AVX_256bit);
+ vpxor(xtmp, xtmp, xtmp, vec_enc);
+ // Blend the result with zero vector using permute mask, each column entry
+ // in a permute table row contains either a valid permute index or a -1 (default)
+ // value, this can potentially be used as a blending mask after
+ // compressing/expanding the source vector lanes.
+ vblendvps(dst, dst, xtmp, permv, vec_enc, false, permv);
+}
+#endif
+
void C2_MacroAssembler::vector_compress_expand(int opcode, XMMRegister dst, XMMRegister src, KRegister mask,
bool merge, BasicType bt, int vec_enc) {
if (opcode == Op_CompressV) {
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
index e9e1412957bd2..26f7fb44aa939 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, 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
@@ -43,6 +43,10 @@
bool use_rtm, bool profile_rtm);
void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm);
+ void fast_lock_lightweight(Register obj, Register box, Register rax_reg,
+ Register t, Register thread);
+ void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);
+
#if INCLUDE_RTM_OPT
void rtm_counters_update(Register abort_status, Register rtm_counters);
void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel);
@@ -390,6 +394,10 @@
void vector_round_float_avx(XMMRegister dst, XMMRegister src, AddressLiteral float_sign_flip, AddressLiteral new_mxcsr, int vec_enc,
Register tmp, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4);
+
+ void vector_compress_expand_avx2(int opcode, XMMRegister dst, XMMRegister src, XMMRegister mask,
+ Register rtmp, Register rscratch, XMMRegister permv, XMMRegister xtmp,
+ BasicType bt, int vec_enc);
#endif // _LP64
void udivI(Register rax, Register divisor, Register rdx);
diff --git a/src/hotspot/cpu/x86/compiledIC_x86.cpp b/src/hotspot/cpu/x86/compiledIC_x86.cpp
index 8fc001039fbd3..95b41f62b6aab 100644
--- a/src/hotspot/cpu/x86/compiledIC_x86.cpp
+++ b/src/hotspot/cpu/x86/compiledIC_x86.cpp
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -36,7 +35,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// movq rbx, 0
@@ -66,32 +65,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return NOT_LP64(10) // movl; jmp
LP64_ONLY(15); // movq (1+1+8); jmp (1+4)
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// x86 doesn't use trampolines.
return 0;
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -105,7 +97,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
assert(CompiledICLocker::is_safe(static_stub->addr()), "mt unsafe call");
// Reset stub.
address stub = static_stub->addr();
@@ -122,7 +114,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp
index f609846f00d6c..f9f77c23f14ca 100644
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp
@@ -28,8 +28,8 @@
#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1BarrierSetRuntime.hpp"
#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1HeapRegion.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
#include "interpreter/interp_masm.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/debug.hpp"
diff --git a/src/hotspot/cpu/x86/icBuffer_x86.cpp b/src/hotspot/cpu/x86/icBuffer_x86.cpp
deleted file mode 100644
index af374b5741659..0000000000000
--- a/src/hotspot/cpu/x86/icBuffer_x86.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_x86.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // Worst case, if destination is not a near call:
- // lea rax, lit1
- // lea scratch, lit2
- // jmp scratch
-
- // Best case
- // lea rax, lit1
- // jmp lit2
-
- int best = NativeMovConstReg::instruction_size + NativeJump::instruction_size;
- int worst = 2 * NativeMovConstReg::instruction_size + 3;
- return MAX2(best, worst);
-}
-
-
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
- // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop");
- masm->lea(rax, AddressLiteral((address) cached_value, relocInfo::metadata_type));
- masm->jump(ExternalAddress(entry_point));
-}
-
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- address jmp = move->next_instruction_address();
- NativeInstruction* ni = nativeInstruction_at(jmp);
- if (ni->is_jump()) {
- NativeJump* jump = nativeJump_at(jmp);
- return jump->jump_destination();
- } else {
- assert(ni->is_far_jump(), "unexpected instruction");
- NativeFarJump* jump = nativeFarJump_at(jmp);
- return jump->jump_destination();
- }
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // creation also verifies the object
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin);
- // Verifies the jump
- address jmp = move->next_instruction_address();
- NativeInstruction* ni = nativeInstruction_at(jmp);
- if (ni->is_jump()) {
- NativeJump* jump = nativeJump_at(jmp);
- } else {
- assert(ni->is_far_jump(), "unexpected instruction");
- NativeFarJump* jump = nativeFarJump_at(jmp);
- }
- void* o = (void*)move->data();
- return o;
-}
diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp
index f5f83ae21f475..33570f3155b15 100644
--- a/src/hotspot/cpu/x86/interp_masm_x86.cpp
+++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -1192,8 +1192,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) {
const Register thread = lock_reg;
get_thread(thread);
#endif
- // Load object header, prepare for CAS from unlocked to locked.
- movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
lightweight_lock(obj_reg, swap_reg, thread, tmp_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load immediate 1 into swap_reg %rax
@@ -1311,20 +1309,13 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
- const Register thread = r15_thread;
+ lightweight_unlock(obj_reg, swap_reg, r15_thread, header_reg, slow_case);
#else
- const Register thread = header_reg;
- get_thread(thread);
+ // This relies on the implementation of lightweight_unlock being able to handle
+ // that the reg_rax and thread Register parameters may alias each other.
+ get_thread(swap_reg);
+ lightweight_unlock(obj_reg, swap_reg, swap_reg, header_reg, slow_case);
#endif
- // Handle unstructured locking.
- Register tmp = swap_reg;
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- cmpptr(obj_reg, Address(thread, tmp, Address::times_1, -oopSize));
- jcc(Assembler::notEqual, slow_case);
- // Try to swing header from locked to unlocked.
- movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load the old header from BasicLock structure
movptr(header_reg, Address(swap_reg,
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index 882966564859e..f0e7a08dd5f2a 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compiler_globals.hpp"
#include "compiler/disassembler.hpp"
#include "crc32c.h"
@@ -1341,13 +1342,45 @@ 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());
+ mov64(rax, (int64_t)Universe::non_oop_word());
#else
movptr(rax, (intptr_t)Universe::non_oop_word());
#endif
call(AddressLiteral(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ return LP64_ONLY(14) NOT_LP64(12);
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = LP64_ONLY(j_rarg0) NOT_LP64(rcx);
+ Register data = rax;
+ Register temp = LP64_ONLY(rscratch1) NOT_LP64(rbx);
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ movl(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ cmpl(temp, Address(data, CompiledICData::speculated_klass_offset()));
+ } else {
+ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ cmpptr(temp, Address(data, CompiledICData::speculated_klass_offset()));
+ }
+
+ // if inline cache check fails, then jump to runtime routine
+ jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
+}
+
void MacroAssembler::emit_static_call_stub() {
// Static stub relocation also tags the Method* in the code-stream.
mov_metadata(rbx, (Metadata*) nullptr); // Method is zapped till fixup time.
@@ -2568,7 +2601,9 @@ 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) {
#ifdef _LP64
- if (is_simm32(src)) {
+ if (is_uimm32(src)) {
+ movl(dst, checked_cast(src));
+ } else if (is_simm32(src)) {
movq(dst, checked_cast(src));
} else {
mov64(dst, src);
@@ -4085,8 +4120,9 @@ static void restore_xmm_register(MacroAssembler* masm, int offset, XMMRegister r
}
}
-int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers, bool save_fpu,
- int& gp_area_size, int& fp_area_size, int& xmm_area_size) {
+static int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers,
+ bool save_fpu, int& gp_area_size,
+ int& fp_area_size, int& xmm_area_size) {
gp_area_size = align_up(gp_registers.size() * Register::max_slots_per_register * VMRegImpl::stack_slot_size,
StackAlignmentInBytes);
@@ -4352,7 +4388,7 @@ 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
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - 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.
@@ -9875,68 +9911,116 @@ void MacroAssembler::check_stack_alignment(Register sp, const char* msg, unsigne
}
// Implements lightweight-locking.
-// Branches to slow upon failure to lock the object, with ZF cleared.
-// Falls through upon success with unspecified ZF.
//
// obj: the object to be locked
-// hdr: the (pre-loaded) header of the object, must be rax
+// reg_rax: rax
// thread: the thread which attempts to lock obj
// tmp: a temporary register
-void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow) {
- assert(hdr == rax, "header must be in rax for cmpxchg");
- assert_different_registers(obj, hdr, thread, tmp);
-
- // First we need to check if the lock-stack has room for pushing the object reference.
- // Note: we subtract 1 from the end-offset so that we can do a 'greater' comparison, instead
- // of 'greaterEqual' below, which readily clears the ZF. This makes C2 code a little simpler and
- // avoids one branch.
- cmpl(Address(thread, JavaThread::lock_stack_top_offset()), LockStack::end_offset() - 1);
- jcc(Assembler::greater, slow);
-
- // Now we attempt to take the fast-lock.
- // Clear lock_mask bits (locked state).
- andptr(hdr, ~(int32_t)markWord::lock_mask_in_place);
- movptr(tmp, hdr);
- // Set unlocked_value bit.
- orptr(hdr, markWord::unlocked_value);
- lock();
- cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+void MacroAssembler::lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) {
+ assert(reg_rax == rax, "");
+ assert_different_registers(obj, reg_rax, thread, tmp);
+
+ Label push;
+ const Register top = tmp;
+
+ // Preload the markWord. It is important that this is the first
+ // instruction emitted as it is part of C1's null check semantics.
+ movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Load top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Check if the lock-stack is full.
+ cmpl(top, LockStack::end_offset());
+ jcc(Assembler::greaterEqual, slow);
+
+ // Check for recursion.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ jcc(Assembler::equal, push);
+
+ // Check header for monitor (0b10).
+ testptr(reg_rax, markWord::monitor_value);
+ jcc(Assembler::notZero, slow);
+
+ // Try to lock. Transition lock bits 0b01 => 0b00
+ movptr(tmp, reg_rax);
+ andptr(tmp, ~(int32_t)markWord::unlocked_value);
+ orptr(reg_rax, markWord::unlocked_value);
+ lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
jcc(Assembler::notEqual, slow);
- // If successful, push object to lock-stack.
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- movptr(Address(thread, tmp), obj);
- incrementl(tmp, oopSize);
- movl(Address(thread, JavaThread::lock_stack_top_offset()), tmp);
+ // Restore top, CAS clobbers register.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ movptr(Address(thread, top), obj);
+ incrementl(top, oopSize);
+ movl(Address(thread, JavaThread::lock_stack_top_offset()), top);
}
// Implements lightweight-unlocking.
-// Branches to slow upon failure, with ZF cleared.
-// Falls through upon success, with unspecified ZF.
//
// obj: the object to be unlocked
-// hdr: the (pre-loaded) header of the object, must be rax
+// reg_rax: rax
+// thread: the thread
// tmp: a temporary register
-void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow) {
- assert(hdr == rax, "header must be in rax for cmpxchg");
- assert_different_registers(obj, hdr, tmp);
-
- // Mark-word must be lock_mask now, try to swing it back to unlocked_value.
- movptr(tmp, hdr); // The expected old value
- orptr(tmp, markWord::unlocked_value);
- lock();
- cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+//
+// x86_32 Note: reg_rax and thread may alias each other due to limited register
+// availiability.
+void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) {
+ assert(reg_rax == rax, "");
+ assert_different_registers(obj, reg_rax, tmp);
+ LP64_ONLY(assert_different_registers(obj, reg_rax, thread, tmp);)
+
+ Label unlocked, push_and_slow;
+ const Register top = tmp;
+
+ // Check if obj is top of lock-stack.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
jcc(Assembler::notEqual, slow);
- // Pop the lock object from the lock-stack.
-#ifdef _LP64
- const Register thread = r15_thread;
-#else
- const Register thread = rax;
- get_thread(thread);
-#endif
+
+ // Pop lock-stack.
+ DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);)
subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize));
+ jcc(Assembler::equal, unlocked);
+
+ // Not recursive. Check header for monitor (0b10).
+ movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes()));
+ testptr(reg_rax, markWord::monitor_value);
+ jcc(Assembler::notZero, push_and_slow);
+
+#ifdef ASSERT
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ testptr(reg_rax, markWord::unlocked_value);
+ jcc(Assembler::zero, not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
+#endif
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ movptr(tmp, reg_rax);
+ orptr(tmp, markWord::unlocked_value);
+ lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::equal, unlocked);
+
+ bind(push_and_slow);
+ // Restore lock-stack and handle the unlock in runtime.
+ if (thread == reg_rax) {
+ // On x86_32 we may lose the thread.
+ get_thread(thread);
+ }
#ifdef ASSERT
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- movptr(Address(thread, tmp), 0);
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+ movptr(Address(thread, top), obj);
#endif
+ addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+ jmp(slow);
+
+ bind(unlocked);
}
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index 4b30168452796..4789b63decc6c 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -896,6 +896,8 @@ class MacroAssembler: public Assembler {
// Emit the CompiledIC call idiom
void ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment);
void emit_static_call_stub();
@@ -2031,8 +2033,8 @@ class MacroAssembler: public Assembler {
void check_stack_alignment(Register sp, const char* msg, unsigned bias = 0, Register tmp = noreg);
- void lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow);
- void lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow);
+ void lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
+ void lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
};
/**
diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp
index 8c956aeb05393..92a29490edaf8 100644
--- a/src/hotspot/cpu/x86/peephole_x86_64.cpp
+++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp
@@ -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
@@ -33,8 +33,8 @@
// lea d, [s1 + s2] and
// mov d, s1; shl d, s2 into
// lea d, [s1 << s2] with s2 = 1, 2, 3
-bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
- MachNode* (*new_root)(), uint inst0_rule, bool imm) {
+static bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
+ MachNode* (*new_root)(), uint inst0_rule, bool imm) {
MachNode* inst0 = block->get_node(block_index)->as_Mach();
assert(inst0->rule() == inst0_rule, "sanity");
@@ -136,7 +136,7 @@ bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseReg
// This helper func takes a condition and returns the flags that need to be set for the condition
// It uses the same flags as the test instruction, so if the e.g. the overflow bit is required,
// this func returns clears_overflow, as that is what the test instruction does and what the downstream path expects
-juint map_condition_to_required_test_flags(Assembler::Condition condition) {
+static juint map_condition_to_required_test_flags(Assembler::Condition condition) {
switch (condition) {
case Assembler::Condition::zero: // Same value as equal
case Assembler::Condition::notZero: // Same value as notEqual
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86.cpp
index de759d2ff5761..3ecbb43f7f518 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86.cpp
@@ -26,6 +26,7 @@
#include "asm/macroAssembler.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "vmreg_x86.inline.hpp"
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
@@ -59,9 +60,16 @@ void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* mas
__ movptr(result, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- // check if locked
- __ testptr(result, markWord::unlocked_value);
- __ jcc(Assembler::zero, slowCase);
+
+ if (LockingMode == LM_LIGHTWEIGHT) {
+ // check if monitor
+ __ testptr(result, markWord::monitor_value);
+ __ jcc(Assembler::notZero, slowCase);
+ } else {
+ // check if locked
+ __ testptr(result, markWord::unlocked_value);
+ __ jcc(Assembler::zero, slowCase);
+ }
// get hash
#ifdef _LP64
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
index 571160523cbe4..febc1b2c3b143 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
@@ -36,7 +36,6 @@
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/jniHandles.hpp"
@@ -944,25 +943,18 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Register holder = rax;
+ Register data = rax;
Register receiver = rcx;
Register temp = rbx;
{
-
- Label missed;
- __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
- __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ jcc(Assembler::notEqual, missed);
+ __ ic_check(1 /* end_alignment */);
+ __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset()));
// Method might have been compiled since the call site was patched to
// interpreted if that is the case treat it as a miss so we can get
// the call site corrected.
__ cmpptr(Address(rbx, in_bytes(Method::code_offset())), NULL_WORD);
__ jcc(Assembler::equal, skip_fixup);
-
- __ bind(missed);
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
}
address c2i_entry = __ pc();
@@ -1449,23 +1441,12 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// as far as the interpreter and the compiler(s) are concerned.
- const Register ic_reg = rax;
const Register receiver = rcx;
- Label hit;
Label exception_pending;
__ verify_oop(receiver);
- __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
- __ jcc(Assembler::equal, hit);
-
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
// verified entry must be aligned for code patching.
- // and the first 5 bytes must be in the same cache line
- // if we align at 8 then we will be sure 5 bytes are in the same line
- __ align(8);
-
- __ bind(hit);
+ __ ic_check(8 /* end_alignment */);
int vep_offset = ((intptr_t)__ pc()) - start;
@@ -1713,8 +1694,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ jcc(Assembler::notEqual, slow_path_lock);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- // Load object header
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ lightweight_lock(obj_reg, swap_reg, thread, lock_reg, slow_path_lock);
}
__ bind(count_mon);
@@ -1872,9 +1851,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ dec_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
+ __ lightweight_unlock(obj_reg, swap_reg, thread, lock_reg, slow_path_unlock);
__ dec_held_monitor_count();
}
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
index faa423bcf8e76..c666f982d0f52 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
@@ -42,7 +41,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -1000,20 +998,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
- Register holder = rax;
+ Register data = rax;
Register receiver = j_rarg0;
Register temp = rbx;
{
- __ load_klass(temp, receiver, rscratch1);
- __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ jcc(Assembler::equal, ok);
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- __ bind(ok);
+ __ ic_check(1 /* end_alignment */);
+ __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset()));
// Method might have been compiled since the call site was patched to
// interpreted if that is the case treat it as a miss so we can get
// the call site corrected.
@@ -1450,7 +1442,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ align(BytesPerWord, __ offset() + NativeCall::displacement_offset);
// Emit stub for static call
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc());
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc());
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1487,7 +1479,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// Emit stub for static call
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc());
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc());
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1744,6 +1736,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
in_ByteSize(-1),
oop_maps,
exception_offset);
+ if (nm == nullptr) return nm;
if (method->is_continuation_enter_intrinsic()) {
ContinuationEntry::set_enter_code(nm, interpreted_entry_offset);
} else if (method->is_continuation_yield_intrinsic()) {
@@ -1882,25 +1875,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// restoring them except rbp. rbp is the only callee save register
// as far as the interpreter and the compiler(s) are concerned.
-
- const Register ic_reg = rax;
const Register receiver = j_rarg0;
- Label hit;
Label exception_pending;
- assert_different_registers(ic_reg, receiver, rscratch1, rscratch2);
+ assert_different_registers(receiver, rscratch1, rscratch2);
__ verify_oop(receiver);
- __ load_klass(rscratch1, receiver, rscratch2);
- __ cmpq(ic_reg, rscratch1);
- __ jcc(Assembler::equal, hit);
-
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // Verified entry point must be aligned
- __ align(8);
-
- __ bind(hit);
+ __ ic_check(8 /* end_alignment */);
int vep_offset = ((intptr_t)__ pc()) - start;
@@ -2189,8 +2170,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ jcc(Assembler::notEqual, slow_path_lock);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- // Load object header
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ lightweight_lock(obj_reg, swap_reg, r15_thread, rscratch1, slow_path_lock);
}
__ bind(count_mon);
@@ -2333,9 +2312,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ dec_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
+ __ lightweight_unlock(obj_reg, swap_reg, r15_thread, lock_reg, slow_path_unlock);
__ dec_held_monitor_count();
}
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
index cad9e6475c610..71aafdc1cd3e2 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
@@ -951,6 +951,92 @@ address StubGenerator::generate_fp_mask(const char *stub_name, int64_t mask) {
return start;
}
+address StubGenerator::generate_compress_perm_table(const char *stub_name, int32_t esize) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", stub_name);
+ address start = __ pc();
+ if (esize == 32) {
+ // Loop to generate 256 x 8 int compression permute index table. A row is
+ // accessed using 8 bit index computed using vector mask. An entry in
+ // a row holds either a valid permute index corresponding to set bit position
+ // or a -1 (default) value.
+ for (int mask = 0; mask < 256; mask++) {
+ int ctr = 0;
+ for (int j = 0; j < 8; j++) {
+ if (mask & (1 << j)) {
+ __ emit_data(j, relocInfo::none);
+ ctr++;
+ }
+ }
+ for (; ctr < 8; ctr++) {
+ __ emit_data(-1, relocInfo::none);
+ }
+ }
+ } else {
+ assert(esize == 64, "");
+ // Loop to generate 16 x 4 long compression permute index table. A row is
+ // accessed using 4 bit index computed using vector mask. An entry in
+ // a row holds either a valid permute index pair for a quadword corresponding
+ // to set bit position or a -1 (default) value.
+ for (int mask = 0; mask < 16; mask++) {
+ int ctr = 0;
+ for (int j = 0; j < 4; j++) {
+ if (mask & (1 << j)) {
+ __ emit_data(2 * j, relocInfo::none);
+ __ emit_data(2 * j + 1, relocInfo::none);
+ ctr++;
+ }
+ }
+ for (; ctr < 4; ctr++) {
+ __ emit_data64(-1L, relocInfo::none);
+ }
+ }
+ }
+ return start;
+}
+
+address StubGenerator::generate_expand_perm_table(const char *stub_name, int32_t esize) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", stub_name);
+ address start = __ pc();
+ if (esize == 32) {
+ // Loop to generate 256 x 8 int expand permute index table. A row is accessed
+ // using 8 bit index computed using vector mask. An entry in a row holds either
+ // a valid permute index (starting from least significant lane) placed at poisition
+ // corresponding to set bit position or a -1 (default) value.
+ for (int mask = 0; mask < 256; mask++) {
+ int ctr = 0;
+ for (int j = 0; j < 8; j++) {
+ if (mask & (1 << j)) {
+ __ emit_data(ctr++, relocInfo::none);
+ } else {
+ __ emit_data(-1, relocInfo::none);
+ }
+ }
+ }
+ } else {
+ assert(esize == 64, "");
+ // Loop to generate 16 x 4 long expand permute index table. A row is accessed
+ // using 4 bit index computed using vector mask. An entry in a row holds either
+ // a valid doubleword permute index pair representing a quadword index (starting
+ // from least significant lane) placed at poisition corresponding to set bit
+ // position or a -1 (default) value.
+ for (int mask = 0; mask < 16; mask++) {
+ int ctr = 0;
+ for (int j = 0; j < 4; j++) {
+ if (mask & (1 << j)) {
+ __ emit_data(2 * ctr, relocInfo::none);
+ __ emit_data(2 * ctr + 1, relocInfo::none);
+ ctr++;
+ } else {
+ __ emit_data64(-1L, relocInfo::none);
+ }
+ }
+ }
+ }
+ return start;
+}
+
address StubGenerator::generate_vector_mask(const char *stub_name, int64_t mask) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", stub_name);
@@ -4095,6 +4181,13 @@ void StubGenerator::generate_compiler_stubs() {
StubRoutines::x86::_vector_reverse_byte_perm_mask_int = generate_vector_reverse_byte_perm_mask_int("perm_mask_int");
StubRoutines::x86::_vector_reverse_byte_perm_mask_short = generate_vector_reverse_byte_perm_mask_short("perm_mask_short");
+ if (VM_Version::supports_avx2() && !VM_Version::supports_avx512vl()) {
+ StubRoutines::x86::_compress_perm_table32 = generate_compress_perm_table("compress_perm_table32", 32);
+ StubRoutines::x86::_compress_perm_table64 = generate_compress_perm_table("compress_perm_table64", 64);
+ StubRoutines::x86::_expand_perm_table32 = generate_expand_perm_table("expand_perm_table32", 32);
+ StubRoutines::x86::_expand_perm_table64 = generate_expand_perm_table("expand_perm_table64", 64);
+ }
+
if (VM_Version::supports_avx2() && !VM_Version::supports_avx512_vpopcntdq()) {
// lut implementation influenced by counting 1s algorithm from section 5-1 of Hackers' Delight.
StubRoutines::x86::_vector_popcount_lut = generate_popcount_avx_lut("popcount_lut");
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
index 6b7da7184988e..db43085d37f3a 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,6 +99,10 @@ class StubGenerator: public StubCodeGenerator {
address generate_fp_mask(const char *stub_name, int64_t mask);
+ address generate_compress_perm_table(const char *stub_name, int32_t esize);
+
+ address generate_expand_perm_table(const char *stub_name, int32_t esize);
+
address generate_vector_mask(const char *stub_name, int64_t mask);
address generate_vector_byte_perm_mask(const char *stub_name);
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
index cebf661ae75ed..bc1cbdbba26b5 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -82,6 +82,10 @@ address StubRoutines::x86::_join_0_1_base64 = nullptr;
address StubRoutines::x86::_join_1_2_base64 = nullptr;
address StubRoutines::x86::_join_2_3_base64 = nullptr;
address StubRoutines::x86::_decoding_table_base64 = nullptr;
+address StubRoutines::x86::_compress_perm_table32 = nullptr;
+address StubRoutines::x86::_compress_perm_table64 = nullptr;
+address StubRoutines::x86::_expand_perm_table32 = nullptr;
+address StubRoutines::x86::_expand_perm_table64 = nullptr;
#endif
address StubRoutines::x86::_pshuffle_byte_flip_mask_addr = nullptr;
@@ -275,7 +279,7 @@ uint32_t _crc32c_pow_2k_table[TILL_CYCLE]; // because _crc32c_pow_2k_table[TILL_
// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 8
// Listing 1: Multiplication of normalized polynomials
// "a" and "b" occupy D least significant bits.
-uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
+static uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
uint32_t product = 0;
uint32_t b_pow_x_table[D + 1]; // b_pow_x_table[k] = (b * x**k) mod P
b_pow_x_table[0] = b;
@@ -299,7 +303,7 @@ uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
#undef P
// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 9
-void crc32c_init_pow_2k(void) {
+static void crc32c_init_pow_2k(void) {
// _crc32c_pow_2k_table(0) =
// x^(2^k) mod P(x) = x mod P(x) = x
// Since we are operating on a reflected values
@@ -314,7 +318,7 @@ void crc32c_init_pow_2k(void) {
}
// x^N mod P(x)
-uint32_t crc32c_f_pow_n(uint32_t n) {
+static uint32_t crc32c_f_pow_n(uint32_t n) {
// result = 1 (polynomial)
uint32_t one, result = 0x80000000, i = 0;
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp
index 6c602324f3ef2..cfb91c5c08368 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -37,7 +37,7 @@ enum platform_dependent_constants {
_continuation_stubs_code_size = 1000 LP64_ONLY(+1000),
// AVX512 intrinsics add more code in 64-bit VM,
// Windows have more code to save/restore registers
- _compiler_stubs_code_size = 20000 LP64_ONLY(+32000) WINDOWS_ONLY(+2000),
+ _compiler_stubs_code_size = 20000 LP64_ONLY(+39000) WINDOWS_ONLY(+2000),
_final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+2000) ZGC_ONLY(+20000)
};
@@ -58,6 +58,10 @@ class x86 {
static address _float_sign_flip;
static address _double_sign_mask;
static address _double_sign_flip;
+ static address _compress_perm_table32;
+ static address _compress_perm_table64;
+ static address _expand_perm_table32;
+ static address _expand_perm_table64;
public:
@@ -338,6 +342,10 @@ class x86 {
static address base64_decoding_table_addr() { return _decoding_table_base64; }
static address base64_AVX2_decode_tables_addr() { return _avx2_decode_tables_base64; }
static address base64_AVX2_decode_LUT_tables_addr() { return _avx2_decode_lut_tables_base64; }
+ static address compress_perm_table32() { return _compress_perm_table32; }
+ static address compress_perm_table64() { return _compress_perm_table64; }
+ static address expand_perm_table32() { return _expand_perm_table32; }
+ static address expand_perm_table64() { return _expand_perm_table64; }
#endif
static address pshuffle_byte_flip_mask_addr() { return _pshuffle_byte_flip_mask_addr; }
static address arrays_hashcode_powers_of_31() { return (address)_arrays_hashcode_powers_of_31; }
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp b/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp
index 417b32eb4a64c..eb6c11d7167da 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp
@@ -44,4 +44,3 @@ address StubRoutines::x86::_float_sign_mask = nullptr;
address StubRoutines::x86::_float_sign_flip = nullptr;
address StubRoutines::x86::_double_sign_mask = nullptr;
address StubRoutines::x86::_double_sign_flip = nullptr;
-
diff --git a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp
index 89e7a466264b9..7b9d49dd46140 100644
--- a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp
+++ b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp
@@ -300,8 +300,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
__ mov_metadata(rbx, entry);
__ movptr(Address(r15_thread, JavaThread::callee_target_offset()), rbx); // just in case callee is deoptimized
+ __ push_cont_fastpath();
+
__ call(Address(rbx, Method::from_compiled_offset()));
+ __ pop_cont_fastpath();
+
// return value shuffle
if (!needs_return_buffer) {
#ifdef ASSERT
diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp
index df1ea6edd300f..f8213a2539f04 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp
@@ -809,7 +809,8 @@ void VM_Version::get_processor_features() {
_stepping = cpu_stepping();
if (cpu_family() > 4) { // it supports CPUID
- _features = feature_flags();
+ _features = _cpuid_info.feature_flags(); // These can be changed by VM settings
+ _cpu_features = _features; // Preserve features
// Logical processors are only available on P4s and above,
// and only if hyperthreading is available.
_logical_processors_per_package = logical_processor_count();
@@ -2890,13 +2891,13 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) {
return _max_qualified_cpu_frequency;
}
-uint64_t VM_Version::feature_flags() {
+uint64_t VM_Version::CpuidInfo::feature_flags() const {
uint64_t result = 0;
- if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
+ if (std_cpuid1_edx.bits.cmpxchg8 != 0)
result |= CPU_CX8;
- if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0)
+ if (std_cpuid1_edx.bits.cmov != 0)
result |= CPU_CMOV;
- if (_cpuid_info.std_cpuid1_edx.bits.clflush != 0)
+ if (std_cpuid1_edx.bits.clflush != 0)
result |= CPU_FLUSH;
#ifdef _LP64
// clflush should always be available on x86_64
@@ -2904,158 +2905,158 @@ uint64_t VM_Version::feature_flags() {
// to flush the code cache.
assert ((result & CPU_FLUSH) != 0, "clflush should be available");
#endif
- if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
- _cpuid_info.ext_cpuid1_edx.bits.fxsr != 0))
+ if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
+ ext_cpuid1_edx.bits.fxsr != 0))
result |= CPU_FXSR;
// HT flag is set for multi-core processors also.
if (threads_per_core() > 1)
result |= CPU_HT;
- if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
- _cpuid_info.ext_cpuid1_edx.bits.mmx != 0))
+ if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
+ ext_cpuid1_edx.bits.mmx != 0))
result |= CPU_MMX;
- if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
+ if (std_cpuid1_edx.bits.sse != 0)
result |= CPU_SSE;
- if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0)
+ if (std_cpuid1_edx.bits.sse2 != 0)
result |= CPU_SSE2;
- if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0)
+ if (std_cpuid1_ecx.bits.sse3 != 0)
result |= CPU_SSE3;
- if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0)
+ if (std_cpuid1_ecx.bits.ssse3 != 0)
result |= CPU_SSSE3;
- if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0)
+ if (std_cpuid1_ecx.bits.sse4_1 != 0)
result |= CPU_SSE4_1;
- if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
+ if (std_cpuid1_ecx.bits.sse4_2 != 0)
result |= CPU_SSE4_2;
- if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
+ if (std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT;
- if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 &&
- _cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 &&
- _cpuid_info.xem_xcr0_eax.bits.sse != 0 &&
- _cpuid_info.xem_xcr0_eax.bits.ymm != 0) {
+ if (std_cpuid1_ecx.bits.avx != 0 &&
+ std_cpuid1_ecx.bits.osxsave != 0 &&
+ xem_xcr0_eax.bits.sse != 0 &&
+ xem_xcr0_eax.bits.ymm != 0) {
result |= CPU_AVX;
result |= CPU_VZEROUPPER;
- if (_cpuid_info.std_cpuid1_ecx.bits.f16c != 0)
+ if (std_cpuid1_ecx.bits.f16c != 0)
result |= CPU_F16C;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
+ if (sef_cpuid7_ebx.bits.avx2 != 0)
result |= CPU_AVX2;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512f != 0 &&
- _cpuid_info.xem_xcr0_eax.bits.opmask != 0 &&
- _cpuid_info.xem_xcr0_eax.bits.zmm512 != 0 &&
- _cpuid_info.xem_xcr0_eax.bits.zmm32 != 0) {
+ if (sef_cpuid7_ebx.bits.avx512f != 0 &&
+ xem_xcr0_eax.bits.opmask != 0 &&
+ xem_xcr0_eax.bits.zmm512 != 0 &&
+ xem_xcr0_eax.bits.zmm32 != 0) {
result |= CPU_AVX512F;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512cd != 0)
+ if (sef_cpuid7_ebx.bits.avx512cd != 0)
result |= CPU_AVX512CD;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512dq != 0)
+ if (sef_cpuid7_ebx.bits.avx512dq != 0)
result |= CPU_AVX512DQ;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512ifma != 0)
+ if (sef_cpuid7_ebx.bits.avx512ifma != 0)
result |= CPU_AVX512_IFMA;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512pf != 0)
+ if (sef_cpuid7_ebx.bits.avx512pf != 0)
result |= CPU_AVX512PF;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512er != 0)
+ if (sef_cpuid7_ebx.bits.avx512er != 0)
result |= CPU_AVX512ER;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512bw != 0)
+ if (sef_cpuid7_ebx.bits.avx512bw != 0)
result |= CPU_AVX512BW;
- if (_cpuid_info.sef_cpuid7_ebx.bits.avx512vl != 0)
+ if (sef_cpuid7_ebx.bits.avx512vl != 0)
result |= CPU_AVX512VL;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
+ if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
result |= CPU_AVX512_VPOPCNTDQ;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
+ if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
result |= CPU_AVX512_VPCLMULQDQ;
- if (_cpuid_info.sef_cpuid7_ecx.bits.vaes != 0)
+ if (sef_cpuid7_ecx.bits.vaes != 0)
result |= CPU_AVX512_VAES;
- if (_cpuid_info.sef_cpuid7_ecx.bits.gfni != 0)
+ if (sef_cpuid7_ecx.bits.gfni != 0)
result |= CPU_GFNI;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vnni != 0)
+ if (sef_cpuid7_ecx.bits.avx512_vnni != 0)
result |= CPU_AVX512_VNNI;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_bitalg != 0)
+ if (sef_cpuid7_ecx.bits.avx512_bitalg != 0)
result |= CPU_AVX512_BITALG;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vbmi != 0)
+ if (sef_cpuid7_ecx.bits.avx512_vbmi != 0)
result |= CPU_AVX512_VBMI;
- if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vbmi2 != 0)
+ if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0)
result |= CPU_AVX512_VBMI2;
}
}
- if (_cpuid_info.std_cpuid1_ecx.bits.hv != 0)
+ if (std_cpuid1_ecx.bits.hv != 0)
result |= CPU_HV;
- if (_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
+ if (sef_cpuid7_ebx.bits.bmi1 != 0)
result |= CPU_BMI1;
- if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
+ if (std_cpuid1_edx.bits.tsc != 0)
result |= CPU_TSC;
- if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
+ if (ext_cpuid7_edx.bits.tsc_invariance != 0)
result |= CPU_TSCINV_BIT;
- if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
+ if (std_cpuid1_ecx.bits.aes != 0)
result |= CPU_AES;
- if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
+ if (sef_cpuid7_ebx.bits.erms != 0)
result |= CPU_ERMS;
- if (_cpuid_info.sef_cpuid7_edx.bits.fast_short_rep_mov != 0)
+ if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0)
result |= CPU_FSRM;
- if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
+ if (std_cpuid1_ecx.bits.clmul != 0)
result |= CPU_CLMUL;
- if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
+ if (sef_cpuid7_ebx.bits.rtm != 0)
result |= CPU_RTM;
- if (_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
+ if (sef_cpuid7_ebx.bits.adx != 0)
result |= CPU_ADX;
- if (_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
+ if (sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2;
- if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0)
+ if (sef_cpuid7_ebx.bits.sha != 0)
result |= CPU_SHA;
- if (_cpuid_info.std_cpuid1_ecx.bits.fma != 0)
+ if (std_cpuid1_ecx.bits.fma != 0)
result |= CPU_FMA;
- if (_cpuid_info.sef_cpuid7_ebx.bits.clflushopt != 0)
+ if (sef_cpuid7_ebx.bits.clflushopt != 0)
result |= CPU_FLUSHOPT;
- if (_cpuid_info.ext_cpuid1_edx.bits.rdtscp != 0)
+ if (ext_cpuid1_edx.bits.rdtscp != 0)
result |= CPU_RDTSCP;
- if (_cpuid_info.sef_cpuid7_ecx.bits.rdpid != 0)
+ if (sef_cpuid7_ecx.bits.rdpid != 0)
result |= CPU_RDPID;
// AMD|Hygon features.
if (is_amd_family()) {
- if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
- (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
+ if ((ext_cpuid1_edx.bits.tdnow != 0) ||
+ (ext_cpuid1_ecx.bits.prefetchw != 0))
result |= CPU_3DNOW_PREFETCH;
- if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
+ if (ext_cpuid1_ecx.bits.lzcnt != 0)
result |= CPU_LZCNT;
- if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
+ if (ext_cpuid1_ecx.bits.sse4a != 0)
result |= CPU_SSE4A;
}
// Intel features.
if (is_intel()) {
- if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) {
+ if (ext_cpuid1_ecx.bits.lzcnt != 0) {
result |= CPU_LZCNT;
}
- if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) {
+ if (ext_cpuid1_ecx.bits.prefetchw != 0) {
result |= CPU_3DNOW_PREFETCH;
}
- if (_cpuid_info.sef_cpuid7_ebx.bits.clwb != 0) {
+ if (sef_cpuid7_ebx.bits.clwb != 0) {
result |= CPU_CLWB;
}
- if (_cpuid_info.sef_cpuid7_edx.bits.serialize != 0)
+ if (sef_cpuid7_edx.bits.serialize != 0)
result |= CPU_SERIALIZE;
}
// ZX features.
if (is_zx()) {
- if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) {
+ if (ext_cpuid1_ecx.bits.lzcnt != 0) {
result |= CPU_LZCNT;
}
- if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) {
+ if (ext_cpuid1_ecx.bits.prefetchw != 0) {
result |= CPU_3DNOW_PREFETCH;
}
}
// Protection key features.
- if (_cpuid_info.sef_cpuid7_ecx.bits.pku != 0) {
+ if (sef_cpuid7_ecx.bits.pku != 0) {
result |= CPU_PKU;
}
- if (_cpuid_info.sef_cpuid7_ecx.bits.ospke != 0) {
+ if (sef_cpuid7_ecx.bits.ospke != 0) {
result |= CPU_OSPKE;
}
// Control flow enforcement (CET) features.
- if (_cpuid_info.sef_cpuid7_ecx.bits.cet_ss != 0) {
+ if (sef_cpuid7_ecx.bits.cet_ss != 0) {
result |= CPU_CET_SS;
}
- if (_cpuid_info.sef_cpuid7_edx.bits.cet_ibt != 0) {
+ if (sef_cpuid7_edx.bits.cet_ibt != 0) {
result |= CPU_CET_IBT;
}
diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp
index e521a6ee3bc0e..03596a6e4468c 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -428,7 +428,8 @@ class VM_Version : public Abstract_VM_Version {
//
// The info block is laid out in subblocks of 4 dwords corresponding to
// eax, ebx, ecx and edx, whether or not they contain anything useful.
- struct CpuidInfo {
+ class CpuidInfo {
+ public:
// cpuid function 0
uint32_t std_max_function;
uint32_t std_vendor_name_0;
@@ -522,6 +523,31 @@ class VM_Version : public Abstract_VM_Version {
// Space to save zmm registers after signal handle
int zmm_save[16*4]; // Save zmm0, zmm7, zmm8, zmm31
+
+ uint64_t feature_flags() const;
+
+ // Asserts
+ void assert_is_initialized() const {
+ assert(std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
+ }
+
+ // Extractors
+ uint32_t extended_cpu_family() const {
+ uint32_t result = std_cpuid1_eax.bits.family;
+ result += std_cpuid1_eax.bits.ext_family;
+ return result;
+ }
+
+ uint32_t extended_cpu_model() const {
+ uint32_t result = std_cpuid1_eax.bits.model;
+ result |= std_cpuid1_eax.bits.ext_model << 4;
+ return result;
+ }
+
+ uint32_t cpu_stepping() const {
+ uint32_t result = std_cpuid1_eax.bits.stepping;
+ return result;
+ }
};
private:
@@ -529,23 +555,6 @@ class VM_Version : public Abstract_VM_Version {
static CpuidInfo _cpuid_info;
// Extractors and predicates
- static uint32_t extended_cpu_family() {
- uint32_t result = _cpuid_info.std_cpuid1_eax.bits.family;
- result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
- return result;
- }
-
- static uint32_t extended_cpu_model() {
- uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model;
- result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4;
- return result;
- }
-
- static uint32_t cpu_stepping() {
- uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping;
- return result;
- }
-
static uint logical_processor_count() {
uint result = threads_per_core();
return result;
@@ -553,7 +562,6 @@ class VM_Version : public Abstract_VM_Version {
static bool compute_has_intel_jcc_erratum();
- static uint64_t feature_flags();
static bool os_supports_avx_vectors();
static void get_processor_features();
@@ -594,11 +602,6 @@ class VM_Version : public Abstract_VM_Version {
// Override Abstract_VM_Version implementation
static void print_platform_virtualization_info(outputStream*);
- // Asserts
- static void assert_is_initialized() {
- assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
- }
-
//
// Processor family:
// 3 - 386
@@ -614,6 +617,10 @@ class VM_Version : public Abstract_VM_Version {
// processors. Use the feature test functions below to
// determine whether a particular instruction is supported.
//
+ static void assert_is_initialized() { _cpuid_info.assert_is_initialized(); }
+ static uint32_t extended_cpu_family() { return _cpuid_info.extended_cpu_family(); }
+ static uint32_t extended_cpu_model() { return _cpuid_info.extended_cpu_model(); }
+ static uint32_t cpu_stepping() { return _cpuid_info.cpu_stepping(); }
static int cpu_family() { return _cpu;}
static bool is_P6() { return cpu_family() >= 6; }
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
@@ -640,7 +647,7 @@ class VM_Version : public Abstract_VM_Version {
}
//
- // Feature identification
+ // Feature identification which can be affected by VM settings
//
static bool supports_cpuid() { return _features != 0; }
static bool supports_cmov() { return (_features & CPU_CMOV) != 0; }
@@ -703,6 +710,11 @@ class VM_Version : public Abstract_VM_Version {
static bool supports_cet_ss() { return (_features & CPU_CET_SS) != 0; }
static bool supports_cet_ibt() { return (_features & CPU_CET_IBT) != 0; }
+ //
+ // Feature identification not affected by VM flags
+ //
+ static bool cpu_supports_evex() { return (_cpu_features & CPU_AVX512F) != 0; }
+
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
@@ -765,6 +777,10 @@ class VM_Version : public Abstract_VM_Version {
return true;
}
+ constexpr static bool supports_recursive_lightweight_locking() {
+ return true;
+ }
+
// For AVX CPUs only. f16c support is disabled if UseAVX == 0.
static bool supports_float16() {
return supports_f16c() || supports_avx512vl();
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
index 0e78e0274d7f2..398f2e37eb5cc 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
@@ -24,10 +24,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -176,21 +176,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif /* PRODUCT */
// Entry arguments:
- // rax: CompiledICHolder
+ // rax: CompiledICData
// rcx: Receiver
// 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 holder_klass_reg = rax; // declaring interface klass (DEFC)
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 icdata_reg = rax;
const Register receiver = rcx;
- __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
Label L_no_such_interface;
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
index f162a651183f9..158d6f9c6922b 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
@@ -24,10 +24,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -168,21 +168,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif // PRODUCT
// Entry arguments:
- // rax: CompiledICHolder
+ // rax: CompiledICData
// j_rarg0: Receiver
// Most registers are in use; we'll use rax, rbx, r10, r11
// (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 holder_klass_reg = rax; // declaring interface klass (DEFC)
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 icdata_reg = rax;
- __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
Label L_no_such_interface;
diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad
index caa82aab99c2d..6df02d280bcef 100644
--- a/src/hotspot/cpu/x86/x86.ad
+++ b/src/hotspot/cpu/x86/x86.ad
@@ -1312,7 +1312,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1330,7 +1330,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
// That's why we must use the macroassembler to generate a handler.
C2_MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
- if (base == NULL) {
+ if (base == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return 0; // CodeBuffer::expand failed
}
@@ -1358,7 +1358,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
return offset;
}
-Assembler::Width widthForType(BasicType bt) {
+static Assembler::Width widthForType(BasicType bt) {
if (bt == T_BYTE) {
return Assembler::B;
} else if (bt == T_SHORT) {
@@ -1425,6 +1425,8 @@ bool Matcher::match_rule_supported(int opcode) {
return false;
}
break;
+ case Op_CompressV:
+ case Op_ExpandV:
case Op_PopCountVL:
if (UseAVX < 2) {
return false;
@@ -1659,12 +1661,6 @@ bool Matcher::match_rule_supported(int opcode) {
return false;
}
break;
- case Op_CompressV:
- case Op_ExpandV:
- if (!VM_Version::supports_avx512vl()) {
- return false;
- }
- break;
case Op_SqrtF:
if (UseSSE < 1) {
return false;
@@ -1703,7 +1699,7 @@ static inline bool is_pop_count_instr_target(BasicType bt) {
(is_non_subword_integral_type(bt) && VM_Version::supports_avx512_vpopcntdq());
}
-bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) {
+bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
return match_rule_supported_vector(opcode, vlen, bt);
}
@@ -1952,13 +1948,12 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
if (is_subword_type(bt) && !VM_Version::supports_avx512_vbmi2()) {
return false;
}
- if (size_in_bits < 128 ) {
+ if (!is_LP64 && !VM_Version::supports_avx512vl() && size_in_bits < 512) {
return false;
}
- if (size_in_bits < 512 && !VM_Version::supports_avx512vl()) {
+ if (size_in_bits < 128 ) {
return false;
}
- break;
case Op_VectorLongToMask:
if (UseAVX < 1 || !is_LP64) {
return false;
@@ -2186,7 +2181,7 @@ MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* generic_opnd,
}
}
ShouldNotReachHere();
- return NULL;
+ return nullptr;
}
bool Matcher::is_reg2reg_move(MachNode* m) {
@@ -2285,7 +2280,7 @@ int Matcher::min_vector_size(const BasicType bt) {
return MIN2(size,max_size);
}
-int Matcher::superword_max_vector_size(const BasicType bt) {
+int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
// Limit the max vector size for auto vectorization to 256 bits (32 bytes)
// by default on Cascade Lake
if (VM_Version::is_default_intel_cascade_lake()) {
@@ -2355,7 +2350,7 @@ class FusedPatternMatcher {
int _con_op;
static int match_next(Node* n, int next_op, int next_op_idx) {
- if (n->in(1) == NULL || n->in(2) == NULL) {
+ if (n->in(1) == nullptr || n->in(2) == nullptr) {
return -1;
}
@@ -2422,7 +2417,7 @@ class FusedPatternMatcher {
static bool is_bmi_pattern(Node* n, Node* m) {
assert(UseBMI1Instructions, "sanity");
- if (n != NULL && m != NULL) {
+ if (n != nullptr && m != nullptr) {
if (m->Opcode() == Op_LoadI) {
FusedPatternMatcher bmii(n, m, Op_ConI);
return bmii.match(Op_AndI, -1, Op_SubI, 1, 0) ||
@@ -7446,7 +7441,7 @@ instruct vround_reg_evex(vec dst, vec src, rRegP tmp, vec xtmp1, vec xtmp2, kReg
// --------------------------------- VectorMaskCmp --------------------------------------
instruct vcmpFD(legVec dst, legVec src1, legVec src2, immI8 cond) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL &&
+ predicate(n->bottom_type()->isa_vectmask() == nullptr &&
Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 8 && // src1
Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1
is_floating_point_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 T_FLOAT, T_DOUBLE
@@ -7466,7 +7461,7 @@ instruct vcmpFD(legVec dst, legVec src1, legVec src2, immI8 cond) %{
instruct evcmpFD64(vec dst, vec src1, vec src2, immI8 cond, kReg ktmp) %{
predicate(Matcher::vector_length_in_bytes(n->in(1)->in(1)) == 64 && // src1
- n->bottom_type()->isa_vectmask() == NULL &&
+ n->bottom_type()->isa_vectmask() == nullptr &&
is_floating_point_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1 T_FLOAT, T_DOUBLE
match(Set dst (VectorMaskCmp (Binary src1 src2) cond));
effect(TEMP ktmp);
@@ -7506,7 +7501,7 @@ instruct evcmpFD(kReg dst, vec src1, vec src2, immI8 cond) %{
%}
instruct vcmp_direct(legVec dst, legVec src1, legVec src2, immI8 cond) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL &&
+ predicate(n->bottom_type()->isa_vectmask() == nullptr &&
!Matcher::is_unsigned_booltest_pred(n->in(2)->get_int()) &&
Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1
Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1
@@ -7526,7 +7521,7 @@ instruct vcmp_direct(legVec dst, legVec src1, legVec src2, immI8 cond) %{
%}
instruct vcmp_negate(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xtmp) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL &&
+ predicate(n->bottom_type()->isa_vectmask() == nullptr &&
!Matcher::is_unsigned_booltest_pred(n->in(2)->get_int()) &&
Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1
Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1
@@ -7547,7 +7542,7 @@ instruct vcmp_negate(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xt
%}
instruct vcmpu(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xtmp) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL &&
+ predicate(n->bottom_type()->isa_vectmask() == nullptr &&
Matcher::is_unsigned_booltest_pred(n->in(2)->get_int()) &&
Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && // src1
Matcher::vector_length_in_bytes(n->in(1)->in(1)) <= 32 && // src1
@@ -7574,7 +7569,7 @@ instruct vcmpu(legVec dst, legVec src1, legVec src2, immI8 cond, legVec xtmp) %{
%}
instruct vcmp64(vec dst, vec src1, vec src2, immI8 cond, kReg ktmp) %{
- predicate((n->bottom_type()->isa_vectmask() == NULL &&
+ predicate((n->bottom_type()->isa_vectmask() == nullptr &&
Matcher::vector_length_in_bytes(n->in(1)->in(1)) == 64) && // src1
is_integral_type(Matcher::vector_element_basic_type(n->in(1)->in(1)))); // src1
match(Set dst (VectorMaskCmp (Binary src1 src2) cond));
@@ -7790,7 +7785,7 @@ instruct blendvp(vec dst, vec src, vec mask, rxmm0 tmp) %{
instruct vblendvpI(legVec dst, legVec src1, legVec src2, legVec mask) %{
predicate(UseAVX > 0 && !EnableX86ECoreOpts &&
- n->in(2)->bottom_type()->isa_vectmask() == NULL &&
+ n->in(2)->bottom_type()->isa_vectmask() == nullptr &&
Matcher::vector_length_in_bytes(n) <= 32 &&
is_integral_type(Matcher::vector_element_basic_type(n)));
match(Set dst (VectorBlend (Binary src1 src2) mask));
@@ -7804,7 +7799,7 @@ instruct vblendvpI(legVec dst, legVec src1, legVec src2, legVec mask) %{
instruct vblendvpFD(legVec dst, legVec src1, legVec src2, legVec mask) %{
predicate(UseAVX > 0 && !EnableX86ECoreOpts &&
- n->in(2)->bottom_type()->isa_vectmask() == NULL &&
+ n->in(2)->bottom_type()->isa_vectmask() == nullptr &&
Matcher::vector_length_in_bytes(n) <= 32 &&
!is_integral_type(Matcher::vector_element_basic_type(n)));
match(Set dst (VectorBlend (Binary src1 src2) mask));
@@ -7818,7 +7813,7 @@ instruct vblendvpFD(legVec dst, legVec src1, legVec src2, legVec mask) %{
instruct vblendvp(legVec dst, legVec src1, legVec src2, legVec mask, legVec vtmp) %{
predicate(UseAVX > 0 && EnableX86ECoreOpts &&
- n->in(2)->bottom_type()->isa_vectmask() == NULL &&
+ n->in(2)->bottom_type()->isa_vectmask() == nullptr &&
Matcher::vector_length_in_bytes(n) <= 32);
match(Set dst (VectorBlend (Binary src1 src2) mask));
format %{ "vector_blend $dst,$src1,$src2,$mask\t! using $vtmp as TEMP" %}
@@ -7834,7 +7829,7 @@ instruct vblendvp(legVec dst, legVec src1, legVec src2, legVec mask, legVec vtmp
instruct evblendvp64(vec dst, vec src1, vec src2, vec mask, kReg ktmp) %{
predicate(Matcher::vector_length_in_bytes(n) == 64 &&
- n->in(2)->bottom_type()->isa_vectmask() == NULL);
+ n->in(2)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorBlend (Binary src1 src2) mask));
format %{ "vector_blend $dst,$src1,$src2,$mask\t! using k2 as TEMP" %}
effect(TEMP ktmp);
@@ -8051,7 +8046,7 @@ instruct ktest_ge8(rFlagsRegU cr, kReg src1, kReg src2) %{
//------------------------------------- LoadMask --------------------------------------------
instruct loadMask(legVec dst, legVec src) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL && !VM_Version::supports_avx512vlbw());
+ predicate(n->bottom_type()->isa_vectmask() == nullptr && !VM_Version::supports_avx512vlbw());
match(Set dst (VectorLoadMask src));
effect(TEMP dst);
format %{ "vector_loadmask_byte $dst, $src\n\t" %}
@@ -8091,7 +8086,7 @@ instruct loadMask_evex(kReg dst, vec src, vec xtmp) %{
//------------------------------------- StoreMask --------------------------------------------
instruct vstoreMask1B(vec dst, vec src, immI_1 size) %{
- predicate(Matcher::vector_length(n) < 64 && n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(Matcher::vector_length(n) < 64 && n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorStoreMask src size));
format %{ "vector_store_mask $dst, $src \t! elem size is $size byte[s]" %}
ins_encode %{
@@ -8109,7 +8104,7 @@ instruct vstoreMask1B(vec dst, vec src, immI_1 size) %{
%}
instruct vstoreMask2B(vec dst, vec src, vec xtmp, immI_2 size) %{
- predicate(Matcher::vector_length(n) <= 16 && n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(Matcher::vector_length(n) <= 16 && n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorStoreMask src size));
effect(TEMP_DEF dst, TEMP xtmp);
format %{ "vector_store_mask $dst, $src \t! elem size is $size byte[s]" %}
@@ -8132,7 +8127,7 @@ instruct vstoreMask2B(vec dst, vec src, vec xtmp, immI_2 size) %{
%}
instruct vstoreMask4B(vec dst, vec src, vec xtmp, immI_4 size) %{
- predicate(UseAVX <= 2 && Matcher::vector_length(n) <= 8 && n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(UseAVX <= 2 && Matcher::vector_length(n) <= 8 && n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorStoreMask src size));
format %{ "vector_store_mask $dst, $src \t! elem size is $size byte[s]" %}
effect(TEMP_DEF dst, TEMP xtmp);
@@ -8192,7 +8187,7 @@ instruct storeMask8B_avx(vec dst, vec src, immI_8 size, vec vtmp) %{
%}
instruct vstoreMask4B_evex_novectmask(vec dst, vec src, immI_4 size) %{
- predicate(UseAVX > 2 && n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(UseAVX > 2 && n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorStoreMask src size));
format %{ "vector_store_mask $dst, $src \t! elem size is $size byte[s]" %}
ins_encode %{
@@ -8208,7 +8203,7 @@ instruct vstoreMask4B_evex_novectmask(vec dst, vec src, immI_4 size) %{
%}
instruct vstoreMask8B_evex_novectmask(vec dst, vec src, immI_8 size) %{
- predicate(UseAVX > 2 && n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(UseAVX > 2 && n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorStoreMask src size));
format %{ "vector_store_mask $dst, $src \t! elem size is $size byte[s]" %}
ins_encode %{
@@ -9045,7 +9040,7 @@ instruct vmask_tolong_evex(rRegL dst, kReg mask, rFlagsReg cr) %{
%}
instruct vmask_tolong_bool(rRegL dst, vec mask, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskToLong mask));
format %{ "vector_tolong_bool $dst, $mask \t! using $xtmp as TEMP" %}
effect(TEMP_DEF dst, TEMP xtmp, KILL cr);
@@ -9061,7 +9056,7 @@ instruct vmask_tolong_bool(rRegL dst, vec mask, vec xtmp, rFlagsReg cr) %{
%}
instruct vmask_tolong_avx(rRegL dst, vec mask, immI size, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskToLong (VectorStoreMask mask size)));
format %{ "vector_tolong_avx $dst, $mask \t! using $xtmp as TEMP" %}
effect(TEMP_DEF dst, TEMP xtmp, KILL cr);
@@ -9094,7 +9089,7 @@ instruct vmask_truecount_evex(rRegI dst, kReg mask, rRegL tmp, rFlagsReg cr) %{
%}
instruct vmask_truecount_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskTrueCount mask));
effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr);
format %{ "vector_truecount_bool $dst, $mask \t! using $tmp, $xtmp as TEMP" %}
@@ -9110,7 +9105,7 @@ instruct vmask_truecount_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp, rFlagsRe
%}
instruct vmask_truecount_avx(rRegI dst, vec mask, immI size, rRegL tmp, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskTrueCount (VectorStoreMask mask size)));
effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr);
format %{ "vector_truecount_avx $dst, $mask \t! using $tmp, $xtmp as TEMP" %}
@@ -9144,7 +9139,7 @@ instruct vmask_first_or_last_true_evex(rRegI dst, kReg mask, rRegL tmp, rFlagsRe
%}
instruct vmask_first_or_last_true_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskFirstTrue mask));
match(Set dst (VectorMaskLastTrue mask));
effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr);
@@ -9161,7 +9156,7 @@ instruct vmask_first_or_last_true_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp,
%}
instruct vmask_first_or_last_true_avx(rRegI dst, vec mask, immI size, rRegL tmp, vec xtmp, rFlagsReg cr) %{
- predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL);
+ predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == nullptr);
match(Set dst (VectorMaskFirstTrue (VectorStoreMask mask size)));
match(Set dst (VectorMaskLastTrue (VectorStoreMask mask size)));
effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr);
@@ -9178,8 +9173,26 @@ instruct vmask_first_or_last_true_avx(rRegI dst, vec mask, immI size, rRegL tmp,
%}
// --------------------------------- Compress/Expand Operations ---------------------------
+#ifdef _LP64
+instruct vcompress_reg_avx(vec dst, vec src, vec mask, rRegI rtmp, rRegL rscratch, vec perm, vec xtmp, rFlagsReg cr) %{
+ predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n) <= 32);
+ match(Set dst (CompressV src mask));
+ match(Set dst (ExpandV src mask));
+ effect(TEMP_DEF dst, TEMP perm, TEMP xtmp, TEMP rtmp, TEMP rscratch, KILL cr);
+ format %{ "vector_compress $dst, $src, $mask \t!using $xtmp, $rtmp, $rscratch and $perm as TEMP" %}
+ ins_encode %{
+ int opcode = this->ideal_Opcode();
+ int vlen_enc = vector_length_encoding(this);
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ __ vector_compress_expand_avx2(opcode, $dst$$XMMRegister, $src$$XMMRegister, $mask$$XMMRegister, $rtmp$$Register,
+ $rscratch$$Register, $perm$$XMMRegister, $xtmp$$XMMRegister, bt, vlen_enc);
+ %}
+ ins_pipe( pipe_slow );
+%}
+#endif
instruct vcompress_expand_reg_evex(vec dst, vec src, kReg mask) %{
+ predicate(VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n) == 64);
match(Set dst (CompressV src mask));
match(Set dst (ExpandV src mask));
format %{ "vector_compress_expand $dst, $src, $mask" %}
@@ -9998,7 +10011,7 @@ instruct mask_not_imm(kReg dst, kReg src, immI_M1 cnt) %{
%}
instruct long_to_maskLE8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec xtmp) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL && Matcher::vector_length(n) <= 8);
+ predicate(n->bottom_type()->isa_vectmask() == nullptr && Matcher::vector_length(n) <= 8);
match(Set dst (VectorLongToMask src));
effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, TEMP xtmp);
format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2, $xtmp as TEMP" %}
@@ -10013,7 +10026,7 @@ instruct long_to_maskLE8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec x
instruct long_to_maskGT8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec xtmp1, rFlagsReg cr) %{
- predicate(n->bottom_type()->isa_vectmask() == NULL && Matcher::vector_length(n) > 8);
+ predicate(n->bottom_type()->isa_vectmask() == nullptr && Matcher::vector_length(n) > 8);
match(Set dst (VectorLongToMask src));
effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, TEMP xtmp1, KILL cr);
format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2, $xtmp1, as TEMP" %}
diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad
index f2e9c042b244f..2fe655a576778 100644
--- a/src/hotspot/cpu/x86/x86_32.ad
+++ b/src/hotspot/cpu/x86/x86_32.ad
@@ -504,7 +504,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) {
__ bind(exit);
}
-void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
+static void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
Label done;
__ movl(dst, -1);
__ jcc(Assembler::parity, done);
@@ -614,7 +614,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
int framesize = C->output()->frame_size_in_bytes();
int bangsize = C->output()->bang_size_in_bytes();
- __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode(), C->stub_function() != NULL);
+ __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode(), C->stub_function() != nullptr);
C->output()->set_frame_complete(cbuf.insts_size());
@@ -1052,7 +1052,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
if( src_first == dst_first && src_second == dst_second )
return size; // Self copy, no move
- if (bottom_type()->isa_vect() != NULL && bottom_type()->isa_vectmask() == NULL) {
+ if (bottom_type()->isa_vect() != nullptr && bottom_type()->isa_vectmask() == nullptr) {
uint ireg = ideal_reg();
assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
assert((src_first_rc != rc_float && dst_first_rc != rc_float), "sanity");
@@ -1320,12 +1320,12 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
#ifndef PRODUCT
void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const {
- implementation( NULL, ra_, false, st );
+ implementation( nullptr, ra_, false, st );
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation( &cbuf, ra_, false, NULL );
+ implementation( &cbuf, ra_, false, nullptr );
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
@@ -1383,24 +1383,12 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
MacroAssembler masm(&cbuf);
-#ifdef ASSERT
- uint insts_size = cbuf.insts_size();
-#endif
- masm.cmpptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes()));
- masm.jump_cc(Assembler::notEqual,
- RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- /* WARNING these NOPs are critical so that verified entry point is properly
- aligned for patching by NativeJump::patch_verified_entry() */
- int nops_cnt = 2;
- if( !OptoBreakpoint ) // Leave space for int3
- nops_cnt += 1;
- masm.nop(nops_cnt);
-
- assert(cbuf.insts_size() - insts_size == size(ra_), "checking code size of inline cache node");
+ masm.ic_check(CodeEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
- return OptoBreakpoint ? 11 : 12;
+ return MachNode::size(ra_); // too many variables; just compute it
+ // the hard way
}
@@ -1725,7 +1713,7 @@ encode %{
MacroAssembler _masm(&cbuf);
__ check_klass_subtype_slow_path(Resi, Reax, Recx, Redi,
- NULL, &miss,
+ nullptr, &miss,
/*set_cond_codes:*/ true);
if ($primary) {
__ xorptr(Redi, Redi);
@@ -1842,8 +1830,8 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, cbuf.insts()->mark_off());
} else {
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -3396,7 +3384,7 @@ operand immP() %{
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immP0() %{
predicate( n->get_ptr() == 0 );
match(ConP);
@@ -13776,7 +13764,7 @@ instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eD
%}
instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr, eRegP thread) %{
- predicate(!Compile::current()->use_rtm());
+ predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box, TEMP thread);
ins_cost(300);
@@ -13790,6 +13778,7 @@ instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP
%}
instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, USE_KILL box);
ins_cost(300);
@@ -13800,6 +13789,32 @@ instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
ins_pipe(pipe_slow);
%}
+instruct cmpFastLockLightweight(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI eax_reg, eRegP tmp, eRegP thread) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP eax_reg, TEMP tmp, USE_KILL box, TEMP thread);
+ ins_cost(300);
+ format %{ "FASTLOCK $object,$box\t! kills $box,$eax_reg,$tmp" %}
+ ins_encode %{
+ __ get_thread($thread$$Register);
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpFastUnlockLightweight(eFlagsReg cr, eRegP object, eAXRegP eax_reg, eRegP tmp, eRegP thread) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object eax_reg));
+ effect(TEMP tmp, USE_KILL eax_reg, TEMP thread);
+ ins_cost(300);
+ format %{ "FASTUNLOCK $object,$eax_reg\t! kills $eax_reg,$tmp" %}
+ ins_encode %{
+ __ get_thread($thread$$Register);
+ __ fast_unlock_lightweight($object$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct mask_all_evexL_LT32(kReg dst, eRegL src) %{
predicate(Matcher::vector_length(n) <= 32);
match(Set dst (MaskAll src));
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 80f281a1bf92d..d43929efd3ec5 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -519,7 +519,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
}
// This could be in MacroAssembler but it's fairly C2 specific
-void emit_cmpfp_fixup(MacroAssembler& _masm) {
+static void emit_cmpfp_fixup(MacroAssembler& _masm) {
Label exit;
__ jccb(Assembler::noParity, exit);
__ pushf();
@@ -539,7 +539,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) {
__ bind(exit);
}
-void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
+static void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
Label done;
__ movl(dst, -1);
__ jcc(Assembler::parity, done);
@@ -558,10 +558,10 @@ void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
// je #
// |-jz -> a | b # a & b
// | -> a #
-void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
- XMMRegister a, XMMRegister b,
- XMMRegister xmmt, Register rt,
- bool min, bool single) {
+static void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
+ XMMRegister a, XMMRegister b,
+ XMMRegister xmmt, Register rt,
+ bool min, bool single) {
Label nan, zero, below, above, done;
@@ -706,7 +706,7 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
st->print("# stack alignment check");
#endif
}
- if (C->stub_function() != NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
+ if (C->stub_function() != nullptr && BarrierSet::barrier_set()->barrier_set_nmethod() != nullptr) {
st->print("\n\t");
st->print("cmpl [r15_thread + #disarmed_guard_value_offset], #disarmed_guard_value\t");
st->print("\n\t");
@@ -741,7 +741,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ bind(L_skip_barrier);
}
- __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != NULL);
+ __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != nullptr);
C->output()->set_frame_complete(cbuf.insts_size());
@@ -970,7 +970,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
PhaseRegAlloc* ra_,
bool do_size,
outputStream* st) const {
- assert(cbuf != NULL || st != NULL, "sanity");
+ assert(cbuf != nullptr || st != nullptr, "sanity");
// Get registers to move
OptoReg::Name src_second = ra_->get_reg_second(in(1));
OptoReg::Name src_first = ra_->get_reg_first(in(1));
@@ -989,7 +989,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
// Self copy, no move
return 0;
}
- if (bottom_type()->isa_vect() != NULL && bottom_type()->isa_vectmask() == NULL) {
+ if (bottom_type()->isa_vect() != nullptr && bottom_type()->isa_vectmask() == nullptr) {
uint ireg = ideal_reg();
assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
@@ -1428,12 +1428,12 @@ uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
#ifndef PRODUCT
void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const {
- implementation(NULL, ra_, false, st);
+ implementation(nullptr, ra_, false, st);
}
#endif
void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
- implementation(&cbuf, ra_, false, NULL);
+ implementation(&cbuf, ra_, false, nullptr);
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
@@ -1472,40 +1472,19 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
if (UseCompressedClassPointers) {
st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
- st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check");
+ st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
} else {
- st->print_cr("\tcmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t"
- "# Inline cache check");
+ st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
}
st->print_cr("\tjne SharedRuntime::_ic_miss_stub");
- st->print_cr("\tnop\t# nops to align entry point");
}
#endif
void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
MacroAssembler masm(&cbuf);
- uint insts_size = cbuf.insts_size();
- if (UseCompressedClassPointers) {
- masm.load_klass(rscratch1, j_rarg0, rscratch2);
- masm.cmpptr(rax, rscratch1);
- } else {
- masm.cmpptr(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
- }
-
- masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- /* WARNING these NOPs are critical so that verified entry point is properly
- 4 bytes aligned for patching by NativeJump::patch_verified_entry() */
- int nops_cnt = 4 - ((cbuf.insts_size() - insts_size) & 0x3);
- if (OptoBreakpoint) {
- // Leave space for int3
- nops_cnt -= 1;
- }
- nops_cnt &= 0x3; // Do not add nops if code is aligned.
- if (nops_cnt > 0)
- masm.nop(nops_cnt);
+ masm.ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
@@ -1784,7 +1763,7 @@ encode %{
MacroAssembler _masm(&cbuf);
__ check_klass_subtype_slow_path(Rrsi, Rrax, Rrcx, Rrdi,
- NULL, &miss,
+ nullptr, &miss,
/*set_cond_codes:*/ true);
if ($primary) {
__ xorptr(Rrdi, Rrdi);
@@ -1840,8 +1819,8 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call_offset);
} else {
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
- if (stub == NULL) {
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark);
+ if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
}
@@ -2179,7 +2158,7 @@ operand immP()
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immP0()
%{
predicate(n->get_ptr() == 0);
@@ -2207,7 +2186,7 @@ operand immNKlass() %{
interface(CONST_INTER);
%}
-// NULL Pointer Immediate
+// Null Pointer Immediate
operand immN0() %{
predicate(n->get_narrowcon() == 0);
match(ConN);
@@ -3121,7 +3100,7 @@ operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale)
// Indirect Narrow Oop Plus Offset Operand
// Note: x86 architecture doesn't support "scale * index + offset" without a base
-// we can't free r12 even with CompressedOops::base() == NULL.
+// we can't free r12 even with CompressedOops::base() == nullptr.
operand indCompressedOopOffset(rRegN reg, immL32 off) %{
predicate(UseCompressedOops && (CompressedOops::shift() == Address::times_8));
constraint(ALLOC_IN_RC(ptr_reg));
@@ -4480,7 +4459,7 @@ instruct loadD(regD dst, memory mem)
// max = java.lang.Math.max(float a, float b)
instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
- predicate(UseAVX > 0 && !SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n));
match(Set dst (MaxF a b));
effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
format %{ "maxF $dst, $a, $b \t! using tmp, atmp and btmp as TEMP" %}
@@ -4491,7 +4470,7 @@ instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp,
%}
instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xmmt, rRegI tmp, rFlagsReg cr) %{
- predicate(UseAVX > 0 && SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && VLoopReductions::is_reduction(n));
match(Set dst (MaxF a b));
effect(USE a, USE b, TEMP xmmt, TEMP tmp, KILL cr);
@@ -4505,7 +4484,7 @@ instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xmmt, rRe
// max = java.lang.Math.max(double a, double b)
instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
- predicate(UseAVX > 0 && !SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n));
match(Set dst (MaxD a b));
effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp);
format %{ "maxD $dst, $a, $b \t! using tmp, atmp and btmp as TEMP" %}
@@ -4516,7 +4495,7 @@ instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp,
%}
instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xmmt, rRegL tmp, rFlagsReg cr) %{
- predicate(UseAVX > 0 && SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && VLoopReductions::is_reduction(n));
match(Set dst (MaxD a b));
effect(USE a, USE b, TEMP xmmt, TEMP tmp, KILL cr);
@@ -4530,7 +4509,7 @@ instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xmmt, rRe
// min = java.lang.Math.min(float a, float b)
instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
- predicate(UseAVX > 0 && !SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n));
match(Set dst (MinF a b));
effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
format %{ "minF $dst, $a, $b \t! using tmp, atmp and btmp as TEMP" %}
@@ -4541,7 +4520,7 @@ instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp,
%}
instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xmmt, rRegI tmp, rFlagsReg cr) %{
- predicate(UseAVX > 0 && SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && VLoopReductions::is_reduction(n));
match(Set dst (MinF a b));
effect(USE a, USE b, TEMP xmmt, TEMP tmp, KILL cr);
@@ -4555,7 +4534,7 @@ instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xmmt, rRe
// min = java.lang.Math.min(double a, double b)
instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
- predicate(UseAVX > 0 && !SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && !VLoopReductions::is_reduction(n));
match(Set dst (MinD a b));
effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
format %{ "minD $dst, $a, $b \t! using tmp, atmp and btmp as TEMP" %}
@@ -4566,7 +4545,7 @@ instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp,
%}
instruct minD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xmmt, rRegL tmp, rFlagsReg cr) %{
- predicate(UseAVX > 0 && SuperWord::is_reduction(n));
+ predicate(UseAVX > 0 && VLoopReductions::is_reduction(n));
match(Set dst (MinD a b));
effect(USE a, USE b, TEMP xmmt, TEMP tmp, KILL cr);
@@ -4902,7 +4881,7 @@ instruct loadConF(regF dst, immF con) %{
instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{
match(Set dst src);
effect(KILL cr);
- format %{ "xorq $dst, $src\t# compressed NULL ptr" %}
+ format %{ "xorq $dst, $src\t# compressed null pointer" %}
ins_encode %{
__ xorq($dst$$Register, $dst$$Register);
%}
@@ -4916,7 +4895,7 @@ instruct loadConN(rRegN dst, immN src) %{
format %{ "movl $dst, $src\t# compressed ptr" %}
ins_encode %{
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
__ set_narrow_oop($dst$$Register, (jobject)$src$$constant);
@@ -4932,7 +4911,7 @@ instruct loadConNKlass(rRegN dst, immNKlass src) %{
format %{ "movl $dst, $src\t# compressed klass ptr" %}
ins_encode %{
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
ShouldNotReachHere();
} else {
__ set_narrow_klass($dst$$Register, (Klass*)$src$$constant);
@@ -5158,7 +5137,7 @@ instruct storeP(memory mem, any_RegP src)
instruct storeImmP0(memory mem, immP0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL) && n->as_Store()->barrier_data() == 0);
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr) && n->as_Store()->barrier_data() == 0);
match(Set mem (StoreP mem zero));
ins_cost(125); // XXX
@@ -5169,7 +5148,7 @@ instruct storeImmP0(memory mem, immP0 zero)
ins_pipe(ialu_mem_reg);
%}
-// Store NULL Pointer, mark word, or other simple pointer constant.
+// Store Null Pointer, mark word, or other simple pointer constant.
instruct storeImmP(memory mem, immP31 src)
%{
predicate(n->as_Store()->barrier_data() == 0);
@@ -5210,7 +5189,7 @@ instruct storeNKlass(memory mem, rRegN src)
instruct storeImmN0(memory mem, immN0 zero)
%{
- predicate(CompressedOops::base() == NULL);
+ predicate(CompressedOops::base() == nullptr);
match(Set mem (StoreN mem zero));
ins_cost(125); // XXX
@@ -5229,7 +5208,7 @@ instruct storeImmN(memory mem, immN src)
format %{ "movl $mem, $src\t# compressed ptr" %}
ins_encode %{
address con = (address)$src$$constant;
- if (con == NULL) {
+ if (con == nullptr) {
__ movl($mem$$Address, 0);
} else {
__ set_narrow_oop($mem$$Address, (jobject)$src$$constant);
@@ -5253,7 +5232,7 @@ instruct storeImmNKlass(memory mem, immNKlass src)
// Store Integer Immediate
instruct storeImmI0(memory mem, immI_0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreI mem zero));
ins_cost(125); // XXX
@@ -5279,7 +5258,7 @@ instruct storeImmI(memory mem, immI src)
// Store Long Immediate
instruct storeImmL0(memory mem, immL0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreL mem zero));
ins_cost(125); // XXX
@@ -5305,7 +5284,7 @@ instruct storeImmL(memory mem, immL32 src)
// Store Short/Char Immediate
instruct storeImmC0(memory mem, immI_0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreC mem zero));
ins_cost(125); // XXX
@@ -5332,7 +5311,7 @@ instruct storeImmI16(memory mem, immI16 src)
// Store Byte Immediate
instruct storeImmB0(memory mem, immI_0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreB mem zero));
ins_cost(125); // XXX
@@ -5358,7 +5337,7 @@ instruct storeImmB(memory mem, immI8 src)
// Store CMS card-mark Immediate
instruct storeImmCM0_reg(memory mem, immI_0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreCM mem zero));
ins_cost(125); // XXX
@@ -5397,7 +5376,7 @@ instruct storeF(memory mem, regF src)
// Store immediate Float value (it is faster than store from XMM register)
instruct storeF0(memory mem, immF0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreF mem zero));
ins_cost(25); // XXX
@@ -5436,7 +5415,7 @@ instruct storeD(memory mem, regD src)
// Store immediate double 0.0 (it is faster than store from XMM register)
instruct storeD0_imm(memory mem, immD0 src)
%{
- predicate(!UseCompressedOops || (CompressedOops::base() != NULL));
+ predicate(!UseCompressedOops || (CompressedOops::base() != nullptr));
match(Set mem (StoreD mem src));
ins_cost(50);
@@ -5449,7 +5428,7 @@ instruct storeD0_imm(memory mem, immD0 src)
instruct storeD0(memory mem, immD0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
match(Set mem (StoreD mem zero));
ins_cost(25); // XXX
@@ -11680,7 +11659,7 @@ instruct testP_reg(rFlagsReg cr, rRegP src, immP0 zero)
// any compare to a zero should be eq/neq.
instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
%{
- predicate((!UseCompressedOops || (CompressedOops::base() != NULL)) &&
+ predicate((!UseCompressedOops || (CompressedOops::base() != nullptr)) &&
n->in(1)->as_Load()->barrier_data() == 0);
match(Set cr (CmpP (LoadP op) zero));
@@ -11694,7 +11673,7 @@ instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL) &&
+ predicate(UseCompressedOops && (CompressedOops::base() == nullptr) &&
n->in(1)->as_Load()->barrier_data() == 0);
match(Set cr (CmpP (LoadP mem) zero));
@@ -11777,7 +11756,7 @@ instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{
instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero)
%{
- predicate(CompressedOops::base() != NULL);
+ predicate(CompressedOops::base() != nullptr);
match(Set cr (CmpN (LoadN mem) zero));
ins_cost(500); // XXX
@@ -11790,7 +11769,7 @@ instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero)
instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero)
%{
- predicate(CompressedOops::base() == NULL);
+ predicate(CompressedOops::base() == nullptr);
match(Set cr (CmpN (LoadN mem) zero));
format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %}
@@ -12404,7 +12383,7 @@ instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp,
%}
instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
- predicate(!Compile::current()->use_rtm());
+ predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box);
ins_cost(300);
@@ -12417,6 +12396,7 @@ instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRe
%}
instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, USE_KILL box);
ins_cost(300);
@@ -12427,6 +12407,30 @@ instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
ins_pipe(pipe_slow);
%}
+instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP rax_reg, TEMP tmp, USE_KILL box);
+ ins_cost(300);
+ format %{ "fastlock $object,$box\t! kills $box,$rax_reg,$tmp" %}
+ ins_encode %{
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object rax_reg));
+ effect(TEMP tmp, USE_KILL rax_reg);
+ ins_cost(300);
+ format %{ "fastunlock $object,$rax_reg\t! kills $rax_reg,$tmp" %}
+ ins_encode %{
+ __ fast_unlock_lightweight($object$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// ============================================================================
// Safepoint Instructions
diff --git a/src/hotspot/cpu/zero/compiledIC_zero.cpp b/src/hotspot/cpu/zero/compiledIC_zero.cpp
index b0564643af080..24153aeacc5e1 100644
--- a/src/hotspot/cpu/zero/compiledIC_zero.cpp
+++ b/src/hotspot/cpu/zero/compiledIC_zero.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
@@ -43,27 +42,27 @@
// ----------------------------------------------------------------------------
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
ShouldNotReachHere(); // Only needed for COMPILER2.
return nullptr;
}
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
ShouldNotReachHere(); // Only needed for COMPILER2.
return 0;
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
ShouldNotReachHere(); // Only needed for COMPILER2.
return 0;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
@@ -71,7 +70,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code.
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
diff --git a/src/hotspot/cpu/zero/icBuffer_zero.cpp b/src/hotspot/cpu/zero/icBuffer_zero.cpp
deleted file mode 100644
index adde916a4c4ad..0000000000000
--- a/src/hotspot/cpu/zero/icBuffer_zero.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007 Red Hat, Inc.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_zero.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // NB set this once the functions below are implemented
- return 4;
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin,
- void* cached_oop,
- address entry_point) {
- // NB ic_stub_code_size() must return the size of the code we generate
- ShouldNotCallThis();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- // NB ic_stub_code_size() must return the size of the code we generate
- ShouldNotCallThis();
- return nullptr;
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- ShouldNotCallThis();
- return nullptr;
-}
diff --git a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
index 4244b5817db98..986cee685123b 100644
--- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
+++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
@@ -26,10 +26,8 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "oops/compiledICHolder.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframeArray.hpp"
diff --git a/src/hotspot/os/aix/attachListener_aix.cpp b/src/hotspot/os/aix/attachListener_aix.cpp
index 2e079c9b3a18b..51e2b2b3c0ac3 100644
--- a/src/hotspot/os/aix/attachListener_aix.cpp
+++ b/src/hotspot/os/aix/attachListener_aix.cpp
@@ -478,14 +478,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) {
@@ -505,8 +505,8 @@ int AttachListener::pd_init() {
bool AttachListener::check_socket_file() {
int ret;
- struct stat64 st;
- ret = stat64(AixAttachListener::path(), &st);
+ struct stat st;
+ ret = stat(AixAttachListener::path(), &st);
if (ret == -1) { // need to restart attach listener.
log_debug(attach)("Socket file %s does not exist - Restart Attach Listener",
AixAttachListener::path());
@@ -545,14 +545,14 @@ bool AttachListener::is_init_trigger() {
}
char fn[PATH_MAX + 1];
int ret;
- struct stat64 st;
+ struct stat st;
os::snprintf_checked(fn, sizeof(fn), ".attach_pid%d", os::current_process_id());
- RESTARTABLE(::stat64(fn, &st), ret);
+ 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/aix/globals_aix.hpp b/src/hotspot/os/aix/globals_aix.hpp
index a047e79b695fa..fb353348a5364 100644
--- a/src/hotspot/os/aix/globals_aix.hpp
+++ b/src/hotspot/os/aix/globals_aix.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. 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
@@ -49,11 +49,12 @@
"Allow VM to run with EXTSHM=ON.") \
\
/* Maximum expected size of the data segment. That correlates with the */ \
- /* to the maximum C Heap consumption we expect. */ \
- /* We need to know this because we need to leave "breathing space" for the */ \
- /* data segment when placing the java heap. If that space is too small, we */ \
- /* reduce our chance of getting a low heap address (needed for compressed */ \
- /* Oops). */ \
+ /* maximum C Heap consumption we expect. */ \
+ /* We need to leave "breathing space" for the data segment when */ \
+ /* placing the java heap. If the MaxExpectedDataSegmentSize setting */ \
+ /* is too small, we might run into resource issues creating many native */ \
+ /* threads, if it is too large, we reduce our chance of getting a low heap */ \
+ /* address (needed for compressed Oops). */ \
product(uintx, MaxExpectedDataSegmentSize, 8*G, \
"Maximum expected Data Segment Size.") \
\
diff --git a/src/hotspot/os/aix/libperfstat_aix.cpp b/src/hotspot/os/aix/libperfstat_aix.cpp
index f547b4c78e77c..0185d7d041c85 100644
--- a/src/hotspot/os/aix/libperfstat_aix.cpp
+++ b/src/hotspot/os/aix/libperfstat_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -213,12 +213,8 @@ bool libperfstat::get_cpuinfo(cpuinfo_t* pci) {
if (-1 == libperfstat::perfstat_cpu_total(nullptr, &psct, sizeof(PERFSTAT_CPU_TOTAL_T_LATEST), 1)) {
if (-1 == libperfstat::perfstat_cpu_total(nullptr, &psct, sizeof(perfstat_cpu_total_t_71), 1)) {
- if (-1 == libperfstat::perfstat_cpu_total(nullptr, &psct, sizeof(perfstat_cpu_total_t_61), 1)) {
- if (-1 == libperfstat::perfstat_cpu_total(nullptr, &psct, sizeof(perfstat_cpu_total_t_53), 1)) {
- trcVerbose("perfstat_cpu_total() failed (errno=%d)", errno);
- return false;
- }
- }
+ trcVerbose("perfstat_cpu_total() failed (errno=%d)", errno);
+ return false;
}
}
@@ -252,14 +248,8 @@ bool libperfstat::get_partitioninfo(partitioninfo_t* ppi) {
if (-1 == libperfstat::perfstat_partition_total(nullptr, &pspt, sizeof(PERFSTAT_PARTITON_TOTAL_T_LATEST), 1)) {
if (-1 == libperfstat::perfstat_partition_total(nullptr, &pspt, sizeof(perfstat_partition_total_t_71), 1)) {
ame_details = false;
- if (-1 == libperfstat::perfstat_partition_total(nullptr, &pspt, sizeof(perfstat_partition_total_t_61), 1)) {
- if (-1 == libperfstat::perfstat_partition_total(nullptr, &pspt, sizeof(perfstat_partition_total_t_53), 1)) {
- if (-1 == libperfstat::perfstat_partition_total(nullptr, &pspt, sizeof(perfstat_partition_total_t_53_5), 1)) {
- trcVerbose("perfstat_partition_total() failed (errno=%d)", errno);
- return false;
- }
- }
- }
+ trcVerbose("perfstat_partition_total() failed (errno=%d)", errno);
+ return false;
}
}
@@ -324,10 +314,8 @@ bool libperfstat::get_wparinfo(wparinfo_t* pwi) {
memset (&pswt, '\0', sizeof(pswt));
if (-1 == libperfstat::perfstat_wpar_total(nullptr, &pswt, sizeof(PERFSTAT_WPAR_TOTAL_T_LATEST), 1)) {
- if (-1 == libperfstat::perfstat_wpar_total(nullptr, &pswt, sizeof(perfstat_wpar_total_t_61), 1)) {
- trcVerbose("perfstat_wpar_total() failed (errno=%d)", errno);
- return false;
- }
+ trcVerbose("perfstat_wpar_total() failed (errno=%d)", errno);
+ return false;
}
// WPAR type info.
diff --git a/src/hotspot/os/aix/libperfstat_aix.hpp b/src/hotspot/os/aix/libperfstat_aix.hpp
index 704c5b41a31b9..67cae0d08b65c 100644
--- a/src/hotspot/os/aix/libperfstat_aix.hpp
+++ b/src/hotspot/os/aix/libperfstat_aix.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -38,16 +38,8 @@
#include
///////////////////////////////////////////////////////////////////////////////////////////////
-// These are excerpts from the AIX 5.3, 6.1, 7.1 libperfstat.h -
+// These are excerpts from the AIX 7.1 libperfstat.h -
// this is all we need from libperfstat.h and I want to avoid having to include
-//
-// Note: I define all structures as if I were to include libperfstat.h on an AIX 5.2
-// build machine.
-//
-// The ratio behind that is that if I would build on an AIX 5.2 build machine,
-// include libperfstat.h and hard-link against libperfstat.a, the program should
-// work without recompilation on all newer AIX versions.
-//
#define IDENTIFIER_LENGTH 64 /* length of strings included in the structures */
#define FIRST_CPU "" /* pseudo-name for fist CPU */
@@ -94,169 +86,6 @@ typedef struct { /* Virtual memory utilization */
} perfstat_memory_total_t;
-typedef struct { /* global cpu information AIX 5.3 < TL10 */
- int ncpus; /* number of active logical processors */
- int ncpus_cfg; /* number of configured processors */
- char description[IDENTIFIER_LENGTH]; /* processor description (type/official name) */
- u_longlong_t processorHZ; /* processor speed in Hz */
- u_longlong_t user; /* raw total number of clock ticks spent in user mode */
- u_longlong_t sys; /* raw total number of clock ticks spent in system mode */
- u_longlong_t idle; /* raw total number of clock ticks spent idle */
- u_longlong_t wait; /* raw total number of clock ticks spent waiting for I/O */
- u_longlong_t pswitch; /* number of process switches (change in currently running process) */
- u_longlong_t syscall; /* number of system calls executed */
- u_longlong_t sysread; /* number of read system calls executed */
- u_longlong_t syswrite; /* number of write system calls executed */
- u_longlong_t sysfork; /* number of forks system calls executed */
- u_longlong_t sysexec; /* number of execs system calls executed */
- u_longlong_t readch; /* number of characters transferred with read system call */
- u_longlong_t writech; /* number of characters transferred with write system call */
- u_longlong_t devintrs; /* number of device interrupts */
- u_longlong_t softintrs; /* number of software interrupts */
- time_t lbolt; /* number of ticks since last reboot */
- u_longlong_t loadavg[3]; /* (1<. */
- u_longlong_t runque; /* length of the run queue (processes ready) */
- u_longlong_t swpque; /* ength of the swap queue (processes waiting to be paged in) */
- u_longlong_t bread; /* number of blocks read */
- u_longlong_t bwrite; /* number of blocks written */
- u_longlong_t lread; /* number of logical read requests */
- u_longlong_t lwrite; /* number of logical write requests */
- u_longlong_t phread; /* number of physical reads (reads on raw devices) */
- u_longlong_t phwrite; /* number of physical writes (writes on raw devices) */
- u_longlong_t runocc; /* updated whenever runque is updated, i.e. the runqueue is occupied.
- * This can be used to compute the simple average of ready processes */
- u_longlong_t swpocc; /* updated whenever swpque is updated. i.e. the swpqueue is occupied.
- * This can be used to compute the simple average processes waiting to be paged in */
- u_longlong_t iget; /* number of inode lookups */
- u_longlong_t namei; /* number of vnode lookup from a path name */
- u_longlong_t dirblk; /* number of 512-byte block reads by the directory search routine to locate an entry for a file */
- u_longlong_t msg; /* number of IPC message operations */
- u_longlong_t sema; /* number of IPC semaphore operations */
- u_longlong_t rcvint; /* number of tty receive interrupts */
- u_longlong_t xmtint; /* number of tyy transmit interrupts */
- u_longlong_t mdmint; /* number of modem interrupts */
- u_longlong_t tty_rawinch; /* number of raw input characters */
- u_longlong_t tty_caninch; /* number of canonical input characters (always zero) */
- u_longlong_t tty_rawoutch; /* number of raw output characters */
- u_longlong_t ksched; /* number of kernel processes created */
- u_longlong_t koverf; /* kernel process creation attempts where:
- * -the user has forked to their maximum limit
- * -the configuration limit of processes has been reached */
- u_longlong_t kexit; /* number of kernel processes that became zombies */
- u_longlong_t rbread; /* number of remote read requests */
- u_longlong_t rcread; /* number of cached remote reads */
- u_longlong_t rbwrt; /* number of remote writes */
- u_longlong_t rcwrt; /* number of cached remote writes */
- u_longlong_t traps; /* number of traps */
- int ncpus_high; /* index of highest processor online */
- u_longlong_t puser; /* raw number of physical processor tics in user mode */
- u_longlong_t psys; /* raw number of physical processor tics in system mode */
- u_longlong_t pidle; /* raw number of physical processor tics idle */
- u_longlong_t pwait; /* raw number of physical processor tics waiting for I/O */
- u_longlong_t decrintrs; /* number of decrementer tics interrupts */
- u_longlong_t mpcrintrs; /* number of mpc's received interrupts */
- u_longlong_t mpcsintrs; /* number of mpc's sent interrupts */
- u_longlong_t phantintrs; /* number of phantom interrupts */
- u_longlong_t idle_donated_purr; /* number of idle cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_donated_spurr; /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_purr; /* number of busy cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_spurr; /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_stolen_purr; /* number of idle cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t idle_stolen_spurr; /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_purr; /* number of busy cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_spurr; /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
- short iowait; /* number of processes that are asleep waiting for buffered I/O */
- short physio; /* number of processes waiting for raw I/O */
- longlong_t twait; /* number of threads that are waiting for filesystem direct(cio) */
- u_longlong_t hpi; /* number of hypervisor page-ins */
- u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds) */
-} perfstat_cpu_total_t_53;
-
-typedef struct { /* global cpu information AIX 6.1|5.3 > TL09 */
- int ncpus; /* number of active logical processors */
- int ncpus_cfg; /* number of configured processors */
- char description[IDENTIFIER_LENGTH]; /* processor description (type/official name) */
- u_longlong_t processorHZ; /* processor speed in Hz */
- u_longlong_t user; /* raw total number of clock ticks spent in user mode */
- u_longlong_t sys; /* raw total number of clock ticks spent in system mode */
- u_longlong_t idle; /* raw total number of clock ticks spent idle */
- u_longlong_t wait; /* raw total number of clock ticks spent waiting for I/O */
- u_longlong_t pswitch; /* number of process switches (change in currently running process) */
- u_longlong_t syscall; /* number of system calls executed */
- u_longlong_t sysread; /* number of read system calls executed */
- u_longlong_t syswrite; /* number of write system calls executed */
- u_longlong_t sysfork; /* number of forks system calls executed */
- u_longlong_t sysexec; /* number of execs system calls executed */
- u_longlong_t readch; /* number of characters transferred with read system call */
- u_longlong_t writech; /* number of characters transferred with write system call */
- u_longlong_t devintrs; /* number of device interrupts */
- u_longlong_t softintrs; /* number of software interrupts */
- time_t lbolt; /* number of ticks since last reboot */
- u_longlong_t loadavg[3]; /* (1<. */
- u_longlong_t runque; /* length of the run queue (processes ready) */
- u_longlong_t swpque; /* length of the swap queue (processes waiting to be paged in) */
- u_longlong_t bread; /* number of blocks read */
- u_longlong_t bwrite; /* number of blocks written */
- u_longlong_t lread; /* number of logical read requests */
- u_longlong_t lwrite; /* number of logical write requests */
- u_longlong_t phread; /* number of physical reads (reads on raw devices) */
- u_longlong_t phwrite; /* number of physical writes (writes on raw devices) */
- u_longlong_t runocc; /* updated whenever runque is updated, i.e. the runqueue is occupied.
- * This can be used to compute the simple average of ready processes */
- u_longlong_t swpocc; /* updated whenever swpque is updated. i.e. the swpqueue is occupied.
- * This can be used to compute the simple average processes waiting to be paged in */
- u_longlong_t iget; /* number of inode lookups */
- u_longlong_t namei; /* number of vnode lookup from a path name */
- u_longlong_t dirblk; /* number of 512-byte block reads by the directory search routine to locate an entry for a file */
- u_longlong_t msg; /* number of IPC message operations */
- u_longlong_t sema; /* number of IPC semaphore operations */
- u_longlong_t rcvint; /* number of tty receive interrupts */
- u_longlong_t xmtint; /* number of tyy transmit interrupts */
- u_longlong_t mdmint; /* number of modem interrupts */
- u_longlong_t tty_rawinch; /* number of raw input characters */
- u_longlong_t tty_caninch; /* number of canonical input characters (always zero) */
- u_longlong_t tty_rawoutch; /* number of raw output characters */
- u_longlong_t ksched; /* number of kernel processes created */
- u_longlong_t koverf; /* kernel process creation attempts where:
- * -the user has forked to their maximum limit
- * -the configuration limit of processes has been reached */
- u_longlong_t kexit; /* number of kernel processes that became zombies */
- u_longlong_t rbread; /* number of remote read requests */
- u_longlong_t rcread; /* number of cached remote reads */
- u_longlong_t rbwrt; /* number of remote writes */
- u_longlong_t rcwrt; /* number of cached remote writes */
- u_longlong_t traps; /* number of traps */
- int ncpus_high; /* index of highest processor online */
- u_longlong_t puser; /* raw number of physical processor tics in user mode */
- u_longlong_t psys; /* raw number of physical processor tics in system mode */
- u_longlong_t pidle; /* raw number of physical processor tics idle */
- u_longlong_t pwait; /* raw number of physical processor tics waiting for I/O */
- u_longlong_t decrintrs; /* number of decrementer tics interrupts */
- u_longlong_t mpcrintrs; /* number of mpc's received interrupts */
- u_longlong_t mpcsintrs; /* number of mpc's sent interrupts */
- u_longlong_t phantintrs; /* number of phantom interrupts */
- u_longlong_t idle_donated_purr; /* number of idle cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_donated_spurr; /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_purr; /* number of busy cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_spurr; /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_stolen_purr; /* number of idle cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t idle_stolen_spurr; /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_purr; /* number of busy cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_spurr; /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
- short iowait; /* number of processes that are asleep waiting for buffered I/O */
- short physio; /* number of processes waiting for raw I/O */
- longlong_t twait; /* number of threads that are waiting for filesystem direct(cio) */
- u_longlong_t hpi; /* number of hypervisor page-ins */
- u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds) */
- u_longlong_t puser_spurr; /* number of spurr cycles spent in user mode */
- u_longlong_t psys_spurr; /* number of spurr cycles spent in kernel mode */
- u_longlong_t pidle_spurr; /* number of spurr cycles spent in idle mode */
- u_longlong_t pwait_spurr; /* number of spurr cycles spent in wait mode */
- int spurrflag; /* set if running in spurr mode */
-} perfstat_cpu_total_t_61;
-
typedef struct { /* global cpu information AIX 7.1 */
int ncpus; /* number of active logical processors */
int ncpus_cfg; /* number of configured processors */
@@ -564,166 +393,6 @@ typedef union {
} b;
} perfstat_partition_type_t;
-typedef struct { /* partition total information AIX 5.3 < TL6 */
- char name[IDENTIFIER_LENGTH]; /* name of the logical partition */
- perfstat_partition_type_t type; /* set of bits describing the partition */
- int lpar_id; /* logical partition identifier */
- int group_id; /* identifier of the LPAR group this partition is a member of */
- int pool_id; /* identifier of the shared pool of physical processors this partition is a member of */
- int online_cpus; /* number of virtual CPUs currently online on the partition */
- int max_cpus; /* maximum number of virtual CPUs this partition can ever have */
- int min_cpus; /* minimum number of virtual CPUs this partition must have */
- u_longlong_t online_memory; /* amount of memory currently online */
- u_longlong_t max_memory; /* maximum amount of memory this partition can ever have */
- u_longlong_t min_memory; /* minimum amount of memory this partition must have */
- int entitled_proc_capacity; /* number of processor units this partition is entitled to receive */
- int max_proc_capacity; /* maximum number of processor units this partition can ever have */
- int min_proc_capacity; /* minimum number of processor units this partition must have */
- int proc_capacity_increment; /* increment value to the entitled capacity */
- int unalloc_proc_capacity; /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
- int var_proc_capacity_weight; /* partition priority weight to receive extra capacity */
- int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated in the shared processor pool this partition belongs to */
- int online_phys_cpus_sys; /* number of physical CPUs currently active in the system containing this partition */
- int max_phys_cpus_sys; /* maximum possible number of physical CPUs in the system containing this partition */
- int phys_cpus_pool; /* number of the physical CPUs currently in the shared processor pool this partition belong to */
- u_longlong_t puser; /* raw number of physical processor tics in user mode */
- u_longlong_t psys; /* raw number of physical processor tics in system mode */
- u_longlong_t pidle; /* raw number of physical processor tics idle */
- u_longlong_t pwait; /* raw number of physical processor tics waiting for I/O */
- u_longlong_t pool_idle_time; /* number of clock tics a processor in the shared pool was idle */
- u_longlong_t phantintrs; /* number of phantom interrupts received by the partition */
- u_longlong_t invol_virt_cswitch; /* number involuntary virtual CPU context switches */
- u_longlong_t vol_virt_cswitch; /* number voluntary virtual CPU context switches */
- u_longlong_t timebase_last; /* most recently cpu time base */
- u_longlong_t reserved_pages; /* Currently number of 16GB pages. Cannot participate in DR operations */
- u_longlong_t reserved_pagesize; /* Currently 16GB pagesize Cannot participate in DR operations */
-} perfstat_partition_total_t_53_5;
-
-typedef struct { /* partition total information AIX 5.3 < TL10 */
- char name[IDENTIFIER_LENGTH]; /* name of the logical partition */
- perfstat_partition_type_t type; /* set of bits describing the partition */
- int lpar_id; /* logical partition identifier */
- int group_id; /* identifier of the LPAR group this partition is a member of */
- int pool_id; /* identifier of the shared pool of physical processors this partition is a member of */
- int online_cpus; /* number of virtual CPUs currently online on the partition */
- int max_cpus; /* maximum number of virtual CPUs this partition can ever have */
- int min_cpus; /* minimum number of virtual CPUs this partition must have */
- u_longlong_t online_memory; /* amount of memory currently online */
- u_longlong_t max_memory; /* maximum amount of memory this partition can ever have */
- u_longlong_t min_memory; /* minimum amount of memory this partition must have */
- int entitled_proc_capacity; /* number of processor units this partition is entitled to receive */
- int max_proc_capacity; /* maximum number of processor units this partition can ever have */
- int min_proc_capacity; /* minimum number of processor units this partition must have */
- int proc_capacity_increment; /* increment value to the entitled capacity */
- int unalloc_proc_capacity; /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
- int var_proc_capacity_weight; /* partition priority weight to receive extra capacity */
- int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated in the shared processor pool this partition belongs to */
- int online_phys_cpus_sys; /* number of physical CPUs currently active in the system containing this partition */
- int max_phys_cpus_sys; /* maximum possible number of physical CPUs in the system containing this partition */
- int phys_cpus_pool; /* number of the physical CPUs currently in the shared processor pool this partition belong to */
- u_longlong_t puser; /* raw number of physical processor tics in user mode */
- u_longlong_t psys; /* raw number of physical processor tics in system mode */
- u_longlong_t pidle; /* raw number of physical processor tics idle */
- u_longlong_t pwait; /* raw number of physical processor tics waiting for I/O */
- u_longlong_t pool_idle_time; /* number of clock tics a processor in the shared pool was idle */
- u_longlong_t phantintrs; /* number of phantom interrupts received by the partition */
- u_longlong_t invol_virt_cswitch; /* number involuntary virtual CPU context switches */
- u_longlong_t vol_virt_cswitch; /* number voluntary virtual CPU context switches */
- u_longlong_t timebase_last; /* most recently cpu time base */
- u_longlong_t reserved_pages; /* Currently number of 16GB pages. Cannot participate in DR operations */
- u_longlong_t reserved_pagesize; /* Currently 16GB pagesize Cannot participate in DR operations */
- u_longlong_t idle_donated_purr; /* number of idle cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_donated_spurr; /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_purr; /* number of busy cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_spurr; /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_stolen_purr; /* number of idle cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t idle_stolen_spurr; /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_purr; /* number of busy cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_spurr; /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t shcpus_in_sys; /* Number of physical processors allocated for shared processor use */
- u_longlong_t max_pool_capacity; /* Maximum processor capacity of partitions pool */
- u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partitions pool */
- u_longlong_t pool_max_time; /* Summation of maximum time that could be consumed by the pool (nano seconds) */
- u_longlong_t pool_busy_time; /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
- u_longlong_t pool_scaled_busy_time; /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
- u_longlong_t shcpu_tot_time; /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
- u_longlong_t shcpu_busy_time; /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
- u_longlong_t shcpu_scaled_busy_time; /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
- int ams_pool_id; /* AMS pool id of the pool the LPAR belongs to */
- int var_mem_weight; /* variable memory capacity weight */
- u_longlong_t iome; /* I/O memory entitlement of the partition in bytes*/
- u_longlong_t pmem; /* Physical memory currently backing the partition's logical memory in bytes*/
- u_longlong_t hpi; /* number of hypervisor page-ins */
- u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds)*/
- u_longlong_t hypv_pagesize; /* Hypervisor page size in KB*/
-} perfstat_partition_total_t_53;
-
-typedef struct { /* partition total information AIX 6.1|5.3 > TL09 */
- char name[IDENTIFIER_LENGTH]; /* name of the logical partition */
- perfstat_partition_type_t type; /* set of bits describing the partition */
- int lpar_id; /* logical partition identifier */
- int group_id; /* identifier of the LPAR group this partition is a member of */
- int pool_id; /* identifier of the shared pool of physical processors this partition is a member of */
- int online_cpus; /* number of virtual CPUs currently online on the partition */
- int max_cpus; /* maximum number of virtual CPUs this partition can ever have */
- int min_cpus; /* minimum number of virtual CPUs this partition must have */
- u_longlong_t online_memory; /* amount of memory currently online */
- u_longlong_t max_memory; /* maximum amount of memory this partition can ever have */
- u_longlong_t min_memory; /* minimum amount of memory this partition must have */
- int entitled_proc_capacity; /* number of processor units this partition is entitled to receive */
- int max_proc_capacity; /* maximum number of processor units this partition can ever have */
- int min_proc_capacity; /* minimum number of processor units this partition must have */
- int proc_capacity_increment; /* increment value to the entitled capacity */
- int unalloc_proc_capacity; /* number of processor units currently unallocated in the shared processor pool this partition belongs to */
- int var_proc_capacity_weight; /* partition priority weight to receive extra capacity */
- int unalloc_var_proc_capacity_weight; /* number of variable processor capacity weight units currently unallocated in the shared processor pool this partition belongs to */
- int online_phys_cpus_sys; /* number of physical CPUs currently active in the system containing this partition */
- int max_phys_cpus_sys; /* maximum possible number of physical CPUs in the system containing this partition */
- int phys_cpus_pool; /* number of the physical CPUs currently in the shared processor pool this partition belong to */
- u_longlong_t puser; /* raw number of physical processor tics in user mode */
- u_longlong_t psys; /* raw number of physical processor tics in system mode */
- u_longlong_t pidle; /* raw number of physical processor tics idle */
- u_longlong_t pwait; /* raw number of physical processor tics waiting for I/O */
- u_longlong_t pool_idle_time; /* number of clock tics a processor in the shared pool was idle */
- u_longlong_t phantintrs; /* number of phantom interrupts received by the partition */
- u_longlong_t invol_virt_cswitch; /* number involuntary virtual CPU context switches */
- u_longlong_t vol_virt_cswitch; /* number voluntary virtual CPU context switches */
- u_longlong_t timebase_last; /* most recently cpu time base */
- u_longlong_t reserved_pages; /* Currently number of 16GB pages. Cannot participate in DR operations */
- u_longlong_t reserved_pagesize; /* Currently 16GB pagesize Cannot participate in DR operations */
- u_longlong_t idle_donated_purr; /* number of idle cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_donated_spurr; /* number of idle spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_purr; /* number of busy cycles donated by a dedicated partition enabled for donation */
- u_longlong_t busy_donated_spurr; /* number of busy spurr cycles donated by a dedicated partition enabled for donation */
- u_longlong_t idle_stolen_purr; /* number of idle cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t idle_stolen_spurr; /* number of idle spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_purr; /* number of busy cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t busy_stolen_spurr; /* number of busy spurr cycles stolen by the hypervisor from a dedicated partition */
- u_longlong_t shcpus_in_sys; /* Number of physical processors allocated for shared processor use */
- u_longlong_t max_pool_capacity; /* Maximum processor capacity of partitions pool */
- u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partitions pool */
- u_longlong_t pool_max_time; /* Summation of maximum time that could be consumed by the pool (nano seconds) */
- u_longlong_t pool_busy_time; /* Summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
- u_longlong_t pool_scaled_busy_time; /* Scaled summation of busy (non-idle) time accumulated across all partitions in the pool (nano seconds) */
- u_longlong_t shcpu_tot_time; /* Summation of total time across all physical processors allocated for shared processor use (nano seconds) */
- u_longlong_t shcpu_busy_time; /* Summation of busy (non-idle) time accumulated across all shared processor partitions (nano seconds) */
- u_longlong_t shcpu_scaled_busy_time; /* Scaled summation of busy time accumulated across all shared processor partitions (nano seconds) */
- int ams_pool_id; /* AMS pool id of the pool the LPAR belongs to */
- int var_mem_weight; /* variable memory capacity weight */
- u_longlong_t iome; /* I/O memory entitlement of the partition in bytes*/
- u_longlong_t pmem; /* Physical memory currently backing the partition's logical memory in bytes*/
- u_longlong_t hpi; /* number of hypervisor page-ins */
- u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds)*/
- u_longlong_t hypv_pagesize; /* Hypervisor page size in KB*/
- uint online_lcpus; /* number of online logical cpus */
- uint smt_thrds; /* number of hardware threads that are running */
- u_longlong_t puser_spurr; /* number of spurr cycles spent in user mode */
- u_longlong_t psys_spurr; /* number of spurr cycles spent in kernel mode */
- u_longlong_t pidle_spurr; /* number of spurr cycles spent in idle mode */
- u_longlong_t pwait_spurr; /* number of spurr cycles spent in wait mode */
- int spurrflag; /* set if running in spurr mode */
-} perfstat_partition_total_t_61;
-
typedef struct { /* partition total information AIX 7.1 */
char name[IDENTIFIER_LENGTH]; /* name of the logical partition */
perfstat_partition_type_t type; /* set of bits describing the partition */
@@ -941,17 +610,6 @@ typedef union { /* WPAR Type & Flags */
} b;
} perfstat_wpar_type_t;
-typedef struct { /* Workload partition Information AIX 5.3 & 6.1*/
- char name[MAXCORRALNAMELEN+1]; /* name of the Workload Partition */
- perfstat_wpar_type_t type; /* set of bits describing the wpar */
- cid_t wpar_id; /* workload partition identifier */
- uint online_cpus; /* Number of Virtual CPUs in partition rset or number of virtual CPUs currently online on the Global partition*/
- int cpu_limit; /* CPU limit in 100ths of % - 1..10000 */
- int mem_limit; /* Memory limit in 100ths of % - 1..10000 */
- u_longlong_t online_memory; /* amount of memory currently online in Global Partition */
- int entitled_proc_capacity; /* number of processor units this partition is entitled to receive */
-} perfstat_wpar_total_t_61;
-
typedef struct { /* Workload partition Information AIX 7.1*/
char name[MAXCORRALNAMELEN+1]; /* name of the Workload Partition */
perfstat_wpar_type_t type; /* set of bits describing the wpar */
@@ -983,7 +641,7 @@ typedef struct { /* WPAR identifier */
-// end: libperfstat.h (AIX 5.2, 5.3, 6.1, 7.1)
+// end: libperfstat.h (AIX 7.1)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1 /* latest perfstat_partition_total_t structure */
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index adaab8914a7fc..f6312f2f88206 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -29,7 +29,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
@@ -117,6 +116,10 @@
#include
#include
+#ifndef _LARGE_FILES
+#error Hotspot on AIX must be compiled with -D_LARGE_FILES
+#endif
+
// Missing prototypes for various system APIs.
extern "C"
int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t);
@@ -273,6 +276,22 @@ julong os::Aix::available_memory() {
}
}
+jlong os::total_swap_space() {
+ perfstat_memory_total_t memory_info;
+ if (libperfstat::perfstat_memory_total(nullptr, &memory_info, sizeof(perfstat_memory_total_t), 1) == -1) {
+ return -1;
+ }
+ return (jlong)(memory_info.pgsp_total * 4 * K);
+}
+
+jlong os::free_swap_space() {
+ perfstat_memory_total_t memory_info;
+ if (libperfstat::perfstat_memory_total(nullptr, &memory_info, sizeof(perfstat_memory_total_t), 1) == -1) {
+ return -1;
+ }
+ return (jlong)(memory_info.pgsp_free * 4 * K);
+}
+
julong os::physical_memory() {
return Aix::physical_memory();
}
@@ -1108,10 +1127,9 @@ bool os::dll_address_to_library_name(address addr, char* buf,
return true;
}
-void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+static void* dll_load_library(const char *filename, char *ebuf, int ebuflen) {
log_info(os)("attempting shared library load of %s", filename);
-
if (ebuf && ebuflen > 0) {
ebuf[0] = '\0';
ebuf[ebuflen - 1] = '\0';
@@ -1159,6 +1177,26 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
return nullptr;
}
+// Load library named
+// If filename matches .so, and loading fails, repeat with .a.
+void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+ void* result = nullptr;
+ char* const file_path = strdup(filename);
+ char* const pointer_to_dot = strrchr(file_path, '.');
+ const char old_extension[] = ".so";
+ const char new_extension[] = ".a";
+ STATIC_ASSERT(sizeof(old_extension) >= sizeof(new_extension));
+ // First try to load the existing file.
+ result = dll_load_library(filename, ebuf, ebuflen);
+ // If the load fails,we try to reload by changing the extension to .a for .so files only.
+ // Shared object in .so format dont have braces, hence they get removed for archives with members.
+ if (result == nullptr && pointer_to_dot != nullptr && strcmp(pointer_to_dot, old_extension) == 0) {
+ snprintf(pointer_to_dot, sizeof(old_extension), "%s", new_extension);
+ result = dll_load_library(file_path, ebuf, ebuflen);
+ }
+ FREE_C_HEAP_ARRAY(char, file_path);
+ return result;
+}
void os::print_dll_info(outputStream *st) {
st->print_cr("Dynamic libraries:");
@@ -1584,7 +1622,7 @@ static char* reserve_shmated_memory (size_t bytes, char* requested_addr) {
// Now attach the shared segment.
// Note that we deliberately *don't* pass SHM_RND. The contract of os::attempt_reserve_memory_at() -
- // which invokes this function with a request address != NULL - is to map at the specified address
+ // which invokes this function with a request address != nullptr - is to map at the specified address
// excactly, or to fail. If the caller passed us an address that is not usable (aka not a valid segment
// boundary), shmat should not round down the address, or think up a completely new one.
// (In places where this matters, e.g. when reserving the heap, we take care of passing segment-aligned
@@ -1886,6 +1924,10 @@ void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
}
+size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) {
+ return page_size;
+}
+
void os::numa_make_global(char *addr, size_t bytes) {
}
@@ -2506,10 +2548,10 @@ int os::open(const char *path, int oflag, int mode) {
// IV90804: OPENING A FILE IN AFS WITH O_CLOEXEC FAILS WITH AN EINVAL ERROR APPLIES TO AIX 7100-04 17/04/14 PTF PECHANGE
int oflag_with_o_cloexec = oflag | O_CLOEXEC;
- int fd = ::open64(path, oflag_with_o_cloexec, mode);
+ int fd = ::open(path, oflag_with_o_cloexec, mode);
if (fd == -1) {
// we might fail in the open call when O_CLOEXEC is set, so try again without (see IV90804)
- fd = ::open64(path, oflag, mode);
+ fd = ::open(path, oflag, mode);
if (fd == -1) {
return -1;
}
@@ -2517,8 +2559,8 @@ int os::open(const char *path, int oflag, int mode) {
// If the open succeeded, the file might still be a directory.
{
- struct stat64 buf64;
- int ret = ::fstat64(fd, &buf64);
+ struct stat buf64;
+ int ret = ::fstat(fd, &buf64);
int st_mode = buf64.st_mode;
if (ret != -1) {
@@ -2572,67 +2614,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);
-}
-
-// Map a block of memory.
-char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- int prot;
- int flags = MAP_PRIVATE;
-
- if (read_only) {
- prot = PROT_READ;
- flags = MAP_SHARED;
- } else {
- prot = PROT_READ | PROT_WRITE;
- flags = MAP_PRIVATE;
- }
-
- if (allow_exec) {
- prot |= PROT_EXEC;
- }
-
- if (addr != nullptr) {
- flags |= MAP_FIXED;
- }
-
- // Allow anonymous mappings if 'fd' is -1.
- if (fd == -1) {
- flags |= MAP_ANONYMOUS;
- }
-
- char* mapped_address = (char*)::mmap(addr, (size_t)bytes, prot, flags,
- fd, file_offset);
- if (mapped_address == MAP_FAILED) {
- return nullptr;
- }
- return mapped_address;
-}
-
-// Remap a block of memory.
-char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- // same as map_memory() on this OS
- return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
- allow_exec);
-}
-
-// Unmap a block of memory.
-bool os::pd_unmap_memory(char* addr, size_t bytes) {
- return munmap(addr, bytes) == 0;
+ return (jlong)::lseek(fd, (off_t)offset, SEEK_SET);
}
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
@@ -3027,4 +3019,3 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
void os::jfr_report_memory_info() {}
#endif // INCLUDE_JFR
-
diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp
index e1719df48c331..b5ae1a6a725a5 100644
--- a/src/hotspot/os/aix/os_perf_aix.cpp
+++ b/src/hotspot/os/aix/os_perf_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2022, IBM Corp.
+ * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,7 @@ static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) {
}
len = fread(&psinfo, 1, sizeof(psinfo_t), fp);
+ fclose(fp);
return len == sizeof(psinfo_t);
}
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 958372e20a5ce..86d81a59f0d58 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -24,7 +24,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
@@ -181,6 +180,32 @@ void os::Bsd::print_uptime_info(outputStream* st) {
}
}
+jlong os::total_swap_space() {
+#if defined(__APPLE__)
+ struct xsw_usage vmusage;
+ size_t size = sizeof(vmusage);
+ if (sysctlbyname("vm.swapusage", &vmusage, &size, nullptr, 0) != 0) {
+ return -1;
+ }
+ return (jlong)vmusage.xsu_total;
+#else
+ return -1;
+#endif
+}
+
+jlong os::free_swap_space() {
+#if defined(__APPLE__)
+ struct xsw_usage vmusage;
+ size_t size = sizeof(vmusage);
+ if (sysctlbyname("vm.swapusage", &vmusage, &size, nullptr, 0) != 0) {
+ return -1;
+ }
+ return (jlong)vmusage.xsu_avail;
+#else
+ return -1;
+#endif
+}
+
julong os::physical_memory() {
return Bsd::physical_memory();
}
@@ -985,6 +1010,13 @@ void *os::Bsd::dlopen_helper(const char *filename, int mode, char *ebuf, int ebu
if (!ieee_handling) {
Events::log_dll_message(nullptr, "IEEE subnormal handling check failed before loading %s", filename);
log_info(os)("IEEE subnormal handling check failed before loading %s", filename);
+ if (CheckJNICalls) {
+ tty->print_cr("WARNING: IEEE subnormal handling check failed before loading %s", filename);
+ Thread* current = Thread::current();
+ if (current->is_Java_thread()) {
+ JavaThread::cast(current)->print_jni_stack();
+ }
+ }
}
// Save and restore the floating-point environment around dlopen().
@@ -1038,6 +1070,13 @@ void *os::Bsd::dlopen_helper(const char *filename, int mode, char *ebuf, int ebu
} else {
Events::log_dll_message(nullptr, "IEEE subnormal handling could not be corrected after loading %s", filename);
log_info(os)("IEEE subnormal handling could not be corrected after loading %s", filename);
+ if (CheckJNICalls) {
+ tty->print_cr("WARNING: IEEE subnormal handling could not be corrected after loading %s", filename);
+ Thread* current = Thread::current();
+ if (current->is_Java_thread()) {
+ JavaThread::cast(current)->print_jni_stack();
+ }
+ }
assert(false, "fesetenv didn't work");
}
}
@@ -1229,7 +1268,8 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
#endif // !__APPLE__
-int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+static int _print_dll_info_cb(const char * name, address base_address,
+ address top_address, void * param) {
outputStream * out = (outputStream *) param;
out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name);
return 0;
@@ -1623,6 +1663,10 @@ void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
::madvise(addr, bytes, MADV_DONTNEED);
}
+size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) {
+ return page_size;
+}
+
void os::numa_make_global(char *addr, size_t bytes) {
}
@@ -2301,53 +2345,6 @@ jlong os::seek_to_file_offset(int fd, jlong offset) {
return (jlong)::lseek(fd, (off_t)offset, SEEK_SET);
}
-// Map a block of memory.
-char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- int prot;
- int flags;
-
- if (read_only) {
- prot = PROT_READ;
- flags = MAP_SHARED;
- } else {
- prot = PROT_READ | PROT_WRITE;
- flags = MAP_PRIVATE;
- }
-
- if (allow_exec) {
- prot |= PROT_EXEC;
- }
-
- if (addr != nullptr) {
- flags |= MAP_FIXED;
- }
-
- char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
- fd, file_offset);
- if (mapped_address == MAP_FAILED) {
- return nullptr;
- }
- return mapped_address;
-}
-
-
-// Remap a block of memory.
-char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- // same as map_memory() on this OS
- return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
- allow_exec);
-}
-
-
-// Unmap a block of memory.
-bool os::pd_unmap_memory(char* addr, size_t bytes) {
- return munmap(addr, bytes) == 0;
-}
-
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
// are used by JVM M&M and JVMTI to get user+sys or user CPU time
// of a thread.
diff --git a/src/hotspot/os/linux/attachListener_linux.cpp b/src/hotspot/os/linux/attachListener_linux.cpp
index 41a24c450073f..0e98bca06078d 100644
--- a/src/hotspot/os/linux/attachListener_linux.cpp
+++ b/src/hotspot/os/linux/attachListener_linux.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, 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
@@ -184,6 +184,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;
@@ -446,14 +448,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) {
@@ -473,8 +475,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());
@@ -513,14 +515,14 @@ bool AttachListener::is_init_trigger() {
}
char fn[PATH_MAX + 1];
int ret;
- struct stat64 st;
+ struct stat st;
os::snprintf_checked(fn, sizeof(fn), ".attach_pid%d", os::current_process_id());
- RESTARTABLE(::stat64(fn, &st), ret);
+ 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/globals_linux.hpp b/src/hotspot/os/linux/globals_linux.hpp
index 577776e9d7e7b..8e4289c7ee3a2 100644
--- a/src/hotspot/os/linux/globals_linux.hpp
+++ b/src/hotspot/os/linux/globals_linux.hpp
@@ -92,7 +92,9 @@
develop(bool, DelayThreadStartALot, false, \
"Artificially delay thread starts randomly for testing.") \
\
-
+ product(bool, UseMadvPopulateWrite, true, DIAGNOSTIC, \
+ "Use MADV_POPULATE_WRITE in os::pd_pretouch_memory.") \
+ \
// end of RUNTIME_OS_FLAGS
diff --git a/src/hotspot/os/linux/hugepages.cpp b/src/hotspot/os/linux/hugepages.cpp
index 67645b91aa566..b71593487cf8a 100644
--- a/src/hotspot/os/linux/hugepages.cpp
+++ b/src/hotspot/os/linux/hugepages.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2023, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2024, 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
@@ -36,15 +36,15 @@
#include
-StaticHugePageSupport::StaticHugePageSupport() :
+ExplicitHugePageSupport::ExplicitHugePageSupport() :
_initialized(false), _pagesizes(), _default_hugepage_size(SIZE_MAX), _inconsistent(false) {}
-os::PageSizes StaticHugePageSupport::pagesizes() const {
+os::PageSizes ExplicitHugePageSupport::pagesizes() const {
assert(_initialized, "Not initialized");
return _pagesizes;
}
-size_t StaticHugePageSupport::default_hugepage_size() const {
+size_t ExplicitHugePageSupport::default_hugepage_size() const {
assert(_initialized, "Not initialized");
return _default_hugepage_size;
}
@@ -132,9 +132,9 @@ static os::PageSizes scan_hugepages() {
return pagesizes;
}
-void StaticHugePageSupport::print_on(outputStream* os) {
+void ExplicitHugePageSupport::print_on(outputStream* os) {
if (_initialized) {
- os->print_cr("Static hugepage support:");
+ os->print_cr("Explicit hugepage support:");
for (size_t s = _pagesizes.smallest(); s != 0; s = _pagesizes.next_larger(s)) {
os->print_cr(" hugepage size: " EXACTFMT, EXACTFMTARGS(s));
}
@@ -143,18 +143,18 @@ void StaticHugePageSupport::print_on(outputStream* os) {
os->print_cr(" unknown.");
}
if (_inconsistent) {
- os->print_cr(" Support inconsistent. JVM will not use static hugepages.");
+ os->print_cr(" Support inconsistent. JVM will not use explicit hugepages.");
}
}
-void StaticHugePageSupport::scan_os() {
+void ExplicitHugePageSupport::scan_os() {
_default_hugepage_size = scan_default_hugepagesize();
if (_default_hugepage_size > 0) {
_pagesizes = scan_hugepages();
// See https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt: /proc/meminfo should match
// /sys/kernel/mm/hugepages/hugepages-xxxx. However, we may run on a broken kernel (e.g. on WSL)
// that only exposes /proc/meminfo but not /sys/kernel/mm/hugepages. In that case, we are not
- // sure about the state of hugepage support by the kernel, so we won't use static hugepages.
+ // sure about the state of hugepage support by the kernel, so we won't use explicit hugepages.
if (!_pagesizes.contains(_default_hugepage_size)) {
log_info(pagesize)("Unexpected configuration: default pagesize (" SIZE_FORMAT ") "
"has no associated directory in /sys/kernel/mm/hugepages..", _default_hugepage_size);
@@ -307,18 +307,31 @@ void ShmemTHPSupport::print_on(outputStream* os) {
}
}
-StaticHugePageSupport HugePages::_static_hugepage_support;
+ExplicitHugePageSupport HugePages::_explicit_hugepage_support;
THPSupport HugePages::_thp_support;
ShmemTHPSupport HugePages::_shmem_thp_support;
+size_t HugePages::thp_pagesize_fallback() {
+ // Older kernels won't publish the THP page size. Fall back to default explicit huge page size,
+ // since that is likely to be the THP page size as well. Don't do it if the page size is considered
+ // too large to avoid large alignment waste. If explicit huge page size is unknown, use educated guess.
+ if (thp_pagesize() != 0) {
+ return thp_pagesize();
+ }
+ if (supports_explicit_hugepages()) {
+ return MIN2(default_explicit_hugepage_size(), 16 * M);
+ }
+ return 2 * M;
+}
+
void HugePages::initialize() {
- _static_hugepage_support.scan_os();
+ _explicit_hugepage_support.scan_os();
_thp_support.scan_os();
_shmem_thp_support.scan_os();
}
void HugePages::print_on(outputStream* os) {
- _static_hugepage_support.print_on(os);
+ _explicit_hugepage_support.print_on(os);
_thp_support.print_on(os);
_shmem_thp_support.print_on(os);
}
diff --git a/src/hotspot/os/linux/hugepages.hpp b/src/hotspot/os/linux/hugepages.hpp
index ce9ab36edccf8..efd27c55fd60f 100644
--- a/src/hotspot/os/linux/hugepages.hpp
+++ b/src/hotspot/os/linux/hugepages.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2023, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2024, 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
@@ -34,13 +34,13 @@ class outputStream;
// Header contains the interface that reads OS information about
// available hugepage support:
-// - class StaticHugePageSupport - about static (non-THP) hugepages
+// - class ExplicitHugePageSupport - about explicit (non-THP) hugepages
// - class THPSupport - about transparent huge pages
// and:
// - class HugePages - a static umbrella wrapper
// Information about static (non-thp) hugepages
-class StaticHugePageSupport {
+class ExplicitHugePageSupport {
bool _initialized;
// All supported hugepage sizes (sizes for which entries exist
@@ -56,7 +56,7 @@ class StaticHugePageSupport {
bool _inconsistent;
public:
- StaticHugePageSupport();
+ ExplicitHugePageSupport();
void scan_os();
@@ -122,22 +122,23 @@ class ShmemTHPSupport {
// Umbrella static interface
class HugePages : public AllStatic {
- static StaticHugePageSupport _static_hugepage_support;
+ static ExplicitHugePageSupport _explicit_hugepage_support;
static THPSupport _thp_support;
static ShmemTHPSupport _shmem_thp_support;
public:
- static const StaticHugePageSupport& static_info() { return _static_hugepage_support; }
+ static const ExplicitHugePageSupport& explicit_hugepage_info() { return _explicit_hugepage_support; }
static const THPSupport& thp_info() { return _thp_support; }
static const ShmemTHPSupport& shmem_thp_info() { return _shmem_thp_support; }
- static size_t default_static_hugepage_size() { return _static_hugepage_support.default_hugepage_size(); }
- static bool supports_static_hugepages() { return default_static_hugepage_size() > 0 && !_static_hugepage_support.inconsistent(); }
+ static size_t default_explicit_hugepage_size() { return _explicit_hugepage_support.default_hugepage_size(); }
+ static bool supports_explicit_hugepages() { return default_explicit_hugepage_size() > 0 && !_explicit_hugepage_support.inconsistent(); }
static bool supports_thp() { return thp_mode() == THPMode::madvise || thp_mode() == THPMode::always; }
static THPMode thp_mode() { return _thp_support.mode(); }
static size_t thp_pagesize() { return _thp_support.pagesize(); }
+ static size_t thp_pagesize_fallback();
static bool supports_shmem_thp() { return _shmem_thp_support.is_enabled(); }
static ShmemTHPMode shmem_thp_mode() { return _shmem_thp_support.mode(); }
diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp
index 14bfa5a7678d4..cd723228a75e5 100644
--- a/src/hotspot/os/linux/osContainer_linux.cpp
+++ b/src/hotspot/os/linux/osContainer_linux.cpp
@@ -149,7 +149,7 @@ jlong OSContainer::pids_current() {
void OSContainer::print_container_helper(outputStream* st, jlong j, const char* metrics) {
st->print("%s: ", metrics);
- if (j > 0) {
+ if (j >= 0) {
if (j >= 1024) {
st->print_cr(UINT64_FORMAT " k", uint64_t(j) / K);
} else {
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 65574294b4099..119f98c687432 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
@@ -86,6 +85,8 @@
#endif
// put OS-includes here
+# include
+# include
# include
# include
# include
@@ -289,6 +290,34 @@ julong os::Linux::free_memory() {
return free_mem;
}
+jlong os::total_swap_space() {
+ if (OSContainer::is_containerized()) {
+ if (OSContainer::memory_limit_in_bytes() > 0) {
+ return (jlong)(OSContainer::memory_and_swap_limit_in_bytes() - OSContainer::memory_limit_in_bytes());
+ }
+ }
+ struct sysinfo si;
+ int ret = sysinfo(&si);
+ if (ret != 0) {
+ return -1;
+ }
+ return (jlong)(si.totalswap * si.mem_unit);
+}
+
+jlong os::free_swap_space() {
+ if (OSContainer::is_containerized()) {
+ // TODO add a good implementation
+ return -1;
+ } else {
+ struct sysinfo si;
+ int ret = sysinfo(&si);
+ if (ret != 0) {
+ return -1;
+ }
+ return (jlong)(si.freeswap * si.mem_unit);
+ }
+}
+
julong os::physical_memory() {
jlong phys_mem = 0;
if (OSContainer::is_containerized()) {
@@ -315,6 +344,29 @@ static void next_line(FILE *f) {
} while (c != '\n' && c != EOF);
}
+void os::Linux::kernel_version(long* major, long* minor) {
+ *major = -1;
+ *minor = -1;
+
+ struct utsname buffer;
+ int ret = uname(&buffer);
+ if (ret != 0) {
+ log_warning(os)("uname(2) failed to get kernel version: %s", os::errno_name(ret));
+ return;
+ }
+
+ char* walker = buffer.release;
+ long* set_v = major;
+ while (*minor == -1 && walker != nullptr) {
+ if (isdigit(walker[0])) {
+ *set_v = strtol(walker, &walker, 10);
+ set_v = minor;
+ } else {
+ ++walker;
+ }
+ }
+}
+
bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu) {
FILE* fh;
uint64_t userTicks, niceTicks, systemTicks, idleTicks;
@@ -417,7 +469,7 @@ pid_t os::Linux::gettid() {
julong os::Linux::host_swap() {
struct sysinfo si;
sysinfo(&si);
- return (julong)si.totalswap;
+ return (julong)(si.totalswap * si.mem_unit);
}
// Most versions of linux have a bug where the number of processors are
@@ -1813,6 +1865,13 @@ void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
if (!ieee_handling) {
Events::log_dll_message(nullptr, "IEEE subnormal handling check failed before loading %s", filename);
log_info(os)("IEEE subnormal handling check failed before loading %s", filename);
+ if (CheckJNICalls) {
+ tty->print_cr("WARNING: IEEE subnormal handling check failed before loading %s", filename);
+ Thread* current = Thread::current();
+ if (current->is_Java_thread()) {
+ JavaThread::cast(current)->print_jni_stack();
+ }
+ }
}
// Save and restore the floating-point environment around dlopen().
@@ -1867,6 +1926,13 @@ void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
} else {
Events::log_dll_message(nullptr, "IEEE subnormal handling could not be corrected after loading %s", filename);
log_info(os)("IEEE subnormal handling could not be corrected after loading %s", filename);
+ if (CheckJNICalls) {
+ tty->print_cr("WARNING: IEEE subnormal handling could not be corrected after loading %s", filename);
+ Thread* current = Thread::current();
+ if (current->is_Java_thread()) {
+ JavaThread::cast(current)->print_jni_stack();
+ }
+ }
assert(false, "fesetenv didn't work");
}
}
@@ -2204,6 +2270,8 @@ void os::Linux::print_proc_sys_info(outputStream* st) {
"/proc/sys/kernel/threads-max", st);
_print_ascii_file_h("/proc/sys/vm/max_map_count (maximum number of memory map areas a process may have)",
"/proc/sys/vm/max_map_count", st);
+ _print_ascii_file_h("/proc/sys/vm/swappiness (control to define how aggressively the kernel swaps out anonymous memory)",
+ "/proc/sys/vm/swappiness", st);
_print_ascii_file_h("/proc/sys/kernel/pid_max (system-wide limit on number of process identifiers)",
"/proc/sys/kernel/pid_max", st);
}
@@ -2758,6 +2826,8 @@ void os::jvm_path(char *buf, jint buflen) {
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;
}
@@ -2882,6 +2952,15 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
#define MADV_HUGEPAGE 14
#endif
+// Define MADV_POPULATE_WRITE here so we can build HotSpot on old systems.
+#define MADV_POPULATE_WRITE_value 23
+#ifndef MADV_POPULATE_WRITE
+ #define MADV_POPULATE_WRITE MADV_POPULATE_WRITE_value
+#else
+ // Sanity-check our assumed default value if we build with a new enough libc.
+ static_assert(MADV_POPULATE_WRITE == MADV_POPULATE_WRITE_value);
+#endif
+
// Note that the value for MAP_FIXED_NOREPLACE differs between architectures, but all architectures
// supported by OpenJDK share the same flag value.
#define MAP_FIXED_NOREPLACE_value 0x100000
@@ -2941,6 +3020,31 @@ void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
}
}
+size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) {
+ const size_t len = pointer_delta(last, first, sizeof(char)) + page_size;
+ // Use madvise to pretouch on Linux when THP is used, and fallback to the
+ // common method if unsupported. THP can form right after madvise rather than
+ // being assembled later.
+ if (HugePages::thp_mode() == THPMode::always || UseTransparentHugePages) {
+ int err = 0;
+ if (UseMadvPopulateWrite &&
+ ::madvise(first, len, MADV_POPULATE_WRITE) == -1) {
+ err = errno;
+ }
+ if (!UseMadvPopulateWrite || err == EINVAL) { // Not to use or not supported
+ // When using THP we need to always pre-touch using small pages as the
+ // OS will initially always use small pages.
+ return os::vm_page_size();
+ } else if (err != 0) {
+ log_info(gc, os)("::madvise(" PTR_FORMAT ", " SIZE_FORMAT ", %d) failed; "
+ "error='%s' (errno=%d)", p2i(first), len,
+ MADV_POPULATE_WRITE, os::strerror(err), err);
+ }
+ return 0;
+ }
+ return page_size;
+}
+
void os::numa_make_global(char *addr, size_t bytes) {
Linux::numa_interleave_memory(addr, bytes);
}
@@ -3660,14 +3764,14 @@ bool os::unguard_memory(char* addr, size_t size) {
}
static int hugetlbfs_page_size_flag(size_t page_size) {
- if (page_size != HugePages::default_static_hugepage_size()) {
+ if (page_size != HugePages::default_explicit_hugepage_size()) {
return (exact_log2(page_size) << MAP_HUGE_SHIFT);
}
return 0;
}
static bool hugetlbfs_sanity_check(size_t page_size) {
- const os::PageSizes page_sizes = HugePages::static_info().pagesizes();
+ const os::PageSizes page_sizes = HugePages::explicit_hugepage_info().pagesizes();
assert(page_sizes.contains(page_size), "Invalid page sizes passed");
// Include the page size flag to ensure we sanity check the correct page size.
@@ -3847,8 +3951,8 @@ void os::Linux::large_page_init() {
return;
}
- // Check if the OS supports static hugepages.
- if (!UseTransparentHugePages && !HugePages::supports_static_hugepages()) {
+ // Check if the OS supports explicit hugepages.
+ if (!UseTransparentHugePages && !HugePages::supports_explicit_hugepages()) {
warn_no_large_pages_configured();
UseLargePages = false;
return;
@@ -3858,8 +3962,12 @@ void os::Linux::large_page_init() {
// In THP mode:
// - os::large_page_size() is the *THP page size*
// - os::pagesizes() has two members, the THP page size and the system page size
- assert(HugePages::thp_pagesize() > 0, "Missing OS info");
_large_page_size = HugePages::thp_pagesize();
+ if (_large_page_size == 0) {
+ log_info(pagesize) ("Cannot determine THP page size (kernel < 4.10 ?)");
+ _large_page_size = HugePages::thp_pagesize_fallback();
+ log_info(pagesize) ("Assuming THP page size to be: " EXACTFMT " (heuristics)", EXACTFMTARGS(_large_page_size));
+ }
_page_sizes.add(_large_page_size);
_page_sizes.add(os::vm_page_size());
// +UseTransparentHugePages implies +UseLargePages
@@ -3867,12 +3975,12 @@ void os::Linux::large_page_init() {
} else {
- // In static hugepage mode:
- // - os::large_page_size() is the default static hugepage size (/proc/meminfo "Hugepagesize")
+ // In explicit hugepage mode:
+ // - os::large_page_size() is the default explicit hugepage size (/proc/meminfo "Hugepagesize")
// - os::pagesizes() contains all hugepage sizes the kernel supports, regardless whether there
// are pages configured in the pool or not (from /sys/kernel/hugepages/hugepage-xxxx ...)
- os::PageSizes all_large_pages = HugePages::static_info().pagesizes();
- const size_t default_large_page_size = HugePages::default_static_hugepage_size();
+ os::PageSizes all_large_pages = HugePages::explicit_hugepage_info().pagesizes();
+ const size_t default_large_page_size = HugePages::default_explicit_hugepage_size();
// 3) Consistency check and post-processing
@@ -3956,7 +4064,7 @@ static bool commit_memory_special(size_t bytes,
char* req_addr,
bool exec) {
assert(UseLargePages, "Should only get here for huge pages");
- assert(!UseTransparentHugePages, "Should only get here for static hugepage mode");
+ assert(!UseTransparentHugePages, "Should only get here for explicit hugepage mode");
assert(is_aligned(bytes, page_size), "Unaligned size");
assert(is_aligned(req_addr, page_size), "Unaligned address");
assert(req_addr != nullptr, "Must have a requested address for special mappings");
@@ -3990,7 +4098,7 @@ static char* reserve_memory_special_huge_tlbfs(size_t bytes,
size_t page_size,
char* req_addr,
bool exec) {
- const os::PageSizes page_sizes = HugePages::static_info().pagesizes();
+ const os::PageSizes page_sizes = HugePages::explicit_hugepage_info().pagesizes();
assert(UseLargePages, "only for Huge TLBFS large pages");
assert(is_aligned(req_addr, alignment), "Must be");
assert(is_aligned(req_addr, page_size), "Must be");
@@ -4069,7 +4177,7 @@ size_t os::large_page_size() {
return _large_page_size;
}
-// static hugepages (hugetlbfs) allow application to commit large page memory
+// explicit hugepages (hugetlbfs) allow application to commit large page memory
// on demand.
// However, when committing memory with hugepages fails, the region
// that was supposed to be committed will lose the old reservation
@@ -4120,7 +4228,7 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool
size_t os::vm_min_address() {
// Determined by sysctl vm.mmap_min_addr. It exists as a safety zone to prevent
- // NULL pointer dereferences.
+ // null pointer dereferences.
// Most distros set this value to 64 KB. It *can* be zero, but rarely is. Here,
// we impose a minimum value if vm.mmap_min_addr is too low, for increased protection.
static size_t value = 0;
@@ -4248,7 +4356,7 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) {
// the number of bytes written to out_fd is returned if transfer was successful
// otherwise, returns -1 that implies an error
jlong os::Linux::sendfile(int out_fd, int in_fd, jlong* offset, jlong count) {
- return ::sendfile64(out_fd, in_fd, (off64_t*)offset, (size_t)count);
+ return ::sendfile(out_fd, in_fd, (off_t*)offset, (size_t)count);
}
// Determine if the vmid is the parent pid for a child in a PID namespace.
@@ -4363,6 +4471,9 @@ void os::init(void) {
check_pax();
+ // Check the availability of MADV_POPULATE_WRITE.
+ FLAG_SET_DEFAULT(UseMadvPopulateWrite, (::madvise(0, 0, MADV_POPULATE_WRITE) == 0));
+
os::Posix::init();
}
@@ -4926,14 +5037,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) {
@@ -4970,62 +5081,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);
-}
-
-// Map a block of memory.
-char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- int prot;
- int flags = MAP_PRIVATE;
-
- if (read_only) {
- prot = PROT_READ;
- } else {
- prot = PROT_READ | PROT_WRITE;
- }
-
- if (allow_exec) {
- prot |= PROT_EXEC;
- }
-
- if (addr != nullptr) {
- flags |= MAP_FIXED;
- }
-
- char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
- fd, file_offset);
- if (mapped_address == MAP_FAILED) {
- return nullptr;
- }
- return mapped_address;
-}
-
-
-// Remap a block of memory.
-char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- // same as map_memory() on this OS
- return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
- allow_exec);
-}
-
-
-// Unmap a block of memory.
-bool os::pd_unmap_memory(char* addr, size_t bytes) {
- return munmap(addr, bytes) == 0;
+ return (jlong)::lseek(fd, (off_t)offset, SEEK_SET);
}
static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time);
diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp
index 4b2ccf8e370db..6b902e8280244 100644
--- a/src/hotspot/os/linux/os_linux.hpp
+++ b/src/hotspot/os/linux/os_linux.hpp
@@ -93,6 +93,8 @@ class os::Linux {
bool has_steal_ticks;
};
+ static void kernel_version(long* major, long* minor);
+
// which_logical_cpu=-1 returns accumulated ticks for all cpus.
static bool get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu);
static bool _stack_is_executable;
diff --git a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
index 446449a40e094..892d825b40cdc 100644
--- a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
+++ b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "logging/log.hpp"
-#include "runtime/os.hpp"
+#include "os_linux.hpp"
#include "utilities/debug.hpp"
#include "utilities/systemMemoryBarrier.hpp"
@@ -61,6 +61,18 @@ static long membarrier(int cmd, unsigned int flags, int cpu_id) {
}
bool LinuxSystemMemoryBarrier::initialize() {
+#if defined(RISCV)
+// RISCV port was introduced in kernel 4.4.
+// 4.4 also made membar private expedited mandatory.
+// But RISCV actually don't support it until 6.9.
+ long major, minor;
+ os::Linux::kernel_version(&major, &minor);
+ if (!(major > 6 || (major == 6 && minor >= 9))) {
+ log_info(os)("Linux kernel %ld.%ld does not support MEMBARRIER PRIVATE_EXPEDITED on RISC-V.",
+ major, minor);
+ return false;
+ }
+#endif
long ret = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
if (ret < 0) {
log_info(os)("MEMBARRIER_CMD_QUERY unsupported");
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index 1158392fa4964..39a6779b3fc04 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -265,7 +265,7 @@ bool os::dir_is_empty(const char* path) {
return result;
}
-static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) {
+static char* reserve_mmapped_memory(size_t bytes, char* requested_addr, MEMFLAGS flag) {
char * addr;
int flags = MAP_PRIVATE NOT_AIX( | MAP_NORESERVE ) | MAP_ANONYMOUS;
if (requested_addr != nullptr) {
@@ -280,13 +280,14 @@ static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) {
flags, -1, 0);
if (addr != MAP_FAILED) {
- MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC, flag);
return addr;
}
return nullptr;
}
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
@@ -392,7 +393,7 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
return chop_extra_memory(size, alignment, extra_base, extra_size);
}
-char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_desc) {
+char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag) {
size_t extra_size = calculate_aligned_extra_size(size, alignment);
// For file mapping, we do not call os:map_memory_to_file(size,fd) since:
// - we later chop away parts of the mapping using os::release_memory and that could fail if the
@@ -400,7 +401,7 @@ char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_des
// - The memory API os::reserve_memory uses is an implementation detail. It may (and usually is)
// mmap but it also may System V shared memory which cannot be uncommitted as a whole, so
// chopping off and unmapping excess bits back and front (see below) would not work.
- char* extra_base = reserve_mmapped_memory(extra_size, nullptr);
+ char* extra_base = reserve_mmapped_memory(extra_size, nullptr, flag);
if (extra_base == nullptr) {
return nullptr;
}
@@ -752,11 +753,11 @@ 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) ::lseek(fd, offset, whence);
}
int os::ftruncate(int fd, jlong length) {
- return BSD_ONLY(::ftruncate) NOT_BSD(::ftruncate64)(fd, length);
+ return ::ftruncate(fd, length);
}
const char* os::get_current_directory(char *buf, size_t buflen) {
@@ -2030,3 +2031,53 @@ void os::die() {
const char* os::file_separator() { return "/"; }
const char* os::line_separator() { return "\n"; }
const char* os::path_separator() { return ":"; }
+
+// Map file into memory; uses mmap().
+// Notes:
+// - if caller specifies addr, MAP_FIXED is used. That means existing
+// mappings will be replaced.
+// - The file descriptor must be valid (to create anonymous mappings, use
+// os::reserve_memory()).
+// Returns address to mapped memory, nullptr on error
+char* os::pd_map_memory(int fd, const char* unused,
+ size_t file_offset, char *addr, size_t bytes,
+ bool read_only, bool allow_exec) {
+
+ assert(fd != -1, "Specify a valid file descriptor");
+
+ int prot;
+ int flags = MAP_PRIVATE;
+
+ if (read_only) {
+ prot = PROT_READ;
+ } else {
+ prot = PROT_READ | PROT_WRITE;
+ }
+
+ if (allow_exec) {
+ prot |= PROT_EXEC;
+ }
+
+ if (addr != nullptr) {
+ flags |= MAP_FIXED;
+ }
+
+ char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
+ fd, file_offset);
+ if (mapped_address == MAP_FAILED) {
+ return nullptr;
+ }
+
+ // If we did specify an address, and the mapping succeeded, it should
+ // have returned that address since we specify MAP_FIXED
+ assert(addr == nullptr || addr == mapped_address,
+ "mmap+MAP_FIXED returned " PTR_FORMAT ", expected " PTR_FORMAT,
+ p2i(mapped_address), p2i(addr));
+
+ return mapped_address;
+}
+
+// Unmap a block of memory. Uses munmap.
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
+ return munmap(addr, bytes) == 0;
+}
diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp
index 8c71516f70b8f..d872a6dae899e 100644
--- a/src/hotspot/os/posix/os_posix.hpp
+++ b/src/hotspot/os/posix/os_posix.hpp
@@ -31,7 +31,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 8736e05bc62ae..4339a21ae4e92 100644
--- a/src/hotspot/os/posix/perfMemory_posix.cpp
+++ b/src/hotspot/os/posix/perfMemory_posix.cpp
@@ -1086,11 +1086,10 @@ static char* mmap_create_shared(size_t size) {
static void unmap_shared(char* addr, size_t bytes) {
int res;
if (MemTracker::enabled()) {
- // Note: Tracker contains a ThreadCritical.
- Tracker tkr(Tracker::release);
+ ThreadCritical tc;
res = ::munmap(addr, bytes);
if (res == 0) {
- tkr.record((address)addr, bytes);
+ MemTracker::record_virtual_memory_release((address)addr, bytes);
}
} else {
res = ::munmap(addr, bytes);
diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp
index eaadb36731518..6a958f8903b8e 100644
--- a/src/hotspot/os/posix/signals_posix.cpp
+++ b/src/hotspot/os/posix/signals_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, 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
@@ -340,7 +340,7 @@ static const struct {
////////////////////////////////////////////////////////////////////////////////
// sun.misc.Signal and BREAK_SIGNAL support
-void jdk_misc_signal_init() {
+static void jdk_misc_signal_init() {
// Initialize signal structures
::memset((void*)pending_signals, 0, sizeof(pending_signals));
@@ -380,7 +380,7 @@ int os::signal_wait() {
////////////////////////////////////////////////////////////////////////////////
// signal chaining support
-struct sigaction* get_chained_signal_action(int sig) {
+static struct sigaction* get_chained_signal_action(int sig) {
struct sigaction *actp = nullptr;
if (libjsig_is_loaded) {
@@ -1245,7 +1245,7 @@ int os::get_signal_number(const char* signal_name) {
return -1;
}
-void set_signal_handler(int sig) {
+static void set_signal_handler(int sig) {
// Check for overwrite.
struct sigaction oldAct;
sigaction(sig, (struct sigaction*)nullptr, &oldAct);
@@ -1292,7 +1292,7 @@ void set_signal_handler(int sig) {
// install signal handlers for signals that HotSpot needs to
// handle in order to support Java-level exception handling.
-void install_signal_handlers() {
+static void install_signal_handlers() {
// signal-chaining
typedef void (*signal_setting_t)();
signal_setting_t begin_signal_setting = nullptr;
@@ -1723,7 +1723,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) {
errno = old_errno;
}
-int SR_initialize() {
+static int SR_initialize() {
struct sigaction act;
char *s;
// Get signal number to use for suspend/resume
diff --git a/src/hotspot/os/windows/attachListener_windows.cpp b/src/hotspot/os/windows/attachListener_windows.cpp
index da3b6c56739f0..7e455cf0a49f2 100644
--- a/src/hotspot/os/windows/attachListener_windows.cpp
+++ b/src/hotspot/os/windows/attachListener_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, 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
@@ -248,10 +248,13 @@ Win32AttachOperation* Win32AttachListener::dequeue() {
DWORD res = ::WaitForSingleObject(enqueued_ops_semaphore(), INFINITE);
// returning from WaitForSingleObject will have decreased
// the current count of the semaphore by 1.
- guarantee(res == WAIT_OBJECT_0, "wait failed");
+ guarantee(res != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ guarantee(res == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", res);
res = ::WaitForSingleObject(mutex(), INFINITE);
- guarantee(res == WAIT_OBJECT_0, "wait failed");
+ guarantee(res != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ guarantee(res == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", res);
+
Win32AttachOperation* op = head();
if (op != nullptr) {
@@ -338,6 +341,9 @@ void Win32AttachOperation::complete(jint result, bufferedStream* result_stream)
}
DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
+ assert(res != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(res == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", res);
+
if (res == WAIT_OBJECT_0) {
// put the operation back on the available list
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index 1b5c7850bf23f..2ddebc9bf6dee 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, 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
@@ -27,7 +27,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
@@ -840,6 +839,20 @@ julong os::win32::available_memory() {
return (julong)ms.ullAvailPhys;
}
+jlong os::total_swap_space() {
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullTotalPageFile;
+}
+
+jlong os::free_swap_space() {
+ MEMORYSTATUSEX ms;
+ ms.dwLength = sizeof(ms);
+ GlobalMemoryStatusEx(&ms);
+ return (jlong) ms.ullAvailPageFile;
+}
+
julong os::physical_memory() {
return win32::physical_memory();
}
@@ -2469,9 +2482,9 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
#elif defined(_M_AMD64)
PCONTEXT ctx = exceptionInfo->ContextRecord;
address pc = (address)ctx->Rip;
- guarantee(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && pc[1] == 0xF7 || pc[0] == 0xF7,
+ guarantee((pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && pc[1] == 0xF7) || pc[0] == 0xF7,
"not an idiv opcode, pc[0] = 0x%x and pc[1] = 0x%x", pc[0], pc[1]);
- guarantee(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && (pc[2] & ~0x7) == 0xF8 || (pc[1] & ~0x7) == 0xF8,
+ guarantee((pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && (pc[2] & ~0x7) == 0xF8) || (pc[1] & ~0x7) == 0xF8,
"cannot handle non-register operands, pc[0] = 0x%x, pc[1] = 0x%x and pc[2] = 0x%x", pc[0], pc[1], pc[2]);
if (pc[0] == 0xF7) {
// set correct result values and continue after idiv instruction
@@ -3330,7 +3343,7 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in
// Multiple threads can race in this code but it's not possible to unmap small sections of
// virtual space to get requested alignment, like posix-like os's.
// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
-static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
+static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag = mtNone) {
assert(is_aligned(alignment, os::vm_allocation_granularity()),
"Alignment must be a multiple of allocation granularity (page size)");
assert(is_aligned(size, os::vm_allocation_granularity()),
@@ -3343,8 +3356,8 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
static const int max_attempts = 20;
for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) {
- char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc) :
- os::reserve_memory(extra_size);
+ char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, flag) :
+ os::reserve_memory(extra_size, false, flag);
if (extra_base == nullptr) {
return nullptr;
}
@@ -3360,8 +3373,8 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
// Attempt to map, into the just vacated space, the slightly smaller aligned area.
// Which may fail, hence the loop.
- aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc) :
- os::attempt_reserve_memory_at(aligned_base, size);
+ aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, flag) :
+ os::attempt_reserve_memory_at(aligned_base, size, false, flag);
}
assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts);
@@ -3374,8 +3387,8 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);
}
-char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd) {
- return map_or_reserve_memory_aligned(size, alignment, fd);
+char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag) {
+ return map_or_reserve_memory_aligned(size, alignment, fd, flag);
}
char* os::pd_reserve_memory(size_t bytes, bool exec) {
@@ -3796,6 +3809,11 @@ bool os::unguard_memory(char* addr, size_t bytes) {
void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
+
+size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) {
+ return page_size;
+}
+
void os::numa_make_global(char *addr, size_t bytes) { }
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
bool os::numa_topology_changed() { return false; }
@@ -5149,22 +5167,6 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
return base;
}
-
-// Remap a block of memory.
-char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec) {
- // This OS does not allow existing memory maps to be remapped so we
- // would have to unmap the memory before we remap it.
-
- // Because there is a small window between unmapping memory and mapping
- // it in again with different protections, CDS archives are mapped RW
- // on windows, so this function isn't called.
- ShouldNotReachHere();
- return nullptr;
-}
-
-
// Unmap a block of memory.
// Returns true=success, otherwise false.
@@ -5354,7 +5356,8 @@ int PlatformEvent::park(jlong Millis) {
phri = new HighResolutionInterval(prd);
}
rv = ::WaitForSingleObject(_ParkHandle, prd);
- assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed");
+ assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed with return value: %lu", rv);
if (rv == WAIT_TIMEOUT) {
Millis -= prd;
}
@@ -5393,7 +5396,8 @@ void PlatformEvent::park() {
// spin attempts by this thread.
while (_Event < 0) {
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
- assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed");
+ assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", rv);
}
// Usually we'll find _Event == 0 at this point, but as
@@ -5456,16 +5460,25 @@ void Parker::park(bool isAbsolute, jlong time) {
JavaThread* thread = JavaThread::current();
// Don't wait if interrupted or already triggered
- if (thread->is_interrupted(false) ||
- WaitForSingleObject(_ParkHandle, 0) == WAIT_OBJECT_0) {
+ if (thread->is_interrupted(false)) {
ResetEvent(_ParkHandle);
return;
} else {
- ThreadBlockInVM tbivm(thread);
- OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+ DWORD rv = WaitForSingleObject(_ParkHandle, 0);
+ assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed with return value: %lu", rv);
+ if (rv == WAIT_OBJECT_0) {
+ ResetEvent(_ParkHandle);
+ return;
+ } else {
+ ThreadBlockInVM tbivm(thread);
+ OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
- WaitForSingleObject(_ParkHandle, time);
- ResetEvent(_ParkHandle);
+ rv = WaitForSingleObject(_ParkHandle, time);
+ assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed with return value: %lu", rv);
+ ResetEvent(_ParkHandle);
+ }
}
}
@@ -5541,7 +5554,9 @@ int os::fork_and_exec(const char* cmd) {
if (rslt) {
// Wait until child process exits.
- WaitForSingleObject(pi.hProcess, INFINITE);
+ DWORD rv = WaitForSingleObject(pi.hProcess, INFINITE);
+ assert(rv != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", rv);
GetExitCodeProcess(pi.hProcess, &exit_code);
diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp
index 5a4f95d044fc8..a71101731fb98 100644
--- a/src/hotspot/os/windows/perfMemory_windows.cpp
+++ b/src/hotspot/os/windows/perfMemory_windows.cpp
@@ -1803,9 +1803,9 @@ void PerfMemory::detach(char* addr, size_t bytes) {
if (MemTracker::enabled()) {
// it does not go through os api, the operation has to record from here
- Tracker tkr(Tracker::release);
+ ThreadCritical tc;
remove_file_mapping(addr);
- tkr.record((address)addr, bytes);
+ MemTracker::record_virtual_memory_release((address)addr, bytes);
} else {
remove_file_mapping(addr);
}
diff --git a/src/hotspot/os/windows/threadCritical_windows.cpp b/src/hotspot/os/windows/threadCritical_windows.cpp
index f781a4224849b..c85143f80930d 100644
--- a/src/hotspot/os/windows/threadCritical_windows.cpp
+++ b/src/hotspot/os/windows/threadCritical_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -64,7 +64,8 @@ ThreadCritical::ThreadCritical() {
if (lock_owner != current_thread) {
// Grab the lock before doing anything.
DWORD ret = WaitForSingleObject(lock_event, INFINITE);
- assert(ret == WAIT_OBJECT_0, "unexpected return value from WaitForSingleObject");
+ assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
+ assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
lock_owner = current_thread;
}
// Atomicity isn't required. Bump the recursion count.
diff --git a/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp
index aeed103c4deb3..a4d34d05df59e 100644
--- a/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp
+++ b/src/hotspot/os_cpu/aix_ppc/javaThread_aix_ppc.cpp
@@ -37,7 +37,8 @@ frame JavaThread::pd_last_frame() {
intptr_t* sp = last_Java_sp();
address pc = _anchor.last_Java_pc();
- return frame(sp, pc);
+ // Likely the frame of a RuntimeStub.
+ return frame(sp, pc, frame::kind::code_blob);
}
bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) {
@@ -50,7 +51,7 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
// pc can be seen as null because not all writers use store pc + release store sp.
// Simply discard the sample in this very rare case.
if (pc == nullptr) return false;
- *fr_addr = frame(sp, pc);
+ *fr_addr = frame(sp, pc, frame::kind::code_blob);
return true;
}
@@ -66,7 +67,8 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
return false;
}
- frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc);
+ // pc could refer to a native address outside the code cache even though the thread isInJava.
+ frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc, frame::kind::unknown);
if (ret_frame.fp() == nullptr) {
// The found frame does not have a valid frame pointer.
diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
index 69dc9dffd80f0..242042d4247aa 100644
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
@@ -28,7 +28,6 @@
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
@@ -126,7 +125,7 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
// Avoid crash during crash if pc broken.
if (epc) {
- frame fr(sp, epc);
+ frame fr(sp, epc, frame::kind::unknown);
return fr;
}
frame fr(sp);
@@ -137,21 +136,21 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
const ucontext_t* uc = (const ucontext_t*)ucVoid;
intptr_t* sp = os::Aix::ucontext_get_sp(uc);
address lr = ucontext_get_lr(uc);
- return frame(sp, lr);
+ return frame(sp, lr, frame::kind::unknown);
}
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == (intptr_t) nullptr) {
// fr is the last C frame
- return frame(nullptr, nullptr);
+ return frame();
}
- return frame(fr->sender_sp(), fr->sender_pc());
+ return frame(fr->sender_sp(), fr->sender_pc(), frame::kind::unknown);
}
frame os::current_frame() {
intptr_t* csp = *(intptr_t**) __builtin_frame_address(0);
- frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame));
+ frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame), frame::kind::unknown);
return os::get_sender_for_C_frame(&topframe);
}
diff --git a/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.S b/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.S
index 7b286820a9a8f..187cd20ddbdad 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.S
+++ b/src/hotspot/os_cpu/bsd_aarch64/copy_bsd_aarch64.S
@@ -28,6 +28,11 @@
.global CFUNC(_Copy_conjoint_words)
.global CFUNC(_Copy_disjoint_words)
+#ifdef __APPLE__
+ .private_extern CFUNC(_Copy_conjoint_words)
+ .private_extern CFUNC(_Copy_disjoint_words)
+#endif
+
s .req x0
d .req x1
count .req x2
diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
index fbd7c4eccd403..4750ed8805644 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
+++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
@@ -29,7 +29,6 @@
#include "classfile/classLoader.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/bsd_aarch64/safefetch_bsd_aarch64.S b/src/hotspot/os_cpu/bsd_aarch64/safefetch_bsd_aarch64.S
index 34d7b8e34a739..b9b6df9b23aa0 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/safefetch_bsd_aarch64.S
+++ b/src/hotspot/os_cpu/bsd_aarch64/safefetch_bsd_aarch64.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -39,6 +39,15 @@
.global SYMBOL(_SafeFetch32_fault)
.global SYMBOL(_SafeFetch32_continuation)
+#ifdef __APPLE__
+ .private_extern SYMBOL(SafeFetchN_impl)
+ .private_extern SYMBOL(_SafeFetchN_fault)
+ .private_extern SYMBOL(_SafeFetchN_continuation)
+ .private_extern SYMBOL(SafeFetch32_impl)
+ .private_extern SYMBOL(_SafeFetch32_fault)
+ .private_extern SYMBOL(_SafeFetch32_continuation)
+#endif
+
# Support for int SafeFetch32(int* address, int defaultval);
#
# x0 : address
diff --git a/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S b/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S
index 02231040e15bd..5cad379df3f2b 100644
--- a/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S
+++ b/src/hotspot/os_cpu/bsd_x86/bsd_x86_32.S
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 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,6 +32,7 @@
#endif
.globl SYMBOL(fixcw)
+ .globl SYMBOL(SpinPause)
# NOTE WELL! The _Copy functions are called directly
# from server-compiler-generated code via CallLeafNoFP,
@@ -50,6 +51,20 @@
.globl SYMBOL(_Atomic_cmpxchg_long)
.globl SYMBOL(_Atomic_move_long)
+#ifdef __APPLE__
+ .private_extern SYMBOL(fixcw)
+ .private_extern SYMBOL(SpinPause)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_bytes)
+ .private_extern SYMBOL(_Copy_conjoint_jshorts_atomic)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_jshorts)
+ .private_extern SYMBOL(_Copy_conjoint_jints_atomic)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_jints)
+ .private_extern SYMBOL(_Copy_conjoint_jlongs_atomic)
+ .private_extern SYMBOL(_mmx_Copy_arrayof_conjoint_jshorts)
+ .private_extern SYMBOL(_Atomic_cmpxchg_long)
+ .private_extern SYMBOL(_Atomic_move_long)
+#endif
+
.text
# Support for void os::Solaris::init_thread_fpu_state() in os_solaris_i486.cpp
@@ -62,7 +77,6 @@ SYMBOL(fixcw):
popl %eax
ret
- .globl SYMBOL(SpinPause)
ELF_TYPE(SpinPause,@function)
.p2align 4,,15
SYMBOL(SpinPause):
diff --git a/src/hotspot/os_cpu/bsd_x86/bsd_x86_64.S b/src/hotspot/os_cpu/bsd_x86/bsd_x86_64.S
index 95cea3bf2a3d3..5e2addc4e6f43 100644
--- a/src/hotspot/os_cpu/bsd_x86/bsd_x86_64.S
+++ b/src/hotspot/os_cpu/bsd_x86/bsd_x86_64.S
@@ -1,5 +1,5 @@
-#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+#
+# Copyright (c) 2004, 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,22 +31,33 @@
#endif
# NOTE WELL! The _Copy functions are called directly
- # from server-compiler-generated code via CallLeafNoFP,
- # which means that they *must* either not use floating
- # point or use it in the same manner as does the server
- # compiler.
-
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
+
+ .globl SYMBOL(SpinPause)
.globl SYMBOL(_Copy_arrayof_conjoint_bytes)
- .globl SYMBOL(_Copy_arrayof_conjoint_jshorts)
+ .globl SYMBOL(_Copy_arrayof_conjoint_jshorts)
.globl SYMBOL(_Copy_conjoint_jshorts_atomic)
.globl SYMBOL(_Copy_arrayof_conjoint_jints)
.globl SYMBOL(_Copy_conjoint_jints_atomic)
.globl SYMBOL(_Copy_arrayof_conjoint_jlongs)
.globl SYMBOL(_Copy_conjoint_jlongs_atomic)
- .text
+#ifdef __APPLE__
+ .private_extern SYMBOL(SpinPause)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_bytes)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_jshorts)
+ .private_extern SYMBOL(_Copy_conjoint_jshorts_atomic)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_jints)
+ .private_extern SYMBOL(_Copy_conjoint_jints_atomic)
+ .private_extern SYMBOL(_Copy_arrayof_conjoint_jlongs)
+ .private_extern SYMBOL(_Copy_conjoint_jlongs_atomic)
+#endif
+
+ .text
- .globl SYMBOL(SpinPause)
.p2align 4,,15
ELF_TYPE(SpinPause,@function)
SYMBOL(SpinPause):
@@ -63,7 +74,7 @@ SYMBOL(SpinPause):
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function)
+ ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function)
SYMBOL(_Copy_arrayof_conjoint_bytes):
movq %rdx,%r8 # byte count
shrq $3,%rdx # qword count
@@ -71,7 +82,7 @@ SYMBOL(_Copy_arrayof_conjoint_bytes):
leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
jbe acb_CopyRight
cmpq %rax,%rsi
- jbe acb_CopyLeft
+ jbe acb_CopyLeft
acb_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -165,8 +176,8 @@ acb_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function)
- ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function)
+ ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function)
+ ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function)
SYMBOL(_Copy_arrayof_conjoint_jshorts):
SYMBOL(_Copy_conjoint_jshorts_atomic):
movq %rdx,%r8 # word count
@@ -175,7 +186,7 @@ SYMBOL(_Copy_conjoint_jshorts_atomic):
leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
jbe acs_CopyRight
cmpq %rax,%rsi
- jbe acs_CopyLeft
+ jbe acs_CopyLeft
acs_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -255,8 +266,8 @@ acs_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- ELF_TYPE(_Copy_arrayof_conjoint_jints,@function)
- ELF_TYPE(_Copy_conjoint_jints_atomic,@function)
+ ELF_TYPE(_Copy_arrayof_conjoint_jints,@function)
+ ELF_TYPE(_Copy_conjoint_jints_atomic,@function)
SYMBOL(_Copy_arrayof_conjoint_jints):
SYMBOL(_Copy_conjoint_jints_atomic):
movq %rdx,%r8 # dword count
@@ -265,7 +276,7 @@ SYMBOL(_Copy_conjoint_jints_atomic):
leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
jbe aci_CopyRight
cmpq %rax,%rsi
- jbe aci_CopyLeft
+ jbe aci_CopyLeft
aci_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -334,15 +345,15 @@ aci_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- ELF_TYPE(_Copy_arrayof_conjoint_jlongs,@function)
- ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function)
+ ELF_TYPE(_Copy_arrayof_conjoint_jlongs,@function)
+ ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function)
SYMBOL(_Copy_arrayof_conjoint_jlongs):
SYMBOL(_Copy_conjoint_jlongs_atomic):
cmpq %rdi,%rsi
leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
jbe acl_CopyRight
cmpq %rax,%rsi
- jbe acl_CopyLeft
+ jbe acl_CopyLeft
acl_CopyRight:
leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
negq %rdx
diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
index 37b92bc7ffd48..c73e83996ff57 100644
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
@@ -351,7 +350,7 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
-intptr_t* _get_previous_fp() {
+static intptr_t* _get_previous_fp() {
#if defined(__clang__) || defined(__llvm__)
intptr_t **ebp;
__asm__("mov %%" SPELL_REG_FP ", %0":"=r"(ebp));
diff --git a/src/hotspot/os_cpu/bsd_x86/safefetch_bsd_x86_64.S b/src/hotspot/os_cpu/bsd_x86/safefetch_bsd_x86_64.S
index 2a75f3dac94b3..1697f6f03b581 100644
--- a/src/hotspot/os_cpu/bsd_x86/safefetch_bsd_x86_64.S
+++ b/src/hotspot/os_cpu/bsd_x86/safefetch_bsd_x86_64.S
@@ -1,6 +1,6 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
-# 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
@@ -38,13 +38,22 @@
.globl SYMBOL(_SafeFetch32_continuation)
.globl SYMBOL(_SafeFetchN_continuation)
+#ifdef __APPLE__
+ .private_extern SYMBOL(SafeFetch32_impl)
+ .private_extern SYMBOL(SafeFetchN_impl)
+ .private_extern SYMBOL(_SafeFetch32_fault)
+ .private_extern SYMBOL(_SafeFetchN_fault)
+ .private_extern SYMBOL(_SafeFetch32_continuation)
+ .private_extern SYMBOL(_SafeFetchN_continuation)
+#endif
+
.text
# Support for int SafeFetch32(int* address, int defaultval);
#
# %rdi : address
# %esi : defaultval
- ELF_TYPE(SafeFetch32_impl,@function)
+ ELF_TYPE(SafeFetch32_impl,@function)
SYMBOL(SafeFetch32_impl:)
SYMBOL(_SafeFetch32_fault:)
movl (%rdi), %eax
diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
index 012f85ac0ff4a..0fc9484ce23ef 100644
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
@@ -27,7 +27,6 @@
#include "asm/assembler.inline.hpp"
#include "atomic_bsd_zero.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S
index 4621e44ca3c47..e67206a9d497f 100644
--- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S
+++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S
@@ -24,6 +24,7 @@
.text
.globl aarch64_atomic_fetch_add_8_default_impl
+ .hidden aarch64_atomic_fetch_add_8_default_impl
.align 5
aarch64_atomic_fetch_add_8_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -40,6 +41,7 @@ aarch64_atomic_fetch_add_8_default_impl:
ret
.globl aarch64_atomic_fetch_add_4_default_impl
+ .hidden aarch64_atomic_fetch_add_4_default_impl
.align 5
aarch64_atomic_fetch_add_4_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -56,6 +58,7 @@ aarch64_atomic_fetch_add_4_default_impl:
ret
.global aarch64_atomic_fetch_add_8_relaxed_default_impl
+ .hidden aarch64_atomic_fetch_add_8_relaxed_default_impl
.align 5
aarch64_atomic_fetch_add_8_relaxed_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -71,6 +74,7 @@ aarch64_atomic_fetch_add_8_relaxed_default_impl:
ret
.global aarch64_atomic_fetch_add_4_relaxed_default_impl
+ .hidden aarch64_atomic_fetch_add_4_relaxed_default_impl
.align 5
aarch64_atomic_fetch_add_4_relaxed_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -86,6 +90,7 @@ aarch64_atomic_fetch_add_4_relaxed_default_impl:
ret
.globl aarch64_atomic_xchg_4_default_impl
+ .hidden aarch64_atomic_xchg_4_default_impl
.align 5
aarch64_atomic_xchg_4_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -101,6 +106,7 @@ aarch64_atomic_xchg_4_default_impl:
ret
.globl aarch64_atomic_xchg_8_default_impl
+ .hidden aarch64_atomic_xchg_8_default_impl
.align 5
aarch64_atomic_xchg_8_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -116,6 +122,7 @@ aarch64_atomic_xchg_8_default_impl:
ret
.globl aarch64_atomic_cmpxchg_1_default_impl
+ .hidden aarch64_atomic_cmpxchg_1_default_impl
.align 5
aarch64_atomic_cmpxchg_1_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -136,6 +143,7 @@ aarch64_atomic_cmpxchg_1_default_impl:
ret
.globl aarch64_atomic_cmpxchg_4_default_impl
+ .hidden aarch64_atomic_cmpxchg_4_default_impl
.align 5
aarch64_atomic_cmpxchg_4_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -155,6 +163,7 @@ aarch64_atomic_cmpxchg_4_default_impl:
ret
.globl aarch64_atomic_cmpxchg_8_default_impl
+ .hidden aarch64_atomic_cmpxchg_8_default_impl
.align 5
aarch64_atomic_cmpxchg_8_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -174,6 +183,7 @@ aarch64_atomic_cmpxchg_8_default_impl:
ret
.globl aarch64_atomic_cmpxchg_4_release_default_impl
+ .hidden aarch64_atomic_cmpxchg_4_release_default_impl
.align 5
aarch64_atomic_cmpxchg_4_release_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -191,6 +201,7 @@ aarch64_atomic_cmpxchg_4_release_default_impl:
ret
.globl aarch64_atomic_cmpxchg_8_release_default_impl
+ .hidden aarch64_atomic_cmpxchg_8_release_default_impl
.align 5
aarch64_atomic_cmpxchg_8_release_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -208,6 +219,7 @@ aarch64_atomic_cmpxchg_8_release_default_impl:
ret
.globl aarch64_atomic_cmpxchg_4_seq_cst_default_impl
+ .hidden aarch64_atomic_cmpxchg_4_seq_cst_default_impl
.align 5
aarch64_atomic_cmpxchg_4_seq_cst_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -225,6 +237,7 @@ aarch64_atomic_cmpxchg_4_seq_cst_default_impl:
ret
.globl aarch64_atomic_cmpxchg_8_seq_cst_default_impl
+ .hidden aarch64_atomic_cmpxchg_8_seq_cst_default_impl
.align 5
aarch64_atomic_cmpxchg_8_seq_cst_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -242,6 +255,7 @@ aarch64_atomic_cmpxchg_8_seq_cst_default_impl:
ret
.globl aarch64_atomic_cmpxchg_1_relaxed_default_impl
+.hidden aarch64_atomic_cmpxchg_1_relaxed_default_impl
.align 5
aarch64_atomic_cmpxchg_1_relaxed_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -260,6 +274,7 @@ aarch64_atomic_cmpxchg_1_relaxed_default_impl:
ret
.globl aarch64_atomic_cmpxchg_4_relaxed_default_impl
+ .hidden aarch64_atomic_cmpxchg_4_relaxed_default_impl
.align 5
aarch64_atomic_cmpxchg_4_relaxed_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
@@ -277,6 +292,7 @@ aarch64_atomic_cmpxchg_4_relaxed_default_impl:
ret
.globl aarch64_atomic_cmpxchg_8_relaxed_default_impl
+ .hidden aarch64_atomic_cmpxchg_8_relaxed_default_impl
.align 5
aarch64_atomic_cmpxchg_8_relaxed_default_impl:
#ifdef __ARM_FEATURE_ATOMICS
diff --git a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S
index 4b8ed597c59fc..ade867ace016b 100644
--- a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S
+++ b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S
@@ -24,6 +24,9 @@
.global _Copy_conjoint_words
.global _Copy_disjoint_words
+ .hidden _Copy_conjoint_words
+ .hidden _Copy_disjoint_words
+
s .req x0
d .req x1
count .req x2
diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
index 4835eb9405a1b..3698896abb78a 100644
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "code/nativeInst.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S
index fcb7e62e6d5e9..cfbd8f45f285f 100644
--- a/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S
+++ b/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -30,6 +30,13 @@
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
+ .hidden SafeFetchN_impl
+ .hidden _SafeFetchN_fault
+ .hidden _SafeFetchN_continuation
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
# Support for int SafeFetch32(int* address, int defaultval);
#
# x0 : address
diff --git a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
index ac60d6aa94168..f9f5aab2a6bd8 100644
--- a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
+++ b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
@@ -25,22 +25,23 @@
// Clobber x1, flags.
// All other registers are preserved,
- .global _ZN10JavaThread25aarch64_get_thread_helperEv
- .type _ZN10JavaThread25aarch64_get_thread_helperEv, %function
+ .global _ZN10JavaThread25aarch64_get_thread_helperEv
+ .hidden _ZN10JavaThread25aarch64_get_thread_helperEv
+ .type _ZN10JavaThread25aarch64_get_thread_helperEv, %function
_ZN10JavaThread25aarch64_get_thread_helperEv:
- hint #0x19 // paciasp
- stp x29, x30, [sp, -16]!
- adrp x0, :tlsdesc:_ZN6Thread12_thr_currentE
- ldr x1, [x0, #:tlsdesc_lo12:_ZN6Thread12_thr_currentE]
- add x0, x0, :tlsdesc_lo12:_ZN6Thread12_thr_currentE
- .tlsdesccall _ZN6Thread12_thr_currentE
- blr x1
- mrs x1, tpidr_el0
- add x0, x1, x0
- ldr x0, [x0]
- ldp x29, x30, [sp], 16
- hint #0x1d // autiasp
- ret
+ hint #0x19 // paciasp
+ stp x29, x30, [sp, -16]!
+ adrp x0, :tlsdesc:_ZN6Thread12_thr_currentE
+ ldr x1, [x0, #:tlsdesc_lo12:_ZN6Thread12_thr_currentE]
+ add x0, x0, :tlsdesc_lo12:_ZN6Thread12_thr_currentE
+ .tlsdesccall _ZN6Thread12_thr_currentE
+ blr x1
+ mrs x1, tpidr_el0
+ add x0, x1, x0
+ ldr x0, [x0]
+ ldp x29, x30, [sp], 16
+ hint #0x1d // autiasp
+ ret
- .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv
+ .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv
diff --git a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
index eb560d8f0c78b..ad88c58ce78ce 100644
--- a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
+++ b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 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
@@ -23,38 +23,46 @@
# NOTE WELL! The _Copy functions are called directly
- # from server-compiler-generated code via CallLeafNoFP,
- # which means that they *must* either not use floating
- # point or use it in the same manner as does the server
- # compiler.
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
- .globl _Copy_conjoint_bytes
- .type _Copy_conjoint_bytes, %function
+ .globl SpinPause
+ .hidden SpinPause
+ .type SpinPause, %function
.globl _Copy_arrayof_conjoint_bytes
- .type _Copy_arrayof_conjoint_bytes, %function
- .globl _Copy_disjoint_words
- .type _Copy_disjoint_words, %function
- .globl _Copy_conjoint_words
- .type _Copy_conjoint_words, %function
+ .hidden _Copy_arrayof_conjoint_bytes
+ .type _Copy_arrayof_conjoint_bytes, %function
+ .globl _Copy_disjoint_words
+ .hidden _Copy_disjoint_words
+ .type _Copy_disjoint_words, %function
+ .globl _Copy_conjoint_words
+ .hidden _Copy_conjoint_words
+ .type _Copy_conjoint_words, %function
.globl _Copy_conjoint_jshorts_atomic
- .type _Copy_conjoint_jshorts_atomic, %function
- .globl _Copy_arrayof_conjoint_jshorts
- .type _Copy_arrayof_conjoint_jshorts, %function
+ .hidden _Copy_conjoint_jshorts_atomic
+ .type _Copy_conjoint_jshorts_atomic, %function
+ .globl _Copy_arrayof_conjoint_jshorts
+ .hidden _Copy_arrayof_conjoint_jshorts
+ .type _Copy_arrayof_conjoint_jshorts, %function
.globl _Copy_conjoint_jints_atomic
- .type _Copy_conjoint_jints_atomic, %function
+ .hidden _Copy_conjoint_jints_atomic
+ .type _Copy_conjoint_jints_atomic, %function
.globl _Copy_arrayof_conjoint_jints
- .type _Copy_arrayof_conjoint_jints, %function
- .globl _Copy_conjoint_jlongs_atomic
- .type _Copy_conjoint_jlongs_atomic, %function
- .globl _Copy_arrayof_conjoint_jlongs
- .type _Copy_arrayof_conjoint_jlongs, %function
+ .hidden _Copy_arrayof_conjoint_jints
+ .type _Copy_arrayof_conjoint_jints, %function
+ .globl _Copy_conjoint_jlongs_atomic
+ .hidden _Copy_conjoint_jlongs_atomic
+ .type _Copy_conjoint_jlongs_atomic, %function
+ .globl _Copy_arrayof_conjoint_jlongs
+ .hidden _Copy_arrayof_conjoint_jlongs
+ .type _Copy_arrayof_conjoint_jlongs, %function
from .req r0
to .req r1
- .text
- .globl SpinPause
- .type SpinPause, %function
+ .text
SpinPause:
bx LR
@@ -70,7 +78,7 @@ _Copy_arrayof_conjoint_bytes:
# size_t count)
_Copy_disjoint_words:
stmdb sp!, {r3 - r9, ip}
-
+
cmp r2, #0
beq disjoint_words_finish
@@ -81,17 +89,17 @@ _Copy_disjoint_words:
.align 3
dw_f2b_loop_32:
subs r2, #32
- blt dw_f2b_loop_32_finish
+ blt dw_f2b_loop_32_finish
ldmia from!, {r3 - r9, ip}
nop
- pld [from]
+ pld [from]
stmia to!, {r3 - r9, ip}
bgt dw_f2b_loop_32
dw_f2b_loop_32_finish:
addlts r2, #32
beq disjoint_words_finish
cmp r2, #16
- blt disjoint_words_small
+ blt disjoint_words_small
ldmia from!, {r3 - r6}
subge r2, r2, #16
stmia to!, {r3 - r6}
@@ -116,8 +124,8 @@ disjoint_words_finish:
_Copy_conjoint_words:
stmdb sp!, {r3 - r9, ip}
- cmp r2, #0
- beq conjoint_words_finish
+ cmp r2, #0
+ beq conjoint_words_finish
pld [from, #0]
cmp r2, #12
@@ -129,17 +137,17 @@ _Copy_conjoint_words:
.align 3
cw_f2b_loop_32:
subs r2, #32
- blt cw_f2b_loop_32_finish
+ blt cw_f2b_loop_32_finish
ldmia from!, {r3 - r9, ip}
nop
- pld [from]
+ pld [from]
stmia to!, {r3 - r9, ip}
bgt cw_f2b_loop_32
cw_f2b_loop_32_finish:
addlts r2, #32
beq conjoint_words_finish
cmp r2, #16
- blt conjoint_words_small
+ blt conjoint_words_small
ldmia from!, {r3 - r6}
subge r2, r2, #16
stmia to!, {r3 - r6}
@@ -154,7 +162,7 @@ conjoint_words_small:
strgt r9, [to], #4
b conjoint_words_finish
- # Src and dest overlap, copy in a descending order
+ # Src and dest overlap, copy in a descending order
cw_b2f_copy:
add from, r2
pld [from, #-32]
@@ -162,17 +170,17 @@ cw_b2f_copy:
.align 3
cw_b2f_loop_32:
subs r2, #32
- blt cw_b2f_loop_32_finish
+ blt cw_b2f_loop_32_finish
ldmdb from!, {r3-r9,ip}
nop
- pld [from, #-32]
+ pld [from, #-32]
stmdb to!, {r3-r9,ip}
bgt cw_b2f_loop_32
cw_b2f_loop_32_finish:
addlts r2, #32
beq conjoint_words_finish
cmp r2, #16
- blt cw_b2f_copy_small
+ blt cw_b2f_copy_small
ldmdb from!, {r3 - r6}
subge r2, r2, #16
stmdb to!, {r3 - r6}
@@ -196,8 +204,8 @@ conjoint_words_finish:
_Copy_conjoint_jshorts_atomic:
stmdb sp!, {r3 - r9, ip}
- cmp r2, #0
- beq conjoint_shorts_finish
+ cmp r2, #0
+ beq conjoint_shorts_finish
subs r3, to, from
cmphi r2, r3
@@ -210,11 +218,11 @@ _Copy_conjoint_jshorts_atomic:
ands r3, from, #3
bne cs_f2b_src_u
- # Aligned source address
+ # Aligned source address
.align 3
cs_f2b_loop_32:
subs r2, #32
- blt cs_f2b_loop_32_finish
+ blt cs_f2b_loop_32_finish
ldmia from!, {r3 - r9, ip}
nop
pld [from]
@@ -244,14 +252,14 @@ cs_f2b_4:
strgth r5, [to], #2
b conjoint_shorts_finish
- # Destination not aligned
+ # Destination not aligned
cs_f2b_dest_u:
ldrh r3, [from], #2
subs r2, #2
strh r3, [to], #2
beq conjoint_shorts_finish
- # Check to see if source is not aligned ether
+ # Check to see if source is not aligned ether
ands r3, from, #3
beq cs_f2b_loop_32
@@ -259,11 +267,11 @@ cs_f2b_src_u:
cmp r2, #16
blt cs_f2b_8_u
- # Load 2 first bytes to r7 and make src ptr word aligned
+ # Load 2 first bytes to r7 and make src ptr word aligned
bic from, #3
ldr r7, [from], #4
- # Destination aligned, source not
+ # Destination aligned, source not
mov r8, r2, lsr #4
.align 3
cs_f2b_16_u_loop:
@@ -306,7 +314,7 @@ cs_f2b_4_u:
strgth r5, [to], #2
b conjoint_shorts_finish
- # Src and dest overlap, copy in a descending order
+ # Src and dest overlap, copy in a descending order
cs_b2f_copy:
add from, r2
pld [from, #-32]
@@ -319,7 +327,7 @@ cs_b2f_copy:
.align 3
cs_b2f_loop_32:
subs r2, #32
- blt cs_b2f_loop_32_finish
+ blt cs_b2f_loop_32_finish
ldmdb from!, {r3-r9,ip}
nop
pld [from, #-32]
@@ -359,16 +367,16 @@ cs_b2f_all_copy:
strgth r5, [to, #-2]!
b conjoint_shorts_finish
- # Destination not aligned
+ # Destination not aligned
cs_b2f_dest_u:
ldrh r3, [from, #-2]!
strh r3, [to, #-2]!
sub r2, #2
- # Check source alignment as well
+ # Check source alignment as well
ands r3, from, #3
beq cs_b2f_loop_32
- # Source not aligned
+ # Source not aligned
cs_b2f_src_u:
bic from, #3
.align 3
@@ -393,7 +401,7 @@ cs_b2f_16_loop_u:
cs_b2f_16_loop_u_finished:
addlts r2, #16
ldr r3, [from]
- cmp r2, #10
+ cmp r2, #10
blt cs_b2f_2_u_loop
ldmdb from!, {r4 - r5}
mov r6, r4, lsr #16
@@ -402,7 +410,7 @@ cs_b2f_16_loop_u_finished:
orr r7, r7, r3, lsl #16
stmdb to!, {r6-r7}
sub r2, #8
- .align 3
+ .align 3
cs_b2f_2_u_loop:
subs r2, #2
ldrh r3, [from], #-2
@@ -426,7 +434,7 @@ _Copy_arrayof_conjoint_jshorts:
_Copy_conjoint_jints_atomic:
_Copy_arrayof_conjoint_jints:
swi 0x9f0001
-
+
# Support for void Copy::conjoint_jlongs_atomic(jlong* from,
# jlong* to,
# size_t count)
@@ -434,8 +442,8 @@ _Copy_conjoint_jlongs_atomic:
_Copy_arrayof_conjoint_jlongs:
stmdb sp!, {r3 - r9, ip}
- cmp r2, #0
- beq conjoint_longs_finish
+ cmp r2, #0
+ beq conjoint_longs_finish
pld [from, #0]
cmp r2, #24
@@ -447,10 +455,10 @@ _Copy_arrayof_conjoint_jlongs:
.align 3
cl_f2b_loop_32:
subs r2, #32
- blt cl_f2b_loop_32_finish
+ blt cl_f2b_loop_32_finish
ldmia from!, {r3 - r9, ip}
nop
- pld [from]
+ pld [from]
stmia to!, {r3 - r9, ip}
bgt cl_f2b_loop_32
cl_f2b_loop_32_finish:
@@ -458,21 +466,21 @@ cl_f2b_loop_32_finish:
beq conjoint_longs_finish
conjoint_longs_small:
cmp r2, #16
- blt cl_f2b_copy_8
- bgt cl_f2b_copy_24
+ blt cl_f2b_copy_8
+ bgt cl_f2b_copy_24
ldmia from!, {r3 - r6}
stmia to!, {r3 - r6}
- b conjoint_longs_finish
+ b conjoint_longs_finish
cl_f2b_copy_8:
ldmia from!, {r3 - r4}
stmia to!, {r3 - r4}
b conjoint_longs_finish
cl_f2b_copy_24:
- ldmia from!, {r3 - r8}
+ ldmia from!, {r3 - r8}
stmia to!, {r3 - r8}
b conjoint_longs_finish
- # Src and dest overlap, copy in a descending order
+ # Src and dest overlap, copy in a descending order
cl_b2f_copy:
add from, r2
pld [from, #-32]
@@ -480,31 +488,29 @@ cl_b2f_copy:
.align 3
cl_b2f_loop_32:
subs r2, #32
- blt cl_b2f_loop_32_finish
+ blt cl_b2f_loop_32_finish
ldmdb from!, {r3 - r9, ip}
nop
- pld [from]
+ pld [from]
stmdb to!, {r3 - r9, ip}
bgt cl_b2f_loop_32
cl_b2f_loop_32_finish:
addlts r2, #32
beq conjoint_longs_finish
cmp r2, #16
- blt cl_b2f_copy_8
- bgt cl_b2f_copy_24
+ blt cl_b2f_copy_8
+ bgt cl_b2f_copy_24
ldmdb from!, {r3 - r6}
stmdb to!, {r3 - r6}
b conjoint_longs_finish
cl_b2f_copy_8:
- ldmdb from!, {r3 - r4}
+ ldmdb from!, {r3 - r4}
stmdb to!, {r3 - r4}
b conjoint_longs_finish
cl_b2f_copy_24:
- ldmdb from!, {r3 - r8}
+ ldmdb from!, {r3 - r8}
stmdb to!, {r3 - r8}
conjoint_longs_finish:
ldmia sp!, {r3 - r9, ip}
bx lr
-
-
diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
index 86e8ed25618c1..551270588438e 100644
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_arm/safefetch_linux_arm.S b/src/hotspot/os_cpu/linux_arm/safefetch_linux_arm.S
index 5196b199f05f6..07e90fa3079f2 100644
--- a/src/hotspot/os_cpu/linux_arm/safefetch_linux_arm.S
+++ b/src/hotspot/os_cpu/linux_arm/safefetch_linux_arm.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -26,6 +26,11 @@
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
+
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
.type SafeFetch32_impl, %function
# Support for int SafeFetch32(int* address, int defaultval);
diff --git a/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp
index d16788222a142..191b7315205f7 100644
--- a/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp
+++ b/src/hotspot/os_cpu/linux_ppc/javaThread_linux_ppc.cpp
@@ -36,7 +36,8 @@ frame JavaThread::pd_last_frame() {
intptr_t* sp = last_Java_sp();
address pc = _anchor.last_Java_pc();
- return frame(sp, pc);
+ // Likely the frame of a RuntimeStub.
+ return frame(sp, pc, frame::kind::code_blob);
}
bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) {
@@ -49,7 +50,7 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
// pc can be seen as null because not all writers use store pc + release store sp.
// Simply discard the sample in this very rare case.
if (pc == nullptr) return false;
- *fr_addr = frame(sp, pc);
+ *fr_addr = frame(sp, pc, frame::kind::code_blob);
return true;
}
@@ -65,7 +66,8 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext,
return false;
}
- frame ret_frame((intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/], pc);
+ // pc could refer to a native address outside the code cache even though the thread isInJava.
+ frame ret_frame((intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/], pc, frame::kind::unknown);
if (ret_frame.fp() == nullptr) {
// The found frame does not have a valid frame pointer.
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 109f2b98d645c..0b666f29c312b 100644
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
@@ -28,7 +28,6 @@
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
@@ -156,28 +155,28 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
- return frame(sp, epc);
+ return frame(sp, epc, frame::kind::unknown);
}
frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
const ucontext_t* uc = (const ucontext_t*)ucVoid;
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
address lr = ucontext_get_lr(uc);
- return frame(sp, lr);
+ return frame(sp, lr, frame::kind::unknown);
}
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == 0) {
// fr is the last C frame
- return frame(nullptr, nullptr);
+ return frame();
}
- return frame(fr->sender_sp(), fr->sender_pc());
+ return frame(fr->sender_sp(), fr->sender_pc(), frame::kind::unknown);
}
frame os::current_frame() {
intptr_t* csp = *(intptr_t**) __builtin_frame_address(0);
- frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame));
+ frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame), frame::kind::unknown);
return os::get_sender_for_C_frame(&topframe);
}
diff --git a/src/hotspot/os_cpu/linux_ppc/safefetch_linux_ppc.S b/src/hotspot/os_cpu/linux_ppc/safefetch_linux_ppc.S
index c8d20cc1b4328..8c96edf01b4d0 100644
--- a/src/hotspot/os_cpu/linux_ppc/safefetch_linux_ppc.S
+++ b/src/hotspot/os_cpu/linux_ppc/safefetch_linux_ppc.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -30,6 +30,13 @@
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
+ .hidden SafeFetchN_impl
+ .hidden _SafeFetchN_fault
+ .hidden _SafeFetchN_continuation
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
# Support for int SafeFetch32(int* address, int defaultval);
#
# r3 : address
diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp
index e85bd60b22659..6546adb6ff33a 100644
--- a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp
+++ b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp
@@ -39,6 +39,12 @@
#define FULL_COMPILER_ATOMIC_SUPPORT
#endif
+#if defined(__clang_major__)
+#define CORRECT_COMPILER_ATOMIC_SUPPORT
+#elif defined(__GNUC__) && (__riscv_xlen <= 32 || __GNUC__ > 13)
+#define CORRECT_COMPILER_ATOMIC_SUPPORT
+#endif
+
template
struct Atomic::PlatformAdd {
template
@@ -114,6 +120,44 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest __attribute__((
}
#endif
+#ifndef CORRECT_COMPILER_ATOMIC_SUPPORT
+// The implementation of `__atomic_compare_exchange` lacks sign extensions
+// in GCC 13 and lower when using with 32-bit unsigned integers on RV64,
+// so we should implement it manually.
+// GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114130.
+// See also JDK-8326936.
+template<>
+template
+inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)),
+ T compare_value,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+
+ int32_t old_value;
+ uint64_t rc_temp;
+
+ if (order != memory_order_relaxed) {
+ FULL_MEM_BARRIER;
+ }
+
+ __asm__ __volatile__ (
+ "1: lr.w %0, %2 \n\t"
+ " bne %0, %3, 2f \n\t"
+ " sc.w %1, %4, %2 \n\t"
+ " bnez %1, 1b \n\t"
+ "2: \n\t"
+ : /*%0*/"=&r" (old_value), /*%1*/"=&r" (rc_temp), /*%2*/"+A" (*dest)
+ : /*%3*/"r" ((int64_t)(int32_t)compare_value), /*%4*/"r" (exchange_value)
+ : "memory" );
+
+ if (order != memory_order_relaxed) {
+ FULL_MEM_BARRIER;
+ }
+ return (T)old_value;
+}
+#endif
+
template
template
inline T Atomic::PlatformXchg::operator()(T volatile* dest,
@@ -151,6 +195,10 @@ inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attri
STATIC_ASSERT(byte_size >= 4);
#endif
+#ifndef CORRECT_COMPILER_ATOMIC_SUPPORT
+ STATIC_ASSERT(byte_size != 4);
+#endif
+
STATIC_ASSERT(byte_size == sizeof(T));
if (order != memory_order_relaxed) {
FULL_MEM_BARRIER;
@@ -187,5 +235,6 @@ struct Atomic::PlatformOrderedStore
};
#undef FULL_COMPILER_ATOMIC_SUPPORT
+#undef CORRECT_COMPILER_ATOMIC_SUPPORT
#endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP
diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
index 282467bc9e096..9f13e2bdd2cb7 100644
--- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
@@ -39,6 +38,7 @@
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/frame.inline.hpp"
+#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
@@ -406,6 +406,14 @@ static inline void atomic_copy64(const volatile void *src, volatile void *dst) {
extern "C" {
int SpinPause() {
+ if (UseZihintpause) {
+ // PAUSE is encoded as a FENCE instruction with pred=W, succ=0, fm=0, rd=x0, and rs1=x0.
+ // To do: __asm__ volatile("pause " : : : );
+ // Since we're currently not passing '-march=..._zihintpause' to the compiler,
+ // it will not recognize the "pause" instruction, hence the hard-coded instruction.
+ __asm__ volatile(".word 0x0100000f " : : : );
+ return 1;
+ }
return 0;
}
diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp
index 243c4b850ee43..df4a2e347ccac 100644
--- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp
@@ -49,6 +49,36 @@
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
+#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
+#define RISCV_HWPROBE_EXT_ZBC (1 << 7)
+#define RISCV_HWPROBE_EXT_ZBKB (1 << 8)
+#define RISCV_HWPROBE_EXT_ZBKC (1 << 9)
+#define RISCV_HWPROBE_EXT_ZBKX (1 << 10)
+#define RISCV_HWPROBE_EXT_ZKND (1 << 11)
+#define RISCV_HWPROBE_EXT_ZKNE (1 << 12)
+#define RISCV_HWPROBE_EXT_ZKNH (1 << 13)
+#define RISCV_HWPROBE_EXT_ZKSED (1 << 14)
+#define RISCV_HWPROBE_EXT_ZKSH (1 << 15)
+#define RISCV_HWPROBE_EXT_ZKT (1 << 16)
+#define RISCV_HWPROBE_EXT_ZVBB (1 << 17)
+#define RISCV_HWPROBE_EXT_ZVBC (1 << 18)
+#define RISCV_HWPROBE_EXT_ZVKB (1 << 19)
+#define RISCV_HWPROBE_EXT_ZVKG (1 << 20)
+#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21)
+#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22)
+#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23)
+#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24)
+#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25)
+#define RISCV_HWPROBE_EXT_ZVKT (1 << 26)
+#define RISCV_HWPROBE_EXT_ZFH (1 << 27)
+#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28)
+#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29)
+#define RISCV_HWPROBE_EXT_ZVFH (1 << 30)
+#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31)
+#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)
+#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)
+#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
+#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
@@ -145,6 +175,9 @@ void RiscvHwprobe::add_features_from_query_result() {
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBS)) {
VM_Version::ext_Zbs.enable_feature();
}
+ if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFH)) {
+ VM_Version::ext_Zfh.enable_feature();
+ }
if (is_valid(RISCV_HWPROBE_KEY_CPUPERF_0)) {
VM_Version::unaligned_access.enable_feature(
query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK);
diff --git a/src/hotspot/os_cpu/linux_riscv/safefetch_linux_riscv.S b/src/hotspot/os_cpu/linux_riscv/safefetch_linux_riscv.S
index ecf0bac6f9e78..150df7567bdb8 100644
--- a/src/hotspot/os_cpu/linux_riscv/safefetch_linux_riscv.S
+++ b/src/hotspot/os_cpu/linux_riscv/safefetch_linux_riscv.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -30,6 +30,13 @@
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
+ .hidden SafeFetchN_impl
+ .hidden _SafeFetchN_fault
+ .hidden _SafeFetchN_continuation
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
# Support for int SafeFetch32(int* address, int defaultval);
#
# x10 (a0) : address
diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
index 354dbd70bb4e1..c7d61b33829ab 100644
--- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
@@ -169,13 +169,13 @@ void VM_Version::os_aux_features() {
}
VM_Version::VM_MODE VM_Version::parse_satp_mode(const char* vm_mode) {
- if (!strcmp(vm_mode, "sv39")) {
+ if (!strncmp(vm_mode, "sv39", sizeof "sv39" - 1)) {
return VM_SV39;
- } else if (!strcmp(vm_mode, "sv48")) {
+ } else if (!strncmp(vm_mode, "sv48", sizeof "sv48" - 1)) {
return VM_SV48;
- } else if (!strcmp(vm_mode, "sv57")) {
+ } else if (!strncmp(vm_mode, "sv57", sizeof "sv57" - 1)) {
return VM_SV57;
- } else if (!strcmp(vm_mode, "sv64")) {
+ } else if (!strncmp(vm_mode, "sv64", sizeof "sv64" - 1)) {
return VM_SV64;
} else {
return VM_MBARE;
@@ -197,7 +197,7 @@ char* VM_Version::os_uarch_additional_features() {
if ((p = strchr(buf, ':')) != nullptr) {
if (mode == VM_NOTSET) {
if (strncmp(buf, "mmu", sizeof "mmu" - 1) == 0) {
- mode = VM_Version::parse_satp_mode(p);
+ mode = VM_Version::parse_satp_mode(p + 2);
}
}
if (ret == nullptr) {
@@ -242,6 +242,10 @@ void VM_Version::rivos_features() {
ext_Zcb.enable_feature();
+ ext_Zfh.enable_feature();
+
+ ext_Zacas.enable_feature();
+ ext_Zicboz.enable_feature();
ext_Zicsr.enable_feature();
ext_Zifencei.enable_feature();
ext_Zic64b.enable_feature();
diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
index 033ea14ead6a4..5aa65e705d9ed 100644
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
@@ -28,7 +28,6 @@
// no precompiled headers
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
diff --git a/src/hotspot/os_cpu/linux_s390/safefetch_linux_s390.S b/src/hotspot/os_cpu/linux_s390/safefetch_linux_s390.S
index 47fe82f5a278b..43d50c798e534 100644
--- a/src/hotspot/os_cpu/linux_s390/safefetch_linux_s390.S
+++ b/src/hotspot/os_cpu/linux_s390/safefetch_linux_s390.S
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
- * 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
@@ -30,6 +30,13 @@
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
+ .hidden SafeFetchN_impl
+ .hidden _SafeFetchN_fault
+ .hidden _SafeFetchN_continuation
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
# Support for int SafeFetch32(int* address, int defaultval);
#
# r2 : address
diff --git a/src/hotspot/os_cpu/linux_x86/linux_x86_32.S b/src/hotspot/os_cpu/linux_x86/linux_x86_32.S
index 344358172defd..e23cd2b9164ae 100644
--- a/src/hotspot/os_cpu/linux_x86/linux_x86_32.S
+++ b/src/hotspot/os_cpu/linux_x86/linux_x86_32.S
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 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
@@ -21,28 +21,41 @@
# questions.
#
+ .globl SpinPause
# NOTE WELL! The _Copy functions are called directly
- # from server-compiler-generated code via CallLeafNoFP,
- # which means that they *must* either not use floating
- # point or use it in the same manner as does the server
- # compiler.
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
.globl _Copy_arrayof_conjoint_bytes
.globl _Copy_conjoint_jshorts_atomic
- .globl _Copy_arrayof_conjoint_jshorts
+ .globl _Copy_arrayof_conjoint_jshorts
.globl _Copy_conjoint_jints_atomic
.globl _Copy_arrayof_conjoint_jints
- .globl _Copy_conjoint_jlongs_atomic
- .globl _mmx_Copy_arrayof_conjoint_jshorts
+ .globl _Copy_conjoint_jlongs_atomic
+ .globl _mmx_Copy_arrayof_conjoint_jshorts
.globl _Atomic_cmpxchg_long
.globl _Atomic_move_long
- .text
+ .hidden SpinPause
- .globl SpinPause
- .type SpinPause,@function
+ .hidden _Copy_arrayof_conjoint_bytes
+ .hidden _Copy_conjoint_jshorts_atomic
+ .hidden _Copy_arrayof_conjoint_jshorts
+ .hidden _Copy_conjoint_jints_atomic
+ .hidden _Copy_arrayof_conjoint_jints
+ .hidden _Copy_conjoint_jlongs_atomic
+ .hidden _mmx_Copy_arrayof_conjoint_jshorts
+
+ .hidden _Atomic_cmpxchg_long
+ .hidden _Atomic_move_long
+
+ .text
+
+ .type SpinPause,@function
.p2align 4,,15
SpinPause:
rep
@@ -55,7 +68,7 @@ SpinPause:
# size_t count)
#
.p2align 4,,15
- .type _Copy_arrayof_conjoint_bytes,@function
+ .type _Copy_arrayof_conjoint_bytes,@function
_Copy_arrayof_conjoint_bytes:
pushl %esi
movl 4+12(%esp),%ecx # count
@@ -115,7 +128,7 @@ acb_CopyLeft:
jbe 2f # <= 32 dwords
rep; smovl
jmp 4f
- .space 8
+ .space 8
2: subl %esi,%edi
.p2align 4,,15
3: movl (%esi),%edx
@@ -131,7 +144,7 @@ acb_CopyLeft:
addl $3,%esi
6: movb (%esi),%dl
movb %dl,(%edi,%esi,1)
- subl $1,%esi
+ subl $1,%esi
subl $1,%ecx
jnz 6b
7: cld
@@ -143,7 +156,7 @@ acb_CopyLeft:
# void* to,
# size_t count)
.p2align 4,,15
- .type _Copy_conjoint_jshorts_atomic,@function
+ .type _Copy_conjoint_jshorts_atomic,@function
_Copy_conjoint_jshorts_atomic:
pushl %esi
movl 4+12(%esp),%ecx # count
@@ -230,7 +243,7 @@ cs_CopyLeft:
# void* to,
# size_t count)
.p2align 4,,15
- .type _Copy_arrayof_conjoint_jshorts,@function
+ .type _Copy_arrayof_conjoint_jshorts,@function
_Copy_arrayof_conjoint_jshorts:
pushl %esi
movl 4+12(%esp),%ecx # count
@@ -307,8 +320,8 @@ acs_CopyLeft:
# Equivalent to
# arrayof_conjoint_jints
.p2align 4,,15
- .type _Copy_conjoint_jints_atomic,@function
- .type _Copy_arrayof_conjoint_jints,@function
+ .type _Copy_conjoint_jints_atomic,@function
+ .type _Copy_arrayof_conjoint_jints,@function
_Copy_conjoint_jints_atomic:
_Copy_arrayof_conjoint_jints:
pushl %esi
@@ -384,7 +397,7 @@ ci_CopyLeft:
# }
*/
.p2align 4,,15
- .type _Copy_conjoint_jlongs_atomic,@function
+ .type _Copy_conjoint_jlongs_atomic,@function
_Copy_conjoint_jlongs_atomic:
movl 4+8(%esp),%ecx # count
movl 4+0(%esp),%eax # from
@@ -413,7 +426,7 @@ cla_CopyLeft:
# void* to,
# size_t count)
.p2align 4,,15
- .type _mmx_Copy_arrayof_conjoint_jshorts,@function
+ .type _mmx_Copy_arrayof_conjoint_jshorts,@function
_mmx_Copy_arrayof_conjoint_jshorts:
pushl %esi
movl 4+12(%esp),%ecx
@@ -465,8 +478,8 @@ mmx_acs_CopyRight:
cmpl $16,%ecx
jge 4b
emms
- testl %ecx,%ecx
- ja 1b
+ testl %ecx,%ecx
+ ja 1b
5: andl $1,%eax
je 7f
6: movw (%esi),%dx
@@ -511,7 +524,7 @@ mmx_acs_CopyLeft:
# jlong exchange_value)
#
.p2align 4,,15
- .type _Atomic_cmpxchg_long,@function
+ .type _Atomic_cmpxchg_long,@function
_Atomic_cmpxchg_long:
# 8(%esp) : return PC
pushl %ebx # 4(%esp) : old %ebx
@@ -530,7 +543,7 @@ _Atomic_cmpxchg_long:
# Support for jlong Atomic::load and Atomic::store.
# void _Atomic_move_long(const volatile jlong* src, volatile jlong* dst)
.p2align 4,,15
- .type _Atomic_move_long,@function
+ .type _Atomic_move_long,@function
_Atomic_move_long:
movl 4(%esp), %eax # src
fildll (%eax)
diff --git a/src/hotspot/os_cpu/linux_x86/linux_x86_64.S b/src/hotspot/os_cpu/linux_x86/linux_x86_64.S
index 89d98cb583786..65580a194afab 100644
--- a/src/hotspot/os_cpu/linux_x86/linux_x86_64.S
+++ b/src/hotspot/os_cpu/linux_x86/linux_x86_64.S
@@ -1,5 +1,5 @@
-#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+#
+# Copyright (c) 2004, 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
@@ -21,24 +21,34 @@
# questions.
#
+ .globl SpinPause
# NOTE WELL! The _Copy functions are called directly
- # from server-compiler-generated code via CallLeafNoFP,
- # which means that they *must* either not use floating
- # point or use it in the same manner as does the server
- # compiler.
-
+ # from server-compiler-generated code via CallLeafNoFP,
+ # which means that they *must* either not use floating
+ # point or use it in the same manner as does the server
+ # compiler.
+
.globl _Copy_arrayof_conjoint_bytes
- .globl _Copy_arrayof_conjoint_jshorts
+ .globl _Copy_arrayof_conjoint_jshorts
.globl _Copy_conjoint_jshorts_atomic
.globl _Copy_arrayof_conjoint_jints
.globl _Copy_conjoint_jints_atomic
.globl _Copy_arrayof_conjoint_jlongs
.globl _Copy_conjoint_jlongs_atomic
- .text
+ .hidden SpinPause
+
+ .hidden _Copy_arrayof_conjoint_bytes
+ .hidden _Copy_arrayof_conjoint_jshorts
+ .hidden _Copy_conjoint_jshorts_atomic
+ .hidden _Copy_arrayof_conjoint_jints
+ .hidden _Copy_conjoint_jints_atomic
+ .hidden _Copy_arrayof_conjoint_jlongs
+ .hidden _Copy_conjoint_jlongs_atomic
+
+ .text
- .globl SpinPause
.align 16
.type SpinPause,@function
SpinPause:
@@ -55,7 +65,7 @@ SpinPause:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- .type _Copy_arrayof_conjoint_bytes,@function
+ .type _Copy_arrayof_conjoint_bytes,@function
_Copy_arrayof_conjoint_bytes:
movq %rdx,%r8 # byte count
shrq $3,%rdx # qword count
@@ -63,7 +73,7 @@ _Copy_arrayof_conjoint_bytes:
leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1
jbe acb_CopyRight
cmpq %rax,%rsi
- jbe acb_CopyLeft
+ jbe acb_CopyLeft
acb_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -157,8 +167,8 @@ acb_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- .type _Copy_arrayof_conjoint_jshorts,@function
- .type _Copy_conjoint_jshorts_atomic,@function
+ .type _Copy_arrayof_conjoint_jshorts,@function
+ .type _Copy_conjoint_jshorts_atomic,@function
_Copy_arrayof_conjoint_jshorts:
_Copy_conjoint_jshorts_atomic:
movq %rdx,%r8 # word count
@@ -167,7 +177,7 @@ _Copy_conjoint_jshorts_atomic:
leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2
jbe acs_CopyRight
cmpq %rax,%rsi
- jbe acs_CopyLeft
+ jbe acs_CopyLeft
acs_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -247,8 +257,8 @@ acs_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- .type _Copy_arrayof_conjoint_jints,@function
- .type _Copy_conjoint_jints_atomic,@function
+ .type _Copy_arrayof_conjoint_jints,@function
+ .type _Copy_conjoint_jints_atomic,@function
_Copy_arrayof_conjoint_jints:
_Copy_conjoint_jints_atomic:
movq %rdx,%r8 # dword count
@@ -257,7 +267,7 @@ _Copy_conjoint_jints_atomic:
leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4
jbe aci_CopyRight
cmpq %rax,%rsi
- jbe aci_CopyLeft
+ jbe aci_CopyLeft
aci_CopyRight:
leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8
leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8
@@ -326,15 +336,15 @@ aci_CopyLeft:
# rdx - count, treated as ssize_t
#
.p2align 4,,15
- .type _Copy_arrayof_conjoint_jlongs,@function
- .type _Copy_conjoint_jlongs_atomic,@function
+ .type _Copy_arrayof_conjoint_jlongs,@function
+ .type _Copy_conjoint_jlongs_atomic,@function
_Copy_arrayof_conjoint_jlongs:
_Copy_conjoint_jlongs_atomic:
cmpq %rdi,%rsi
leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8
jbe acl_CopyRight
cmpq %rax,%rsi
- jbe acl_CopyLeft
+ jbe acl_CopyLeft
acl_CopyRight:
leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8
negq %rdx
diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
index b211330409d59..4dcaedf71da8c 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, 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
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
@@ -165,7 +164,7 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
-intptr_t* _get_previous_fp() {
+static intptr_t* _get_previous_fp() {
#if defined(__clang__)
intptr_t **ebp;
__asm__ __volatile__ ("mov %%" SPELL_REG_FP ", %0":"=r"(ebp):);
diff --git a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S
index 492b1207db6e2..54775cb7e8ede 100644
--- a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S
+++ b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S
@@ -1,6 +1,6 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
-# 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
@@ -25,7 +25,11 @@
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
- .text
+ .hidden SafeFetch32_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetch32_continuation
+
+ .text
# Support for int SafeFetch32(int* address, int defaultval);
#
diff --git a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_64.S b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_64.S
index 617851e8327d4..1937e71708897 100644
--- a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_64.S
+++ b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_64.S
@@ -1,6 +1,6 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
-# 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
@@ -28,7 +28,14 @@
.globl _SafeFetch32_continuation
.globl _SafeFetchN_continuation
- .text
+ .hidden SafeFetch32_impl
+ .hidden SafeFetchN_impl
+ .hidden _SafeFetch32_fault
+ .hidden _SafeFetchN_fault
+ .hidden _SafeFetch32_continuation
+ .hidden _SafeFetchN_continuation
+
+ .text
# Support for int SafeFetch32(int* address, int defaultval);
diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
index 1ce73588524c1..d593c46d15d91 100644
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
@@ -27,7 +27,6 @@
#include "asm/assembler.inline.hpp"
#include "atomic_linux_zero.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
index 46f718a9cd0f5..78e98609b6bdc 100644
--- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
+++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "code/nativeInst.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
index 4e18334315a37..7e0814c014bec 100644
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp
index d27bf0865608a..93fa7451dc0b9 100644
--- a/src/hotspot/share/adlc/archDesc.cpp
+++ b/src/hotspot/share/adlc/archDesc.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 1997, 2023, 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
@@ -24,6 +24,7 @@
// archDesc.cpp - Internal format for architecture definition
+#include
#include "adlc.hpp"
static FILE *errfile = stderr;
@@ -684,6 +685,98 @@ bool ArchDesc::verify() {
return true;
}
+class MarkUsageFormClosure : public FormClosure {
+private:
+ ArchDesc* _ad;
+ std::unordered_set