mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-23 13:20:34 +00:00
Merge remote-tracking branch 'upstream_jdk/master' into JDK-8374694
This commit is contained in:
commit
7e2a9cb329
6
.github/actions/build-jtreg/action.yml
vendored
6
.github/actions/build-jtreg/action.yml
vendored
@ -37,13 +37,13 @@ runs:
|
||||
|
||||
- name: 'Check cache for already built JTReg'
|
||||
id: get-cached
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: jtreg/installed
|
||||
key: jtreg-${{ steps.version.outputs.value }}
|
||||
|
||||
- name: 'Checkout the JTReg source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: openjdk/jtreg
|
||||
ref: jtreg-${{ steps.version.outputs.value }}
|
||||
@ -61,7 +61,7 @@ runs:
|
||||
if: (steps.get-cached.outputs.cache-hit != 'true')
|
||||
|
||||
- name: 'Upload JTReg artifact'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: bundles-jtreg-${{ steps.version.outputs.value }}
|
||||
path: jtreg/installed
|
||||
|
||||
4
.github/actions/do-build/action.yml
vendored
4
.github/actions/do-build/action.yml
vendored
@ -66,7 +66,7 @@ runs:
|
||||
shell: bash
|
||||
|
||||
- name: 'Upload build logs'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
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@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: core.setFailed('Build failed. See summary for details.')
|
||||
if: steps.check.outputs.failure == 'true'
|
||||
|
||||
2
.github/actions/get-bootjdk/action.yml
vendored
2
.github/actions/get-bootjdk/action.yml
vendored
@ -65,7 +65,7 @@ runs:
|
||||
|
||||
- name: 'Check cache for BootJDK'
|
||||
id: get-cached-bootjdk
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: bootjdk/jdk
|
||||
key: boot-jdk-${{ inputs.platform }}-${{ steps.sha256.outputs.value }}
|
||||
|
||||
6
.github/actions/get-bundles/action.yml
vendored
6
.github/actions/get-bundles/action.yml
vendored
@ -54,14 +54,14 @@ runs:
|
||||
steps:
|
||||
- name: 'Download bundles artifact'
|
||||
id: download-bundles
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
|
||||
path: bundles
|
||||
continue-on-error: true
|
||||
|
||||
- name: 'Download bundles artifact (retry)'
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
|
||||
path: bundles
|
||||
@ -69,7 +69,7 @@ runs:
|
||||
|
||||
- name: 'Download static bundles artifact'
|
||||
id: download-static-bundles
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}
|
||||
path: bundles
|
||||
|
||||
2
.github/actions/get-gtest/action.yml
vendored
2
.github/actions/get-gtest/action.yml
vendored
@ -40,7 +40,7 @@ runs:
|
||||
var: GTEST_VERSION
|
||||
|
||||
- name: 'Checkout GTest source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: google/googletest
|
||||
ref: 'v${{ steps.version.outputs.value }}'
|
||||
|
||||
2
.github/actions/get-jtreg/action.yml
vendored
2
.github/actions/get-jtreg/action.yml
vendored
@ -41,7 +41,7 @@ runs:
|
||||
|
||||
- name: 'Download JTReg artifact'
|
||||
id: download-jtreg
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundles-jtreg-${{ steps.version.outputs.value }}
|
||||
path: jtreg/installed
|
||||
|
||||
2
.github/actions/get-msys2/action.yml
vendored
2
.github/actions/get-msys2/action.yml
vendored
@ -31,7 +31,7 @@ runs:
|
||||
steps:
|
||||
- name: 'Install MSYS2'
|
||||
id: msys2
|
||||
uses: msys2/setup-msys2@v2.28.0
|
||||
uses: msys2/setup-msys2@v2.31.0
|
||||
with:
|
||||
install: 'autoconf tar unzip zip make'
|
||||
path-type: minimal
|
||||
|
||||
2
.github/actions/upload-bundles/action.yml
vendored
2
.github/actions/upload-bundles/action.yml
vendored
@ -87,7 +87,7 @@ runs:
|
||||
shell: bash
|
||||
|
||||
- name: 'Upload bundles artifact'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}${{ inputs.bundle-suffix }}
|
||||
path: bundles
|
||||
|
||||
5
.github/pull_request_template.md
vendored
Normal file
5
.github/pull_request_template.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
|
||||
---------
|
||||
- [ ] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
|
||||
2
.github/workflows/build-alpine-linux.yml
vendored
2
.github/workflows/build-alpine-linux.yml
vendored
@ -74,7 +74,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Install toolchain and dependencies'
|
||||
run: |
|
||||
|
||||
4
.github/workflows/build-cross-compile.yml
vendored
4
.github/workflows/build-cross-compile.yml
vendored
@ -94,7 +94,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Get the BootJDK'
|
||||
id: bootjdk
|
||||
@ -122,7 +122,7 @@ jobs:
|
||||
|
||||
- name: 'Check cache for sysroot'
|
||||
id: get-cached-sysroot
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: sysroot
|
||||
key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('./.github/workflows/build-cross-compile.yml') }}
|
||||
|
||||
2
.github/workflows/build-linux.yml
vendored
2
.github/workflows/build-linux.yml
vendored
@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Get the BootJDK'
|
||||
id: bootjdk
|
||||
|
||||
2
.github/workflows/build-macos.yml
vendored
2
.github/workflows/build-macos.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Get the BootJDK'
|
||||
id: bootjdk
|
||||
|
||||
2
.github/workflows/build-windows.yml
vendored
2
.github/workflows/build-windows.yml
vendored
@ -83,7 +83,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Get MSYS2'
|
||||
uses: ./.github/actions/get-msys2
|
||||
|
||||
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the scripts'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -128,7 +128,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 'Get MSYS2'
|
||||
uses: ./.github/actions/get-msys2
|
||||
@ -239,7 +239,7 @@ jobs:
|
||||
if: always()
|
||||
|
||||
- name: 'Upload test results'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
path: results
|
||||
name: ${{ steps.package.outputs.artifact-name }}
|
||||
@ -247,7 +247,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@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: core.setFailed('${{ steps.run-tests.outputs.error-message }}')
|
||||
if: steps.run-tests.outputs.failure == 'true'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,6 +16,7 @@ NashornProfile.txt
|
||||
**/JTreport/**
|
||||
**/JTwork/**
|
||||
/src/utils/LogCompilation/target/
|
||||
/src/utils/LogCompilation/logc.jar
|
||||
/.project/
|
||||
/.settings/
|
||||
/compile_commands.json
|
||||
|
||||
@ -187,14 +187,18 @@ fi
|
||||
SOURCE_PREFIX="<sourceFolder url=\"file://"
|
||||
SOURCE_POSTFIX="\" isTestSource=\"false\" />"
|
||||
|
||||
# SOURCES is a single string containing embeded newlines.
|
||||
for root in $MODULE_ROOTS; do
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
root=`$CYGPATH -am $root`
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
root=`wslpath -am $root`
|
||||
fi
|
||||
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
# Add line termination/indentation for everything after the first entry.
|
||||
if [ "x$SOURCES" != "x" ]; then
|
||||
SOURCES="${SOURCES}\n "
|
||||
fi
|
||||
SOURCES="${SOURCES}${SOURCE_PREFIX}${root}${SOURCE_POSTFIX}"
|
||||
done
|
||||
|
||||
add_replacement "###SOURCE_ROOTS###" "$SOURCES"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/bin/bash -f
|
||||
|
||||
#
|
||||
# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,13 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
# Script to update the Copyright YEAR range in Mercurial & Git sources.
|
||||
# Script to update the Copyright YEAR range in Git sources.
|
||||
# (Originally from xdono, Thanks!)
|
||||
|
||||
# To update Copyright years for changes in a specific branch,
|
||||
# you use a command along these lines:
|
||||
# $ git diff upstream/master...<branch-name> | lsdiff | cut -d '/' -f 2- | bash bin/update_copyright_year.sh -m -
|
||||
|
||||
#------------------------------------------------------------
|
||||
copyright="Copyright"
|
||||
copyright_symbol="(c)"
|
||||
@ -47,7 +51,7 @@ rm -f -r ${tmp}
|
||||
mkdir -p ${tmp}
|
||||
total=0
|
||||
|
||||
usage="Usage: `basename "$0"` [-c company] [-y year] [-h|f]"
|
||||
usage="Usage: `basename "$0"` [-c company] [-y year] [-m file] [-h|f]"
|
||||
Help()
|
||||
{
|
||||
# Display Help
|
||||
@ -65,15 +69,18 @@ Help()
|
||||
echo "-b Specifies the base reference for change set lookup."
|
||||
echo "-f Updates the copyright for all change sets in a given year,"
|
||||
echo " as specified by -y. Overrides -b flag."
|
||||
echo "-m Read the list of modified files from the given file,"
|
||||
echo " use - to read from stdin"
|
||||
echo "-h Print this help."
|
||||
echo
|
||||
}
|
||||
|
||||
full_year=false
|
||||
base_reference=master
|
||||
modified_files_origin="";
|
||||
|
||||
# Process options
|
||||
while getopts "b:c:fhy:" option; do
|
||||
while getopts "b:c:fhm:y:" option; do
|
||||
case $option in
|
||||
b) # supplied base reference
|
||||
base_reference=${OPTARG}
|
||||
@ -91,6 +98,9 @@ while getopts "b:c:fhy:" option; do
|
||||
y) # supplied company year
|
||||
year=${OPTARG}
|
||||
;;
|
||||
m) # modified files will be read from the given origin
|
||||
modified_files_origin="${OPTARG}"
|
||||
;;
|
||||
\?) # illegal option
|
||||
echo "$usage"
|
||||
exit 1
|
||||
@ -110,18 +120,10 @@ git status &> /dev/null && git_found=true
|
||||
if [ "$git_found" != "true" ]; then
|
||||
echo "Error: Please execute script from within a JDK git repository."
|
||||
exit 1
|
||||
else
|
||||
echo "Using Git version control system"
|
||||
vcs_status=(git ls-files -m)
|
||||
if [ "$full_year" = "true" ]; then
|
||||
vcs_list_changesets=(git log --no-merges --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H")
|
||||
else
|
||||
vcs_list_changesets=(git log --no-merges "${base_reference}..HEAD" --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H")
|
||||
fi
|
||||
vcs_changeset_message=(git log -1 --pretty=tformat:"%B") # followed by ${changeset}
|
||||
vcs_changeset_files=(git diff-tree --no-commit-id --name-only -r) # followed by ${changeset}
|
||||
fi
|
||||
|
||||
echo "Using Git version control system"
|
||||
|
||||
# Return true if it makes sense to edit this file
|
||||
saneFileToCheck()
|
||||
{
|
||||
@ -168,6 +170,25 @@ updateFile() # file
|
||||
echo "${changed}"
|
||||
}
|
||||
|
||||
# Update the copyright year on files sent in stdin
|
||||
updateFiles() # stdin: list of files to update
|
||||
{
|
||||
count=0
|
||||
fcount=0
|
||||
while read i; do
|
||||
fcount=`expr ${fcount} '+' 1`
|
||||
if [ `updateFile "${i}"` = "true" ] ; then
|
||||
count=`expr ${count} '+' 1`
|
||||
fi
|
||||
done
|
||||
if [ ${count} -gt 0 ] ; then
|
||||
printf " UPDATED year on %d of %d files.\n" ${count} ${fcount}
|
||||
total=`expr ${total} '+' ${count}`
|
||||
else
|
||||
printf " None of the %d files were changed.\n" ${fcount}
|
||||
fi
|
||||
}
|
||||
|
||||
# Update the copyright year on all files changed by this changeset
|
||||
updateChangesetFiles() # changeset
|
||||
{
|
||||
@ -178,18 +199,7 @@ updateChangesetFiles() # changeset
|
||||
| ${awk} -F' ' '{for(i=1;i<=NF;i++)print $i}' \
|
||||
> ${files}
|
||||
if [ -f "${files}" -a -s "${files}" ] ; then
|
||||
fcount=`cat ${files}| wc -l`
|
||||
for i in `cat ${files}` ; do
|
||||
if [ `updateFile "${i}"` = "true" ] ; then
|
||||
count=`expr ${count} '+' 1`
|
||||
fi
|
||||
done
|
||||
if [ ${count} -gt 0 ] ; then
|
||||
printf " UPDATED year on %d of %d files.\n" ${count} ${fcount}
|
||||
total=`expr ${total} '+' ${count}`
|
||||
else
|
||||
printf " None of the %d files were changed.\n" ${fcount}
|
||||
fi
|
||||
cat ${files} | updateFiles
|
||||
else
|
||||
printf " ERROR: No files changed in the changeset? Must be a mistake.\n"
|
||||
set -x
|
||||
@ -204,67 +214,80 @@ updateChangesetFiles() # changeset
|
||||
}
|
||||
|
||||
# Check if repository is clean
|
||||
vcs_status=(git ls-files -m)
|
||||
previous=`"${vcs_status[@]}"|wc -l`
|
||||
if [ ${previous} -ne 0 ] ; then
|
||||
echo "WARNING: This repository contains previously edited working set files."
|
||||
echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`"
|
||||
fi
|
||||
|
||||
# Get all changesets this year
|
||||
all_changesets=${tmp}/all_changesets
|
||||
rm -f ${all_changesets}
|
||||
"${vcs_list_changesets[@]}" > ${all_changesets}
|
||||
|
||||
# Check changeset to see if it is Copyright only changes, filter changesets
|
||||
if [ -s ${all_changesets} ] ; then
|
||||
echo "Changesets made in ${year}: `cat ${all_changesets} | wc -l`"
|
||||
index=0
|
||||
cat ${all_changesets} | while read changeset ; do
|
||||
index=`expr ${index} '+' 1`
|
||||
desc=${tmp}/desc.${changeset}
|
||||
rm -f ${desc}
|
||||
echo "------------------------------------------------"
|
||||
"${vcs_changeset_message[@]}" "${changeset}" > ${desc}
|
||||
printf "%d: %s\n%s\n" ${index} "${changeset}" "`cat ${desc}|head -1`"
|
||||
if [ "${year}" = "2010" ] ; then
|
||||
if cat ${desc} | grep -i -F "Added tag" > /dev/null ; then
|
||||
printf " EXCLUDED tag changeset.\n"
|
||||
elif cat ${desc} | grep -i -F rebrand > /dev/null ; then
|
||||
printf " EXCLUDED rebrand changeset.\n"
|
||||
elif cat ${desc} | grep -i -F copyright > /dev/null ; then
|
||||
printf " EXCLUDED copyright changeset.\n"
|
||||
else
|
||||
updateChangesetFiles ${changeset}
|
||||
fi
|
||||
else
|
||||
if cat ${desc} | grep -i -F "Added tag" > /dev/null ; then
|
||||
printf " EXCLUDED tag changeset.\n"
|
||||
elif cat ${desc} | grep -i -F "copyright year" > /dev/null ; then
|
||||
printf " EXCLUDED copyright year changeset.\n"
|
||||
else
|
||||
updateChangesetFiles ${changeset}
|
||||
fi
|
||||
fi
|
||||
rm -f ${desc}
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${total} -gt 0 ] ; then
|
||||
echo "---------------------------------------------"
|
||||
echo "Updated the copyright year on a total of ${total} files."
|
||||
if [ ${previous} -eq 0 ] ; then
|
||||
echo "This count should match the count of modified files in the repository: ${vcs_status[*]}"
|
||||
else
|
||||
echo "WARNING: This repository contained previously edited working set files."
|
||||
fi
|
||||
echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`"
|
||||
if [ "x$modified_files_origin" != "x" ]; then
|
||||
cat $modified_files_origin | updateFiles
|
||||
else
|
||||
echo "---------------------------------------------"
|
||||
echo "No files were changed"
|
||||
if [ ${previous} -ne 0 ] ; then
|
||||
echo "WARNING: This repository contained previously edited working set files."
|
||||
fi
|
||||
echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`"
|
||||
# Get all changesets this year
|
||||
if [ "$full_year" = "true" ]; then
|
||||
vcs_list_changesets=(git log --no-merges --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H")
|
||||
else
|
||||
vcs_list_changesets=(git log --no-merges "${base_reference}..HEAD" --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H")
|
||||
fi
|
||||
vcs_changeset_message=(git log -1 --pretty=tformat:"%B") # followed by ${changeset}
|
||||
vcs_changeset_files=(git diff-tree --no-commit-id --name-only -r) # followed by ${changeset}
|
||||
|
||||
all_changesets=${tmp}/all_changesets
|
||||
rm -f ${all_changesets}
|
||||
"${vcs_list_changesets[@]}" > ${all_changesets}
|
||||
|
||||
# Check changeset to see if it is Copyright only changes, filter changesets
|
||||
if [ -s ${all_changesets} ] ; then
|
||||
echo "Changesets made in ${year}: `cat ${all_changesets} | wc -l`"
|
||||
index=0
|
||||
cat ${all_changesets} | while read changeset ; do
|
||||
index=`expr ${index} '+' 1`
|
||||
desc=${tmp}/desc.${changeset}
|
||||
rm -f ${desc}
|
||||
echo "------------------------------------------------"
|
||||
"${vcs_changeset_message[@]}" "${changeset}" > ${desc}
|
||||
printf "%d: %s\n%s\n" ${index} "${changeset}" "`cat ${desc}|head -1`"
|
||||
if [ "${year}" = "2010" ] ; then
|
||||
if cat ${desc} | grep -i -F "Added tag" > /dev/null ; then
|
||||
printf " EXCLUDED tag changeset.\n"
|
||||
elif cat ${desc} | grep -i -F rebrand > /dev/null ; then
|
||||
printf " EXCLUDED rebrand changeset.\n"
|
||||
elif cat ${desc} | grep -i -F copyright > /dev/null ; then
|
||||
printf " EXCLUDED copyright changeset.\n"
|
||||
else
|
||||
updateChangesetFiles ${changeset}
|
||||
fi
|
||||
else
|
||||
if cat ${desc} | grep -i -F "Added tag" > /dev/null ; then
|
||||
printf " EXCLUDED tag changeset.\n"
|
||||
elif cat ${desc} | grep -i -F "copyright year" > /dev/null ; then
|
||||
printf " EXCLUDED copyright year changeset.\n"
|
||||
else
|
||||
updateChangesetFiles ${changeset}
|
||||
fi
|
||||
fi
|
||||
rm -f ${desc}
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${total} -gt 0 ] ; then
|
||||
echo "---------------------------------------------"
|
||||
echo "Updated the copyright year on a total of ${total} files."
|
||||
if [ ${previous} -eq 0 ] ; then
|
||||
echo "This count should match the count of modified files in the repository: ${vcs_status[*]}"
|
||||
else
|
||||
echo "WARNING: This repository contained previously edited working set files."
|
||||
fi
|
||||
echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`"
|
||||
else
|
||||
echo "---------------------------------------------"
|
||||
echo "No files were changed"
|
||||
if [ ${previous} -ne 0 ] ; then
|
||||
echo "WARNING: This repository contained previously edited working set files."
|
||||
fi
|
||||
echo " ${vcs_status[*]} | wc -l = `"${vcs_status[@]}" | wc -l`"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
|
||||
@ -1385,10 +1385,9 @@ dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li>
|
||||
can specify it by <code>--with-alsa</code>.</p></li>
|
||||
</ul>
|
||||
<h4 id="x11-1">X11</h4>
|
||||
<p>You will need X11 libraries suitable for your <em>target</em> system.
|
||||
In most cases, using Debian's pre-built libraries work fine.</p>
|
||||
<p>Note that X11 is needed even if you only want to build a headless
|
||||
JDK.</p>
|
||||
<p>When not building a headless JDK, you will need X11 libraries
|
||||
suitable for your <em>target</em> system. In most cases, using Debian's
|
||||
pre-built libraries work fine.</p>
|
||||
<ul>
|
||||
<li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian
|
||||
Package Search</a>, search for the following packages for your
|
||||
|
||||
@ -1178,10 +1178,8 @@ Note that alsa is needed even if you only want to build a headless JDK.
|
||||
|
||||
#### X11
|
||||
|
||||
You will need X11 libraries suitable for your *target* system. In most cases,
|
||||
using Debian's pre-built libraries work fine.
|
||||
|
||||
Note that X11 is needed even if you only want to build a headless JDK.
|
||||
When not building a headless JDK, you will need X11 libraries suitable for your
|
||||
*target* system. In most cases, using Debian's pre-built libraries work fine.
|
||||
|
||||
* Go to [Debian Package Search](https://www.debian.org/distrib/packages),
|
||||
search for the following packages for your *target* system, and download them
|
||||
|
||||
@ -965,9 +965,8 @@ rather than <code>NULL</code>. See the paper for reasons to avoid
|
||||
<code>NULL</code>.</p>
|
||||
<p>Don't use (constant expression or literal) 0 for pointers. Note that
|
||||
C++14 removed non-literal 0 constants from <em>null pointer
|
||||
constants</em>, though some compilers continue to treat them as such.
|
||||
For historical reasons there may be lingering uses of 0 as a
|
||||
pointer.</p>
|
||||
constants</em>, though some compilers continue to treat them as
|
||||
such.</p>
|
||||
<h3 id="atomic"><atomic></h3>
|
||||
<p>Do not use facilities provided by the <code><atomic></code>
|
||||
header (<a
|
||||
|
||||
@ -884,8 +884,7 @@ rather than `NULL`. See the paper for reasons to avoid `NULL`.
|
||||
|
||||
Don't use (constant expression or literal) 0 for pointers. Note that C++14
|
||||
removed non-literal 0 constants from _null pointer constants_, though some
|
||||
compilers continue to treat them as such. For historical reasons there may be
|
||||
lingering uses of 0 as a pointer.
|
||||
compilers continue to treat them as such.
|
||||
|
||||
### <atomic>
|
||||
|
||||
|
||||
@ -284,9 +284,10 @@ possible, or if you want to use a fully qualified test descriptor, add
|
||||
<h3 id="gtest">Gtest</h3>
|
||||
<p><strong>Note:</strong> To be able to run the Gtest suite, you need to
|
||||
configure your build to be able to find a proper version of the gtest
|
||||
source. For details, see the section <a
|
||||
href="building.html#running-tests">"Running Tests" in the build
|
||||
documentation</a>.</p>
|
||||
source. For details, see the section <strong>"Running Tests" in the
|
||||
build documentation</strong> (<a
|
||||
href="building.html#running-tests">html</a>, <a
|
||||
href="building.md#running-tests">markdown</a>).</p>
|
||||
<p>Since the Hotspot Gtest suite is so quick, the default is to run all
|
||||
tests. This is specified by just <code>gtest</code>, or as a fully
|
||||
qualified test descriptor <code>gtest:all</code>.</p>
|
||||
|
||||
@ -198,8 +198,8 @@ use a fully qualified test descriptor, add `jtreg:`, e.g.
|
||||
|
||||
**Note:** To be able to run the Gtest suite, you need to configure your build
|
||||
to be able to find a proper version of the gtest source. For details, see the
|
||||
section ["Running Tests" in the build
|
||||
documentation](building.html#running-tests).
|
||||
section **"Running Tests" in the build
|
||||
documentation** ([html](building.html#running-tests), [markdown](building.md#running-tests)).
|
||||
|
||||
Since the Hotspot Gtest suite is so quick, the default is to run all tests.
|
||||
This is specified by just `gtest`, or as a fully qualified test descriptor
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -68,17 +68,19 @@ java.compiler.interim_EXTRA_FILES := \
|
||||
TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.compiler.interim/javax/tools/ToolProvider.java
|
||||
|
||||
################################################################################
|
||||
# Use the up-to-date PreviewFeature.java and NoPreview.java from the current
|
||||
# sources, instead of the versions from the boot JDK, as javac may be referring
|
||||
# to constants from the up-to-date versions.
|
||||
# Create a hybrid PreviewFeature.java that combines constants
|
||||
# from the current sources, as those can be used in javac APIs, and from the
|
||||
# bootstrap JDK, as those can be used from bootstrap JDK classfiles.
|
||||
|
||||
$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
|
||||
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
|
||||
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
|
||||
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
|
||||
))
|
||||
$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java: \
|
||||
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
|
||||
$(call LogInfo, Generating $@)
|
||||
$(JAVA) $(TOPDIR)/make/langtools/tools/previewfeature/SetupPreviewFeature.java \
|
||||
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
|
||||
$@
|
||||
|
||||
TARGETS += $(COPY_PREVIEW_FEATURES)
|
||||
|
||||
TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java
|
||||
|
||||
################################################################################
|
||||
# Setup the rules to build interim langtools, which is compiled by the boot
|
||||
@ -123,7 +125,8 @@ define SetupInterimModule
|
||||
$1_DEPS_INTERIM := $$(addsuffix .interim, $$(filter \
|
||||
$$(INTERIM_LANGTOOLS_BASE_MODULES), $$(call FindTransitiveDepsForModule, $1)))
|
||||
|
||||
$$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) $(COPY_PREVIEW_FEATURES)
|
||||
$$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java
|
||||
|
||||
TARGETS += $$(BUILD_$1.interim)
|
||||
endef
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,19 +93,16 @@ JAVADOC_DISABLED_DOCLINT_WARNINGS := missing
|
||||
JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio
|
||||
|
||||
# The initial set of options for javadoc
|
||||
# -XDaccessInternalAPI is a temporary workaround, see 8373909
|
||||
JAVADOC_OPTIONS := -use -keywords -notimestamp \
|
||||
-serialwarn -encoding utf-8 -docencoding utf-8 -breakiterator \
|
||||
-splitIndex --system none -javafx --expand-requires transitive \
|
||||
--override-methods=summary \
|
||||
-XDaccessInternalAPI
|
||||
--override-methods=summary
|
||||
|
||||
# The reference options must stay stable to allow for comparisons across the
|
||||
# development cycle.
|
||||
REFERENCE_OPTIONS := -XDignore.symbol.file=true -use -keywords -notimestamp \
|
||||
-serialwarn -encoding utf-8 -breakiterator -splitIndex --system none \
|
||||
-html5 -javafx --expand-requires transitive \
|
||||
-XDaccessInternalAPI
|
||||
-html5 -javafx --expand-requires transitive
|
||||
|
||||
# Should we add DRAFT stamps to the generated javadoc?
|
||||
ifeq ($(VERSION_IS_GA), true)
|
||||
|
||||
@ -70,12 +70,15 @@ CLASSLIST_FILE_VM_OPTS = \
|
||||
|
||||
# Save the stderr output of the command and print it along with stdout in case
|
||||
# something goes wrong.
|
||||
# The classlists must be generated with -Xint to avoid non-determinism
|
||||
# introduced by JIT compiled code
|
||||
$(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST_JAR)
|
||||
$(call MakeDir, $(LINK_OPT_DIR))
|
||||
$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
|
||||
$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $(JLI_TRACE_FILE)))
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \
|
||||
$(CLASSLIST_FILE_VM_OPTS) \
|
||||
-Xint \
|
||||
-Xlog:aot=off \
|
||||
-Xlog:cds=off \
|
||||
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
@ -90,6 +93,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
|
||||
-XX:SharedClassListFile=$@.interim -XX:SharedArchiveFile=$@.jsa \
|
||||
-Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
|
||||
$(CLASSLIST_FILE_VM_OPTS) \
|
||||
-Xint \
|
||||
--module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
-Xlog:aot=off \
|
||||
-Xlog:cds=off \
|
||||
|
||||
@ -44,6 +44,9 @@ ifeq ($(HSDIS_BACKEND), capstone)
|
||||
else ifeq ($(call isTargetCpuArch, aarch64), true)
|
||||
CAPSTONE_ARCH := CS_ARCH_$(CAPSTONE_ARCH_AARCH64_NAME)
|
||||
CAPSTONE_MODE := CS_MODE_ARM
|
||||
else ifeq ($(call isTargetCpuArch, arm), true)
|
||||
CAPSTONE_ARCH := CS_ARCH_ARM
|
||||
CAPSTONE_MODE := CS_MODE_ARM
|
||||
else
|
||||
$(error No support for Capstone on this platform)
|
||||
endif
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,7 +66,8 @@ CALLED_SPEC_TARGETS := $(filter-out $(ALL_GLOBAL_TARGETS), $(CALLED_TARGETS))
|
||||
ifeq ($(CALLED_SPEC_TARGETS), )
|
||||
SKIP_SPEC := true
|
||||
endif
|
||||
ifeq ($(findstring p, $(MAKEFLAGS))$(findstring q, $(MAKEFLAGS)), pq)
|
||||
MFLAGS_SINGLE := $(filter-out --%, $(MFLAGS))
|
||||
ifeq ($(findstring p, $(MFLAGS_SINGLE))$(findstring q, $(MFLAGS_SINGLE)), pq)
|
||||
SKIP_SPEC := true
|
||||
endif
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -972,6 +972,10 @@ define SetupRunJtregTestBody
|
||||
JTREG_AUTO_PROBLEM_LISTS += ProblemList-enable-preview.txt
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring -XX:+UseCompactObjectHeaders, $$(JTREG_ALL_OPTIONS)), )
|
||||
JTREG_AUTO_PROBLEM_LISTS += ProblemList-coh.txt
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), )
|
||||
# Accept both absolute paths as well as relative to the current test root.
|
||||
@ -1016,6 +1020,9 @@ define SetupRunJtregTestBody
|
||||
VM_OPTIONS := $$(JTREG_ALL_OPTIONS) ))
|
||||
$$(call LogWarn, AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE))
|
||||
$1_JTREG_BASIC_OPTIONS += -vmoption:-XX:AOTCache="$$($1_AOT_JDK_CACHE)"
|
||||
$1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \
|
||||
$$(addprefix $$($1_TEST_ROOT)/, ProblemList-AotJdk.txt) \
|
||||
))
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -369,6 +369,10 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
|
||||
IS_GNU_DATE=yes
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
# Likely at the AIX provided version of the date utility here, which is not compatible
|
||||
if test "x$OPENJDK_TARGET_OS" = "xaix"; then
|
||||
AC_MSG_ERROR([gnu date from AIX toolbox is required])
|
||||
fi
|
||||
IS_GNU_DATE=no
|
||||
fi
|
||||
AC_SUBST(IS_GNU_DATE)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -209,8 +209,12 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-wd"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-WX"
|
||||
|
||||
WARNINGS_ENABLE_ALL="-W3"
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-W3"
|
||||
WARNINGS_ENABLE_ADDITIONAL=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM=""
|
||||
DISABLED_WARNINGS="4800 5105"
|
||||
CFLAGS_CONVERSION_WARNINGS=
|
||||
;;
|
||||
|
||||
gcc)
|
||||
@ -218,14 +222,16 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
|
||||
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-Wall -Wextra"
|
||||
|
||||
# Additional warnings that are not activated by -Wall and -Wextra
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Winvalid-pch -Wpointer-arith -Wreturn-type \
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wformat=2 \
|
||||
-Winvalid-pch -Wpointer-arith -Wreturn-type \
|
||||
-Wsign-compare -Wtrampolines -Wtype-limits -Wundef -Wuninitialized \
|
||||
-Wunused-const-variable=1 -Wunused-function -Wunused-result \
|
||||
-Wunused-value"
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX="-Woverloaded-virtual -Wreorder"
|
||||
WARNINGS_ENABLE_ALL_CFLAGS="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ALL_CXXFLAGS="$WARNINGS_ENABLE_ALL_CFLAGS $WARNINGS_ENABLE_ADDITIONAL_CXX"
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM="-Wzero-as-null-pointer-constant"
|
||||
|
||||
# These warnings will never be turned on, since they generate too many
|
||||
# false positives.
|
||||
@ -234,6 +240,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
if test "x$OPENJDK_TARGET_CPU_ARCH" = "xppc"; then
|
||||
DISABLED_WARNINGS="$DISABLED_WARNINGS psabi"
|
||||
fi
|
||||
CFLAGS_CONVERSION_WARNINGS="-Wconversion -Wno-float-conversion"
|
||||
;;
|
||||
|
||||
clang)
|
||||
@ -241,22 +248,32 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
|
||||
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-Wall -Wextra"
|
||||
|
||||
# Additional warnings that are not activated by -Wall and -Wextra
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wpointer-arith -Wsign-compare -Wreorder \
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wformat=2 \
|
||||
-Wpointer-arith -Wsign-compare -Wreorder \
|
||||
-Wunused-function -Wundef -Wunused-value -Woverloaded-virtual"
|
||||
WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM="-Wzero-as-null-pointer-constant"
|
||||
|
||||
# These warnings will never be turned on, since they generate too many
|
||||
# false positives.
|
||||
DISABLED_WARNINGS="unknown-warning-option unused-parameter"
|
||||
CFLAGS_CONVERSION_WARNINGS="-Wimplicit-int-conversion"
|
||||
;;
|
||||
esac
|
||||
WARNINGS_ENABLE_ALL="$WARNINGS_ENABLE_ALL_NORMAL $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ALL_CXX="$WARNINGS_ENABLE_ALL $WARNINGS_ENABLE_ADDITIONAL_CXX"
|
||||
WARNINGS_ENABLE_ALL_JVM="$WARNINGS_ENABLE_ALL_CXX $WARNINGS_ENABLE_ADDITIONAL_JVM"
|
||||
|
||||
AC_SUBST(DISABLE_WARNING_PREFIX)
|
||||
AC_SUBST(BUILD_CC_DISABLE_WARNING_PREFIX)
|
||||
AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
|
||||
AC_SUBST(DISABLED_WARNINGS)
|
||||
AC_SUBST(DISABLED_WARNINGS_C)
|
||||
AC_SUBST(DISABLED_WARNINGS_CXX)
|
||||
AC_SUBST(CFLAGS_CONVERSION_WARNINGS)
|
||||
])
|
||||
|
||||
AC_DEFUN([FLAGS_SETUP_QUALITY_CHECKS],
|
||||
@ -527,12 +544,9 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fstack-protector"
|
||||
TOOLCHAIN_CFLAGS_JDK="-fvisibility=hidden -pipe -fstack-protector"
|
||||
# reduce lib size on linux in link step, this needs also special compile flags
|
||||
# do this on s390x also for libjvm (where serviceability agent is not supported)
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections"
|
||||
if test "x$OPENJDK_TARGET_CPU" = xs390x && test "x$DEBUG_LEVEL" == xrelease; then
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
# technically NOT for CXX (but since this gives *worse* performance, use
|
||||
# no-strict-aliasing everywhere!)
|
||||
@ -561,6 +575,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX
|
||||
fi
|
||||
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections"
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
|
||||
if test "x$OPENJDK_TARGET_OS" = xaix; then
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -ftls-model -fno-math-errno"
|
||||
TOOLCHAIN_CFLAGS_JDK="-ffunction-sections -fsigned-char"
|
||||
@ -604,19 +623,9 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
ADLC_LANGSTD_CXXFLAGS="$LANGSTD_CXXFLAGS"
|
||||
|
||||
# CFLAGS WARNINGS STUFF
|
||||
# Set JVM_CFLAGS warning handling
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL_CFLAGS"
|
||||
WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXXFLAGS"
|
||||
WARNING_CFLAGS_JVM="$WARNINGS_ENABLE_ALL_CXXFLAGS"
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
WARNING_CFLAGS="$WARNINGS_ENABLE_ALL"
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
WARNING_CFLAGS="$WARNINGS_ENABLE_ALL"
|
||||
|
||||
fi
|
||||
WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL"
|
||||
WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXX"
|
||||
WARNING_CFLAGS_JVM="$WARNINGS_ENABLE_ALL_JVM"
|
||||
|
||||
# Set some additional per-OS defines.
|
||||
|
||||
@ -878,12 +887,12 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
CFLAGS_JVM_COMMON="$ALWAYS_CFLAGS_JVM $ALWAYS_DEFINES_JVM \
|
||||
$TOOLCHAIN_CFLAGS_JVM ${$1_TOOLCHAIN_CFLAGS_JVM} \
|
||||
$OS_CFLAGS $OS_CFLAGS_JVM $CFLAGS_OS_DEF_JVM $DEBUG_CFLAGS_JVM \
|
||||
$WARNING_CFLAGS $WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \
|
||||
$WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \
|
||||
$REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS"
|
||||
|
||||
CFLAGS_JDK_COMMON="$ALWAYS_DEFINES_JDK $TOOLCHAIN_CFLAGS_JDK \
|
||||
$OS_CFLAGS $CFLAGS_OS_DEF_JDK $DEBUG_CFLAGS_JDK $DEBUG_OPTIONS_FLAGS_JDK \
|
||||
$WARNING_CFLAGS $WARNING_CFLAGS_JDK $DEBUG_SYMBOLS_CFLAGS_JDK \
|
||||
$DEBUG_SYMBOLS_CFLAGS_JDK \
|
||||
$FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS"
|
||||
|
||||
# Use ${$2EXTRA_CFLAGS} to block EXTRA_CFLAGS to be added to build flags.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -53,16 +53,15 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
# add --icf=all (Identical Code Folding — merges identical functions)
|
||||
BASIC_LDFLAGS="-Wl,-z,defs -Wl,-z,relro -Wl,-z,now -Wl,--no-as-needed -Wl,--exclude-libs,ALL"
|
||||
|
||||
BASIC_LDFLAGS_JVM_ONLY=""
|
||||
# Linux : remove unused code+data in link step
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = xs390x; then
|
||||
BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,--gc-sections"
|
||||
else
|
||||
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
|
||||
fi
|
||||
# keep vtables : -Wl,--undefined-glob=_ZTV* (but this seems not to work with gold ld)
|
||||
# so keep at least the Metadata vtable that is used in the serviceability agent
|
||||
BASIC_LDFLAGS_JVM_ONLY="$BASIC_LDFLAGS_JVM_ONLY -Wl,--gc-sections -Wl,--undefined=_ZTV8Metadata"
|
||||
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
|
||||
fi
|
||||
|
||||
BASIC_LDFLAGS_JVM_ONLY=""
|
||||
LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing $DEBUG_PREFIX_CFLAGS"
|
||||
|
||||
LDFLAGS_CXX_PARTIAL_LINKING="$MACHINE_FLAG -r"
|
||||
@ -80,6 +79,10 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
if test "x$CXX_IS_USER_SUPPLIED" = xfalse && test "x$CC_IS_USER_SUPPLIED" = xfalse; then
|
||||
UTIL_REQUIRE_TOOLCHAIN_PROGS(LLD, lld)
|
||||
fi
|
||||
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
|
||||
fi
|
||||
fi
|
||||
if test "x$OPENJDK_TARGET_OS" = xaix; then
|
||||
BASIC_LDFLAGS="-Wl,-b64 -Wl,-brtl -Wl,-bnorwexec -Wl,-blibpath:/usr/lib:lib -Wl,-bnoexpall \
|
||||
|
||||
@ -102,9 +102,20 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
|
||||
CHECKING_MSG: [if we should build headless-only (no GUI)])
|
||||
AC_SUBST(ENABLE_HEADLESS_ONLY)
|
||||
|
||||
# Avoid headless-only on macOS and Windows, it is not supported there
|
||||
if test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
AC_MSG_ERROR([headless-only is not supported on macOS and Windows])
|
||||
fi
|
||||
fi
|
||||
|
||||
# should we linktime gc unused code sections in the JDK build ?
|
||||
if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = xs390x; then
|
||||
LINKTIME_GC_DEFAULT=true
|
||||
if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xs390x" || test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then
|
||||
LINKTIME_GC_DEFAULT=true
|
||||
else
|
||||
LINKTIME_GC_DEFAULT=false
|
||||
fi
|
||||
else
|
||||
LINKTIME_GC_DEFAULT=false
|
||||
fi
|
||||
|
||||
@ -267,8 +267,8 @@ AC_DEFUN_ONCE([LIB_SETUP_ZLIB],
|
||||
LIBZ_LIBS=""
|
||||
if test "x$USE_EXTERNAL_LIBZ" = "xfalse"; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -I$TOPDIR/src/java.base/share/native/libzip/zlib"
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -DHAVE_UNISTD_H"
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx -o "x$OPENJDK_TARGET_OS" = xaix -o "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1"
|
||||
fi
|
||||
else
|
||||
LIBZ_LIBS="-lz"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,7 @@
|
||||
################################################################################
|
||||
|
||||
# Minimum supported versions
|
||||
JTREG_MINIMUM_VERSION=8.1
|
||||
JTREG_MINIMUM_VERSION=8.2.1
|
||||
GTEST_MINIMUM_VERSION=1.14.0
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -42,12 +42,12 @@ m4_include([lib-tests.m4])
|
||||
AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
|
||||
[
|
||||
# Check if X11 is needed
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
# No X11 support on windows or macosx
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows ||
|
||||
test "x$OPENJDK_TARGET_OS" = xmacosx ||
|
||||
test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
|
||||
NEEDS_LIB_X11=false
|
||||
else
|
||||
# All other instances need X11, even if building headless only, libawt still
|
||||
# needs X11 headers.
|
||||
# All other instances need X11 for libawt.
|
||||
NEEDS_LIB_X11=true
|
||||
fi
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -311,6 +311,12 @@ AC_DEFUN([PLATFORM_EXTRACT_TARGET_AND_BUILD],
|
||||
else
|
||||
OPENJDK_BUILD_OS_ENV="$VAR_OS"
|
||||
fi
|
||||
# Special handling for MSYS2 that reports a Cygwin triplet as the default host triplet.
|
||||
case `uname` in
|
||||
MSYS*)
|
||||
OPENJDK_BUILD_OS_ENV=windows.msys2
|
||||
;;
|
||||
esac
|
||||
OPENJDK_BUILD_CPU="$VAR_CPU"
|
||||
OPENJDK_BUILD_CPU_ARCH="$VAR_CPU_ARCH"
|
||||
OPENJDK_BUILD_CPU_BITS="$VAR_CPU_BITS"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -529,6 +529,7 @@ CFLAGS_WARNINGS_ARE_ERRORS := @CFLAGS_WARNINGS_ARE_ERRORS@
|
||||
DISABLED_WARNINGS := @DISABLED_WARNINGS@
|
||||
DISABLED_WARNINGS_C := @DISABLED_WARNINGS_C@
|
||||
DISABLED_WARNINGS_CXX := @DISABLED_WARNINGS_CXX@
|
||||
CFLAGS_CONVERSION_WARNINGS := @CFLAGS_CONVERSION_WARNINGS@
|
||||
|
||||
# A global flag (true or false) determining if native warnings are considered errors.
|
||||
WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@
|
||||
|
||||
@ -217,10 +217,12 @@ AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO_BAT_FILE],
|
||||
TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
[$PROGRAMFILES_X86/$VS_INSTALL_DIR], [well-known name])
|
||||
fi
|
||||
# Derive system drive root from CMD (which is at <drive>/windows/system32/cmd.exe)
|
||||
WINSYSDRIVE_ROOT="$(dirname "$(dirname "$(dirname "$CMD")")")"
|
||||
TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
[c:/program files/$VS_INSTALL_DIR], [well-known name])
|
||||
[$WINSYSDRIVE_ROOT/program files/$VS_INSTALL_DIR], [well-known name])
|
||||
TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
[c:/program files (x86)/$VS_INSTALL_DIR], [well-known name])
|
||||
[$WINSYSDRIVE_ROOT/program files (x86)/$VS_INSTALL_DIR], [well-known name])
|
||||
if test "x$SDK_INSTALL_DIR" != x; then
|
||||
if test "x$ProgramW6432" != x; then
|
||||
TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
@ -235,9 +237,9 @@ AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO_BAT_FILE],
|
||||
[$PROGRAMFILES/$SDK_INSTALL_DIR], [well-known name])
|
||||
fi
|
||||
TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
[c:/program files/$SDK_INSTALL_DIR], [well-known name])
|
||||
[$WINSYSDRIVE_ROOT/program files/$SDK_INSTALL_DIR], [well-known name])
|
||||
TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT([$TARGET_CPU], [$VS_VERSION],
|
||||
[c:/program files (x86)/$SDK_INSTALL_DIR], [well-known name])
|
||||
[$WINSYSDRIVE_ROOT/program files (x86)/$SDK_INSTALL_DIR], [well-known name])
|
||||
fi
|
||||
|
||||
VCVARS_VER=auto
|
||||
@ -338,7 +340,7 @@ AC_DEFUN([TOOLCHAIN_EXTRACT_VISUAL_STUDIO_ENV],
|
||||
OLDPATH="$PATH"
|
||||
# Make sure we only capture additions to PATH needed by VS.
|
||||
# Clear out path, but need system dir present for vsvars cmd file to be able to run
|
||||
export PATH=$WINENV_PREFIX/c/windows/system32
|
||||
export PATH="$(dirname "$CMD")"
|
||||
# The "| cat" is to stop SetEnv.Cmd to mess with system colors on some systems
|
||||
# We can't pass -vcvars_ver=$VCVARS_VER here because cmd.exe eats all '='
|
||||
# in bat file arguments. :-(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -141,6 +141,66 @@ endef
|
||||
# Make sure logging is setup for everyone that includes MakeBase.gmk.
|
||||
$(eval $(call SetupLogging))
|
||||
|
||||
################################################################################
|
||||
# Make does not have support for VARARGS, you can send variable amount
|
||||
# of arguments, but you can for example not append a list at the end.
|
||||
# It is therefore not easy to send the elements of a list of unknown
|
||||
# length as argument to a function. This can somewhat be worked around
|
||||
# by sending a list as an argument, and then interpreting each element
|
||||
# of the list as an argument to the function. However, Make is
|
||||
# limited, and using this method you can not easily send spaces.
|
||||
#
|
||||
# We need to quote strings for two reasons when sending them as
|
||||
# "variable append packs":
|
||||
#
|
||||
# 1) variable appends can include spaces, and those must be preserved
|
||||
# 2) variable appends can include assignment strings ":=", and those
|
||||
# must be quoted to a form so that we can recognise the "append pack".
|
||||
# We recognise an "append pack" by its lack of strict assignment ":="
|
||||
|
||||
Q := $(HASH)
|
||||
SpaceQ := $(Q)s
|
||||
AppendQ := $(Q)+
|
||||
AssignQ := $(Q)a
|
||||
QQ := $(Q)$(Q)
|
||||
|
||||
# $(call Quote,echo "#trala:=") -> echo#s"##trala#a"
|
||||
Quote = $(subst :=,$(AssignQ),$(subst $(SPACE),$(SpaceQ),$(subst $(Q),$(QQ),$1)))
|
||||
|
||||
# $(call Unquote,echo#s"##trala#a") -> echo "#trala:="
|
||||
Unquote = $(subst $(QQ),$(Q),$(subst $(SpaceQ),$(SPACE),$(subst $(AssignQ),:=,$1)))
|
||||
|
||||
# $(call QuoteAppend,name,some value) -> name#+some#svalue
|
||||
# $(call QuoteAppend,bad+=name,some value) -> error
|
||||
QuoteAppend = $(if $(findstring +=,$1),$(error you can not have += in a variable name: "$1"),$(call Quote,$1)$(AppendQ)$(call Quote,$2))
|
||||
|
||||
# $(call UnquoteAppendIndex,name#+some#svalue,1) -> name
|
||||
# $(call UnquoteAppendIndex,name#+some#svalue,2) -> some value
|
||||
UnquoteAppendIndex = $(call Unquote,$(word $2,$(subst $(AppendQ),$(SPACE),$1)))
|
||||
|
||||
# $(call FilterFiles,dir,%.cpp) -> file1.cpp file2.cpp (without path)
|
||||
FilterFiles = $(filter $2,$(notdir $(call FindFiles,$1)))
|
||||
|
||||
# $(call Unpack module_,file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion) -> module_file1.cpp_CXXFLAGS += -Wconversion
|
||||
# module_file2.cpp_CXXFLAGS += -Wconversion
|
||||
Unpack = $(foreach pair,$2,$1$(call UnquoteAppendIndex,$(pair),1) += $(call UnquoteAppendIndex,$(pair),2)$(NEWLINE))
|
||||
|
||||
# This macro takes four arguments:
|
||||
# $1: directory where to find files (striped), example: $(TOPDIR)/src/hotspot/share/gc/g1
|
||||
# $2: filter to match what to keep (striped), example: g1Concurrent%.cpp
|
||||
# $3: what flags to override (striped), example: _CXXFLAGS
|
||||
# $4: what value to append to the flag (striped), example: $(CFLAGS_CONVERSION_WARNINGS)
|
||||
#
|
||||
# The result will be a quoted string that can be unpacked to a list of
|
||||
# variable appendings (see macro Unpack above). You do not need to take
|
||||
# care of unpacking, it is done in NamedParamsMacroTemplate.
|
||||
#
|
||||
# This feature should only be used for warnings that we want to
|
||||
# incrementally add to the rest of the code base.
|
||||
#
|
||||
# $(call ExtendFlags,dir,%.cpp,_CXXFLAGS,-Wconversion) -> file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion
|
||||
ExtendFlags = $(foreach file,$(call FilterFiles,$(strip $1),$(strip $2)),$(call QuoteAppend,$(file)$(strip $3),$(strip $4)))
|
||||
|
||||
################################################################################
|
||||
|
||||
MAX_PARAMS := 96
|
||||
@ -166,7 +226,10 @@ define NamedParamsMacroTemplate
|
||||
Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk))
|
||||
# Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix
|
||||
$(foreach i, $(PARAM_SEQUENCE), $(if $(strip $($i)), \
|
||||
$(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE)))
|
||||
$(if $(findstring :=,$($i)), \
|
||||
$(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE), \
|
||||
$(call Unpack,$(strip $1)_,$($i)))))
|
||||
|
||||
# Debug print all named parameter names and values
|
||||
$(if $(findstring $(LOG_LEVEL), trace), \
|
||||
$(info $0 $(strip $1) $(foreach i, $(PARAM_SEQUENCE), \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,11 +35,17 @@ include ProcessMarkdown.gmk
|
||||
include $(TOPDIR)/make/ToolsJdk.gmk
|
||||
|
||||
LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher
|
||||
|
||||
LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \
|
||||
-I$(TOPDIR)/src/java.base/share/native/libjli \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \
|
||||
#
|
||||
|
||||
ifeq ($(call isTargetOs, aix), true)
|
||||
LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/aix/native/include
|
||||
endif
|
||||
|
||||
MACOSX_PLIST_DIR := $(TOPDIR)/src/java.base/macosx/native/launcher
|
||||
JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,24 +26,24 @@
|
||||
# Versions and download locations for dependencies used by GitHub Actions (GHA)
|
||||
|
||||
GTEST_VERSION=1.14.0
|
||||
JTREG_VERSION=8.1+1
|
||||
JTREG_VERSION=8.2.1+1
|
||||
|
||||
LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz
|
||||
LINUX_X64_BOOT_JDK_SHA256=59cdcaf255add4721de38eb411d4ecfe779356b61fb671aee63c7dec78054c2b
|
||||
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_linux-x64_bin.tar.gz
|
||||
LINUX_X64_BOOT_JDK_SHA256=83c78367f8c81257beef72aca4bbbf8e6dac8ca2b3a4546a85879a09e6e4e128
|
||||
|
||||
ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25%2B36/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25_36.tar.gz
|
||||
ALPINE_LINUX_X64_BOOT_JDK_SHA256=637e47474d411ed86134f413af7d5fef4180ddb0bf556347b7e74a88cf8904c8
|
||||
ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26%2B35/OpenJDK26U-jdk_x64_alpine-linux_hotspot_26_35.tar.gz
|
||||
ALPINE_LINUX_X64_BOOT_JDK_SHA256=c105e581fdccb4e7120d889235d1ad8d5b2bed0af4972bc881e0a8ba687c94a4
|
||||
|
||||
MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
|
||||
MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-aarch64_bin.tar.gz
|
||||
MACOS_AARCH64_BOOT_JDK_SHA256=2006337bf326fdfdf6117081751ba38c1c8706d63419ecac7ff102ff7c776876
|
||||
MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_macos-aarch64_bin.tar.gz
|
||||
MACOS_AARCH64_BOOT_JDK_SHA256=254586bcd1bf6dcd125ad667ac32562cb1e2ab1abf3a61fb117b6fabb571e765
|
||||
|
||||
MACOS_X64_BOOT_JDK_EXT=tar.gz
|
||||
MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-x64_bin.tar.gz
|
||||
MACOS_X64_BOOT_JDK_SHA256=47482ad9888991ecac9b2bcc131e2b53ff78aff275104cef85f66252308e8a09
|
||||
MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_macos-x64_bin.tar.gz
|
||||
MACOS_X64_BOOT_JDK_SHA256=8642b89d889c14ede2c446fd5bbe3621c8a3082e3df02013fd1658e39f52929a
|
||||
|
||||
WINDOWS_X64_BOOT_JDK_EXT=zip
|
||||
WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_windows-x64_bin.zip
|
||||
WINDOWS_X64_BOOT_JDK_SHA256=85bcc178461e2cb3c549ab9ca9dfa73afd54c09a175d6510d0884071867137d3
|
||||
WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_windows-x64_bin.zip
|
||||
WINDOWS_X64_BOOT_JDK_SHA256=2dd2d92c9374cd49a120fe9d916732840bf6bb9f0e0cc29794917a3c08b99c5f
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) {
|
||||
};
|
||||
};
|
||||
|
||||
common.boot_jdk_version = "25";
|
||||
common.boot_jdk_build_number = "37";
|
||||
common.boot_jdk_version = "26";
|
||||
common.boot_jdk_build_number = "35";
|
||||
common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-"
|
||||
+ common.boot_jdk_version
|
||||
+ (input.build_os == "macosx" ? ".jdk/Contents/Home" : "");
|
||||
@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
|
||||
jtreg: {
|
||||
server: "jpg",
|
||||
product: "jtreg",
|
||||
version: "8.1",
|
||||
version: "8.2.1",
|
||||
build_number: "1",
|
||||
file: "bundles/jtreg-8.1+1.zip",
|
||||
file: "bundles/jtreg-8.2.1+1.zip",
|
||||
environment_name: "JT_HOME",
|
||||
environment_path: input.get("jtreg", "home_path") + "/bin",
|
||||
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,6 +37,6 @@ DEFAULT_VERSION_DATE=2026-09-15
|
||||
DEFAULT_VERSION_CLASSFILE_MAJOR=71 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
|
||||
DEFAULT_VERSION_CLASSFILE_MINOR=0
|
||||
DEFAULT_VERSION_DOCS_API_SINCE=11
|
||||
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26 27"
|
||||
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="26 27"
|
||||
DEFAULT_JDK_SOURCE_TARGET_VERSION=27
|
||||
DEFAULT_PROMOTED_VERSION_PRE=ea
|
||||
|
||||
@ -78,7 +78,7 @@ else ifeq ($(BASE_OS), Fedora)
|
||||
endif
|
||||
BASE_URL := http://fedora.riscv.rocks/repos-dist/f$(BASE_OS_VERSION)/latest/$(ARCH)/Packages/
|
||||
else
|
||||
LATEST_ARCHIVED_OS_VERSION := 36
|
||||
LATEST_ARCHIVED_OS_VERSION := 41
|
||||
ifeq ($(filter aarch64 armhfp x86_64, $(ARCH)), )
|
||||
FEDORA_TYPE := fedora-secondary
|
||||
else
|
||||
|
||||
@ -63,6 +63,10 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \
|
||||
unused-result zero-as-null-pointer-constant, \
|
||||
DISABLED_WARNINGS_clang := format-nonliteral undef unused-result \
|
||||
zero-as-null-pointer-constant, \
|
||||
$(comment Disable deprecated-declarations warnings to workaround) \
|
||||
$(comment clang18+glibc12 bug https://github.com/llvm/llvm-project/issues/76515) \
|
||||
$(comment until the clang bug has been fixed) \
|
||||
DISABLED_WARNINGS_clang_gtest-all.cc := deprecated-declarations, \
|
||||
DISABLED_WARNINGS_microsoft := 4530, \
|
||||
DEFAULT_CFLAGS := false, \
|
||||
CFLAGS := $(JVM_CFLAGS) \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -105,7 +105,7 @@ DISABLED_WARNINGS_gcc := array-bounds comment delete-non-virtual-dtor \
|
||||
DISABLED_WARNINGS_clang := delete-non-abstract-non-virtual-dtor \
|
||||
invalid-offsetof missing-braces \
|
||||
sometimes-uninitialized unknown-pragmas unused-but-set-variable \
|
||||
unused-function unused-local-typedef unused-private-field unused-variable
|
||||
unused-local-typedef unused-private-field unused-variable
|
||||
|
||||
ifneq ($(DEBUG_LEVEL), release)
|
||||
# Assert macro gives warning
|
||||
@ -190,6 +190,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
|
||||
abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||
arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||
whitebox.cpp_CXXFLAGS := $(CFLAGS_SHIP_DEBUGINFO), \
|
||||
$(call ExtendFlags, $(TOPDIR)/src/hotspot/share/gc/g1, \
|
||||
g1Numa.cpp, _CXXFLAGS, $(CFLAGS_CONVERSION_WARNINGS)), \
|
||||
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc), \
|
||||
DISABLED_WARNINGS_gcc_ad_$(HOTSPOT_TARGET_CPU_ARCH).cpp := nonnull, \
|
||||
DISABLED_WARNINGS_gcc_bytecodeInterpreter.cpp := unused-label, \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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,10 +43,15 @@ JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \
|
||||
$(JVM_VARIANT_OUTPUTDIR)/gensrc
|
||||
#
|
||||
|
||||
ifeq ($(call isTargetOs, aix), true)
|
||||
ADD_PLATFORM_INCLUDE_DIR := -I$(TOPDIR)/src/java.base/aix/native/include
|
||||
endif
|
||||
|
||||
JVM_CFLAGS_INCLUDES += \
|
||||
$(patsubst %,-I%,$(JVM_SRC_DIRS)) \
|
||||
-I$(TOPDIR)/src/hotspot/share/include \
|
||||
-I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \
|
||||
$(ADD_PLATFORM_INCLUDE_DIR) \
|
||||
-I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
|
||||
-I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \
|
||||
-I$(TOPDIR)/src/java.base/share/native/libjimage \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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 @@ public class CLDRConverter {
|
||||
static final String EXEMPLAR_CITY_PREFIX = "timezone.excity.";
|
||||
static final String ZONE_NAME_PREFIX = "timezone.displayname.";
|
||||
static final String METAZONE_ID_PREFIX = "metazone.id.";
|
||||
static final String METAZONE_DSTOFFSET_PREFIX = "metazone.dstoffset.";
|
||||
static final String PARENT_LOCALE_PREFIX = "parentLocale.";
|
||||
static final String LIKELY_SCRIPT_PREFIX = "likelyScript.";
|
||||
static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE";
|
||||
@ -139,6 +140,11 @@ public class CLDRConverter {
|
||||
private static final Map<String, String> tzdbSubstLetters = HashMap.newHashMap(512);
|
||||
private static final Map<String, String> tzdbLinks = HashMap.newHashMap(512);
|
||||
|
||||
// Map of explicit dst offsets for metazones
|
||||
// key: time zone ID
|
||||
// value: explicit dstOffset for the corresponding metazone name
|
||||
static final Map<String, String> explicitDstOffsets = HashMap.newHashMap(32);
|
||||
|
||||
static enum DraftType {
|
||||
UNCONFIRMED,
|
||||
PROVISIONAL,
|
||||
@ -293,8 +299,10 @@ public class CLDRConverter {
|
||||
bundleGenerator = new ResourceBundleGenerator();
|
||||
|
||||
// Parse data independent of locales
|
||||
parseSupplemental();
|
||||
// parseBCP47() must precede parseSupplemental(). The latter depends
|
||||
// on IANA alias map, which is produced by the former.
|
||||
parseBCP47();
|
||||
parseSupplemental();
|
||||
|
||||
// rules maps
|
||||
pluralRules = generateRules(handlerPlurals);
|
||||
@ -536,6 +544,12 @@ public class CLDRConverter {
|
||||
|
||||
// canonical tz name map
|
||||
// alias -> primary
|
||||
//
|
||||
// Note that CLDR meta zones do not necessarily align with IANA's
|
||||
// current time zone identifiers. For example, the CLDR "India"
|
||||
// meta zone maps to "Asia/Calcutta", whereas IANA now uses
|
||||
// "Asia/Kolkata" for the zone. Accordingly, "canonical" here is
|
||||
// defined in terms of CLDR's zone mappings.
|
||||
handlerTimeZone.getData().forEach((k, v) -> {
|
||||
String[] ids = ((String)v).split("\\s");
|
||||
for (int i = 1; i < ids.length; i++) {
|
||||
@ -787,10 +801,7 @@ public class CLDRConverter {
|
||||
String tzKey = Optional.ofNullable((String)handlerSupplMeta.get(tzid))
|
||||
.orElse(tzid);
|
||||
// Follow link, if needed
|
||||
String tzLink = null;
|
||||
for (var k = tzKey; tzdbLinks.containsKey(k);) {
|
||||
k = tzLink = tzdbLinks.get(k);
|
||||
}
|
||||
String tzLink = getTZDBLink(tzKey);
|
||||
if (tzLink == null && tzdbLinks.containsValue(tzKey)) {
|
||||
// reverse link search
|
||||
// this is needed as in tzdb, "America/Buenos_Aires" links to
|
||||
@ -819,7 +830,7 @@ public class CLDRConverter {
|
||||
} else {
|
||||
// TZDB short names
|
||||
tznames = Arrays.copyOf(tznames, tznames.length);
|
||||
fillTZDBShortNames(tzid, tznames);
|
||||
fillTZDBShortNames(tzKey, tznames);
|
||||
names.put(tzid, tznames);
|
||||
}
|
||||
} else {
|
||||
@ -832,11 +843,13 @@ public class CLDRConverter {
|
||||
String metaKey = METAZONE_ID_PREFIX + meta;
|
||||
data = map.get(metaKey);
|
||||
if (data instanceof String[] tznames) {
|
||||
// TZDB short names
|
||||
tznames = Arrays.copyOf((String[])names.getOrDefault(metaKey, tznames), 6);
|
||||
fillTZDBShortNames(tzid, tznames);
|
||||
// Keep the metazone prefix here.
|
||||
names.putIfAbsent(metaKey, tznames);
|
||||
if (isDefaultZone(meta, tzKey)) {
|
||||
// Record the metazone names only from the default
|
||||
// (001) zone, with short names filled from TZDB
|
||||
tznames = Arrays.copyOf(tznames, tznames.length);
|
||||
fillTZDBShortNames(tzKey, tznames);
|
||||
names.put(metaKey, tznames);
|
||||
}
|
||||
names.put(tzid, meta);
|
||||
if (tzLink != null && availableIds.contains(tzLink)) {
|
||||
names.put(tzLink, meta);
|
||||
@ -859,6 +872,12 @@ public class CLDRConverter {
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
names.putAll(exCities);
|
||||
|
||||
// Explicit metazone offsets
|
||||
if (id.equals("root")) {
|
||||
explicitDstOffsets.forEach((k, v) ->
|
||||
names.put(METAZONE_DSTOFFSET_PREFIX + k, v));
|
||||
}
|
||||
|
||||
// If there's no UTC entry at this point, add an empty one
|
||||
if (!names.isEmpty() && !names.containsKey("UTC")) {
|
||||
names.putIfAbsent(METAZONE_ID_PREFIX + META_EMPTY_ZONE_NAME, EMPTY_ZONE);
|
||||
@ -1484,12 +1503,12 @@ public class CLDRConverter {
|
||||
* Fill the TZDB short names if there is no name provided by the CLDR
|
||||
*/
|
||||
private static void fillTZDBShortNames(String tzid, String[] names) {
|
||||
var val = tzdbShortNamesMap.get(tzdbLinks.getOrDefault(tzid, tzid));
|
||||
var val = tzdbShortNamesMap.getOrDefault(tzid, tzdbShortNamesMap.get(getTZDBLink(tzid)));
|
||||
if (val != null) {
|
||||
var format = val.split(NBSP)[0];
|
||||
var rule = val.split(NBSP)[1];
|
||||
IntStream.of(1, 3, 5).forEach(i -> {
|
||||
if (names[i] == null) {
|
||||
if (names[i] == null || names[i].isEmpty()) {
|
||||
if (format.contains("%s")) {
|
||||
names[i] = switch (i) {
|
||||
case 1 -> format.formatted(tzdbSubstLetters.get(rule + NBSP + STD));
|
||||
@ -1511,6 +1530,21 @@ public class CLDRConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDefaultZone(String meta, String tzid) {
|
||||
String zone001 = handlerMetaZones.zidMap().get(meta);
|
||||
var tzLink = getTZDBLink(tzid);
|
||||
return canonicalTZMap.getOrDefault(tzid, tzid).equals(zone001) ||
|
||||
tzLink != null && canonicalTZMap.getOrDefault(tzLink, tzLink).equals(zone001);
|
||||
}
|
||||
|
||||
private static String getTZDBLink(String tzid) {
|
||||
String tzLink = null;
|
||||
for (var k = tzid; tzdbLinks.containsKey(k);) {
|
||||
k = tzLink = tzdbLinks.get(k);
|
||||
}
|
||||
return tzLink;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert TZDB offsets to JDK's offsets, eg, "-08" to "GMT-08:00".
|
||||
* If it cannot recognize the pattern, return the argument as is.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -84,7 +84,15 @@ class MetaZonesParseHandler extends AbstractLDMLHandler<String> {
|
||||
|
||||
if (fromLDT.isBefore(now) && toLDT.isAfter(now)) {
|
||||
metazone = attributes.getValue("mzone");
|
||||
|
||||
// Explicit metazone DST offsets. Only the "dst" offset is needed,
|
||||
// as "std" is used by default when it doesn't match.
|
||||
String dstOffset = attributes.getValue("dstOffset");
|
||||
if (dstOffset != null) {
|
||||
CLDRConverter.explicitDstOffsets.put(tzid, dstOffset);
|
||||
}
|
||||
}
|
||||
|
||||
pushIgnoredContainer(qName);
|
||||
break;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -198,7 +198,8 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
} else if (value instanceof String) {
|
||||
String valStr = (String)value;
|
||||
if (type == BundleType.TIMEZONE &&
|
||||
!key.startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX) ||
|
||||
!(key.startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX) ||
|
||||
key.startsWith(CLDRConverter.METAZONE_DSTOFFSET_PREFIX)) ||
|
||||
valStr.startsWith(META_VALUE_PREFIX)) {
|
||||
out.printf(" { \"%s\", %s },\n", key, CLDRConverter.saveConvert(valStr, useJava));
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,9 @@ package build.tools.cldrconverter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
@ -40,6 +43,10 @@ import org.xml.sax.SAXException;
|
||||
class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
private static final String PREF_PREFIX = "preferred:";
|
||||
|
||||
// CLDR aliases to IANA ids map. The initial capacity is estimated
|
||||
// from the number of aliases in timezone.xml as of CLDR v48
|
||||
private final Map<String, String> ianaAliasMap = HashMap.newHashMap(32);
|
||||
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException {
|
||||
// avoid HTTP traffic to unicode.org
|
||||
@ -61,7 +68,16 @@ class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
put(attributes.getValue("name"), PREF_PREFIX + preferred);
|
||||
}
|
||||
} else {
|
||||
put(attributes.getValue("name"), attributes.getValue("alias"));
|
||||
var alias = attributes.getValue("alias");
|
||||
var iana = attributes.getValue("iana");
|
||||
if (iana != null) {
|
||||
for (var a : alias.split("\\s+")) {
|
||||
if (!a.equals(iana)) {
|
||||
ianaAliasMap.put(a, iana);
|
||||
}
|
||||
}
|
||||
}
|
||||
put(attributes.getValue("name"), alias);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -80,4 +96,8 @@ class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
.forEach(e -> map.put(e.getKey(),
|
||||
map.get(e.getValue().toString().substring(PREF_PREFIX.length()))));
|
||||
}
|
||||
|
||||
Map<String, String> getIanaAliasMap() {
|
||||
return ianaAliasMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -56,6 +56,7 @@ class WinZonesParseHandler extends AbstractLDMLHandler<Object> {
|
||||
String zoneName = attributes.getValue("other");
|
||||
String territory = attributes.getValue("territory");
|
||||
String javatz = attributes.getValue("type").replaceFirst("\\s.*", "");
|
||||
javatz = CLDRConverter.handlerTimeZone.getIanaAliasMap().getOrDefault(javatz, javatz);
|
||||
put(zoneName + ":" + territory, javatz);
|
||||
pushIgnoredContainer(qName);
|
||||
break;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,36 +34,6 @@ import java.util.*;
|
||||
|
||||
public class FieldGen {
|
||||
|
||||
static FieldParams Curve25519 = new FieldParams(
|
||||
"IntegerPolynomial25519", 26, 10, 1, 255,
|
||||
Arrays.asList(
|
||||
new Term(0, -19)
|
||||
),
|
||||
Curve25519CrSequence(), simpleSmallCrSequence(10)
|
||||
);
|
||||
|
||||
private static List<CarryReduce> Curve25519CrSequence() {
|
||||
List<CarryReduce> result = new ArrayList<CarryReduce>();
|
||||
|
||||
// reduce(7,2)
|
||||
result.add(new Reduce(17));
|
||||
result.add(new Reduce(18));
|
||||
|
||||
// carry(8,2)
|
||||
result.add(new Carry(8));
|
||||
result.add(new Carry(9));
|
||||
|
||||
// reduce(0,7)
|
||||
for (int i = 10; i < 17; i++) {
|
||||
result.add(new Reduce(i));
|
||||
}
|
||||
|
||||
// carry(0,9)
|
||||
result.addAll(fullCarry(10));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static FieldParams Curve448 = new FieldParams(
|
||||
"IntegerPolynomial448", 28, 16, 1, 448,
|
||||
Arrays.asList(
|
||||
@ -224,8 +194,7 @@ public class FieldGen {
|
||||
}
|
||||
|
||||
static final FieldParams[] ALL_FIELDS = {
|
||||
Curve25519, Curve448,
|
||||
P256, P384, P521, O256, O384, O521, O25519, O448
|
||||
Curve448, P256, P384, P521, O256, O384, O521, O25519, O448
|
||||
};
|
||||
|
||||
public static class Term {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,13 +25,13 @@
|
||||
|
||||
package build.tools.taglet;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
|
||||
@ -49,13 +49,15 @@ import static com.sun.source.doctree.DocTree.Kind.*;
|
||||
* The tags can be used as follows:
|
||||
*
|
||||
* <pre>
|
||||
* @jls section-number description
|
||||
* @jls chapter.section description
|
||||
* @jls preview-feature-chapter.section description
|
||||
* </pre>
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* <pre>
|
||||
* @jls 3.4 Line Terminators
|
||||
* @jls primitive-types-in-patterns-instanceof-switch-5.7.1 Exact Testing Conversions
|
||||
* </pre>
|
||||
*
|
||||
* will produce the following HTML, depending on the file containing
|
||||
@ -64,10 +66,24 @@ import static com.sun.source.doctree.DocTree.Kind.*;
|
||||
* <pre>{@code
|
||||
* <dt>See <i>Java Language Specification</i>:
|
||||
* <dd><a href="../../specs/jls/jls-3.html#jls-3.4">3.4 Line terminators</a>
|
||||
* <dd><a href="../../specs/primitive-types-in-patterns-instanceof-switch-jls.html#jls-5.7.1">
|
||||
* 5.7.1 Exact Testing Conversions</a><sup class="preview-mark">
|
||||
* <a href="../../specs/jls/jls-1.html#jls-1.5.1">PREVIEW</a></sup>
|
||||
* }</pre>
|
||||
*
|
||||
* Copies of JLS and JVMS are expected to have been placed in the {@code specs}
|
||||
* folder. These documents are not included in open-source repositories.
|
||||
* In inline tags (note you need manual JLS/JVMS prefix):
|
||||
* <pre>
|
||||
* JLS {@jls 3.4}
|
||||
* </pre>
|
||||
*
|
||||
* produces (note the section sign and no trailing dot):
|
||||
* <pre>
|
||||
* JLS <a href="../../specs/jls/jls-3.html#jls-3.4">§3.4</a>
|
||||
* </pre>
|
||||
*
|
||||
* Copies of JLS, JVMS, and preview JLS and JVMS changes are expected to have
|
||||
* been placed in the {@code specs} folder. These documents are not included
|
||||
* in open-source repositories.
|
||||
*/
|
||||
public class JSpec implements Taglet {
|
||||
|
||||
@ -87,9 +103,9 @@ public class JSpec implements Taglet {
|
||||
}
|
||||
}
|
||||
|
||||
private String tagName;
|
||||
private String specTitle;
|
||||
private String idPrefix;
|
||||
private final String tagName;
|
||||
private final String specTitle;
|
||||
private final String idPrefix;
|
||||
|
||||
JSpec(String tagName, String specTitle, String idPrefix) {
|
||||
this.tagName = tagName;
|
||||
@ -98,7 +114,7 @@ public class JSpec implements Taglet {
|
||||
}
|
||||
|
||||
// Note: Matches special cases like @jvms 6.5.checkcast
|
||||
private static final Pattern TAG_PATTERN = Pattern.compile("(?s)(.+ )?(?<chapter>[1-9][0-9]*)(?<section>[0-9a-z_.]*)( .*)?$");
|
||||
private static final Pattern TAG_PATTERN = Pattern.compile("(?s)(.+ )?(?<preview>([a-z0-9]+-)+)?(?<chapter>[1-9][0-9]*)(?<section>[0-9a-z_.]*)( .*)?$");
|
||||
|
||||
/**
|
||||
* Returns the set of locations in which the tag may be used.
|
||||
@ -125,6 +141,11 @@ public class JSpec implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element elem) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element elem, URI docRoot) {
|
||||
|
||||
if (tags.isEmpty())
|
||||
return "";
|
||||
@ -157,19 +178,50 @@ public class JSpec implements Taglet {
|
||||
.trim();
|
||||
Matcher m = TAG_PATTERN.matcher(tagText);
|
||||
if (m.find()) {
|
||||
// preview-feature-4.6 is preview-feature-, 4, .6
|
||||
String preview = m.group("preview"); // null if no preview feature
|
||||
String chapter = m.group("chapter");
|
||||
String section = m.group("section");
|
||||
String rootParent = currentPath().replaceAll("[^/]+", "..");
|
||||
String rootParent = docRoot.resolve("..").toString();
|
||||
|
||||
String url = String.format("%1$s/specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s",
|
||||
rootParent, idPrefix, chapter, section);
|
||||
String url = preview == null ?
|
||||
String.format("%1$s/specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s",
|
||||
rootParent, idPrefix, chapter, section) :
|
||||
String.format("%1$s/specs/%5$s%2$s.html#%2$s-%3$s%4$s",
|
||||
rootParent, idPrefix, chapter, section, preview);
|
||||
|
||||
var literal = expand(contents).trim();
|
||||
var prefix = (preview == null ? "" : preview) + chapter + section;
|
||||
if (literal.startsWith(prefix)) {
|
||||
var hasFullTitle = literal.length() > prefix.length();
|
||||
if (hasFullTitle) {
|
||||
// Drop the preview identifier
|
||||
literal = chapter + section + literal.substring(prefix.length());
|
||||
} else {
|
||||
// No section sign if the tag refers to a chapter, like {@jvms 4}
|
||||
String sectionSign = section.isEmpty() ? "" : "§";
|
||||
// Change whole text to "§chapter.x" in inline tags.
|
||||
literal = sectionSign + chapter + section;
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("<a href=\"")
|
||||
.append(url)
|
||||
.append("\">")
|
||||
.append(expand(contents))
|
||||
.append(literal)
|
||||
.append("</a>");
|
||||
|
||||
if (preview != null) {
|
||||
// Add PREVIEW superscript that links to JLS/JVMS 1.5.1
|
||||
// "Restrictions on the Use of Preview Features"
|
||||
// Similar to how APIs link to the Preview info box warning
|
||||
var sectionLink = String.format("%1$s/specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s",
|
||||
rootParent, idPrefix, "1", ".5.1");
|
||||
sb.append("<sup class=\"preview-mark\"><a href=\"")
|
||||
.append(sectionLink)
|
||||
.append("\">PREVIEW</a></sup>");
|
||||
}
|
||||
|
||||
if (tag.getKind() == DocTree.Kind.UNKNOWN_BLOCK_TAG) {
|
||||
sb.append("<br>");
|
||||
}
|
||||
@ -183,23 +235,6 @@ public class JSpec implements Taglet {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static ThreadLocal<String> CURRENT_PATH = null;
|
||||
|
||||
private String currentPath() {
|
||||
if (CURRENT_PATH == null) {
|
||||
try {
|
||||
Field f = Class.forName("jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter")
|
||||
.getField("CURRENT_PATH");
|
||||
@SuppressWarnings("unchecked")
|
||||
ThreadLocal<String> tl = (ThreadLocal<String>) f.get(null);
|
||||
CURRENT_PATH = tl;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Cannot determine current path", e);
|
||||
}
|
||||
}
|
||||
return CURRENT_PATH.get();
|
||||
}
|
||||
|
||||
private String expand(List<? extends DocTree> trees) {
|
||||
return (new SimpleDocTreeVisitor<StringBuilder, StringBuilder>() {
|
||||
public StringBuilder defaultAction(DocTree tree, StringBuilder sb) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,7 +32,9 @@ import jdk.javadoc.doclet.Taglet;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.util.Elements;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
@ -78,6 +80,11 @@ public final class SealedGraph implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element element, URI docRoot) {
|
||||
if (sealedDotOutputDir == null || sealedDotOutputDir.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
@ -85,9 +92,15 @@ public final class SealedGraph implements Taglet {
|
||||
return "";
|
||||
}
|
||||
|
||||
ModuleElement module = docletEnvironment.getElementUtils().getModuleOf(element);
|
||||
Elements util = docletEnvironment.getElementUtils();
|
||||
ModuleElement module = util.getModuleOf(element);
|
||||
|
||||
// '.' in .DOT file name is converted to '/' in .SVG path, so we use '-' as separator for nested classes.
|
||||
// module_package.subpackage.Outer-Inner.dot => module/package/subpackage/Outer-Inner-sealed-graph.svg
|
||||
Path dotFile = Path.of(sealedDotOutputDir,
|
||||
module.getQualifiedName() + "_" + typeElement.getQualifiedName() + ".dot");
|
||||
module.getQualifiedName() + "_"
|
||||
+ util.getPackageOf(element).getQualifiedName() + "."
|
||||
+ packagelessCanonicalName(typeElement).replace(".", "-") + ".dot");
|
||||
|
||||
Set<String> exports = module.getDirectives().stream()
|
||||
.filter(ModuleElement.ExportsDirective.class::isInstance)
|
||||
@ -99,7 +112,7 @@ public final class SealedGraph implements Taglet {
|
||||
.map(Objects::toString)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
|
||||
String dotContent = new Renderer().graph(typeElement, exports);
|
||||
String dotContent = new Renderer().graph(typeElement, exports, docRoot);
|
||||
|
||||
try {
|
||||
Files.writeString(dotFile, dotContent, WRITE, CREATE, TRUNCATE_EXISTING);
|
||||
@ -107,8 +120,8 @@ public final class SealedGraph implements Taglet {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String simpleTypeName = packagelessCanonicalName(typeElement).replace('.', '/');
|
||||
String imageFile = simpleTypeName + "-sealed-graph.svg";
|
||||
String simpleTypeName = packagelessCanonicalName(typeElement);
|
||||
String imageFile = simpleTypeName.replace(".", "-") + "-sealed-graph.svg";
|
||||
int thumbnailHeight = 100; // also appears in the stylesheet
|
||||
String hoverImage = "<span>"
|
||||
+ getImage(simpleTypeName, imageFile, -1, true)
|
||||
@ -137,21 +150,26 @@ public final class SealedGraph implements Taglet {
|
||||
private final class Renderer {
|
||||
|
||||
// Generates a graph in DOT format
|
||||
String graph(TypeElement rootClass, Set<String> exports) {
|
||||
final State state = new State(rootClass);
|
||||
String graph(TypeElement rootClass, Set<String> exports, URI pathToRoot) {
|
||||
if (!isInPublicApi(rootClass, exports)) {
|
||||
// Alternatively we can return "" for the graph since there is no single root to render
|
||||
throw new IllegalArgumentException("Root not in public API: " + rootClass.getQualifiedName());
|
||||
}
|
||||
final State state = new State(pathToRoot);
|
||||
traverse(state, rootClass, exports);
|
||||
return state.render();
|
||||
}
|
||||
|
||||
static void traverse(State state, TypeElement node, Set<String> exports) {
|
||||
if (!isInPublicApi(node, exports)) {
|
||||
throw new IllegalArgumentException("Bad request, not in public API: " + node.getQualifiedName());
|
||||
}
|
||||
state.addNode(node);
|
||||
if (!(node.getModifiers().contains(Modifier.SEALED) || node.getModifiers().contains(Modifier.FINAL))) {
|
||||
state.addNonSealedEdge(node);
|
||||
} else {
|
||||
for (TypeElement subNode : permittedSubclasses(node, exports)) {
|
||||
if (isInPublicApi(node, exports) && isInPublicApi(subNode, exports)) {
|
||||
state.addEdge(node, subNode);
|
||||
}
|
||||
state.addEdge(node, subNode);
|
||||
traverse(state, subNode, exports);
|
||||
}
|
||||
}
|
||||
@ -163,7 +181,7 @@ public final class SealedGraph implements Taglet {
|
||||
private static final String TOOLTIP = "tooltip";
|
||||
private static final String LINK = "href";
|
||||
|
||||
private final TypeElement rootNode;
|
||||
private final URI pathToRoot;
|
||||
|
||||
private final StringBuilder builder;
|
||||
|
||||
@ -188,8 +206,8 @@ public final class SealedGraph implements Taglet {
|
||||
}
|
||||
}
|
||||
|
||||
public State(TypeElement rootNode) {
|
||||
this.rootNode = rootNode;
|
||||
public State(URI pathToRoot) {
|
||||
this.pathToRoot = pathToRoot;
|
||||
nodeStyleMap = new LinkedHashMap<>();
|
||||
builder = new StringBuilder()
|
||||
.append("digraph G {")
|
||||
@ -212,24 +230,15 @@ public final class SealedGraph implements Taglet {
|
||||
var styles = nodeStyleMap.computeIfAbsent(id(node), n -> new LinkedHashMap<>());
|
||||
styles.put(LABEL, new StyleItem.PlainString(node.getSimpleName().toString()));
|
||||
styles.put(TOOLTIP, new StyleItem.PlainString(node.getQualifiedName().toString()));
|
||||
styles.put(LINK, new StyleItem.PlainString(relativeLink(node)));
|
||||
styles.put(LINK, new StyleItem.PlainString(pathToRoot.resolve(relativeLink(node)).toString()));
|
||||
}
|
||||
|
||||
// A permitted class must be in the same package or in the same module.
|
||||
// This implies the module is always the same.
|
||||
private String relativeLink(TypeElement node) {
|
||||
var util = SealedGraph.this.docletEnvironment.getElementUtils();
|
||||
var nodePackage = util.getPackageOf(node);
|
||||
// Note: SVG files for nested types use the simple names of containing types as parent directories.
|
||||
// We therefore need to convert all dots in the qualified name to "../" below.
|
||||
var backNavigator = rootNode.getQualifiedName().toString().chars()
|
||||
.filter(c -> c == '.')
|
||||
.mapToObj(c -> "../")
|
||||
.collect(joining());
|
||||
var forwardNavigator = nodePackage.getQualifiedName().toString()
|
||||
.replace(".", "/");
|
||||
var path = util.getModuleOf(node).getQualifiedName().toString() + "/"
|
||||
+ util.getPackageOf(node).getQualifiedName().toString().replace(".", "/");
|
||||
|
||||
return backNavigator + forwardNavigator + "/" + packagelessCanonicalName(node) + ".html";
|
||||
return path + "/" + packagelessCanonicalName(node) + ".html";
|
||||
}
|
||||
|
||||
public void addEdge(TypeElement node, TypeElement subNode) {
|
||||
@ -281,25 +290,33 @@ public final class SealedGraph implements Taglet {
|
||||
private String quotedId(TypeElement node) {
|
||||
return "\"" + id(node) + "\"";
|
||||
}
|
||||
|
||||
private String simpleName(String name) {
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
return lastDot < 0
|
||||
? name
|
||||
: name.substring(lastDot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<TypeElement> permittedSubclasses(TypeElement node, Set<String> exports) {
|
||||
return node.getPermittedSubclasses().stream()
|
||||
.filter(DeclaredType.class::isInstance)
|
||||
.map(DeclaredType.class::cast)
|
||||
.map(DeclaredType::asElement)
|
||||
.filter(TypeElement.class::isInstance)
|
||||
.map(TypeElement.class::cast)
|
||||
.filter(te -> isInPublicApi(te, exports))
|
||||
.toList();
|
||||
List<TypeElement> dfsStack = new ArrayList<TypeElement>().reversed(); // Faster operations to head
|
||||
SequencedCollection<TypeElement> result = new LinkedHashSet<>(); // Deduplicate diamond interface inheritance
|
||||
// The starting node may be in the public API - still expand it
|
||||
prependSubclasses(node, dfsStack);
|
||||
|
||||
while (!dfsStack.isEmpty()) {
|
||||
TypeElement now = dfsStack.removeFirst();
|
||||
if (isInPublicApi(now, exports)) {
|
||||
result.addLast(now);
|
||||
} else {
|
||||
// Skip the non-exported classes in the hierarchy
|
||||
prependSubclasses(now, dfsStack);
|
||||
}
|
||||
}
|
||||
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
private static void prependSubclasses(TypeElement node, List<TypeElement> dfs) {
|
||||
for (var e : node.getPermittedSubclasses().reversed()) {
|
||||
if (e instanceof DeclaredType dt && dt.asElement() instanceof TypeElement te) {
|
||||
dfs.addFirst(te);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInPublicApi(TypeElement typeElement, Set<String> exports) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,13 +25,13 @@
|
||||
|
||||
package build.tools.taglet;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
|
||||
@ -91,6 +91,11 @@ public class ToolGuide implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element elem) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element elem, URI docRoot) {
|
||||
|
||||
if (tags.isEmpty())
|
||||
return "";
|
||||
@ -118,7 +123,7 @@ public class ToolGuide implements Taglet {
|
||||
if (label.isEmpty()) {
|
||||
label = name;
|
||||
}
|
||||
String rootParent = currentPath().replaceAll("[^/]+", "..");
|
||||
String rootParent = docRoot.resolve("..").toString();
|
||||
|
||||
String url = String.format("%s/%s/%s.html",
|
||||
rootParent, BASE_URL, name);
|
||||
@ -141,22 +146,4 @@ public class ToolGuide implements Taglet {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static ThreadLocal<String> CURRENT_PATH = null;
|
||||
|
||||
private String currentPath() {
|
||||
if (CURRENT_PATH == null) {
|
||||
try {
|
||||
Field f = Class.forName("jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter")
|
||||
.getField("CURRENT_PATH");
|
||||
@SuppressWarnings("unchecked")
|
||||
ThreadLocal<String> tl = (ThreadLocal<String>) f.get(null);
|
||||
CURRENT_PATH = tl;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Cannot determine current path", e);
|
||||
}
|
||||
}
|
||||
return CURRENT_PATH.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
94
make/langtools/tools/previewfeature/SetupPreviewFeature.java
Normal file
94
make/langtools/tools/previewfeature/SetupPreviewFeature.java
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package previewfeature;
|
||||
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.Trees;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
/* Construct a hybrid PreviewFeature.Feature enum that includes constants both
|
||||
* from the current JDK sources (so that they can be used in the javac API sources),
|
||||
* and from the bootstrap JDK (so that they can be used in the bootstrap classfiles).
|
||||
*
|
||||
* This hybrid enum is only used for the interim javac.
|
||||
*/
|
||||
public class SetupPreviewFeature {
|
||||
public static void main(String... args) throws Exception {
|
||||
Class<?> runtimeFeature = Class.forName("jdk.internal.javac.PreviewFeature$Feature");
|
||||
Set<String> constantsToAdd = new HashSet<>();
|
||||
for (Field runtimeField : runtimeFeature.getDeclaredFields()) {
|
||||
if (runtimeField.isEnumConstant()) {
|
||||
constantsToAdd.add(runtimeField.getName());
|
||||
}
|
||||
}
|
||||
var dummy = new StringWriter();
|
||||
var compiler = ToolProvider.getSystemJavaCompiler();
|
||||
var source = Path.of(args[0]);
|
||||
try (var fm = compiler.getStandardFileManager(null, null, null)) {
|
||||
JavacTask task =
|
||||
(JavacTask) compiler.getTask(dummy, null, null, null, null, fm.getJavaFileObjects(source));
|
||||
task.analyze();
|
||||
var sourceFeature = task.getElements()
|
||||
.getTypeElement("jdk.internal.javac.PreviewFeature.Feature");
|
||||
int insertPosition = -1;
|
||||
for (var el : sourceFeature.getEnclosedElements()) {
|
||||
if (el.getKind() == ElementKind.ENUM_CONSTANT) {
|
||||
constantsToAdd.remove(el.getSimpleName().toString());
|
||||
if (insertPosition == (-1)) {
|
||||
var trees = Trees.instance(task);
|
||||
var elPath = trees.getPath(el);
|
||||
insertPosition = (int) trees.getSourcePositions()
|
||||
.getStartPosition(elPath.getCompilationUnit(),
|
||||
elPath.getLeaf());
|
||||
}
|
||||
}
|
||||
}
|
||||
var target = Path.of(args[1]);
|
||||
Files.createDirectories(target.getParent());
|
||||
if (constantsToAdd.isEmpty()) {
|
||||
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
} else {
|
||||
String sourceCode = Files.readString(source);
|
||||
try (var out = Files.newBufferedWriter(target)) {
|
||||
out.write(sourceCode, 0, insertPosition);
|
||||
out.write(constantsToAdd.stream()
|
||||
.collect(Collectors.joining(", ",
|
||||
"/*compatibility constants:*/ ",
|
||||
",\n")));
|
||||
out.write(sourceCode, insertPosition, sourceCode.length() - insertPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -172,6 +172,10 @@ ifeq ($(USE_EXTERNAL_LIBZ), true)
|
||||
LEGAL_EXCLUDES += zlib.md
|
||||
endif
|
||||
|
||||
ifneq ($(TOOLCHAIN_TYPE), gcc)
|
||||
LEGAL_EXCLUDES += gcc.md
|
||||
endif
|
||||
|
||||
$(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \
|
||||
EXCLUDES := $(LEGAL_EXCLUDES), \
|
||||
))
|
||||
|
||||
@ -95,7 +95,8 @@ ifeq ($(call isTargetOsType, unix), true)
|
||||
CFLAGS := $(VERSION_CFLAGS), \
|
||||
EXTRA_HEADER_DIRS := libjava, \
|
||||
EXTRA_OBJECT_FILES := \
|
||||
$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc$(OBJ_SUFFIX), \
|
||||
$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc$(OBJ_SUFFIX) \
|
||||
$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc_errorcodes$(OBJ_SUFFIX), \
|
||||
LD_SET_ORIGIN := false, \
|
||||
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \
|
||||
))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -88,6 +88,10 @@ LIBAWT_EXTRA_HEADER_DIRS := \
|
||||
|
||||
LIBAWT_CFLAGS := -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES -DMLIB_NO_LIBSUNMATH
|
||||
|
||||
ifeq ($(ENABLE_HEADLESS_ONLY), true)
|
||||
LIBAWT_CFLAGS += -DHEADLESS
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE -DMLIB_OS64BIT
|
||||
LIBAWT_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons
|
||||
@ -95,14 +99,16 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
$(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc
|
||||
endif
|
||||
|
||||
# This is the object file to provide the dladdr API, which is not
|
||||
# part of AIX. It occurs several times in the jdk code base.
|
||||
# Do not include it. When statically linking the java
|
||||
# launcher with all JDK and VM static libraries, we use the
|
||||
# --whole-archive linker option. The duplicate objects in different
|
||||
# static libraries cause linking errors due to duplicate symbols.
|
||||
ifeq ($(call isTargetOs, aix), true)
|
||||
# This is the object file to provide the dladdr API, which is not
|
||||
# part of AIX. It occurs several times in the jdk code base.
|
||||
# Do not include it. When statically linking the java
|
||||
# launcher with all JDK and VM static libraries, we use the
|
||||
# --whole-archive linker option. The duplicate objects in different
|
||||
# static libraries cause linking errors due to duplicate symbols.
|
||||
LIBAWT_STATIC_EXCLUDE_OBJS := porting_aix.o
|
||||
|
||||
LIBAWT_CFLAGS += -I$(TOPDIR)/src/java.base/aix/native/include
|
||||
endif
|
||||
|
||||
# -fgcse-after-reload improves performance of MaskFill in Java2D by 20% for
|
||||
@ -167,11 +173,18 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
$(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
|
||||
#
|
||||
|
||||
LIBAWT_HEADLESS_EXCLUDE_FILES := \
|
||||
GLXGraphicsConfig.c \
|
||||
GLXSurfaceData.c \
|
||||
X11PMBlitLoops.c \
|
||||
X11Renderer.c \
|
||||
X11SurfaceData.c \
|
||||
#
|
||||
|
||||
LIBAWT_HEADLESS_EXTRA_HEADER_DIRS := \
|
||||
$(LIBAWT_DEFAULT_HEADER_DIRS) \
|
||||
common/awt/debug \
|
||||
common/font \
|
||||
common/java2d/opengl \
|
||||
java.base:libjvm \
|
||||
#
|
||||
|
||||
@ -191,7 +204,8 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBAWT_HEADLESS, \
|
||||
NAME := awt_headless, \
|
||||
EXTRA_SRC := $(LIBAWT_HEADLESS_EXTRA_SRC), \
|
||||
EXCLUDES := medialib, \
|
||||
EXCLUDES := medialib opengl, \
|
||||
EXCLUDE_FILES := $(LIBAWT_HEADLESS_EXCLUDE_FILES), \
|
||||
ONLY_EXPORTED := $(LIBAWT_HEADLESS_ONLY_EXPORTED), \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := -DHEADLESS=true $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||
@ -411,6 +425,9 @@ endif
|
||||
ifeq ($(call isTargetOs, linux)+$(ENABLE_HEADLESS_ONLY), true+true)
|
||||
LIBJAWT_CFLAGS += -DHEADLESS
|
||||
endif
|
||||
ifeq ($(call isTargetOs, aix)+$(ENABLE_HEADLESS_ONLY), true+true)
|
||||
LIBJAWT_CFLAGS += -DHEADLESS
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows)+$(call isTargetCpu, x86), true+true)
|
||||
LIBJAWT_LIBS_windows := kernel32.lib
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -257,6 +257,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
DISABLED_WARNINGS_microsoft_dgif_lib.c := 4018 4267, \
|
||||
DISABLED_WARNINGS_microsoft_splashscreen_impl.c := 4018 4267 4244, \
|
||||
DISABLED_WARNINGS_microsoft_splashscreen_png.c := 4267, \
|
||||
DISABLED_WARNINGS_microsoft_pngread.c := 4146, \
|
||||
DISABLED_WARNINGS_microsoft_splashscreen_sys.c := 4267 4244, \
|
||||
LDFLAGS := $(ICONV_LDFLAGS), \
|
||||
LDFLAGS_windows := -delayload:user32.dll, \
|
||||
@ -338,11 +339,8 @@ 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 \
|
||||
calloc-transposed-args
|
||||
expansion-to-defined dangling-reference maybe-uninitialized
|
||||
HARFBUZZ_DISABLED_WARNINGS_clang := missing-field-initializers \
|
||||
range-loop-analysis unused-variable
|
||||
HARFBUZZ_DISABLED_WARNINGS_microsoft := 4267 4244
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -55,6 +55,12 @@ else
|
||||
LIBSAPROC_LINK_TYPE := C
|
||||
endif
|
||||
|
||||
# DWARF related sources would be included on supported platforms only.
|
||||
LIBSAPROC_EXCLUDE_FILES :=
|
||||
ifneq ($(call And, $(call isTargetOs, linux) $(call isTargetCpu, x86_64 aarch64)), true)
|
||||
LIBSAPROC_EXCLUDE_FILES := DwarfParser.cpp dwarf.cpp
|
||||
endif
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \
|
||||
NAME := saproc, \
|
||||
LINK_TYPE := $(LIBSAPROC_LINK_TYPE), \
|
||||
@ -70,6 +76,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \
|
||||
CFLAGS := $(LIBSAPROC_CFLAGS), \
|
||||
CXXFLAGS := $(LIBSAPROC_CFLAGS) $(LIBSAPROC_CXXFLAGS), \
|
||||
EXTRA_SRC := $(LIBSAPROC_EXTRA_SRC), \
|
||||
EXCLUDE_FILES := $(LIBSAPROC_EXCLUDE_FILES), \
|
||||
JDK_LIBS := java.base:libjava, \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
LIBS_macosx := \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,7 @@ DISABLED_WARNINGS_java += dangling-doc-comments
|
||||
|
||||
COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \
|
||||
.icns .scpt .wxs .wxl .wxi .wxf .ico .bmp .tiff .service .xsl
|
||||
.icns .scpt .wxs .wxl .wxi .wxf .ico .bmp .tiff .service .xsl .js
|
||||
|
||||
CLEAN += .properties
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,7 +54,7 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGEAPPLAUNCHER, \
|
||||
SRC := applauncher, \
|
||||
EXTRA_SRC := common, \
|
||||
INCLUDE_FILES := $(JPACKAGEAPPLAUNCHER_INCLUDE_FILES), \
|
||||
OPTIMIZATION := LOW, \
|
||||
OPTIMIZATION := SIZE, \
|
||||
DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_LinuxPackage.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_Log.cpp := unused-const-variable, \
|
||||
@ -91,7 +91,7 @@ ifeq ($(call isTargetOs, linux), true)
|
||||
common, \
|
||||
EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \
|
||||
LINK_TYPE := C++, \
|
||||
OPTIMIZATION := LOW, \
|
||||
OPTIMIZATION := SIZE, \
|
||||
DISABLED_WARNINGS_gcc_Log.cpp := unused-const-variable, \
|
||||
DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_tstrings.cpp := format-nonliteral, \
|
||||
|
||||
@ -88,7 +88,10 @@ function setup() {
|
||||
fi
|
||||
|
||||
if [[ -z ${CMD+x} ]]; then
|
||||
CMD="$DRIVEPREFIX/c/windows/system32/cmd.exe"
|
||||
CMD="$(type -p cmd.exe 2>/dev/null)"
|
||||
if [[ -z "$CMD" ]]; then
|
||||
CMD="$DRIVEPREFIX/c/windows/system32/cmd.exe"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z ${WINTEMP+x} ]]; then
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -63,7 +63,8 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c \
|
||||
libExplicitAttach.c libImplicitAttach.c \
|
||||
exelauncher.c libFDLeaker.c exeFDLeakTester.c \
|
||||
libChangeSignalDisposition.c exePrintSignalDisposition.c
|
||||
libChangeSignalDisposition.c exePrintSignalDisposition.c \
|
||||
libConcNativeFork.c libPipesCloseOnExec.c
|
||||
|
||||
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerTest := $(LIBCXX)
|
||||
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
|
||||
@ -77,6 +78,9 @@ else
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerUnnamed := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerModule := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libConcNativeFork := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libPipesCloseOnExec := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := -pthread
|
||||
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libExplicitAttach := -pthread
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libImplicitAttach := -pthread
|
||||
|
||||
@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code is provided to illustrate the usage of a given feature
|
||||
* or technique and has been deliberately simplified. Additional steps
|
||||
* required for a production-quality application, such as security checks,
|
||||
* input validation and proper error handling, might not be present in
|
||||
* this sample code.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
|
||||
|
||||
/**
|
||||
* The OldJTable is an unsupported class containing some methods that were
|
||||
* deleted from the JTable between releases 0.6 and 0.7
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class OldJTable extends JTable
|
||||
{
|
||||
/*
|
||||
* A new convenience method returning the index of the column in the
|
||||
* co-ordinate space of the view.
|
||||
*/
|
||||
public int getColumnIndex(Object identifier) {
|
||||
return getColumnModel().getColumnIndex(identifier);
|
||||
}
|
||||
|
||||
//
|
||||
// Methods deleted from the JTable because they only work with the
|
||||
// DefaultTableModel.
|
||||
//
|
||||
|
||||
public TableColumn addColumn(Object columnIdentifier, int width) {
|
||||
return addColumn(columnIdentifier, width, null, null, null);
|
||||
}
|
||||
|
||||
public TableColumn addColumn(Object columnIdentifier, List<?> columnData) {
|
||||
return addColumn(columnIdentifier, -1, null, null, columnData);
|
||||
}
|
||||
|
||||
// Override the new JTable implementation - it will not add a column to the
|
||||
// DefaultTableModel.
|
||||
public TableColumn addColumn(Object columnIdentifier, int width,
|
||||
TableCellRenderer renderer,
|
||||
TableCellEditor editor) {
|
||||
return addColumn(columnIdentifier, width, renderer, editor, null);
|
||||
}
|
||||
|
||||
public TableColumn addColumn(Object columnIdentifier, int width,
|
||||
TableCellRenderer renderer,
|
||||
TableCellEditor editor, List<?> columnData) {
|
||||
checkDefaultTableModel();
|
||||
|
||||
// Set up the model side first
|
||||
DefaultTableModel m = (DefaultTableModel)getModel();
|
||||
m.addColumn(columnIdentifier, columnData.toArray());
|
||||
|
||||
// The column will have been added to the end, so the index of the
|
||||
// column in the model is the last element.
|
||||
TableColumn newColumn = new TableColumn(
|
||||
m.getColumnCount()-1, width, renderer, editor);
|
||||
super.addColumn(newColumn);
|
||||
return newColumn;
|
||||
}
|
||||
|
||||
// Not possilble to make this work the same way ... change it so that
|
||||
// it does not delete columns from the model.
|
||||
public void removeColumn(Object columnIdentifier) {
|
||||
super.removeColumn(getColumn(columnIdentifier));
|
||||
}
|
||||
|
||||
public void addRow(Object[] rowData) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).addRow(rowData);
|
||||
}
|
||||
|
||||
public void addRow(List<?> rowData) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).addRow(rowData.toArray());
|
||||
}
|
||||
|
||||
public void removeRow(int rowIndex) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).removeRow(rowIndex);
|
||||
}
|
||||
|
||||
public void moveRow(int startIndex, int endIndex, int toIndex) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).moveRow(startIndex, endIndex, toIndex);
|
||||
}
|
||||
|
||||
public void insertRow(int rowIndex, Object[] rowData) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).insertRow(rowIndex, rowData);
|
||||
}
|
||||
|
||||
public void insertRow(int rowIndex, List<?> rowData) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).insertRow(rowIndex, rowData.toArray());
|
||||
}
|
||||
|
||||
public void setNumRows(int newSize) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).setNumRows(newSize);
|
||||
}
|
||||
|
||||
public void setDataVector(Object[][] newData, List<?> columnIds) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).setDataVector(
|
||||
newData, columnIds.toArray());
|
||||
}
|
||||
|
||||
public void setDataVector(Object[][] newData, Object[] columnIds) {
|
||||
checkDefaultTableModel();
|
||||
((DefaultTableModel)getModel()).setDataVector(newData, columnIds);
|
||||
}
|
||||
|
||||
protected void checkDefaultTableModel() {
|
||||
if(!(dataModel instanceof DefaultTableModel))
|
||||
throw new InternalError("In order to use this method, the data model must be an instance of DefaultTableModel.");
|
||||
}
|
||||
|
||||
//
|
||||
// Methods removed from JTable in the move from identifiers to ints.
|
||||
//
|
||||
|
||||
public Object getValueAt(Object columnIdentifier, int rowIndex) {
|
||||
return super.getValueAt(rowIndex, getColumnIndex(columnIdentifier));
|
||||
}
|
||||
|
||||
public boolean isCellEditable(Object columnIdentifier, int rowIndex) {
|
||||
return super.isCellEditable(rowIndex, getColumnIndex(columnIdentifier));
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, Object columnIdentifier, int rowIndex) {
|
||||
super.setValueAt(aValue, rowIndex, getColumnIndex(columnIdentifier));
|
||||
}
|
||||
|
||||
public boolean editColumnRow(Object identifier, int row) {
|
||||
return super.editCellAt(row, getColumnIndex(identifier));
|
||||
}
|
||||
|
||||
public void moveColumn(Object columnIdentifier, Object targetColumnIdentifier) {
|
||||
moveColumn(getColumnIndex(columnIdentifier),
|
||||
getColumnIndex(targetColumnIdentifier));
|
||||
}
|
||||
|
||||
public boolean isColumnSelected(Object identifier) {
|
||||
return isColumnSelected(getColumnIndex(identifier));
|
||||
}
|
||||
|
||||
public TableColumn addColumn(int modelColumn, int width) {
|
||||
return addColumn(modelColumn, width, null, null);
|
||||
}
|
||||
|
||||
public TableColumn addColumn(int modelColumn) {
|
||||
return addColumn(modelColumn, 75, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new column with <I>modelColumn</I>, <I>width</I>,
|
||||
* <I>renderer</I>, and <I>editor</I> and adds it to the end of
|
||||
* the JTable's array of columns. This method also retrieves the
|
||||
* name of the column using the model's <I>getColumnName(modelColumn)</I>
|
||||
* method, and sets the both the header value and the identifier
|
||||
* for this TableColumn accordingly.
|
||||
* <p>
|
||||
* The <I>modelColumn</I> is the index of the column in the model which
|
||||
* will supply the data for this column in the table. This, like the
|
||||
* <I>columnIdentifier</I> in previous releases, does not change as the
|
||||
* columns are moved in the view.
|
||||
* <p>
|
||||
* For the rest of the JTable API, and all of its associated classes,
|
||||
* columns are referred to in the co-ordinate system of the view, the
|
||||
* index of the column in the model is kept inside the TableColumn
|
||||
* and is used only to retrieve the information from the appropraite
|
||||
* column in the model.
|
||||
* <p>
|
||||
*
|
||||
* @param modelColumn The index of the column in the model
|
||||
* @param width The new column's width. Or -1 to use
|
||||
* the default width
|
||||
* @param renderer The renderer used with the new column.
|
||||
* Or null to use the default renderer.
|
||||
* @param editor The editor used with the new column.
|
||||
* Or null to use the default editor.
|
||||
*/
|
||||
public TableColumn addColumn(int modelColumn, int width,
|
||||
TableCellRenderer renderer,
|
||||
TableCellEditor editor) {
|
||||
TableColumn newColumn = new TableColumn(
|
||||
modelColumn, width, renderer, editor);
|
||||
addColumn(newColumn);
|
||||
return newColumn;
|
||||
}
|
||||
|
||||
//
|
||||
// Methods that had their arguments switched.
|
||||
//
|
||||
|
||||
// These won't work with the new table package.
|
||||
|
||||
/*
|
||||
public Object getValueAt(int columnIndex, int rowIndex) {
|
||||
return super.getValueAt(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int columnIndex, int rowIndex) {
|
||||
return super.isCellEditable(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int columnIndex, int rowIndex) {
|
||||
super.setValueAt(aValue, rowIndex, columnIndex);
|
||||
}
|
||||
*/
|
||||
|
||||
public boolean editColumnRow(int columnIndex, int rowIndex) {
|
||||
return super.editCellAt(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public boolean editColumnRow(int columnIndex, int rowIndex, EventObject e){
|
||||
return super.editCellAt(rowIndex, columnIndex, e);
|
||||
}
|
||||
|
||||
|
||||
} // End Of Class OldJTable
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2014, 2024, Red Hat, Inc. All rights reserved.
|
||||
// Copyright 2025 Arm Limited and/or its affiliates.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -1182,12 +1182,12 @@ class CallStubImpl {
|
||||
public:
|
||||
// Size of call trampoline stub.
|
||||
static uint size_call_trampoline() {
|
||||
return 0; // no call trampolines on this platform
|
||||
return MacroAssembler::max_trampoline_stub_size();
|
||||
}
|
||||
|
||||
// number of relocations needed by a call trampoline stub
|
||||
static uint reloc_call_trampoline() {
|
||||
return 0; // no call trampolines on this platform
|
||||
return 5; // metadata; call dest; trampoline address; trampoline destination; trampoline_owner_metadata
|
||||
}
|
||||
};
|
||||
|
||||
@ -1229,7 +1229,7 @@ public:
|
||||
// predicate controlling addressing modes
|
||||
bool size_fits_all_mem_uses(AddPNode* addp, int shift);
|
||||
|
||||
// Convert BootTest condition to Assembler condition.
|
||||
// Convert BoolTest condition to Assembler condition.
|
||||
// Replicate the logic of cmpOpOper::ccode() and cmpOpUOper::ccode().
|
||||
Assembler::Condition to_assembler_cond(BoolTest::mask cond);
|
||||
%}
|
||||
@ -2233,15 +2233,9 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
|
||||
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");
|
||||
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 r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
|
||||
st->print_cr("\tcmp rscratch1, r10");
|
||||
}
|
||||
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");
|
||||
st->print_cr("\tbne, SharedRuntime::_ic_miss_stub");
|
||||
}
|
||||
#endif
|
||||
@ -2467,11 +2461,8 @@ bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
return opnd->opcode() == VREG;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Return whether or not this register is ever used as an argument.
|
||||
// This function is used on startup to build the trampoline stubs in
|
||||
// generateOptoStub. Registers not mentioned will be killed by the VM
|
||||
// call in the trampoline, and arguments in those registers not be
|
||||
// available to the callee.
|
||||
bool Matcher::can_be_java_arg(int reg)
|
||||
{
|
||||
return
|
||||
@ -2492,11 +2483,7 @@ bool Matcher::can_be_java_arg(int reg)
|
||||
reg == V6_num || reg == V6_H_num ||
|
||||
reg == V7_num || reg == V7_H_num;
|
||||
}
|
||||
|
||||
bool Matcher::is_spillable_arg(int reg)
|
||||
{
|
||||
return can_be_java_arg(reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint Matcher::int_pressure_limit()
|
||||
{
|
||||
@ -2531,10 +2518,6 @@ uint Matcher::float_pressure_limit()
|
||||
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
|
||||
}
|
||||
|
||||
bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RegMask& Matcher::divI_proj_mask() {
|
||||
ShouldNotReachHere();
|
||||
return RegMask::EMPTY;
|
||||
@ -2579,7 +2562,7 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert BootTest condition to Assembler condition.
|
||||
// Convert BoolTest condition to Assembler condition.
|
||||
// Replicate the logic of cmpOpOper::ccode() and cmpOpUOper::ccode().
|
||||
Assembler::Condition to_assembler_cond(BoolTest::mask cond) {
|
||||
Assembler::Condition result;
|
||||
@ -3403,11 +3386,13 @@ encode %{
|
||||
} else if (rtype == relocInfo::metadata_type) {
|
||||
__ mov_metadata(dst_reg, (Metadata*)con);
|
||||
} else {
|
||||
assert(rtype == relocInfo::none, "unexpected reloc type");
|
||||
assert(rtype == relocInfo::none || rtype == relocInfo::external_word_type, "unexpected reloc type");
|
||||
// load fake address constants using a normal move
|
||||
if (! __ is_valid_AArch64_address(con) ||
|
||||
con < (address)(uintptr_t)os::vm_page_size()) {
|
||||
__ mov(dst_reg, con);
|
||||
} else {
|
||||
// no reloc so just use adrp and add
|
||||
uint64_t offset;
|
||||
__ adrp(dst_reg, con, offset);
|
||||
__ add(dst_reg, dst_reg, offset);
|
||||
@ -3812,11 +3797,6 @@ frame %{
|
||||
// Compiled code's Frame Pointer
|
||||
frame_pointer(R31);
|
||||
|
||||
// Interpreter stores its frame pointer in a register which is
|
||||
// stored to the stack by I2CAdaptors.
|
||||
// I2CAdaptors convert from interpreted java to compiled java.
|
||||
interpreter_frame_pointer(R29);
|
||||
|
||||
// Stack alignment requirement
|
||||
stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes)
|
||||
|
||||
@ -4535,6 +4515,18 @@ operand immP_1()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// AOT Runtime Constants Address
|
||||
operand immAOTRuntimeConstantsAddress()
|
||||
%{
|
||||
// Check if the address is in the range of AOT Runtime Constants
|
||||
predicate(AOTRuntimeConstants::contains((address)(n->get_ptr())));
|
||||
match(ConP);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Float and Double operands
|
||||
// Double Immediate
|
||||
operand immD()
|
||||
@ -6898,6 +6890,20 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con)
|
||||
ins_pipe(ialu_imm);
|
||||
%}
|
||||
|
||||
instruct loadAOTRCAddress(iRegPNoSp dst, immAOTRuntimeConstantsAddress con)
|
||||
%{
|
||||
match(Set dst con);
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "adr $dst, $con\t# AOT Runtime Constants Address" %}
|
||||
|
||||
ins_encode %{
|
||||
__ load_aotrc_address($dst$$Register, (address)$con$$constant);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_imm);
|
||||
%}
|
||||
|
||||
// Load Narrow Pointer Constant
|
||||
|
||||
instruct loadConN(iRegNNoSp dst, immN con)
|
||||
@ -8008,6 +8014,21 @@ instruct membar_release_lock() %{
|
||||
ins_pipe(pipe_serial);
|
||||
%}
|
||||
|
||||
instruct membar_storeload() %{
|
||||
match(MemBarStoreLoad);
|
||||
ins_cost(VOLATILE_REF_COST*100);
|
||||
|
||||
format %{ "MEMBAR-store-load\n\t"
|
||||
"dmb ish" %}
|
||||
|
||||
ins_encode %{
|
||||
__ block_comment("membar_storeload");
|
||||
__ membar(Assembler::StoreLoad);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_serial);
|
||||
%}
|
||||
|
||||
instruct unnecessary_membar_volatile() %{
|
||||
predicate(unnecessary_volatile(n));
|
||||
match(MemBarVolatile);
|
||||
@ -8037,6 +8058,20 @@ instruct membar_volatile() %{
|
||||
ins_pipe(pipe_serial);
|
||||
%}
|
||||
|
||||
instruct membar_full() %{
|
||||
match(MemBarFull);
|
||||
ins_cost(VOLATILE_REF_COST*100);
|
||||
|
||||
format %{ "membar_full\n\t"
|
||||
"dmb ish" %}
|
||||
ins_encode %{
|
||||
__ block_comment("membar_full");
|
||||
__ membar(Assembler::AnyAny);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_serial);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
// Cast/Convert Instructions
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2025, Arm Limited. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Arm Limited. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -201,6 +201,8 @@ source %{
|
||||
case Op_XorReductionV:
|
||||
case Op_MinReductionV:
|
||||
case Op_MaxReductionV:
|
||||
case Op_UMinReductionV:
|
||||
case Op_UMaxReductionV:
|
||||
// Reductions with less than 8 bytes vector length are
|
||||
// not supported.
|
||||
if (length_in_bytes < 8) {
|
||||
@ -245,10 +247,39 @@ source %{
|
||||
case Op_MinVHF:
|
||||
case Op_MaxVHF:
|
||||
case Op_SqrtVHF:
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// At the time of writing this, the Vector API has no half-float (FP16) species.
|
||||
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
|
||||
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
|
||||
//
|
||||
// There is no direct Neon instruction that performs strictly ordered floating
|
||||
// point add reduction. Hence, on Neon only machines, the add reduction operation
|
||||
// is implemented as a scalarized sequence using half-precision scalar instruction
|
||||
// FADD which requires FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// On SVE machines (UseSVE > 0) however, there is a direct instruction (FADDA) which
|
||||
// implements strictly ordered floating point add reduction which does not require
|
||||
// the FEAT_FP16 and ASIMDHP checks as SVE supports half-precision floats by default.
|
||||
case Op_AddReductionVHF:
|
||||
// FEAT_FP16 is enabled if both "fphp" and "asimdhp" features are supported.
|
||||
// Only the Neon instructions need this check. SVE supports half-precision floats
|
||||
// by default.
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
if (length_in_bytes < 8 || (UseSVE == 0 && !is_feat_fp16_supported())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_MulReductionVHF:
|
||||
// There are no direct Neon/SVE instructions that perform strictly ordered
|
||||
// floating point multiply reduction.
|
||||
// For vector length ≤ 16 bytes, the reduction is implemented as a scalarized
|
||||
// sequence using half-precision scalar instruction FMUL. This path requires
|
||||
// FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// For vector length > 16 bytes, this operation is disabled because there is no
|
||||
// direct SVE instruction that performs a strictly ordered FP16 multiply
|
||||
// reduction.
|
||||
if (length_in_bytes < 8 || length_in_bytes > 16 || !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -298,6 +329,7 @@ source %{
|
||||
case Op_VectorRearrange:
|
||||
case Op_MulReductionVD:
|
||||
case Op_MulReductionVF:
|
||||
case Op_MulReductionVHF:
|
||||
case Op_MulReductionVI:
|
||||
case Op_MulReductionVL:
|
||||
case Op_CompressBitsV:
|
||||
@ -362,6 +394,7 @@ source %{
|
||||
case Op_VectorMaskCmp:
|
||||
case Op_LoadVectorGather:
|
||||
case Op_StoreVectorScatter:
|
||||
case Op_AddReductionVHF:
|
||||
case Op_AddReductionVF:
|
||||
case Op_AddReductionVD:
|
||||
case Op_AndReductionV:
|
||||
@ -383,6 +416,8 @@ source %{
|
||||
return !VM_Version::use_neon_for_vector(length_in_bytes);
|
||||
case Op_MinReductionV:
|
||||
case Op_MaxReductionV:
|
||||
case Op_UMinReductionV:
|
||||
case Op_UMaxReductionV:
|
||||
// For BYTE/SHORT/INT/FLOAT/DOUBLE types, we prefer using NEON
|
||||
// instructions rather than SVE predicated instructions for
|
||||
// better performance.
|
||||
@ -593,13 +628,9 @@ instruct vloadcon(vReg dst, immI0 src) %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
if (UseSVE == 0) {
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
|
||||
int entry_idx = __ vector_iota_entry_index(bt);
|
||||
assert(length_in_bytes <= 16, "must be");
|
||||
// The iota indices are ordered by type B/S/I/L/F/D, and the offset between two types is 16.
|
||||
int offset = exact_log2(type2aelembytes(bt)) << 4;
|
||||
if (is_floating_point_type(bt)) {
|
||||
offset += 32;
|
||||
}
|
||||
__ lea(rscratch1, ExternalAddress(StubRoutines::aarch64::vector_iota_indices() + offset));
|
||||
__ lea(rscratch1, ExternalAddress(StubRoutines::aarch64::vector_iota_indices(entry_idx)));
|
||||
if (length_in_bytes == 16) {
|
||||
__ ldrq($dst$$FloatRegister, rscratch1);
|
||||
} else {
|
||||
@ -3402,6 +3433,44 @@ instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Add Reduction for Half floats (FP16).
|
||||
// Neon does not provide direct instructions for strictly ordered floating-point add reductions.
|
||||
// On Neon-only targets (UseSVE = 0), this operation is implemented as a sequence of scalar additions:
|
||||
// values equal to the vector width are loaded into a vector register, each lane is extracted,
|
||||
// and its value is accumulated into the running sum, producing a final scalar result.
|
||||
instruct reduce_addHF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (AddReductionVHF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_addHF $dst, $fsrc, $vsrc\t# 4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_add_fp16($dst$$FloatRegister, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// This rule calculates the reduction result in strict order. Two cases will
|
||||
// reach here:
|
||||
// 1. Non strictly-ordered AddReductionVHF when vector size > 128-bits. For example -
|
||||
// AddReductionVHF generated by Vector API. For vector size > 128-bits, it is more
|
||||
// beneficial performance-wise to generate direct SVE instruction even if it is
|
||||
// strictly ordered.
|
||||
// 2. Strictly-ordered AddReductionVHF. For example - AddReductionVHF generated by
|
||||
// auto-vectorization on SVE machine.
|
||||
instruct reduce_addHF_sve(vRegF dst_src1, vReg src2) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionVHF dst_src1 src2));
|
||||
format %{ "reduce_addHF_sve $dst_src1, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ H, ptrue, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// This rule calculates the reduction result in strict order. Two cases will
|
||||
// reach here:
|
||||
// 1. Non strictly-ordered AddReductionVF when vector size > 128-bits. For example -
|
||||
@ -3492,12 +3561,14 @@ instruct reduce_addL_masked(iRegLNoSp dst, iRegL isrc, vReg vsrc, pRegGov pg, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_addF_masked(vRegF dst_src1, vReg src2, pRegGov pg) %{
|
||||
instruct reduce_addFHF_masked(vRegF dst_src1, vReg src2, pRegGov pg) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionVHF (Binary dst_src1 src2) pg));
|
||||
match(Set dst_src1 (AddReductionVF (Binary dst_src1 src2) pg));
|
||||
format %{ "reduce_addF_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
format %{ "reduce_addFHF_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ S,
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
|
||||
$pg$$PRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
@ -3545,14 +3616,17 @@ instruct reduce_mulL(iRegLNoSp dst, iRegL isrc, vReg vsrc) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
|
||||
instruct reduce_mulFHF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) <= 16);
|
||||
match(Set dst (MulReductionVHF fsrc vsrc));
|
||||
match(Set dst (MulReductionVF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulF $dst, $fsrc, $vsrc\t# 2F/4F. KILL $tmp" %}
|
||||
format %{ "reduce_mulFHF $dst, $fsrc, $vsrc\t# 2F/4F/4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_FLOAT, $fsrc$$FloatRegister,
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, bt, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
@ -4218,6 +4292,224 @@ instruct reduce_minD_masked(vRegD dst, vRegD dsrc, vReg vsrc, pRegGov pg) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// -------------------- Vector reduction unsigned min/max ----------------------
|
||||
|
||||
// reduction uminI
|
||||
|
||||
instruct reduce_uminI_neon(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc,
|
||||
vReg tmp, rFlagsReg cr) %{
|
||||
predicate(VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) &&
|
||||
(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_INT));
|
||||
match(Set dst (UMinReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_uminI_neon $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_minmax_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_uminI_sve(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) &&
|
||||
(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_INT));
|
||||
match(Set dst (UMinReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_uminI_sve $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
ptrue, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// reduction uminL
|
||||
|
||||
instruct reduce_uminL_neon(iRegLNoSp dst, iRegL isrc, vReg vsrc, rFlagsReg cr) %{
|
||||
predicate(UseSVE == 0 && Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
|
||||
match(Set dst (UMinReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, KILL cr);
|
||||
format %{ "reduce_uminL_neon $dst, $isrc, $vsrc\t# 2L. KILL cr" %}
|
||||
ins_encode %{
|
||||
__ neon_reduce_minmax_integral(this->ideal_Opcode(), $dst$$Register, T_LONG,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
/* vector_length_in_bytes */ 16, fnoreg);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_uminL_sve(iRegLNoSp dst, iRegL isrc, vReg vsrc,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
|
||||
match(Set dst (UMinReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_uminL_sve $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
ptrue, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// reduction umin - predicated
|
||||
|
||||
instruct reduce_uminI_masked(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc, pRegGov pg,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 &&
|
||||
(Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_INT));
|
||||
match(Set dst (UMinReductionV (Binary isrc vsrc) pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_uminI_masked $dst, $isrc, $pg, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
$pg$$PRegister, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_uminL_masked(iRegLNoSp dst, iRegL isrc, vReg vsrc, pRegGov pg,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_LONG);
|
||||
match(Set dst (UMinReductionV (Binary isrc vsrc) pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_uminL_masked $dst, $isrc, $pg, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
$pg$$PRegister, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// reduction umaxI
|
||||
|
||||
instruct reduce_umaxI_neon(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc,
|
||||
vReg tmp, rFlagsReg cr) %{
|
||||
predicate(VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) &&
|
||||
(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_INT));
|
||||
match(Set dst (UMaxReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_umaxI_neon $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_minmax_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_umaxI_sve(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) &&
|
||||
(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(2)) == T_INT));
|
||||
match(Set dst (UMaxReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_umaxI_sve $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
ptrue, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// reduction umaxL
|
||||
|
||||
instruct reduce_umaxL_neon(iRegLNoSp dst, iRegL isrc, vReg vsrc, rFlagsReg cr) %{
|
||||
predicate(UseSVE == 0 && Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
|
||||
match(Set dst (UMaxReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, KILL cr);
|
||||
format %{ "reduce_umaxL_neon $dst, $isrc, $vsrc\t# 2L. KILL cr" %}
|
||||
ins_encode %{
|
||||
__ neon_reduce_minmax_integral(this->ideal_Opcode(), $dst$$Register, T_LONG,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
/* vector_length_in_bytes */ 16, fnoreg);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_umaxL_sve(iRegLNoSp dst, iRegL isrc, vReg vsrc,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n->in(2)) == T_LONG);
|
||||
match(Set dst (UMaxReductionV isrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_umaxL_sve $dst, $isrc, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, T_LONG,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
ptrue, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// reduction umax - predicated
|
||||
|
||||
instruct reduce_umaxI_masked(iRegINoSp dst, iRegIorL2I isrc, vReg vsrc, pRegGov pg,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 &&
|
||||
(Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_BYTE ||
|
||||
Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_INT));
|
||||
match(Set dst (UMaxReductionV (Binary isrc vsrc) pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_umaxI_masked $dst, $isrc, $pg, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
$pg$$PRegister, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_umaxL_masked(iRegLNoSp dst, iRegL isrc, vReg vsrc, pRegGov pg,
|
||||
vRegD tmp, rFlagsReg cr) %{
|
||||
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n->in(1)->in(2)) == T_LONG);
|
||||
match(Set dst (UMaxReductionV (Binary isrc vsrc) pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp, KILL cr);
|
||||
format %{ "reduce_umaxL_masked $dst, $isrc, $pg, $vsrc\t# KILL $tmp, cr" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ sve_reduce_integral(this->ideal_Opcode(), $dst$$Register, bt,
|
||||
$isrc$$Register, $vsrc$$FloatRegister,
|
||||
$pg$$PRegister, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// ------------------------------ Vector reinterpret ---------------------------
|
||||
|
||||
instruct reinterpret_same_size(vReg dst_src) %{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2025, Arm Limited. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Arm Limited. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -191,6 +191,8 @@ source %{
|
||||
case Op_XorReductionV:
|
||||
case Op_MinReductionV:
|
||||
case Op_MaxReductionV:
|
||||
case Op_UMinReductionV:
|
||||
case Op_UMaxReductionV:
|
||||
// Reductions with less than 8 bytes vector length are
|
||||
// not supported.
|
||||
if (length_in_bytes < 8) {
|
||||
@ -235,10 +237,39 @@ source %{
|
||||
case Op_MinVHF:
|
||||
case Op_MaxVHF:
|
||||
case Op_SqrtVHF:
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// At the time of writing this, the Vector API has no half-float (FP16) species.
|
||||
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
|
||||
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
|
||||
//
|
||||
// There is no direct Neon instruction that performs strictly ordered floating
|
||||
// point add reduction. Hence, on Neon only machines, the add reduction operation
|
||||
// is implemented as a scalarized sequence using half-precision scalar instruction
|
||||
// FADD which requires FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// On SVE machines (UseSVE > 0) however, there is a direct instruction (FADDA) which
|
||||
// implements strictly ordered floating point add reduction which does not require
|
||||
// the FEAT_FP16 and ASIMDHP checks as SVE supports half-precision floats by default.
|
||||
case Op_AddReductionVHF:
|
||||
// FEAT_FP16 is enabled if both "fphp" and "asimdhp" features are supported.
|
||||
// Only the Neon instructions need this check. SVE supports half-precision floats
|
||||
// by default.
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
if (length_in_bytes < 8 || (UseSVE == 0 && !is_feat_fp16_supported())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_MulReductionVHF:
|
||||
// There are no direct Neon/SVE instructions that perform strictly ordered
|
||||
// floating point multiply reduction.
|
||||
// For vector length ≤ 16 bytes, the reduction is implemented as a scalarized
|
||||
// sequence using half-precision scalar instruction FMUL. This path requires
|
||||
// FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// For vector length > 16 bytes, this operation is disabled because there is no
|
||||
// direct SVE instruction that performs a strictly ordered FP16 multiply
|
||||
// reduction.
|
||||
if (length_in_bytes < 8 || length_in_bytes > 16 || !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -288,6 +319,7 @@ source %{
|
||||
case Op_VectorRearrange:
|
||||
case Op_MulReductionVD:
|
||||
case Op_MulReductionVF:
|
||||
case Op_MulReductionVHF:
|
||||
case Op_MulReductionVI:
|
||||
case Op_MulReductionVL:
|
||||
case Op_CompressBitsV:
|
||||
@ -352,6 +384,7 @@ source %{
|
||||
case Op_VectorMaskCmp:
|
||||
case Op_LoadVectorGather:
|
||||
case Op_StoreVectorScatter:
|
||||
case Op_AddReductionVHF:
|
||||
case Op_AddReductionVF:
|
||||
case Op_AddReductionVD:
|
||||
case Op_AndReductionV:
|
||||
@ -373,6 +406,8 @@ source %{
|
||||
return !VM_Version::use_neon_for_vector(length_in_bytes);
|
||||
case Op_MinReductionV:
|
||||
case Op_MaxReductionV:
|
||||
case Op_UMinReductionV:
|
||||
case Op_UMaxReductionV:
|
||||
// For BYTE/SHORT/INT/FLOAT/DOUBLE types, we prefer using NEON
|
||||
// instructions rather than SVE predicated instructions for
|
||||
// better performance.
|
||||
@ -2059,6 +2094,25 @@ instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
dnl
|
||||
|
||||
// Add Reduction for Half floats (FP16).
|
||||
// Neon does not provide direct instructions for strictly ordered floating-point add reductions.
|
||||
// On Neon-only targets (UseSVE = 0), this operation is implemented as a sequence of scalar additions:
|
||||
// values equal to the vector width are loaded into a vector register, each lane is extracted,
|
||||
// and its value is accumulated into the running sum, producing a final scalar result.
|
||||
instruct reduce_addHF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (AddReductionVHF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_addHF $dst, $fsrc, $vsrc\t# 4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_add_fp16($dst$$FloatRegister, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
dnl
|
||||
dnl REDUCE_ADD_FP_SVE($1, $2 )
|
||||
dnl REDUCE_ADD_FP_SVE(type, size)
|
||||
define(`REDUCE_ADD_FP_SVE', `
|
||||
@ -2070,21 +2124,26 @@ define(`REDUCE_ADD_FP_SVE', `
|
||||
// strictly ordered.
|
||||
// 2. Strictly-ordered AddReductionV$1. For example - AddReductionV$1 generated by
|
||||
// auto-vectorization on SVE machine.
|
||||
instruct reduce_add$1_sve(vReg$1 dst_src1, vReg src2) %{
|
||||
predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) ||
|
||||
n->as_Reduction()->requires_strict_order());
|
||||
instruct reduce_add$1_sve(vReg`'ifelse($1, HF, F, $1) dst_src1, vReg src2) %{
|
||||
ifelse($1, HF,
|
||||
`predicate(UseSVE > 0);',
|
||||
`predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) ||
|
||||
n->as_Reduction()->requires_strict_order());')
|
||||
match(Set dst_src1 (AddReductionV$1 dst_src1 src2));
|
||||
format %{ "reduce_add$1_sve $dst_src1, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
ifelse($1, HF, `',
|
||||
`assert(UseSVE > 0, "must be sve");
|
||||
')dnl
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ $2, ptrue, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_ADD_FP_SVE(F, S)
|
||||
REDUCE_ADD_FP_SVE(HF, H)
|
||||
REDUCE_ADD_FP_SVE(F, S)
|
||||
|
||||
// reduction addD
|
||||
|
||||
@ -2125,21 +2184,30 @@ dnl
|
||||
dnl REDUCE_ADD_FP_PREDICATE($1, $2 )
|
||||
dnl REDUCE_ADD_FP_PREDICATE(insn_name, op_name)
|
||||
define(`REDUCE_ADD_FP_PREDICATE', `
|
||||
instruct reduce_add$1_masked(vReg$1 dst_src1, vReg src2, pRegGov pg) %{
|
||||
instruct reduce_add$1_masked(vReg$2 dst_src1, vReg src2, pRegGov pg) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionV$1 (Binary dst_src1 src2) pg));
|
||||
ifelse($2, F,
|
||||
`match(Set dst_src1 (AddReductionVHF (Binary dst_src1 src2) pg));
|
||||
match(Set dst_src1 (AddReductionV$2 (Binary dst_src1 src2) pg));',
|
||||
`match(Set dst_src1 (AddReductionV$2 (Binary dst_src1 src2) pg));')
|
||||
format %{ "reduce_add$1_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ $2,
|
||||
$pg$$PRegister, $src2$$FloatRegister);
|
||||
ifelse($2, F,
|
||||
`BasicType bt = Matcher::vector_element_basic_type(this, $src2);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`__ sve_fadda($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
|
||||
$pg$$PRegister, $src2$$FloatRegister);',
|
||||
`__ sve_fadda($dst_src1$$FloatRegister, __ $2,
|
||||
$pg$$PRegister, $src2$$FloatRegister);')
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_ADD_INT_PREDICATE(I, iRegIorL2I)
|
||||
REDUCE_ADD_INT_PREDICATE(L, iRegL)
|
||||
REDUCE_ADD_FP_PREDICATE(F, S)
|
||||
REDUCE_ADD_FP_PREDICATE(D, D)
|
||||
REDUCE_ADD_FP_PREDICATE(FHF, F)
|
||||
REDUCE_ADD_FP_PREDICATE(D, D)
|
||||
|
||||
// ------------------------------ Vector reduction mul -------------------------
|
||||
|
||||
@ -2172,30 +2240,37 @@ instruct reduce_mulL(iRegLNoSp dst, iRegL isrc, vReg vsrc) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) <= 16);
|
||||
match(Set dst (MulReductionVF fsrc vsrc));
|
||||
dnl REDUCE_MUL_FP($1, $2 )
|
||||
dnl REDUCE_MUL_FP(insn_name, op_name)
|
||||
define(`REDUCE_MUL_FP', `
|
||||
instruct reduce_mul$1(vReg$2 dst, vReg$2 ifelse($2, F, fsrc, dsrc), vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) ifelse($2, F, <=, ==) 16);
|
||||
ifelse($2, F,
|
||||
`match(Set dst (MulReductionVHF fsrc vsrc));
|
||||
match(Set dst (MulReductionV$2 fsrc vsrc));',
|
||||
`match(Set dst (MulReductionV$2 dsrc vsrc));')
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulF $dst, $fsrc, $vsrc\t# 2F/4F. KILL $tmp" %}
|
||||
ifelse($2, F,
|
||||
`format %{ "reduce_mul$1 $dst, $fsrc, $vsrc\t# 2F/4F/4HF/8HF. KILL $tmp" %}',
|
||||
`format %{ "reduce_mul$1 $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %}')
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_FLOAT, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
ifelse($2, F,
|
||||
`uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`__ neon_reduce_mul_fp($dst$$FloatRegister, bt, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);',
|
||||
`__ neon_reduce_mul_fp($dst$$FloatRegister, T_DOUBLE, $dsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, 16, $tmp$$FloatRegister);')
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulD(vRegD dst, vRegD dsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) == 16);
|
||||
match(Set dst (MulReductionVD dsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulD $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_DOUBLE, $dsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, 16, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_MUL_FP(FHF, F)
|
||||
REDUCE_MUL_FP(D, D)
|
||||
|
||||
dnl
|
||||
dnl REDUCE_BITWISE_OP_NEON($1, $2 $3 $4 )
|
||||
@ -2505,6 +2580,32 @@ REDUCE_MAXMIN_INT_PREDICATE(min, L, iRegL, MinReductionV)
|
||||
REDUCE_MAXMIN_FP_PREDICATE(min, F, fsrc, MinReductionV, sve_fminv, fmins)
|
||||
REDUCE_MAXMIN_FP_PREDICATE(min, D, dsrc, MinReductionV, sve_fminv, fmind)
|
||||
|
||||
// -------------------- Vector reduction unsigned min/max ----------------------
|
||||
|
||||
// reduction uminI
|
||||
REDUCE_MAXMIN_I_NEON(umin, UMinReductionV)
|
||||
REDUCE_MAXMIN_I_SVE(umin, UMinReductionV)
|
||||
|
||||
// reduction uminL
|
||||
REDUCE_MAXMIN_L_NEON(umin, UMinReductionV)
|
||||
REDUCE_MAXMIN_L_SVE(umin, UMinReductionV)
|
||||
|
||||
// reduction umin - predicated
|
||||
REDUCE_MAXMIN_INT_PREDICATE(umin, I, iRegIorL2I, UMinReductionV)
|
||||
REDUCE_MAXMIN_INT_PREDICATE(umin, L, iRegL, UMinReductionV)
|
||||
|
||||
// reduction umaxI
|
||||
REDUCE_MAXMIN_I_NEON(umax, UMaxReductionV)
|
||||
REDUCE_MAXMIN_I_SVE(umax, UMaxReductionV)
|
||||
|
||||
// reduction umaxL
|
||||
REDUCE_MAXMIN_L_NEON(umax, UMaxReductionV)
|
||||
REDUCE_MAXMIN_L_SVE(umax, UMaxReductionV)
|
||||
|
||||
// reduction umax - predicated
|
||||
REDUCE_MAXMIN_INT_PREDICATE(umax, I, iRegIorL2I, UMaxReductionV)
|
||||
REDUCE_MAXMIN_INT_PREDICATE(umax, L, iRegL, UMaxReductionV)
|
||||
|
||||
// ------------------------------ Vector reinterpret ---------------------------
|
||||
|
||||
instruct reinterpret_same_size(vReg dst_src) %{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -1000,30 +1000,6 @@ public:
|
||||
f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0);
|
||||
}
|
||||
|
||||
#define INSN(NAME, cond) \
|
||||
void NAME(address dest) { \
|
||||
br(cond, dest); \
|
||||
}
|
||||
|
||||
INSN(beq, EQ);
|
||||
INSN(bne, NE);
|
||||
INSN(bhs, HS);
|
||||
INSN(bcs, CS);
|
||||
INSN(blo, LO);
|
||||
INSN(bcc, CC);
|
||||
INSN(bmi, MI);
|
||||
INSN(bpl, PL);
|
||||
INSN(bvs, VS);
|
||||
INSN(bvc, VC);
|
||||
INSN(bhi, HI);
|
||||
INSN(bls, LS);
|
||||
INSN(bge, GE);
|
||||
INSN(blt, LT);
|
||||
INSN(bgt, GT);
|
||||
INSN(ble, LE);
|
||||
INSN(bal, AL);
|
||||
INSN(bnv, NV);
|
||||
|
||||
void br(Condition cc, Label &L);
|
||||
|
||||
#undef INSN
|
||||
@ -1095,6 +1071,10 @@ public:
|
||||
|
||||
#undef INSN
|
||||
|
||||
void wfet(Register rt) {
|
||||
system(0b00, 0b011, 0b0001, 0b0000, 0b000, rt);
|
||||
}
|
||||
|
||||
// we only provide mrs and msr for the special purpose system
|
||||
// registers where op1 (instr[20:19]) == 11
|
||||
// n.b msr has L (instr[21]) == 0 mrs has L == 1
|
||||
@ -2658,6 +2638,8 @@ template<typename R, typename... Rx>
|
||||
INSN(uminv, 1, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(smaxp, 0, 0b101001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(sminp, 0, 0b101011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(umaxp, 1, 0b101001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(uminp, 1, 0b101011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(sqdmulh,0, 0b101101, false); // accepted arrangements: T4H, T8H, T2S, T4S
|
||||
INSN(shsubv, 0, 0b001001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
|
||||
@ -3490,7 +3472,9 @@ public:
|
||||
INSN(sve_sub, 0b00000100, 0b000001000); // vector sub
|
||||
INSN(sve_uaddv, 0b00000100, 0b000001001); // unsigned add reduction to scalar
|
||||
INSN(sve_umax, 0b00000100, 0b001001000); // unsigned maximum vectors
|
||||
INSN(sve_umaxv, 0b00000100, 0b001001001); // unsigned maximum reduction to scalar
|
||||
INSN(sve_umin, 0b00000100, 0b001011000); // unsigned minimum vectors
|
||||
INSN(sve_uminv, 0b00000100, 0b001011001); // unsigned minimum reduction to scalar
|
||||
#undef INSN
|
||||
|
||||
// SVE floating-point arithmetic - predicate
|
||||
@ -3810,8 +3794,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8,
|
||||
bool isMerge, bool isFloat) {
|
||||
void _sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8,
|
||||
bool isMerge, bool isFloat) {
|
||||
starti;
|
||||
assert(T != Q, "invalid size");
|
||||
int sh = 0;
|
||||
@ -3835,11 +3819,11 @@ private:
|
||||
public:
|
||||
// SVE copy signed integer immediate to vector elements (predicated)
|
||||
void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8, bool isMerge) {
|
||||
sve_cpy(Zd, T, Pg, imm8, isMerge, /*isFloat*/false);
|
||||
_sve_cpy(Zd, T, Pg, imm8, isMerge, /*isFloat*/false);
|
||||
}
|
||||
// SVE copy floating-point immediate to vector elements (predicated)
|
||||
void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, double d) {
|
||||
sve_cpy(Zd, T, Pg, checked_cast<uint8_t>(pack(d)), /*isMerge*/true, /*isFloat*/true);
|
||||
_sve_cpy(Zd, T, Pg, checked_cast<uint8_t>(pack(d)), /*isMerge*/true, /*isFloat*/true);
|
||||
}
|
||||
|
||||
// SVE conditionally select elements from two vectors
|
||||
@ -4325,6 +4309,7 @@ public:
|
||||
#undef INSN
|
||||
|
||||
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
||||
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
|
||||
}
|
||||
|
||||
// Stack overflow checking
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, 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.
|
||||
*
|
||||
@ -33,6 +33,7 @@
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "ci/ciArrayKlass.hpp"
|
||||
#include "ci/ciInstance.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "code/compiledIC.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
@ -41,6 +42,7 @@
|
||||
#include "runtime/frame.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/threadIdentifier.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#include "vmreg_aarch64.inline.hpp"
|
||||
|
||||
@ -58,22 +60,6 @@ const Register SHIFT_count = r0; // where count for shift operations must be
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
static void select_different_registers(Register preserve,
|
||||
Register extra,
|
||||
Register &tmp1,
|
||||
Register &tmp2) {
|
||||
if (tmp1 == preserve) {
|
||||
assert_different_registers(tmp1, tmp2, extra);
|
||||
tmp1 = extra;
|
||||
} else if (tmp2 == preserve) {
|
||||
assert_different_registers(tmp1, tmp2, extra);
|
||||
tmp2 = extra;
|
||||
}
|
||||
assert_different_registers(preserve, tmp1, tmp2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void select_different_registers(Register preserve,
|
||||
Register extra,
|
||||
Register &tmp1,
|
||||
@ -532,6 +518,19 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
|
||||
case T_LONG: {
|
||||
assert(patch_code == lir_patch_none, "no patching handled here");
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address b = c->as_pointer();
|
||||
if (b == (address)ThreadIdentifier::unsafe_offset()) {
|
||||
__ lea(dest->as_register_lo(), ExternalAddress(b));
|
||||
break;
|
||||
}
|
||||
if (AOTRuntimeConstants::contains(b)) {
|
||||
__ load_aotrc_address(dest->as_register_lo(), b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__ mov(dest->as_register_lo(), (intptr_t)c->as_jlong());
|
||||
break;
|
||||
}
|
||||
@ -1218,43 +1217,11 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
|
||||
__ bind(*op->stub()->continuation());
|
||||
}
|
||||
|
||||
void LIR_Assembler::type_profile_helper(Register mdo,
|
||||
ciMethodData *md, ciProfileData *data,
|
||||
Register recv, Label* update_done) {
|
||||
void LIR_Assembler::type_profile_helper(Register mdo, ciMethodData *md,
|
||||
ciProfileData *data, Register recv) {
|
||||
|
||||
// Given a profile data offset, generate an Address which points to
|
||||
// the corresponding slot in mdo->data().
|
||||
// Clobbers rscratch2.
|
||||
auto slot_at = [=](ByteSize offset) -> Address {
|
||||
return __ form_address(rscratch2, mdo,
|
||||
md->byte_offset_of_slot(data, offset),
|
||||
LogBytesPerWord);
|
||||
};
|
||||
|
||||
for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
// See if the receiver is receiver[n].
|
||||
__ ldr(rscratch1, slot_at(ReceiverTypeData::receiver_offset(i)));
|
||||
__ cmp(recv, rscratch1);
|
||||
__ br(Assembler::NE, next_test);
|
||||
__ addptr(slot_at(ReceiverTypeData::receiver_count_offset(i)),
|
||||
DataLayout::counter_increment);
|
||||
__ b(*update_done);
|
||||
__ bind(next_test);
|
||||
}
|
||||
|
||||
// Didn't find receiver; find next empty slot and fill it in
|
||||
for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
Address recv_addr(slot_at(ReceiverTypeData::receiver_offset(i)));
|
||||
__ ldr(rscratch1, recv_addr);
|
||||
__ cbnz(rscratch1, next_test);
|
||||
__ str(recv, recv_addr);
|
||||
__ mov(rscratch1, DataLayout::counter_increment);
|
||||
__ str(rscratch1, slot_at(ReceiverTypeData::receiver_count_offset(i)));
|
||||
__ b(*update_done);
|
||||
__ bind(next_test);
|
||||
}
|
||||
int mdp_offset = md->byte_offset_of_slot(data, in_ByteSize(0));
|
||||
__ profile_receiver_type(recv, mdo, mdp_offset);
|
||||
}
|
||||
|
||||
void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) {
|
||||
@ -1291,12 +1258,9 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
|
||||
} else if (obj == klass_RInfo) {
|
||||
klass_RInfo = dst;
|
||||
}
|
||||
if (k->is_loaded() && !UseCompressedClassPointers) {
|
||||
select_different_registers(obj, dst, k_RInfo, klass_RInfo);
|
||||
} else {
|
||||
Rtmp1 = op->tmp3()->as_register();
|
||||
select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1);
|
||||
}
|
||||
|
||||
Rtmp1 = op->tmp3()->as_register();
|
||||
select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1);
|
||||
|
||||
assert_different_registers(obj, k_RInfo, klass_RInfo);
|
||||
|
||||
@ -1316,14 +1280,9 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
|
||||
__ b(*obj_is_null);
|
||||
__ bind(not_null);
|
||||
|
||||
Label update_done;
|
||||
Register recv = k_RInfo;
|
||||
__ load_klass(recv, obj);
|
||||
type_profile_helper(mdo, md, data, recv, &update_done);
|
||||
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
|
||||
__ addptr(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
__ bind(update_done);
|
||||
type_profile_helper(mdo, md, data, recv);
|
||||
} else {
|
||||
__ cbz(obj, *obj_is_null);
|
||||
}
|
||||
@ -1430,13 +1389,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||
__ b(done);
|
||||
__ bind(not_null);
|
||||
|
||||
Label update_done;
|
||||
Register recv = k_RInfo;
|
||||
__ load_klass(recv, value);
|
||||
type_profile_helper(mdo, md, data, recv, &update_done);
|
||||
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
|
||||
__ addptr(counter_addr, DataLayout::counter_increment);
|
||||
__ bind(update_done);
|
||||
type_profile_helper(mdo, md, data, recv);
|
||||
} else {
|
||||
__ cbz(value, done);
|
||||
}
|
||||
@ -2540,13 +2495,9 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
if (C1OptimizeVirtualCallProfiling && known_klass != nullptr) {
|
||||
// We know the type that will be seen at this call site; we can
|
||||
// statically update the MethodData* rather than needing to do
|
||||
// dynamic tests on the receiver type
|
||||
|
||||
// NOTE: we should probably put a lock around this search to
|
||||
// avoid collisions by concurrent compilations
|
||||
// dynamic tests on the receiver type.
|
||||
ciVirtualCallData* vc_data = (ciVirtualCallData*) data;
|
||||
uint i;
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
for (uint i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (known_klass->equals(receiver)) {
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
||||
@ -2554,36 +2505,13 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Receiver type not found in profile data; select an empty slot
|
||||
|
||||
// Note that this is less efficient than it should be because it
|
||||
// always does a write to the receiver part of the
|
||||
// VirtualCallData rather than just the first time
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (receiver == nullptr) {
|
||||
__ mov_metadata(rscratch1, known_klass->constant_encoding());
|
||||
Address recv_addr =
|
||||
__ form_address(rscratch2, mdo,
|
||||
md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)),
|
||||
LogBytesPerWord);
|
||||
__ str(rscratch1, recv_addr);
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
||||
__ addptr(data_addr, DataLayout::counter_increment);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Receiver type is not found in profile data.
|
||||
// Fall back to runtime helper to handle the rest at runtime.
|
||||
__ mov_metadata(recv, known_klass->constant_encoding());
|
||||
} else {
|
||||
__ load_klass(recv, recv);
|
||||
Label update_done;
|
||||
type_profile_helper(mdo, md, data, recv, &update_done);
|
||||
// Receiver did not match any saved receiver and there is no empty row for it.
|
||||
// Increment total counter to indicate polymorphic case.
|
||||
__ addptr(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
__ bind(update_done);
|
||||
}
|
||||
type_profile_helper(mdo, md, data, recv);
|
||||
} else {
|
||||
// Static call
|
||||
__ addptr(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
@ -50,9 +50,8 @@ friend class ArrayCopyStub;
|
||||
Address stack_slot_address(int index, uint shift, Register tmp, int adjust = 0);
|
||||
|
||||
// Record the type of the receiver in ReceiverTypeData
|
||||
void type_profile_helper(Register mdo,
|
||||
ciMethodData *md, ciProfileData *data,
|
||||
Register recv, Label* update_done);
|
||||
void type_profile_helper(Register mdo, ciMethodData *md,
|
||||
ciProfileData *data, Register recv);
|
||||
void add_debug_info_for_branch(address adr, CodeEmitInfo* info);
|
||||
|
||||
void casw(Register addr, Register newval, Register cmpval);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2026, 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.
|
||||
*
|
||||
@ -1287,9 +1287,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
|
||||
}
|
||||
LIR_Opr reg = rlock_result(x);
|
||||
LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
|
||||
if (!x->klass()->is_loaded() || UseCompressedClassPointers) {
|
||||
tmp3 = new_register(objectType);
|
||||
}
|
||||
tmp3 = new_register(objectType);
|
||||
__ checkcast(reg, obj.result(), x->klass(),
|
||||
new_register(objectType), new_register(objectType), tmp3,
|
||||
x->direct_compare(), info_for_exception, patching_info, stub,
|
||||
@ -1308,9 +1306,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
|
||||
}
|
||||
obj.load_item();
|
||||
LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
|
||||
if (!x->klass()->is_loaded() || UseCompressedClassPointers) {
|
||||
tmp3 = new_register(objectType);
|
||||
}
|
||||
tmp3 = new_register(objectType);
|
||||
__ instanceof(reg, obj.result(), x->klass(),
|
||||
new_register(objectType), new_register(objectType), tmp3,
|
||||
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2026, 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.
|
||||
*
|
||||
@ -105,12 +105,8 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
|
||||
} else {
|
||||
mov(t1, checked_cast<int32_t>(markWord::prototype().value()));
|
||||
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
|
||||
if (UseCompressedClassPointers) { // Take care not to kill klass
|
||||
encode_klass_not_null(t1, klass);
|
||||
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
} else {
|
||||
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
encode_klass_not_null(t1, klass); // Take care not to kill klass
|
||||
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
|
||||
if (len->is_valid()) {
|
||||
@ -121,7 +117,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
|
||||
// Clear gap/first 4 bytes following the length field.
|
||||
strw(zr, Address(obj, base_offset));
|
||||
}
|
||||
} else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
|
||||
} else if (!UseCompactObjectHeaders) {
|
||||
store_klass_gap(obj, zr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ define_pd_global(bool, TieredCompilation, false);
|
||||
define_pd_global(intx, CompileThreshold, 1500 );
|
||||
|
||||
define_pd_global(intx, OnStackReplacePercentage, 933 );
|
||||
define_pd_global(intx, NewSizeThreadIncrease, 4*K );
|
||||
define_pd_global(size_t, InitialCodeCacheSize, 160*K);
|
||||
define_pd_global(size_t, ReservedCodeCacheSize, 32*M );
|
||||
define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M );
|
||||
@ -52,7 +51,6 @@ define_pd_global(bool, ProfileInterpreter, false);
|
||||
define_pd_global(size_t, CodeCacheExpansionSize, 32*K );
|
||||
define_pd_global(size_t, CodeCacheMinBlockLength, 1);
|
||||
define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K);
|
||||
define_pd_global(bool, NeverActAsServerClassMachine, true );
|
||||
define_pd_global(bool, CICompileOSR, true );
|
||||
#endif // !COMPILER2
|
||||
define_pd_global(bool, UseTypeProfile, false);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2026 Arm Limited and/or its affiliates.
|
||||
* 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 +31,9 @@
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
@ -221,37 +224,52 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1,
|
||||
if (!UseObjectMonitorTable) {
|
||||
assert(t1_monitor == t1_mark, "should be the same here");
|
||||
} else {
|
||||
const Register t1_hash = t1;
|
||||
Label monitor_found;
|
||||
|
||||
// Load cache address
|
||||
lea(t3_t, Address(rthread, JavaThread::om_cache_oops_offset()));
|
||||
// Save the mark, we might need it to extract the hash.
|
||||
mov(t3, t1_mark);
|
||||
|
||||
const int num_unrolled = 2;
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
ldr(t1, Address(t3_t));
|
||||
cmp(obj, t1);
|
||||
ldr(t1_monitor, Address(rthread, cache_offset + monitor_offset));
|
||||
ldr(t2, Address(rthread, cache_offset));
|
||||
cmp(obj, t2);
|
||||
br(Assembler::EQ, monitor_found);
|
||||
increment(t3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
Label loop;
|
||||
// Look for the monitor in the table.
|
||||
|
||||
// Search for obj in cache.
|
||||
bind(loop);
|
||||
// Get the hash code.
|
||||
ubfx(t1_hash, t3, markWord::hash_shift, markWord::hash_bits);
|
||||
|
||||
// Check for match.
|
||||
ldr(t1, Address(t3_t));
|
||||
cmp(obj, t1);
|
||||
br(Assembler::EQ, monitor_found);
|
||||
// Get the table and calculate the bucket's address
|
||||
lea(t3, ExternalAddress(ObjectMonitorTable::current_table_address()));
|
||||
ldr(t3, Address(t3));
|
||||
ldr(t2, Address(t3, ObjectMonitorTable::table_capacity_mask_offset()));
|
||||
ands(t1_hash, t1_hash, t2);
|
||||
ldr(t3, Address(t3, ObjectMonitorTable::table_buckets_offset()));
|
||||
|
||||
// Search until null encountered, guaranteed _null_sentinel at end.
|
||||
increment(t3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cbnz(t1, loop);
|
||||
// Cache Miss, NE set from cmp above, cbnz does not set flags
|
||||
b(slow_path);
|
||||
// Read the monitor from the bucket.
|
||||
ldr(t1_monitor, Address(t3, t1_hash, Address::lsl(LogBytesPerWord)));
|
||||
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed).
|
||||
cmp(t1_monitor, (unsigned char)ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
br(Assembler::LO, slow_path);
|
||||
|
||||
// Check if object matches.
|
||||
ldr(t3, Address(t1_monitor, ObjectMonitor::object_offset()));
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, t3, t2, slow_path);
|
||||
cmp(t3, obj);
|
||||
br(Assembler::NE, slow_path);
|
||||
|
||||
bind(monitor_found);
|
||||
ldr(t1_monitor, Address(t3_t, OMCache::oop_to_monitor_difference()));
|
||||
}
|
||||
|
||||
const Register t2_owner_addr = t2;
|
||||
@ -1866,6 +1884,27 @@ void C2_MacroAssembler::neon_reduce_mul_fp(FloatRegister dst, BasicType bt,
|
||||
|
||||
BLOCK_COMMENT("neon_reduce_mul_fp {");
|
||||
switch(bt) {
|
||||
// The T_SHORT type below is for Float16 type which also uses floating-point
|
||||
// instructions.
|
||||
case T_SHORT:
|
||||
fmulh(dst, fsrc, vsrc);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 2);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 4);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 6);
|
||||
fmulh(dst, dst, vtmp);
|
||||
if (isQ) {
|
||||
ext(vtmp, T16B, vsrc, vsrc, 8);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 10);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 12);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 14);
|
||||
fmulh(dst, dst, vtmp);
|
||||
}
|
||||
break;
|
||||
case T_FLOAT:
|
||||
fmuls(dst, fsrc, vsrc);
|
||||
ins(vtmp, S, vsrc, 0, 1);
|
||||
@ -1890,6 +1929,33 @@ void C2_MacroAssembler::neon_reduce_mul_fp(FloatRegister dst, BasicType bt,
|
||||
BLOCK_COMMENT("} neon_reduce_mul_fp");
|
||||
}
|
||||
|
||||
// Vector reduction add for half float type with ASIMD instructions.
|
||||
void C2_MacroAssembler::neon_reduce_add_fp16(FloatRegister dst, FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp) {
|
||||
assert(vector_length_in_bytes == 8 || vector_length_in_bytes == 16, "unsupported");
|
||||
bool isQ = vector_length_in_bytes == 16;
|
||||
|
||||
BLOCK_COMMENT("neon_reduce_add_fp16 {");
|
||||
faddh(dst, fsrc, vsrc);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 2);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 4);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 6);
|
||||
faddh(dst, dst, vtmp);
|
||||
if (isQ) {
|
||||
ext(vtmp, T16B, vsrc, vsrc, 8);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 10);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 12);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 14);
|
||||
faddh(dst, dst, vtmp);
|
||||
}
|
||||
BLOCK_COMMENT("} neon_reduce_add_fp16");
|
||||
}
|
||||
|
||||
// Helper to select logical instruction
|
||||
void C2_MacroAssembler::neon_reduce_logical_helper(int opc, bool is64, Register Rd,
|
||||
Register Rn, Register Rm,
|
||||
@ -1960,50 +2026,76 @@ void C2_MacroAssembler::neon_reduce_logical(int opc, Register dst, BasicType bt,
|
||||
BLOCK_COMMENT("} neon_reduce_logical");
|
||||
}
|
||||
|
||||
// Vector reduction min/max for integral type with ASIMD instructions.
|
||||
// Helper function to decode min/max reduction operation properties
|
||||
void C2_MacroAssembler::decode_minmax_reduction_opc(int opc, bool* is_min,
|
||||
bool* is_unsigned,
|
||||
Condition* cond) {
|
||||
switch(opc) {
|
||||
case Op_MinReductionV:
|
||||
*is_min = true; *is_unsigned = false; *cond = LT; break;
|
||||
case Op_MaxReductionV:
|
||||
*is_min = false; *is_unsigned = false; *cond = GT; break;
|
||||
case Op_UMinReductionV:
|
||||
*is_min = true; *is_unsigned = true; *cond = LO; break;
|
||||
case Op_UMaxReductionV:
|
||||
*is_min = false; *is_unsigned = true; *cond = HI; break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
// Vector reduction min/max/umin/umax for integral type with ASIMD instructions.
|
||||
// Note: vtmp is not used and expected to be fnoreg for T_LONG case.
|
||||
// Clobbers: rscratch1, rflags
|
||||
void C2_MacroAssembler::neon_reduce_minmax_integral(int opc, Register dst, BasicType bt,
|
||||
Register isrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes,
|
||||
FloatRegister vtmp) {
|
||||
assert(opc == Op_MinReductionV || opc == Op_MaxReductionV, "unsupported");
|
||||
assert(opc == Op_MinReductionV || opc == Op_MaxReductionV ||
|
||||
opc == Op_UMinReductionV || opc == Op_UMaxReductionV, "unsupported");
|
||||
assert(vector_length_in_bytes == 8 || vector_length_in_bytes == 16, "unsupported");
|
||||
assert(bt == T_BYTE || bt == T_SHORT || bt == T_INT || bt == T_LONG, "unsupported");
|
||||
assert_different_registers(dst, isrc);
|
||||
bool isQ = vector_length_in_bytes == 16;
|
||||
bool is_min = opc == Op_MinReductionV;
|
||||
|
||||
bool is_min;
|
||||
bool is_unsigned;
|
||||
Condition cond;
|
||||
decode_minmax_reduction_opc(opc, &is_min, &is_unsigned, &cond);
|
||||
BLOCK_COMMENT("neon_reduce_minmax_integral {");
|
||||
if (bt == T_LONG) {
|
||||
assert(vtmp == fnoreg, "should be");
|
||||
assert(isQ, "should be");
|
||||
umov(rscratch1, vsrc, D, 0);
|
||||
cmp(isrc, rscratch1);
|
||||
csel(dst, isrc, rscratch1, is_min ? LT : GT);
|
||||
csel(dst, isrc, rscratch1, cond);
|
||||
umov(rscratch1, vsrc, D, 1);
|
||||
cmp(dst, rscratch1);
|
||||
csel(dst, dst, rscratch1, is_min ? LT : GT);
|
||||
csel(dst, dst, rscratch1, cond);
|
||||
} else {
|
||||
SIMD_Arrangement size = esize2arrangement((unsigned)type2aelembytes(bt), isQ);
|
||||
if (size == T2S) {
|
||||
is_min ? sminp(vtmp, size, vsrc, vsrc) : smaxp(vtmp, size, vsrc, vsrc);
|
||||
// For T2S (2x32-bit elements), use pairwise instructions because
|
||||
// uminv/umaxv/sminv/smaxv don't support arrangement 2S.
|
||||
neon_minmaxp(is_unsigned, is_min, vtmp, size, vsrc, vsrc);
|
||||
} else {
|
||||
is_min ? sminv(vtmp, size, vsrc) : smaxv(vtmp, size, vsrc);
|
||||
// For other sizes, use reduction to scalar instructions.
|
||||
neon_minmaxv(is_unsigned, is_min, vtmp, size, vsrc);
|
||||
}
|
||||
if (bt == T_INT) {
|
||||
umov(dst, vtmp, S, 0);
|
||||
} else if (is_unsigned) {
|
||||
umov(dst, vtmp, elemType_to_regVariant(bt), 0);
|
||||
} else {
|
||||
smov(dst, vtmp, elemType_to_regVariant(bt), 0);
|
||||
}
|
||||
cmpw(dst, isrc);
|
||||
cselw(dst, dst, isrc, is_min ? LT : GT);
|
||||
cselw(dst, dst, isrc, cond);
|
||||
}
|
||||
BLOCK_COMMENT("} neon_reduce_minmax_integral");
|
||||
}
|
||||
|
||||
// Vector reduction for integral type with SVE instruction.
|
||||
// Supported operations are Add, And, Or, Xor, Max, Min.
|
||||
// Supported operations are Add, And, Or, Xor, Max, Min, UMax, UMin.
|
||||
// rflags would be clobbered if opc is Op_MaxReductionV or Op_MinReductionV.
|
||||
void C2_MacroAssembler::sve_reduce_integral(int opc, Register dst, BasicType bt, Register src1,
|
||||
FloatRegister src2, PRegister pg, FloatRegister tmp) {
|
||||
@ -2075,35 +2167,27 @@ void C2_MacroAssembler::sve_reduce_integral(int opc, Register dst, BasicType bt,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Op_MaxReductionV: {
|
||||
sve_smaxv(tmp, size, pg, src2);
|
||||
if (bt == T_INT || bt == T_LONG) {
|
||||
case Op_MaxReductionV:
|
||||
case Op_MinReductionV:
|
||||
case Op_UMaxReductionV:
|
||||
case Op_UMinReductionV: {
|
||||
bool is_min;
|
||||
bool is_unsigned;
|
||||
Condition cond;
|
||||
decode_minmax_reduction_opc(opc, &is_min, &is_unsigned, &cond);
|
||||
sve_minmaxv(is_unsigned, is_min, tmp, size, pg, src2);
|
||||
// Move result from vector to general register
|
||||
if (is_unsigned || bt == T_INT || bt == T_LONG) {
|
||||
umov(dst, tmp, size, 0);
|
||||
} else {
|
||||
smov(dst, tmp, size, 0);
|
||||
}
|
||||
if (bt == T_LONG) {
|
||||
cmp(dst, src1);
|
||||
csel(dst, dst, src1, Assembler::GT);
|
||||
csel(dst, dst, src1, cond);
|
||||
} else {
|
||||
cmpw(dst, src1);
|
||||
cselw(dst, dst, src1, Assembler::GT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Op_MinReductionV: {
|
||||
sve_sminv(tmp, size, pg, src2);
|
||||
if (bt == T_INT || bt == T_LONG) {
|
||||
umov(dst, tmp, size, 0);
|
||||
} else {
|
||||
smov(dst, tmp, size, 0);
|
||||
}
|
||||
if (bt == T_LONG) {
|
||||
cmp(dst, src1);
|
||||
csel(dst, dst, src1, Assembler::LT);
|
||||
} else {
|
||||
cmpw(dst, src1);
|
||||
cselw(dst, dst, src1, Assembler::LT);
|
||||
cselw(dst, dst, src1, cond);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2379,17 +2463,17 @@ void C2_MacroAssembler::neon_rearrange_hsd(FloatRegister dst, FloatRegister src,
|
||||
break;
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
// Load the iota indices for Long type. The indices are ordered by
|
||||
// type B/S/I/L/F/D, and the offset between two types is 16; Hence
|
||||
// the offset for L is 48.
|
||||
lea(rscratch1,
|
||||
ExternalAddress(StubRoutines::aarch64::vector_iota_indices() + 48));
|
||||
ldrq(tmp, rscratch1);
|
||||
// Check whether the input "shuffle" is the same with iota indices.
|
||||
// Return "src" if true, otherwise swap the two elements of "src".
|
||||
cm(EQ, dst, size2, shuffle, tmp);
|
||||
ext(tmp, size1, src, src, 8);
|
||||
bsl(dst, size1, src, tmp);
|
||||
{
|
||||
int idx = vector_iota_entry_index(T_LONG);
|
||||
lea(rscratch1,
|
||||
ExternalAddress(StubRoutines::aarch64::vector_iota_indices(idx)));
|
||||
ldrq(tmp, rscratch1);
|
||||
// Check whether the input "shuffle" is the same with iota indices.
|
||||
// Return "src" if true, otherwise swap the two elements of "src".
|
||||
cm(EQ, dst, size2, shuffle, tmp);
|
||||
ext(tmp, size1, src, src, 8);
|
||||
bsl(dst, size1, src, tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported element type");
|
||||
@ -2840,3 +2924,45 @@ void C2_MacroAssembler::vector_expand_sve(FloatRegister dst, FloatRegister src,
|
||||
// dst = 00 87 00 65 00 43 00 21
|
||||
sve_tbl(dst, size, src, dst);
|
||||
}
|
||||
|
||||
// Optimized SVE cpy (imm, zeroing) instruction.
|
||||
//
|
||||
// `movi; cpy(imm, merging)` and `cpy(imm, zeroing)` have the same
|
||||
// functionality, but test results show that `movi; cpy(imm, merging)` has
|
||||
// higher throughput on some microarchitectures. This would depend on
|
||||
// microarchitecture and so may vary between implementations.
|
||||
void C2_MacroAssembler::sve_cpy(FloatRegister dst, SIMD_RegVariant T,
|
||||
PRegister pg, int imm8, bool isMerge) {
|
||||
if (VM_Version::prefer_sve_merging_mode_cpy() && !isMerge) {
|
||||
// Generates a NEON instruction `movi V<dst>.2d, #0`.
|
||||
// On AArch64, Z and V registers alias in the low 128 bits, so V<dst> is
|
||||
// the low 128 bits of Z<dst>. A write to V<dst> also clears all bits of
|
||||
// Z<dst> above 128, so this `movi` instruction effectively zeroes the
|
||||
// entire Z<dst> register. According to the Arm Software Optimization
|
||||
// Guide, `movi` is zero latency.
|
||||
movi(dst, T2D, 0);
|
||||
isMerge = true;
|
||||
}
|
||||
Assembler::sve_cpy(dst, T, pg, imm8, isMerge);
|
||||
}
|
||||
|
||||
int C2_MacroAssembler::vector_iota_entry_index(BasicType bt) {
|
||||
// The vector iota entries array is ordered by type B/S/I/L/F/D, and
|
||||
// the offset between two types is 16.
|
||||
switch(bt) {
|
||||
case T_BYTE:
|
||||
return 0;
|
||||
case T_SHORT:
|
||||
return 1;
|
||||
case T_INT:
|
||||
return 2;
|
||||
case T_LONG:
|
||||
return 3;
|
||||
case T_FLOAT:
|
||||
return 4;
|
||||
case T_DOUBLE:
|
||||
return 5;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,6 +34,37 @@
|
||||
void neon_reduce_logical_helper(int opc, bool sf, Register Rd, Register Rn, Register Rm,
|
||||
enum shift_kind kind = Assembler::LSL, unsigned shift = 0);
|
||||
|
||||
// Helper functions for min/max reduction operations
|
||||
|
||||
void decode_minmax_reduction_opc(int opc, bool* is_min, bool* is_unsigned, Condition* cond);
|
||||
|
||||
void neon_minmaxp(bool is_unsigned, bool is_min, FloatRegister dst,
|
||||
SIMD_Arrangement size, FloatRegister src1, FloatRegister src2) {
|
||||
auto m = is_unsigned ? (is_min ? &Assembler::uminp : &Assembler::umaxp)
|
||||
: (is_min ? &Assembler::sminp : &Assembler::smaxp);
|
||||
(this->*m)(dst, size, src1, src2);
|
||||
}
|
||||
|
||||
// Typedefs used to disambiguate overloaded member functions.
|
||||
typedef void (Assembler::*neon_reduction2)
|
||||
(FloatRegister, SIMD_Arrangement, FloatRegister);
|
||||
|
||||
void neon_minmaxv(bool is_unsigned, bool is_min, FloatRegister dst,
|
||||
SIMD_Arrangement size, FloatRegister src) {
|
||||
auto m = is_unsigned ? (is_min ? (neon_reduction2)&Assembler::uminv
|
||||
: (neon_reduction2)&Assembler::umaxv)
|
||||
: (is_min ? &Assembler::sminv
|
||||
: &Assembler::smaxv);
|
||||
(this->*m)(dst, size, src);
|
||||
}
|
||||
|
||||
void sve_minmaxv(bool is_unsigned, bool is_min, FloatRegister dst,
|
||||
SIMD_RegVariant size, PRegister pg, FloatRegister src) {
|
||||
auto m = is_unsigned ? (is_min ? &Assembler::sve_uminv : &Assembler::sve_umaxv)
|
||||
: (is_min ? &Assembler::sve_sminv : &Assembler::sve_smaxv);
|
||||
(this->*m)(dst, size, pg, src);
|
||||
}
|
||||
|
||||
void select_from_two_vectors_neon(FloatRegister dst, FloatRegister src1,
|
||||
FloatRegister src2, FloatRegister index,
|
||||
FloatRegister tmp, unsigned vector_length_in_bytes);
|
||||
@ -44,6 +75,8 @@
|
||||
unsigned vector_length_in_bytes);
|
||||
|
||||
public:
|
||||
using Assembler::sve_cpy;
|
||||
|
||||
// jdk.internal.util.ArraysSupport.vectorizedHashCode
|
||||
address arrays_hashcode(Register ary, Register cnt, Register result, FloatRegister vdata0,
|
||||
FloatRegister vdata1, FloatRegister vdata2, FloatRegister vdata3,
|
||||
@ -144,6 +177,9 @@
|
||||
FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp);
|
||||
|
||||
void neon_reduce_add_fp16(FloatRegister dst, FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp);
|
||||
|
||||
void neon_reduce_logical(int opc, Register dst, BasicType bt, Register isrc,
|
||||
FloatRegister vsrc, unsigned vector_length_in_bytes);
|
||||
|
||||
@ -213,4 +249,8 @@
|
||||
void vector_expand_sve(FloatRegister dst, FloatRegister src, PRegister pg,
|
||||
FloatRegister tmp1, FloatRegister tmp2, BasicType bt,
|
||||
int vector_length_in_bytes);
|
||||
|
||||
void sve_cpy(FloatRegister dst, SIMD_RegVariant T, PRegister pg, int imm8,
|
||||
bool isMerge);
|
||||
int vector_iota_entry_index(BasicType bt);
|
||||
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
||||
|
||||
@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, MinJumpTableSize, 10);
|
||||
define_pd_global(intx, InteriorEntryAlignment, 16);
|
||||
define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
|
||||
define_pd_global(intx, LoopUnrollLimit, 60);
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
// InitialCodeCacheSize derived from specjbb2000 run.
|
||||
@ -75,9 +74,6 @@ define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M );
|
||||
define_pd_global(size_t, CodeCacheMinBlockLength, 6);
|
||||
define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K);
|
||||
|
||||
// Ergonomics related flags
|
||||
define_pd_global(bool, NeverActAsServerClassMachine, false);
|
||||
|
||||
define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed.
|
||||
|
||||
#endif // CPU_AARCH64_C2_GLOBALS_AARCH64_HPP
|
||||
|
||||
@ -89,16 +89,21 @@ void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address
|
||||
NativeMovConstReg* method_holder
|
||||
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
|
||||
|
||||
// In AOT "production" run we have mixture of AOTed and normal JITed code.
|
||||
// Static call stub in AOTed nmethod always has far jump.
|
||||
// Normal JITed nmethod may have short or far jump depending on distance.
|
||||
// Determine actual jump instruction we have in code.
|
||||
address next_instr = method_holder->next_instruction_address();
|
||||
bool is_general_jump = nativeInstruction_at(next_instr)->is_general_jump();
|
||||
|
||||
#ifdef ASSERT
|
||||
NativeJump* jump = MacroAssembler::codestub_branch_needs_far_jump()
|
||||
? nativeGeneralJump_at(method_holder->next_instruction_address())
|
||||
: nativeJump_at(method_holder->next_instruction_address());
|
||||
NativeJump* jump = is_general_jump ? nativeGeneralJump_at(next_instr) : nativeJump_at(next_instr);
|
||||
verify_mt_safe(callee, entry, method_holder, jump);
|
||||
#endif
|
||||
|
||||
// Update stub.
|
||||
method_holder->set_data((intptr_t)callee());
|
||||
MacroAssembler::pd_patch_instruction(method_holder->next_instruction_address(), entry);
|
||||
MacroAssembler::pd_patch_instruction(next_instr, entry);
|
||||
ICache::invalidate_range(stub, to_interp_stub_size());
|
||||
// Update jump to call.
|
||||
set_destination_mt_safe(stub);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -146,10 +146,10 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
|
||||
bool should_save_return_value = !_needs_return_buffer;
|
||||
RegSpiller out_reg_spiller(_output_registers);
|
||||
int spill_offset = -1;
|
||||
int out_spill_offset = -1;
|
||||
|
||||
if (should_save_return_value) {
|
||||
spill_offset = 0;
|
||||
out_spill_offset = 0;
|
||||
// spill area can be shared with shadow space and out args,
|
||||
// since they are only used before the call,
|
||||
// and spill area is only used after.
|
||||
@ -174,6 +174,9 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
// FP-> | |
|
||||
// |---------------------| = frame_bottom_offset = frame_size
|
||||
// | (optional) |
|
||||
// | in_reg_spiller area |
|
||||
// |---------------------|
|
||||
// | (optional) |
|
||||
// | capture state buf |
|
||||
// |---------------------| = StubLocations::CAPTURED_STATE_BUFFER
|
||||
// | (optional) |
|
||||
@ -187,6 +190,19 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
GrowableArray<VMStorage> out_regs = ForeignGlobals::replace_place_holders(_input_registers, locs);
|
||||
ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, shuffle_reg);
|
||||
|
||||
// Need to spill for state capturing runtime call.
|
||||
// The area spilled into is distinct from the capture state buffer.
|
||||
RegSpiller in_reg_spiller(out_regs);
|
||||
int in_spill_offset = -1;
|
||||
if (_captured_state_mask != 0) {
|
||||
// The spill area cannot be shared with the out_spill since
|
||||
// spilling needs to happen before the call. Allocate a new
|
||||
// region in the stack for this spill space.
|
||||
in_spill_offset = allocated_frame_size;
|
||||
allocated_frame_size += in_reg_spiller.spill_size_bytes();
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
LogTarget(Trace, foreign, downcall) lt;
|
||||
if (lt.is_enabled()) {
|
||||
@ -228,6 +244,20 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes);
|
||||
__ block_comment("} argument shuffle");
|
||||
|
||||
if (_captured_state_mask != 0) {
|
||||
assert(in_spill_offset != -1, "must be");
|
||||
__ block_comment("{ load initial thread local");
|
||||
in_reg_spiller.generate_spill(_masm, in_spill_offset);
|
||||
|
||||
// Copy the contents of the capture state buffer into thread local
|
||||
__ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER)));
|
||||
__ movw(c_rarg1, _captured_state_mask);
|
||||
__ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_pre), tmp1);
|
||||
|
||||
in_reg_spiller.generate_fill(_masm, in_spill_offset);
|
||||
__ block_comment("} load initial thread local");
|
||||
}
|
||||
|
||||
__ blr(as_Register(locs.get(StubLocations::TARGET_ADDRESS)));
|
||||
// this call is assumed not to have killed rthread
|
||||
|
||||
@ -254,15 +284,15 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
__ block_comment("{ save thread local");
|
||||
|
||||
if (should_save_return_value) {
|
||||
out_reg_spiller.generate_spill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_spill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER)));
|
||||
__ movw(c_rarg1, _captured_state_mask);
|
||||
__ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state), tmp1);
|
||||
__ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_post), tmp1);
|
||||
|
||||
if (should_save_return_value) {
|
||||
out_reg_spiller.generate_fill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_fill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ block_comment("} save thread local");
|
||||
@ -321,7 +351,7 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
|
||||
if (should_save_return_value) {
|
||||
// Need to save the native result registers around any runtime calls.
|
||||
out_reg_spiller.generate_spill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_spill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ mov(c_rarg0, rthread);
|
||||
@ -330,7 +360,7 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
__ blr(tmp1);
|
||||
|
||||
if (should_save_return_value) {
|
||||
out_reg_spiller.generate_fill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_fill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ b(L_after_safepoint_poll);
|
||||
@ -342,13 +372,13 @@ void DowncallLinker::StubGenerator::generate() {
|
||||
__ bind(L_reguard);
|
||||
|
||||
if (should_save_return_value) {
|
||||
out_reg_spiller.generate_spill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_spill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1);
|
||||
|
||||
if (should_save_return_value) {
|
||||
out_reg_spiller.generate_fill(_masm, spill_offset);
|
||||
out_reg_spiller.generate_fill(_masm, out_spill_offset);
|
||||
}
|
||||
|
||||
__ b(L_after_reguard);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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.
|
||||
*
|
||||
@ -245,8 +245,8 @@ inline bool frame::equal(frame other) const {
|
||||
|
||||
// Return unique id for this frame. The id must have a value where we can distinguish
|
||||
// identity and younger/older relationship. null represents an invalid (incomparable)
|
||||
// frame.
|
||||
inline intptr_t* frame::id(void) const { return unextended_sp(); }
|
||||
// frame. Should not be called for heap frames.
|
||||
inline intptr_t* frame::id(void) const { return real_fp(); }
|
||||
|
||||
// Return true if the frame is older (less recent activation) than the frame represented by id
|
||||
inline bool frame::is_older(intptr_t* id) const { assert(this->id() != nullptr && id != nullptr, "null frame id");
|
||||
@ -412,6 +412,9 @@ inline frame frame::sender(RegisterMap* map) const {
|
||||
StackWatermarkSet::on_iteration(map->thread(), result);
|
||||
}
|
||||
|
||||
// Calling frame::id() is currently not supported for heap frames.
|
||||
assert(result._on_heap || this->_on_heap || result.is_older(this->id()), "Must be");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BarrierSetAssembler.hpp"
|
||||
#include "gc/g1/g1BarrierSetRuntime.hpp"
|
||||
@ -243,9 +244,25 @@ static void generate_post_barrier(MacroAssembler* masm,
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg, rscratch1);
|
||||
|
||||
// Does store cross heap regions?
|
||||
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ cbz(tmp1, done);
|
||||
#if INCLUDE_CDS
|
||||
// AOT code needs to load the barrier grain shift from the aot
|
||||
// runtime constants area in the code cache otherwise we can compile
|
||||
// it as an immediate operand
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address grain_shift_address = (address)AOTRuntimeConstants::grain_shift_address();
|
||||
__ eor(tmp1, store_addr, new_val);
|
||||
__ lea(tmp2, ExternalAddress(grain_shift_address));
|
||||
__ ldrb(tmp2, tmp2);
|
||||
__ lsrv(tmp1, tmp1, tmp2);
|
||||
__ cbz(tmp1, done);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ cbz(tmp1, done);
|
||||
}
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
__ cbz(new_val, done);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,6 +441,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
return opto_reg;
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Load the oop from the weak handle.
|
||||
__ ldr(obj, Address(obj));
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -135,6 +135,7 @@ public:
|
||||
OptoReg::Name opto_reg);
|
||||
OptoReg::Name refine_register(const Node* node,
|
||||
OptoReg::Name opto_reg);
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
|
||||
@ -209,6 +209,10 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
|
||||
bs_asm->increment_patching_epoch();
|
||||
}
|
||||
|
||||
// Enable WXWrite: the function is called directly from nmethod_entry_barrier
|
||||
// stub.
|
||||
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
|
||||
|
||||
NativeNMethodBarrier barrier(nm);
|
||||
barrier.set_value(value, bit_mask);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,10 @@ void CardTableBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet d
|
||||
}
|
||||
}
|
||||
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
|
||||
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2) {
|
||||
precond(tmp1 != noreg);
|
||||
precond(tmp2 != noreg);
|
||||
assert_different_registers(obj, tmp1, tmp2);
|
||||
BarrierSet* bs = BarrierSet::barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind");
|
||||
|
||||
@ -65,16 +67,16 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob
|
||||
|
||||
assert(CardTable::dirty_card_val() == 0, "must be");
|
||||
|
||||
__ load_byte_map_base(rscratch1);
|
||||
__ load_byte_map_base(tmp1);
|
||||
|
||||
if (UseCondCardMark) {
|
||||
Label L_already_dirty;
|
||||
__ ldrb(rscratch2, Address(obj, rscratch1));
|
||||
__ cbz(rscratch2, L_already_dirty);
|
||||
__ strb(zr, Address(obj, rscratch1));
|
||||
__ ldrb(tmp2, Address(obj, tmp1));
|
||||
__ cbz(tmp2, L_already_dirty);
|
||||
__ strb(zr, Address(obj, tmp1));
|
||||
__ bind(L_already_dirty);
|
||||
} else {
|
||||
__ strb(zr, Address(obj, rscratch1));
|
||||
__ strb(zr, Address(obj, tmp1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,10 +114,10 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS
|
||||
if (needs_post_barrier) {
|
||||
// flatten object address if needed
|
||||
if (!precise || (dst.index() == noreg && dst.offset() == 0)) {
|
||||
store_check(masm, dst.base(), dst);
|
||||
store_check(masm, dst.base(), tmp1, tmp2);
|
||||
} else {
|
||||
__ lea(tmp3, dst);
|
||||
store_check(masm, tmp3, dst);
|
||||
store_check(masm, tmp3, tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,7 +46,7 @@ protected:
|
||||
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
void store_check(MacroAssembler* masm, Register obj, Address dst);
|
||||
void store_check(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2);
|
||||
};
|
||||
|
||||
#endif // CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -85,26 +86,16 @@ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Dec
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp,
|
||||
bool tosca_live,
|
||||
bool expand_call) {
|
||||
if (ShenandoahSATBBarrier) {
|
||||
satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, rscratch1, tosca_live, expand_call);
|
||||
}
|
||||
}
|
||||
void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
bool tosca_live,
|
||||
bool expand_call) {
|
||||
assert(ShenandoahSATBBarrier, "Should be checked by caller");
|
||||
|
||||
void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
bool tosca_live,
|
||||
bool expand_call) {
|
||||
// If expand_call is true then we expand the call_VM_leaf macro
|
||||
// directly to skip generating the check by
|
||||
// InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
|
||||
@ -358,20 +349,20 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d
|
||||
if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
|
||||
__ enter(/*strip_ret_addr*/true);
|
||||
__ push_call_clobbered_registers();
|
||||
satb_write_barrier_pre(masm /* masm */,
|
||||
noreg /* obj */,
|
||||
dst /* pre_val */,
|
||||
rthread /* thread */,
|
||||
tmp1 /* tmp1 */,
|
||||
tmp2 /* tmp2 */,
|
||||
true /* tosca_live */,
|
||||
true /* expand_call */);
|
||||
satb_barrier(masm /* masm */,
|
||||
noreg /* obj */,
|
||||
dst /* pre_val */,
|
||||
rthread /* thread */,
|
||||
tmp1 /* tmp1 */,
|
||||
tmp2 /* tmp2 */,
|
||||
true /* tosca_live */,
|
||||
true /* expand_call */);
|
||||
__ pop_call_clobbered_registers();
|
||||
__ leave();
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj) {
|
||||
void ShenandoahBarrierSetAssembler::card_barrier(MacroAssembler* masm, Register obj) {
|
||||
assert(ShenandoahCardBarrier, "Should have been checked by caller");
|
||||
|
||||
__ lsr(obj, obj, CardTable::card_shift());
|
||||
@ -394,13 +385,13 @@ void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register o
|
||||
|
||||
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
|
||||
bool on_oop = is_reference_type(type);
|
||||
if (!on_oop) {
|
||||
// 1: non-reference types require no barriers
|
||||
if (!is_reference_type(type)) {
|
||||
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
|
||||
return;
|
||||
}
|
||||
|
||||
// flatten object address if needed
|
||||
// Flatten object address right away for simplicity: likely needed by barriers
|
||||
if (dst.index() == noreg && dst.offset() == 0) {
|
||||
if (dst.base() != tmp3) {
|
||||
__ mov(tmp3, dst.base());
|
||||
@ -409,20 +400,26 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet
|
||||
__ lea(tmp3, dst);
|
||||
}
|
||||
|
||||
shenandoah_write_barrier_pre(masm,
|
||||
tmp3 /* obj */,
|
||||
tmp2 /* pre_val */,
|
||||
rthread /* thread */,
|
||||
tmp1 /* tmp */,
|
||||
val != noreg /* tosca_live */,
|
||||
false /* expand_call */);
|
||||
bool storing_non_null = (val != noreg);
|
||||
|
||||
// 2: pre-barrier: SATB needs the previous value
|
||||
if (ShenandoahBarrierSet::need_satb_barrier(decorators, type)) {
|
||||
satb_barrier(masm,
|
||||
tmp3 /* obj */,
|
||||
tmp2 /* pre_val */,
|
||||
rthread /* thread */,
|
||||
tmp1 /* tmp */,
|
||||
rscratch1 /* tmp2 */,
|
||||
storing_non_null /* tosca_live */,
|
||||
false /* expand_call */);
|
||||
}
|
||||
|
||||
// Store!
|
||||
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg);
|
||||
|
||||
bool in_heap = (decorators & IN_HEAP) != 0;
|
||||
bool needs_post_barrier = (val != noreg) && in_heap && ShenandoahCardBarrier;
|
||||
if (needs_post_barrier) {
|
||||
store_check(masm, tmp3);
|
||||
// 3: post-barrier: card barrier needs store address
|
||||
if (ShenandoahBarrierSet::need_card_barrier(decorators, type) && storing_non_null) {
|
||||
card_barrier(masm, tmp3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,6 +443,30 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj,
|
||||
Register tmp, Label& slow_path) {
|
||||
assert_different_registers(obj, tmp);
|
||||
|
||||
Label done;
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the reference is null, and if it is, take the fast path.
|
||||
__ cbz(obj, done);
|
||||
|
||||
Address gc_state(rthread, ShenandoahThreadLocalData::gc_state_offset());
|
||||
__ lea(tmp, gc_state);
|
||||
__ ldrb(tmp, __ legitimize_address(gc_state, 1, tmp));
|
||||
|
||||
// Check if the heap is under weak-reference/roots processing, in
|
||||
// which case we need to take the slow path.
|
||||
__ tbnz(tmp, ShenandoahHeap::WEAK_ROOTS_BITPOS, slow_path);
|
||||
__ bind(done);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Special Shenandoah CAS implementation that handles false negatives due
|
||||
// to concurrent evacuation. The service is more complex than a
|
||||
// traditional CAS operation because the CAS operation is intended to
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -40,23 +41,16 @@ class StubCodeGenerator;
|
||||
class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
|
||||
private:
|
||||
|
||||
void satb_write_barrier_pre(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
bool tosca_live,
|
||||
bool expand_call);
|
||||
void shenandoah_write_barrier_pre(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp,
|
||||
bool tosca_live,
|
||||
bool expand_call);
|
||||
void satb_barrier(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register pre_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
bool tosca_live,
|
||||
bool expand_call);
|
||||
|
||||
void store_check(MacroAssembler* masm, Register obj);
|
||||
void card_barrier(MacroAssembler* masm, Register obj);
|
||||
|
||||
void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg);
|
||||
void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg);
|
||||
@ -86,6 +80,9 @@ public:
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3);
|
||||
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath);
|
||||
#ifdef COMPILER2
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif
|
||||
void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val,
|
||||
bool acquire, bool release, bool is_cae, Register result);
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -879,7 +879,9 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
ICache::invalidate_word((address)patch_addr);
|
||||
if (!UseSingleICacheInvalidation) {
|
||||
ICache::invalidate_word((address)patch_addr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPILER1
|
||||
@ -1326,6 +1328,23 @@ void ZStoreBarrierStubC2Aarch64::emit_code(MacroAssembler& masm) {
|
||||
register_stub(this);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ masm->
|
||||
|
||||
void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the oop is bad, in which case we need to take the slow path.
|
||||
__ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadBeforeMov);
|
||||
__ movzw(tmp, barrier_Relocation::unpatched);
|
||||
__ tst(obj, tmp);
|
||||
__ br(Assembler::NE, slow_path);
|
||||
|
||||
// Oop is okay, so we uncolor it.
|
||||
__ lsr(obj, obj, ZPointerLoadShift);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER2
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -191,6 +191,7 @@ public:
|
||||
ZLoadBarrierStubC2* stub) const;
|
||||
void generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
ZStoreBarrierStubC2* stub) const;
|
||||
void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, 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.
|
||||
*
|
||||
@ -39,7 +39,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls
|
||||
define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI);
|
||||
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 64);
|
||||
define_pd_global(intx, CodeEntryAlignment, 64);
|
||||
define_pd_global(uint, CodeEntryAlignment, 64);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
|
||||
#define DEFAULT_STACK_YELLOW_PAGES (2)
|
||||
@ -95,7 +95,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
"Use simplest and shortest implementation for array equals") \
|
||||
product(bool, UseSIMDForBigIntegerShiftIntrinsics, true, \
|
||||
"Use SIMD instructions for left/right shift of BigInteger") \
|
||||
product(bool, UseSIMDForSHA3Intrinsic, true, \
|
||||
product(bool, UseSIMDForSHA3Intrinsic, false, \
|
||||
"Use SIMD SHA3 instructions for SHA3 intrinsic") \
|
||||
product(bool, AvoidUnalignedAccesses, false, \
|
||||
"Avoid generating unaligned memory accesses") \
|
||||
@ -115,18 +115,26 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
"Value -1 means off.") \
|
||||
range(-1, 4096) \
|
||||
product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \
|
||||
"The instruction to use to implement " \
|
||||
"java.lang.Thread.onSpinWait()." \
|
||||
"Valid values are: none, nop, isb, yield, sb.") \
|
||||
"The instruction to use for java.lang.Thread.onSpinWait(). " \
|
||||
"Valid values are: none, nop, isb, yield, sb, wfet.") \
|
||||
constraint(OnSpinWaitInstNameConstraintFunc, AtParse) \
|
||||
product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \
|
||||
"The number of OnSpinWaitInst instructions to generate." \
|
||||
"It cannot be used with OnSpinWaitInst=none.") \
|
||||
"The number of OnSpinWaitInst instructions to generate. " \
|
||||
"It cannot be used with OnSpinWaitInst=none. " \
|
||||
"For OnSpinWaitInst=wfet it must be 1.") \
|
||||
range(1, 99) \
|
||||
product(uint, OnSpinWaitDelay, 40, DIAGNOSTIC, \
|
||||
"The minimum delay (in nanoseconds) of the OnSpinWait loop. " \
|
||||
"It can only be used with -XX:OnSpinWaitInst=wfet.") \
|
||||
range(1, 1000) \
|
||||
product(ccstr, UseBranchProtection, "none", \
|
||||
"Branch Protection to use: none, standard, pac-ret") \
|
||||
product(bool, AlwaysMergeDMB, true, DIAGNOSTIC, \
|
||||
"Always merge DMB instructions in code emission") \
|
||||
product(bool, NeoverseN1ICacheErratumMitigation, false, DIAGNOSTIC, \
|
||||
"Enable workaround for Neoverse N1 erratum 1542419") \
|
||||
product(bool, UseSingleICacheInvalidation, false, DIAGNOSTIC, \
|
||||
"Defer multiple ICache invalidation to single invalidation") \
|
||||
|
||||
// end of ARCH_FLAGS
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2026, 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.
|
||||
*
|
||||
@ -240,15 +240,14 @@ void InterpreterMacroAssembler::load_resolved_klass_at_offset(
|
||||
// Rsub_klass: subklass
|
||||
//
|
||||
// Kills:
|
||||
// r2, r5
|
||||
// r2
|
||||
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
|
||||
Label& ok_is_subtype) {
|
||||
assert(Rsub_klass != r0, "r0 holds superklass");
|
||||
assert(Rsub_klass != r2, "r2 holds 2ndary super array length");
|
||||
assert(Rsub_klass != r5, "r5 holds 2ndary super array scan ptr");
|
||||
|
||||
// Profile the not-null value's klass.
|
||||
profile_typecheck(r2, Rsub_klass, r5); // blows r2, reloads r5
|
||||
profile_typecheck(r2, Rsub_klass); // blows r2
|
||||
|
||||
// Do the check.
|
||||
check_klass_subtype(Rsub_klass, r0, r2, ok_is_subtype); // blows r2
|
||||
@ -990,27 +989,15 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) {
|
||||
|
||||
|
||||
void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
|
||||
Register mdp,
|
||||
Register reg2,
|
||||
bool receiver_can_be_null) {
|
||||
Register mdp) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
|
||||
// If no method data exists, go to profile_continue.
|
||||
test_method_data_pointer(mdp, profile_continue);
|
||||
|
||||
Label skip_receiver_profile;
|
||||
if (receiver_can_be_null) {
|
||||
Label not_null;
|
||||
// We are making a call. Increment the count for null receiver.
|
||||
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
|
||||
b(skip_receiver_profile);
|
||||
bind(not_null);
|
||||
}
|
||||
|
||||
// Record the receiver type.
|
||||
record_klass_in_profile(receiver, mdp, reg2);
|
||||
bind(skip_receiver_profile);
|
||||
profile_receiver_type(receiver, mdp, 0);
|
||||
|
||||
// The method data pointer needs to be updated to reflect the new target.
|
||||
update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
|
||||
@ -1018,131 +1005,6 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
|
||||
}
|
||||
}
|
||||
|
||||
// This routine creates a state machine for updating the multi-row
|
||||
// type profile at a virtual call site (or other type-sensitive bytecode).
|
||||
// The machine visits each row (of receiver/count) until the receiver type
|
||||
// is found, or until it runs out of rows. At the same time, it remembers
|
||||
// the location of the first empty row. (An empty row records null for its
|
||||
// receiver, and can be allocated for a newly-observed receiver type.)
|
||||
// Because there are two degrees of freedom in the state, a simple linear
|
||||
// search will not work; it must be a decision tree. Hence this helper
|
||||
// function is recursive, to generate the required tree structured code.
|
||||
// It's the interpreter, so we are trading off code space for speed.
|
||||
// See below for example code.
|
||||
void InterpreterMacroAssembler::record_klass_in_profile_helper(
|
||||
Register receiver, Register mdp,
|
||||
Register reg2, int start_row,
|
||||
Label& done) {
|
||||
if (TypeProfileWidth == 0) {
|
||||
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
|
||||
} else {
|
||||
record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
|
||||
&VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
|
||||
Register reg2, int start_row, Label& done, int total_rows,
|
||||
OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn) {
|
||||
int last_row = total_rows - 1;
|
||||
assert(start_row <= last_row, "must be work left to do");
|
||||
// Test this row for both the item and for null.
|
||||
// Take any of three different outcomes:
|
||||
// 1. found item => increment count and goto done
|
||||
// 2. found null => keep looking for case 1, maybe allocate this cell
|
||||
// 3. found something else => keep looking for cases 1 and 2
|
||||
// Case 3 is handled by a recursive call.
|
||||
for (int row = start_row; row <= last_row; row++) {
|
||||
Label next_test;
|
||||
bool test_for_null_also = (row == start_row);
|
||||
|
||||
// See if the item is item[n].
|
||||
int item_offset = in_bytes(item_offset_fn(row));
|
||||
test_mdp_data_at(mdp, item_offset, item,
|
||||
(test_for_null_also ? reg2 : noreg),
|
||||
next_test);
|
||||
// (Reg2 now contains the item from the CallData.)
|
||||
|
||||
// The item is item[n]. Increment count[n].
|
||||
int count_offset = in_bytes(item_count_offset_fn(row));
|
||||
increment_mdp_data_at(mdp, count_offset);
|
||||
b(done);
|
||||
bind(next_test);
|
||||
|
||||
if (test_for_null_also) {
|
||||
Label found_null;
|
||||
// Failed the equality check on item[n]... Test for null.
|
||||
if (start_row == last_row) {
|
||||
// The only thing left to do is handle the null case.
|
||||
cbz(reg2, found_null);
|
||||
// Item did not match any saved item 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()));
|
||||
b(done);
|
||||
bind(found_null);
|
||||
break;
|
||||
}
|
||||
// Since null is rare, make it be the branch-taken case.
|
||||
cbz(reg2, found_null);
|
||||
|
||||
// Put all the "Case 3" tests here.
|
||||
record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
|
||||
item_offset_fn, item_count_offset_fn);
|
||||
|
||||
// Found a null. Keep searching for a matching item,
|
||||
// but remember that this is an empty (unused) slot.
|
||||
bind(found_null);
|
||||
}
|
||||
}
|
||||
|
||||
// In the fall-through case, we found no matching item, but we
|
||||
// observed the item[start_row] is null.
|
||||
|
||||
// Fill in the item field and increment the count.
|
||||
int item_offset = in_bytes(item_offset_fn(start_row));
|
||||
set_mdp_data_at(mdp, item_offset, item);
|
||||
int count_offset = in_bytes(item_count_offset_fn(start_row));
|
||||
mov(reg2, DataLayout::counter_increment);
|
||||
set_mdp_data_at(mdp, count_offset, reg2);
|
||||
if (start_row > 0) {
|
||||
b(done);
|
||||
}
|
||||
}
|
||||
|
||||
// Example state machine code for three profile rows:
|
||||
// // main copy of decision tree, rooted at row[1]
|
||||
// if (row[0].rec == rec) { row[0].incr(); goto done; }
|
||||
// if (row[0].rec != nullptr) {
|
||||
// // inner copy of decision tree, rooted at row[1]
|
||||
// if (row[1].rec == rec) { row[1].incr(); goto done; }
|
||||
// if (row[1].rec != nullptr) {
|
||||
// // degenerate decision tree, rooted at row[2]
|
||||
// if (row[2].rec == rec) { row[2].incr(); goto done; }
|
||||
// if (row[2].rec != nullptr) { count.incr(); goto done; } // overflow
|
||||
// row[2].init(rec); goto done;
|
||||
// } else {
|
||||
// // remember row[1] is empty
|
||||
// if (row[2].rec == rec) { row[2].incr(); goto done; }
|
||||
// row[1].init(rec); goto done;
|
||||
// }
|
||||
// } else {
|
||||
// // remember row[0] is empty
|
||||
// if (row[1].rec == rec) { row[1].incr(); goto done; }
|
||||
// if (row[2].rec == rec) { row[2].incr(); goto done; }
|
||||
// row[0].init(rec); goto done;
|
||||
// }
|
||||
// done:
|
||||
|
||||
void InterpreterMacroAssembler::record_klass_in_profile(Register receiver,
|
||||
Register mdp, Register reg2) {
|
||||
assert(ProfileInterpreter, "must be profiling");
|
||||
Label done;
|
||||
|
||||
record_klass_in_profile_helper(receiver, mdp, reg2, 0, done);
|
||||
|
||||
bind (done);
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::profile_ret(Register return_bci,
|
||||
Register mdp) {
|
||||
if (ProfileInterpreter) {
|
||||
@ -1200,7 +1062,7 @@ void InterpreterMacroAssembler::profile_null_seen(Register mdp) {
|
||||
}
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) {
|
||||
void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
|
||||
@ -1213,7 +1075,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);
|
||||
profile_receiver_type(klass, mdp, 0);
|
||||
}
|
||||
update_mdp_by_constant(mdp, mdp_delta);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -273,15 +273,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
Register test_value_out,
|
||||
Label& not_equal_continue);
|
||||
|
||||
void record_klass_in_profile(Register receiver, Register mdp,
|
||||
Register reg2);
|
||||
void record_klass_in_profile_helper(Register receiver, Register mdp,
|
||||
Register reg2, int start_row,
|
||||
Label& done);
|
||||
void record_item_in_profile_helper(Register item, Register mdp,
|
||||
Register reg2, int start_row, Label& done, int total_rows,
|
||||
OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn);
|
||||
|
||||
void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
|
||||
void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
|
||||
void update_mdp_by_constant(Register mdp_in, int constant);
|
||||
@ -294,12 +285,10 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
void profile_not_taken_branch(Register mdp);
|
||||
void profile_call(Register mdp);
|
||||
void profile_final_call(Register mdp);
|
||||
void profile_virtual_call(Register receiver, Register mdp,
|
||||
Register scratch2,
|
||||
bool receiver_can_be_null = false);
|
||||
void profile_virtual_call(Register receiver, Register mdp);
|
||||
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(Register mdp, Register klass);
|
||||
void profile_typecheck_failed(Register mdp);
|
||||
void profile_switch_default(Register mdp);
|
||||
void profile_switch_case(Register index_in_scratch, Register mdp,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -55,6 +55,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/integerCast.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_LIRAssembler.hpp"
|
||||
@ -406,7 +407,6 @@ public:
|
||||
offset <<= shift;
|
||||
uint64_t target_page = ((uint64_t)insn_addr) + offset;
|
||||
target_page &= ((uint64_t)-1) << shift;
|
||||
uint32_t insn2 = insn_at(insn_addr, 1);
|
||||
target = address(target_page);
|
||||
precond(inner != nullptr);
|
||||
inner(insn_addr, target);
|
||||
@ -473,6 +473,7 @@ address MacroAssembler::target_addr_for_insn(address insn_addr) {
|
||||
// Patch any kind of instruction; there may be several instructions.
|
||||
// Return the total length (in bytes) of the instructions.
|
||||
int MacroAssembler::pd_patch_instruction_size(address insn_addr, address target) {
|
||||
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
|
||||
return RelocActions<Patcher>::run(insn_addr, target);
|
||||
}
|
||||
|
||||
@ -481,6 +482,8 @@ int MacroAssembler::patch_oop(address insn_addr, address o) {
|
||||
unsigned insn = *(unsigned*)insn_addr;
|
||||
assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
|
||||
|
||||
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
|
||||
|
||||
// OOPs are either narrow (32 bits) or wide (48 bits). We encode
|
||||
// narrow OOPs by setting the upper 16 bits in the first
|
||||
// instruction.
|
||||
@ -510,18 +513,13 @@ int MacroAssembler::patch_narrow_klass(address insn_addr, narrowKlass n) {
|
||||
assert(Instruction_aarch64::extract(insn->encoding(), 31, 21) == 0b11010010101 &&
|
||||
nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
|
||||
|
||||
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
|
||||
|
||||
Instruction_aarch64::patch(insn_addr, 20, 5, n >> 16);
|
||||
Instruction_aarch64::patch(insn_addr+4, 20, 5, n & 0xffff);
|
||||
return 2 * NativeInstruction::instruction_size;
|
||||
}
|
||||
|
||||
address MacroAssembler::target_addr_for_insn_or_null(address insn_addr) {
|
||||
if (NativeInstruction::is_ldrw_to_zr(insn_addr)) {
|
||||
return nullptr;
|
||||
}
|
||||
return MacroAssembler::target_addr_for_insn(insn_addr);
|
||||
}
|
||||
|
||||
void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp) {
|
||||
ldr(tmp, Address(rthread, JavaThread::polling_word_offset()));
|
||||
if (at_return) {
|
||||
@ -765,7 +763,7 @@ void MacroAssembler::call_VM_base(Register oop_result,
|
||||
assert(java_thread == rthread, "unexpected register");
|
||||
#ifdef ASSERT
|
||||
// TraceBytecodes does not use r12 but saves it over the call, so don't verify
|
||||
// if ((UseCompressedOops || UseCompressedClassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");
|
||||
// if (!TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");
|
||||
#endif // ASSERT
|
||||
|
||||
assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result");
|
||||
@ -955,7 +953,10 @@ void MacroAssembler::emit_static_call_stub() {
|
||||
}
|
||||
|
||||
int MacroAssembler::static_call_stub_size() {
|
||||
if (!codestub_branch_needs_far_jump()) {
|
||||
// During AOT production run AOT and JIT compiled code
|
||||
// are used at the same time. We need this size
|
||||
// to be the same for both types of code.
|
||||
if (!codestub_branch_needs_far_jump() && !AOTCodeCache::is_on_for_use()) {
|
||||
// isb; movk; movz; movz; b
|
||||
return 5 * NativeInstruction::instruction_size;
|
||||
}
|
||||
@ -1005,14 +1006,10 @@ int MacroAssembler::ic_check(int end_alignment) {
|
||||
load_narrow_klass_compact(tmp1, receiver);
|
||||
ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
|
||||
cmpw(tmp1, tmp2);
|
||||
} else if (UseCompressedClassPointers) {
|
||||
} else {
|
||||
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;
|
||||
@ -1955,9 +1952,7 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass,
|
||||
|
||||
const Register
|
||||
r_array_base = temp1,
|
||||
r_array_length = temp2,
|
||||
r_array_index = noreg, // unused
|
||||
r_bitmap = noreg; // unused
|
||||
r_array_length = temp2;
|
||||
|
||||
BLOCK_COMMENT("verify_secondary_supers_table {");
|
||||
|
||||
@ -2118,6 +2113,161 @@ Address MacroAssembler::argument_address(RegisterOrConstant arg_slot,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the receiver type profile update given the "recv" klass.
|
||||
//
|
||||
// Normally updates the ReceiverData (RD) that starts at "mdp" + "mdp_offset".
|
||||
// If there are no matching or claimable receiver entries in RD, updates
|
||||
// the polymorphic counter.
|
||||
//
|
||||
// This code expected to run by either the interpreter or JIT-ed code, without
|
||||
// extra synchronization. For safety, receiver cells are claimed atomically, which
|
||||
// avoids grossly misrepresenting the profiles under concurrent updates. For speed,
|
||||
// counter updates are not atomic.
|
||||
//
|
||||
void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_offset) {
|
||||
assert_different_registers(recv, mdp, rscratch1, rscratch2);
|
||||
|
||||
int base_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(0));
|
||||
int end_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(ReceiverTypeData::row_limit()));
|
||||
int poly_count_offset = in_bytes(CounterData::count_offset());
|
||||
int receiver_step = in_bytes(ReceiverTypeData::receiver_offset(1)) - base_receiver_offset;
|
||||
int receiver_to_count_step = in_bytes(ReceiverTypeData::receiver_count_offset(0)) - base_receiver_offset;
|
||||
|
||||
// Adjust for MDP offsets.
|
||||
base_receiver_offset += mdp_offset;
|
||||
end_receiver_offset += mdp_offset;
|
||||
poly_count_offset += mdp_offset;
|
||||
|
||||
#ifdef ASSERT
|
||||
// We are about to walk the MDO slots without asking for offsets.
|
||||
// Check that our math hits all the right spots.
|
||||
for (uint c = 0; c < ReceiverTypeData::row_limit(); c++) {
|
||||
int real_recv_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_offset(c));
|
||||
int real_count_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_count_offset(c));
|
||||
int offset = base_receiver_offset + receiver_step*c;
|
||||
int count_offset = offset + receiver_to_count_step;
|
||||
assert(offset == real_recv_offset, "receiver slot math");
|
||||
assert(count_offset == real_count_offset, "receiver count math");
|
||||
}
|
||||
int real_poly_count_offset = mdp_offset + in_bytes(CounterData::count_offset());
|
||||
assert(poly_count_offset == real_poly_count_offset, "poly counter math");
|
||||
#endif
|
||||
|
||||
// Corner case: no profile table. Increment poly counter and exit.
|
||||
if (ReceiverTypeData::row_limit() == 0) {
|
||||
increment(Address(mdp, poly_count_offset), DataLayout::counter_increment);
|
||||
return;
|
||||
}
|
||||
|
||||
Register offset = rscratch2;
|
||||
|
||||
Label L_loop_search_receiver, L_loop_search_empty;
|
||||
Label L_restart, L_found_recv, L_found_empty, L_polymorphic, L_count_update;
|
||||
|
||||
// The code here recognizes three major cases:
|
||||
// A. Fastest: receiver found in the table
|
||||
// B. Fast: no receiver in the table, and the table is full
|
||||
// C. Slow: no receiver in the table, free slots in the table
|
||||
//
|
||||
// The case A performance is most important, as perfectly-behaved code would end up
|
||||
// there, especially with larger TypeProfileWidth. The case B performance is
|
||||
// important as well, this is where bulk of code would land for normally megamorphic
|
||||
// cases. The case C performance is not essential, its job is to deal with installation
|
||||
// races, we optimize for code density instead. Case C needs to make sure that receiver
|
||||
// rows are only claimed once. This makes sure we never overwrite a row for another
|
||||
// receiver and never duplicate the receivers in the list, making profile type-accurate.
|
||||
//
|
||||
// It is very tempting to handle these cases in a single loop, and claim the first slot
|
||||
// without checking the rest of the table. But, profiling code should tolerate free slots
|
||||
// in the table, as class unloading can clear them. After such cleanup, the receiver
|
||||
// we need might be _after_ the free slot. Therefore, we need to let at least full scan
|
||||
// to complete, before trying to install new slots. Splitting the code in several tight
|
||||
// loops also helpfully optimizes for cases A and B.
|
||||
//
|
||||
// This code is effectively:
|
||||
//
|
||||
// restart:
|
||||
// // Fastest: receiver is already installed
|
||||
// for (i = 0; i < receiver_count(); i++) {
|
||||
// if (receiver(i) == recv) goto found_recv(i);
|
||||
// }
|
||||
//
|
||||
// // Fast: no receiver, but profile is full
|
||||
// for (i = 0; i < receiver_count(); i++) {
|
||||
// if (receiver(i) == null) goto found_null(i);
|
||||
// }
|
||||
// goto polymorphic
|
||||
//
|
||||
// // Slow: try to install receiver
|
||||
// found_null(i):
|
||||
// CAS(&receiver(i), null, recv);
|
||||
// goto restart
|
||||
//
|
||||
// polymorphic:
|
||||
// count++;
|
||||
// return
|
||||
//
|
||||
// found_recv(i):
|
||||
// *receiver_count(i)++
|
||||
//
|
||||
|
||||
bind(L_restart);
|
||||
|
||||
// Fastest: receiver is already installed
|
||||
mov(offset, base_receiver_offset);
|
||||
bind(L_loop_search_receiver);
|
||||
ldr(rscratch1, Address(mdp, offset));
|
||||
cmp(rscratch1, recv);
|
||||
br(Assembler::EQ, L_found_recv);
|
||||
add(offset, offset, receiver_step);
|
||||
sub(rscratch1, offset, end_receiver_offset);
|
||||
cbnz(rscratch1, L_loop_search_receiver);
|
||||
|
||||
// Fast: no receiver, but profile is full
|
||||
mov(offset, base_receiver_offset);
|
||||
bind(L_loop_search_empty);
|
||||
ldr(rscratch1, Address(mdp, offset));
|
||||
cbz(rscratch1, L_found_empty);
|
||||
add(offset, offset, receiver_step);
|
||||
sub(rscratch1, offset, end_receiver_offset);
|
||||
cbnz(rscratch1, L_loop_search_empty);
|
||||
b(L_polymorphic);
|
||||
|
||||
// Slow: try to install receiver
|
||||
bind(L_found_empty);
|
||||
|
||||
// Atomically swing receiver slot: null -> recv.
|
||||
//
|
||||
// The update uses CAS, which clobbers rscratch1. Therefore, rscratch2
|
||||
// is used to hold the destination address. This is safe because the
|
||||
// offset is no longer needed after the address is computed.
|
||||
|
||||
lea(rscratch2, Address(mdp, offset));
|
||||
cmpxchg(/*addr*/ rscratch2, /*expected*/ zr, /*new*/ recv, Assembler::xword,
|
||||
/*acquire*/ false, /*release*/ false, /*weak*/ true, noreg);
|
||||
|
||||
// CAS success means the slot now has the receiver we want. CAS failure means
|
||||
// something had claimed the slot concurrently: it can be the same receiver we want,
|
||||
// or something else. Since this is a slow path, we can optimize for code density,
|
||||
// and just restart the search from the beginning.
|
||||
b(L_restart);
|
||||
|
||||
// Counter updates:
|
||||
|
||||
// Increment polymorphic counter instead of receiver slot.
|
||||
bind(L_polymorphic);
|
||||
mov(offset, poly_count_offset);
|
||||
b(L_count_update);
|
||||
|
||||
// Found a receiver, convert its slot offset to corresponding count offset.
|
||||
bind(L_found_recv);
|
||||
add(offset, offset, receiver_to_count_step);
|
||||
|
||||
bind(L_count_update);
|
||||
increment(Address(mdp, offset), DataLayout::counter_increment);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::call_VM_leaf_base(address entry_point,
|
||||
int number_of_arguments,
|
||||
Label *retaddr) {
|
||||
@ -2767,7 +2917,11 @@ void MacroAssembler::increment(Address dst, int value)
|
||||
|
||||
// Push lots of registers in the bit set supplied. Don't push sp.
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
@ -2797,7 +2951,11 @@ int MacroAssembler::push(unsigned int bitset, Register stack) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int MacroAssembler::pop(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
@ -2829,7 +2987,11 @@ int MacroAssembler::pop(unsigned int bitset, Register stack) {
|
||||
|
||||
// Push lots of registers in the bit set supplied. Don't push sp.
|
||||
// Return the number of dwords pushed
|
||||
int MacroAssembler::push_fp(unsigned int bitset, Register stack, FpPushPopMode mode) {
|
||||
int MacroAssembler::push_fp(FloatRegSet regset, Register stack, FpPushPopMode mode) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
@ -2942,7 +3104,11 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack, FpPushPopMode m
|
||||
}
|
||||
|
||||
// Return the number of dwords popped
|
||||
int MacroAssembler::pop_fp(unsigned int bitset, Register stack, FpPushPopMode mode) {
|
||||
int MacroAssembler::pop_fp(FloatRegSet regset, Register stack, FpPushPopMode mode) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
@ -3052,7 +3218,11 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack, FpPushPopMode mo
|
||||
}
|
||||
|
||||
// Return the number of dwords pushed
|
||||
int MacroAssembler::push_p(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push_p(PRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
bool use_sve = false;
|
||||
int sve_predicate_size_in_slots = 0;
|
||||
|
||||
@ -3089,7 +3259,11 @@ int MacroAssembler::push_p(unsigned int bitset, Register stack) {
|
||||
}
|
||||
|
||||
// Return the number of dwords popped
|
||||
int MacroAssembler::pop_p(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop_p(PRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
bool use_sve = false;
|
||||
int sve_predicate_size_in_slots = 0;
|
||||
|
||||
@ -3128,7 +3302,6 @@ int MacroAssembler::pop_p(unsigned int bitset, Register stack) {
|
||||
#ifdef ASSERT
|
||||
void MacroAssembler::verify_heapbase(const char* msg) {
|
||||
#if 0
|
||||
assert (UseCompressedOops || UseCompressedClassPointers, "should be compressed");
|
||||
assert (Universe::heap() != nullptr, "java heap should be initialized");
|
||||
if (!UseCompressedOops || Universe::ptr_base() == nullptr) {
|
||||
// rheapbase is allocated as general register
|
||||
@ -3306,7 +3479,7 @@ void MacroAssembler::subw(Register Rd, Register Rn, RegisterOrConstant decrement
|
||||
void MacroAssembler::reinit_heapbase()
|
||||
{
|
||||
if (UseCompressedOops) {
|
||||
if (Universe::is_fully_initialized()) {
|
||||
if (Universe::is_fully_initialized() && !AOTCodeCache::is_on_for_dump()) {
|
||||
mov(rheapbase, CompressedOops::base());
|
||||
} else {
|
||||
lea(rheapbase, ExternalAddress(CompressedOops::base_addr()));
|
||||
@ -3451,9 +3624,8 @@ extern "C" void findpc(intptr_t x);
|
||||
void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
|
||||
{
|
||||
// In order to get locks to work, we need to fake a in_VM state
|
||||
if (ShowMessageBoxOnError ) {
|
||||
if (ShowMessageBoxOnError) {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
JavaThreadState saved_state = thread->thread_state();
|
||||
thread->set_thread_state(_thread_in_vm);
|
||||
#ifndef PRODUCT
|
||||
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
|
||||
@ -4918,13 +5090,10 @@ void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) {
|
||||
void MacroAssembler::load_klass(Register dst, Register src) {
|
||||
if (UseCompactObjectHeaders) {
|
||||
load_narrow_klass_compact(dst, src);
|
||||
decode_klass_not_null(dst);
|
||||
} else if (UseCompressedClassPointers) {
|
||||
ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
decode_klass_not_null(dst);
|
||||
} else {
|
||||
ldr(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
decode_klass_not_null(dst);
|
||||
}
|
||||
|
||||
void MacroAssembler::restore_cpu_control_state_after_jni(Register tmp1, Register tmp2) {
|
||||
@ -4976,25 +5145,22 @@ void MacroAssembler::load_mirror(Register dst, Register method, Register tmp1, R
|
||||
|
||||
void MacroAssembler::cmp_klass(Register obj, Register klass, Register tmp) {
|
||||
assert_different_registers(obj, klass, tmp);
|
||||
if (UseCompressedClassPointers) {
|
||||
if (UseCompactObjectHeaders) {
|
||||
load_narrow_klass_compact(tmp, obj);
|
||||
} else {
|
||||
ldrw(tmp, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
if (CompressedKlassPointers::base() == nullptr) {
|
||||
cmp(klass, tmp, LSL, CompressedKlassPointers::shift());
|
||||
return;
|
||||
} else if (((uint64_t)CompressedKlassPointers::base() & 0xffffffff) == 0
|
||||
&& CompressedKlassPointers::shift() == 0) {
|
||||
// Only the bottom 32 bits matter
|
||||
cmpw(klass, tmp);
|
||||
return;
|
||||
}
|
||||
decode_klass_not_null(tmp);
|
||||
if (UseCompactObjectHeaders) {
|
||||
load_narrow_klass_compact(tmp, obj);
|
||||
} else {
|
||||
ldr(tmp, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
ldrw(tmp, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
if (CompressedKlassPointers::base() == nullptr) {
|
||||
cmp(klass, tmp, LSL, CompressedKlassPointers::shift());
|
||||
return;
|
||||
} else if (!AOTCodeCache::is_on_for_dump() &&
|
||||
((uint64_t)CompressedKlassPointers::base() & 0xffffffff) == 0
|
||||
&& CompressedKlassPointers::shift() == 0) {
|
||||
// Only the bottom 32 bits matter
|
||||
cmpw(klass, tmp);
|
||||
return;
|
||||
}
|
||||
decode_klass_not_null(tmp);
|
||||
cmp(klass, tmp);
|
||||
}
|
||||
|
||||
@ -5002,36 +5168,25 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi
|
||||
if (UseCompactObjectHeaders) {
|
||||
load_narrow_klass_compact(tmp1, obj1);
|
||||
load_narrow_klass_compact(tmp2, obj2);
|
||||
cmpw(tmp1, tmp2);
|
||||
} else if (UseCompressedClassPointers) {
|
||||
} else {
|
||||
ldrw(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes()));
|
||||
ldrw(tmp2, Address(obj2, oopDesc::klass_offset_in_bytes()));
|
||||
cmpw(tmp1, tmp2);
|
||||
} else {
|
||||
ldr(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes()));
|
||||
ldr(tmp2, Address(obj2, oopDesc::klass_offset_in_bytes()));
|
||||
cmp(tmp1, tmp2);
|
||||
}
|
||||
cmpw(tmp1, tmp2);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_klass(Register dst, Register src) {
|
||||
// FIXME: Should this be a store release? concurrent gcs assumes
|
||||
// klass length is valid if klass field is not null.
|
||||
assert(!UseCompactObjectHeaders, "not with compact headers");
|
||||
if (UseCompressedClassPointers) {
|
||||
encode_klass_not_null(src);
|
||||
strw(src, Address(dst, oopDesc::klass_offset_in_bytes()));
|
||||
} else {
|
||||
str(src, Address(dst, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
encode_klass_not_null(src);
|
||||
strw(src, Address(dst, oopDesc::klass_offset_in_bytes()));
|
||||
}
|
||||
|
||||
void MacroAssembler::store_klass_gap(Register dst, Register src) {
|
||||
assert(!UseCompactObjectHeaders, "not with compact headers");
|
||||
if (UseCompressedClassPointers) {
|
||||
// Store to klass gap in destination
|
||||
strw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes()));
|
||||
}
|
||||
// Store to klass gap in destination
|
||||
strw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes()));
|
||||
}
|
||||
|
||||
// Algorithm must match CompressedOops::encode.
|
||||
@ -5177,8 +5332,6 @@ MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() {
|
||||
}
|
||||
|
||||
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) {
|
||||
assert(UseCompressedClassPointers, "not using compressed class pointers");
|
||||
|
||||
// KlassDecodeMode shouldn't be set already.
|
||||
assert(_klass_decode_mode == KlassDecodeNone, "set once");
|
||||
|
||||
@ -5244,7 +5397,7 @@ void MacroAssembler::encode_klass_not_null_for_aot(Register dst, Register src) {
|
||||
}
|
||||
|
||||
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
if (CompressedKlassPointers::base() != nullptr && AOTCodeCache::is_on_for_dump()) {
|
||||
encode_klass_not_null_for_aot(dst, src);
|
||||
return;
|
||||
}
|
||||
@ -5308,8 +5461,6 @@ void MacroAssembler::decode_klass_not_null_for_aot(Register dst, Register src) {
|
||||
}
|
||||
|
||||
void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
|
||||
assert (UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
decode_klass_not_null_for_aot(dst, src);
|
||||
return;
|
||||
@ -5376,7 +5527,6 @@ void MacroAssembler::set_narrow_oop(Register dst, jobject obj) {
|
||||
}
|
||||
|
||||
void MacroAssembler::set_narrow_klass(Register dst, Klass* k) {
|
||||
assert (UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder");
|
||||
int index = oop_recorder()->find_index(k);
|
||||
|
||||
@ -5578,7 +5728,6 @@ address MacroAssembler::read_polling_page(Register r, relocInfo::relocType rtype
|
||||
}
|
||||
|
||||
void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset) {
|
||||
relocInfo::relocType rtype = dest.rspec().reloc()->type();
|
||||
uint64_t low_page = (uint64_t)CodeCache::low_bound() >> 12;
|
||||
uint64_t high_page = (uint64_t)(CodeCache::high_bound()-1) >> 12;
|
||||
uint64_t dest_page = (uint64_t)dest.target() >> 12;
|
||||
@ -5606,12 +5755,33 @@ void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_off
|
||||
}
|
||||
|
||||
void MacroAssembler::load_byte_map_base(Register reg) {
|
||||
CardTable::CardValue* byte_map_base =
|
||||
((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address byte_map_base_adr = AOTRuntimeConstants::card_table_base_address();
|
||||
lea(reg, ExternalAddress(byte_map_base_adr));
|
||||
ldr(reg, Address(reg));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CardTableBarrierSet* ctbs = CardTableBarrierSet::barrier_set();
|
||||
|
||||
// Strictly speaking the byte_map_base isn't an address at all, and it might
|
||||
// Strictly speaking the card table base isn't an address at all, and it might
|
||||
// even be negative. It is thus materialised as a constant.
|
||||
mov(reg, (uint64_t)byte_map_base);
|
||||
mov(reg, (uint64_t)ctbs->card_table_base_const());
|
||||
}
|
||||
|
||||
void MacroAssembler::load_aotrc_address(Register reg, address a) {
|
||||
#if INCLUDE_CDS
|
||||
assert(AOTRuntimeConstants::contains(a), "address out of range for data area");
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
// all aotrc field addresses should be registered in the AOTCodeCache address table
|
||||
lea(reg, ExternalAddress(a));
|
||||
} else {
|
||||
mov(reg, (uint64_t)a);
|
||||
}
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::build_frame(int framesize) {
|
||||
@ -5955,7 +6125,6 @@ void MacroAssembler::string_equals(Register a1, Register a2,
|
||||
Label SAME, DONE, SHORT, NEXT_WORD;
|
||||
Register tmp1 = rscratch1;
|
||||
Register tmp2 = rscratch2;
|
||||
Register cnt2 = tmp2; // cnt2 only used in array length compare
|
||||
|
||||
assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
|
||||
|
||||
@ -6265,10 +6434,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value)
|
||||
|
||||
// Intrinsic for
|
||||
//
|
||||
// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray
|
||||
// return the number of characters copied.
|
||||
// - java/lang/StringUTF16.compress
|
||||
// return index of non-latin1 character if copy fails, otherwise 'len'.
|
||||
// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes char[] to byte[] in ISO-8859-1
|
||||
//
|
||||
// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1
|
||||
//
|
||||
// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes char[] to byte[] in ASCII
|
||||
//
|
||||
// This version always returns the number of characters copied, and does not
|
||||
// clobber the 'len' register. A successful copy will complete with the post-
|
||||
@ -6663,6 +6836,9 @@ void MacroAssembler::spin_wait() {
|
||||
assert(VM_Version::supports_sb(), "current CPU does not support SB instruction");
|
||||
sb();
|
||||
break;
|
||||
case SpinWait::WFET:
|
||||
spin_wait_wfet(VM_Version::spin_wait_desc().delay());
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
@ -6670,6 +6846,28 @@ void MacroAssembler::spin_wait() {
|
||||
block_comment("}");
|
||||
}
|
||||
|
||||
void MacroAssembler::spin_wait_wfet(int delay_ns) {
|
||||
// The sequence assumes CNTFRQ_EL0 is fixed to 1GHz. The assumption is valid
|
||||
// starting from Armv8.6, according to the "D12.1.2 The system counter" of the
|
||||
// Arm Architecture Reference Manual for A-profile architecture version M.a.a.
|
||||
// This is sufficient because FEAT_WFXT is introduced from Armv8.6.
|
||||
Register target = rscratch1;
|
||||
Register current = rscratch2;
|
||||
get_cntvctss_el0(current);
|
||||
add(target, current, delay_ns);
|
||||
|
||||
Label L_wait_loop;
|
||||
bind(L_wait_loop);
|
||||
|
||||
wfet(target);
|
||||
get_cntvctss_el0(current);
|
||||
|
||||
cmp(current, target);
|
||||
br(LT, L_wait_loop);
|
||||
|
||||
sb();
|
||||
}
|
||||
|
||||
// Stack frame creation/removal
|
||||
|
||||
void MacroAssembler::enter(bool strip_ret_addr) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -499,29 +499,20 @@ private:
|
||||
void mov_immediate64(Register dst, uint64_t imm64);
|
||||
void mov_immediate32(Register dst, uint32_t imm32);
|
||||
|
||||
int push(unsigned int bitset, Register stack);
|
||||
int pop(unsigned int bitset, Register stack);
|
||||
|
||||
int push_fp(unsigned int bitset, Register stack, FpPushPopMode mode);
|
||||
int pop_fp(unsigned int bitset, Register stack, FpPushPopMode mode);
|
||||
|
||||
int push_p(unsigned int bitset, Register stack);
|
||||
int pop_p(unsigned int bitset, Register stack);
|
||||
|
||||
void mov(Register dst, Address a);
|
||||
|
||||
public:
|
||||
|
||||
void push(RegSet regs, Register stack) { if (regs.bits()) push(regs.bits(), stack); }
|
||||
void pop(RegSet regs, Register stack) { if (regs.bits()) pop(regs.bits(), stack); }
|
||||
int push(RegSet regset, Register stack);
|
||||
int pop(RegSet regset, Register stack);
|
||||
|
||||
void push_fp(FloatRegSet regs, Register stack, FpPushPopMode mode = PushPopFull) { if (regs.bits()) push_fp(regs.bits(), stack, mode); }
|
||||
void pop_fp(FloatRegSet regs, Register stack, FpPushPopMode mode = PushPopFull) { if (regs.bits()) pop_fp(regs.bits(), stack, mode); }
|
||||
int push_fp(FloatRegSet regset, Register stack, FpPushPopMode mode = PushPopFull);
|
||||
int pop_fp(FloatRegSet regset, Register stack, FpPushPopMode mode = PushPopFull);
|
||||
|
||||
static RegSet call_clobbered_gp_registers();
|
||||
|
||||
void push_p(PRegSet regs, Register stack) { if (regs.bits()) push_p(regs.bits(), stack); }
|
||||
void pop_p(PRegSet regs, Register stack) { if (regs.bits()) pop_p(regs.bits(), stack); }
|
||||
int push_p(PRegSet regset, Register stack);
|
||||
int pop_p(PRegSet regset, Register stack);
|
||||
|
||||
// Push and pop everything that might be clobbered by a native
|
||||
// runtime call except rscratch1 and rscratch2. (They are always
|
||||
@ -660,6 +651,14 @@ public:
|
||||
msr(0b011, 0b0100, 0b0010, 0b000, reg);
|
||||
}
|
||||
|
||||
// CNTVCTSS_EL0: op1 == 011
|
||||
// CRn == 1110
|
||||
// CRm == 0000
|
||||
// op2 == 110
|
||||
inline void get_cntvctss_el0(Register reg) {
|
||||
mrs(0b011, 0b1110, 0b0000, 0b110, reg);
|
||||
}
|
||||
|
||||
// idiv variant which deals with MINLONG as dividend and -1 as divisor
|
||||
int corrected_idivl(Register result, Register ra, Register rb,
|
||||
bool want_remainder, Register tmp = rscratch1);
|
||||
@ -678,7 +677,6 @@ public:
|
||||
static bool uses_implicit_null_check(void* address);
|
||||
|
||||
static address target_addr_for_insn(address insn_addr);
|
||||
static address target_addr_for_insn_or_null(address insn_addr);
|
||||
|
||||
// Required platform-specific helpers for Label::patch_instructions.
|
||||
// They _shadow_ the declarations in AbstractAssembler, which are undefined.
|
||||
@ -892,10 +890,6 @@ public:
|
||||
// thread in the default location (rthread)
|
||||
void reset_last_Java_frame(bool clear_fp);
|
||||
|
||||
// Stores
|
||||
void store_check(Register obj); // store check for obj - register is destroyed afterwards
|
||||
void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
|
||||
|
||||
void resolve_jobject(Register value, Register tmp1, Register tmp2);
|
||||
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
|
||||
|
||||
@ -1122,6 +1116,8 @@ public:
|
||||
|
||||
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
|
||||
|
||||
void profile_receiver_type(Register recv, Register mdp, int mdp_offset);
|
||||
|
||||
void verify_sve_vector_length(Register tmp = rscratch1);
|
||||
void reinitialize_ptrue() {
|
||||
if (UseSVE > 0) {
|
||||
@ -1475,6 +1471,9 @@ public:
|
||||
// Load the base of the cardtable byte map into reg.
|
||||
void load_byte_map_base(Register reg);
|
||||
|
||||
// Load a constant address in the AOT Runtime Constants area
|
||||
void load_aotrc_address(Register reg, address a);
|
||||
|
||||
// Prolog generator routines to support switch between x86 code and
|
||||
// generated ARM code
|
||||
|
||||
@ -1720,6 +1719,7 @@ public:
|
||||
|
||||
// Code for java.lang.Thread::onSpinWait() intrinsic.
|
||||
void spin_wait();
|
||||
void spin_wait_wfet(int delay_ns);
|
||||
|
||||
void fast_lock(Register basic_lock, Register obj, Register t1, Register t2, Register t3, Label& slow);
|
||||
void fast_unlock(Register obj, Register t1, Register t2, Register t3, Label& slow);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user