mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-12 11:28:35 +00:00
Merge branch 'master' into 8044609-ssl
This commit is contained in:
commit
c21bca38af
12
.github/workflows/build-cross-compile.yml
vendored
12
.github/workflows/build-cross-compile.yml
vendored
@ -64,33 +64,33 @@ jobs:
|
||||
gnu-arch: aarch64
|
||||
debian-arch: arm64
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: arm
|
||||
gnu-arch: arm
|
||||
debian-arch: armhf
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
gnu-abi: eabihf
|
||||
- target-cpu: s390x
|
||||
gnu-arch: s390x
|
||||
debian-arch: s390x
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: ppc64le
|
||||
gnu-arch: powerpc64le
|
||||
debian-arch: ppc64el
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: riscv64
|
||||
gnu-arch: riscv64
|
||||
debian-arch: riscv64
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: sid
|
||||
tolerate-sysroot-errors: true
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,12 +52,39 @@
|
||||
# include the SCM state that was used to build it, which can be found in ${JDK_N_INSTALL}/release,
|
||||
# in property "SOURCE".
|
||||
|
||||
source_path="$(dirname ${0})"
|
||||
this_script_dir="$(cd -- "${source_path}" > /dev/null && pwd)"
|
||||
if test -z "${this_script_dir}"; then
|
||||
echo "Error: Could not determine location of this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
symbols_dir="$(dirname $this_script_dir)/src/jdk.compiler/share/data/symbols"
|
||||
if [ ! -d $symbols_dir ] ; then
|
||||
echo "Cannot locate symbols directory: $symbols_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
generator_dir="$(dirname $this_script_dir)/make/langtools/src/classes/build/tools/symbolgenerator"
|
||||
|
||||
if [ "$1x" = "x" ] ; then
|
||||
echo "Must provide the target JDK as a parameter:" >&2
|
||||
echo "$0 <target-jdk>" >&2
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
if [ ! -d $1 ] ; then
|
||||
echo "Target JDK argument is not a directory:" $1 >&2
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
if [ ! -x $1/bin/java ] ; then
|
||||
echo "Target JDK argument is not a valid JDK: $1" >&2
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
cd $symbols_dir
|
||||
|
||||
if [ ! -f symbols ] ; then
|
||||
echo "Must run inside the src/jdk.compiler/share/data/symbols directory" >&2
|
||||
exit 1
|
||||
@ -72,5 +99,5 @@ $1/bin/java --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
|
||||
--add-modules jdk.jdeps \
|
||||
../../../../../make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java \
|
||||
$generator_dir/CreateSymbols.java \
|
||||
build-description-incremental symbols include.list
|
||||
@ -1,6 +1,6 @@
|
||||
#! /bin/sh -f
|
||||
#
|
||||
# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -62,7 +62,7 @@ B=`basename "${script_directory}"`
|
||||
script_dir="`cd \"${D}\" 2>/dev/null && pwd || echo \"${D}\"`/${B}"
|
||||
|
||||
# set up a variable for the template directory
|
||||
template_dir=${script_dir}/../data/license-templates
|
||||
template_dir=${script_dir}/../make/data/license-templates
|
||||
|
||||
# Check existence of the template directory.
|
||||
if [ ! -d ${template_dir} ] ; then
|
||||
@ -1,191 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
src/bsd : jdk/src/bsd
|
||||
src/demo : jdk/src/demo
|
||||
src/java.activation : jaxws/src/java.activation
|
||||
src/java.base : jdk/src/java.base
|
||||
src/java.compiler : langtools/src/java.compiler
|
||||
src/java.corba : corba/src/java.corba
|
||||
src/java.datatransfer : jdk/src/java.datatransfer
|
||||
src/java.desktop : jdk/src/java.desktop
|
||||
src/java.instrument : jdk/src/java.instrument
|
||||
src/java.logging : jdk/src/java.logging
|
||||
src/java.management : jdk/src/java.management
|
||||
src/java.management.rmi : jdk/src/java.management.rmi
|
||||
src/java.naming : jdk/src/java.naming
|
||||
src/java.prefs : jdk/src/java.prefs
|
||||
src/java.rmi : jdk/src/java.rmi
|
||||
src/java.scripting : jdk/src/java.scripting
|
||||
src/java.se : jdk/src/java.se
|
||||
src/java.security.jgss : jdk/src/java.security.jgss
|
||||
src/java.security.sasl : jdk/src/java.security.sasl
|
||||
src/java.se.ee : jdk/src/java.se.ee
|
||||
src/java.smartcardio : jdk/src/java.smartcardio
|
||||
src/java.sql : jdk/src/java.sql
|
||||
src/java.sql.rowset : jdk/src/java.sql.rowset
|
||||
src/java.transaction : jdk/src/java.transaction
|
||||
src/java.xml : jaxp/src/java.xml
|
||||
src/java.xml.bind : jaxws/src/java.xml.bind
|
||||
src/java.xml.crypto : jdk/src/java.xml.crypto
|
||||
src/java.xml.ws : jaxws/src/java.xml.ws
|
||||
src/java.xml.ws.annotation : jaxws/src/java.xml.ws.annotation
|
||||
src/jdk.accessibility : jdk/src/jdk.accessibility
|
||||
src/jdk.aot : hotspot/src/jdk.aot
|
||||
src/jdk.attach : jdk/src/jdk.attach
|
||||
src/jdk.charsets : jdk/src/jdk.charsets
|
||||
src/jdk.compiler : jdk/src/jdk.compiler langtools/src/jdk.compiler
|
||||
src/jdk.crypto.cryptoki : jdk/src/jdk.crypto.cryptoki
|
||||
src/jdk.crypto.ec : jdk/src/jdk.crypto.ec
|
||||
src/jdk.crypto.mscapi : jdk/src/jdk.crypto.mscapi
|
||||
src/jdk.dynalink : nashorn/src/jdk.dynalink
|
||||
src/jdk.editpad : jdk/src/jdk.editpad
|
||||
src/jdk.hotspot.agent : hotspot/src/jdk.hotspot.agent
|
||||
src/jdk.httpserver : jdk/src/jdk.httpserver
|
||||
src/jdk.incubator.httpclient : jdk/src/jdk.incubator.httpclient
|
||||
src/jdk.internal.ed : jdk/src/jdk.internal.ed
|
||||
src/jdk.internal.jvmstat : jdk/src/jdk.internal.jvmstat
|
||||
src/jdk.internal.le : jdk/src/jdk.internal.le
|
||||
src/jdk.internal.opt : jdk/src/jdk.internal.opt
|
||||
src/jdk.internal.vm.ci : hotspot/src/jdk.internal.vm.ci
|
||||
src/jdk.internal.vm.compiler : hotspot/src/jdk.internal.vm.compiler
|
||||
src/jdk.jartool : jdk/src/jdk.jartool
|
||||
src/jdk.javadoc : langtools/src/jdk.javadoc
|
||||
src/jdk.jcmd : jdk/src/jdk.jcmd
|
||||
src/jdk.jconsole : jdk/src/jdk.jconsole
|
||||
src/jdk.jdeps : langtools/src/jdk.jdeps
|
||||
src/jdk.jdi : jdk/src/jdk.jdi
|
||||
src/jdk.jdwp.agent : jdk/src/jdk.jdwp.agent
|
||||
src/jdk.jlink : jdk/src/jdk.jlink
|
||||
src/jdk.jshell : langtools/src/jdk.jshell
|
||||
src/jdk.jstatd : jdk/src/jdk.jstatd
|
||||
src/jdk.localedata : jdk/src/jdk.localedata
|
||||
src/jdk.management : jdk/src/jdk.management
|
||||
src/jdk.management.agent : jdk/src/jdk.management.agent
|
||||
src/jdk.naming.dns : jdk/src/jdk.naming.dns
|
||||
src/jdk.naming.rmi : jdk/src/jdk.naming.rmi
|
||||
src/jdk.net : jdk/src/jdk.net
|
||||
src/jdk.pack : jdk/src/jdk.pack
|
||||
src/jdk.scripting.nashorn : nashorn/src/jdk.scripting.nashorn
|
||||
src/jdk.scripting.nashorn.shell : nashorn/src/jdk.scripting.nashorn.shell
|
||||
src/jdk.sctp : jdk/src/jdk.sctp
|
||||
src/jdk.security.auth : jdk/src/jdk.security.auth
|
||||
src/jdk.security.jgss : jdk/src/jdk.security.jgss
|
||||
src/jdk.unsupported : jdk/src/jdk.unsupported
|
||||
src/jdk.xml.bind : jaxws/src/jdk.xml.bind
|
||||
src/jdk.xml.dom : jaxp/src/jdk.xml.dom
|
||||
src/jdk.xml.ws : jaxws/src/jdk.xml.ws
|
||||
src/jdk.zipfs : jdk/src/jdk.zipfs
|
||||
src/langtools/sample : langtools/src/sample
|
||||
src/linux : jdk/src/linux
|
||||
src/sample : jdk/src/sample
|
||||
src/hotspot/share : hotspot/src/share/vm
|
||||
src/hotspot/cpu/aarch64 : hotspot/src/cpu/aarch64/vm
|
||||
src/hotspot/cpu/arm : hotspot/src/cpu/arm/vm
|
||||
src/hotspot/cpu/ppc : hotspot/src/cpu/ppc/vm
|
||||
src/hotspot/cpu/s390 : hotspot/src/cpu/s390/vm
|
||||
src/hotspot/cpu/x86 : hotspot/src/cpu/x86/vm
|
||||
src/hotspot/cpu/zero : hotspot/src/cpu/zero/vm
|
||||
src/hotspot/os/aix : hotspot/src/os/aix/vm
|
||||
src/hotspot/os/bsd : hotspot/src/os/bsd/vm
|
||||
src/hotspot/os/linux : hotspot/src/os/linux/vm
|
||||
src/hotspot/os/posix/dtrace : hotspot/src/os/posix/dtrace
|
||||
src/hotspot/os/posix : hotspot/src/os/posix/vm
|
||||
src/hotspot/os/windows : hotspot/src/os/windows/vm
|
||||
src/hotspot/os_cpu/aix_ppc : hotspot/src/os_cpu/aix_ppc/vm
|
||||
src/hotspot/os_cpu/bsd_x86 : hotspot/src/os_cpu/bsd_x86/vm
|
||||
src/hotspot/os_cpu/bsd_zero : hotspot/src/os_cpu/bsd_zero/vm
|
||||
src/hotspot/os_cpu/linux_aarch64 : hotspot/src/os_cpu/linux_aarch64/vm
|
||||
src/hotspot/os_cpu/linux_arm : hotspot/src/os_cpu/linux_arm/vm
|
||||
src/hotspot/os_cpu/linux_ppc : hotspot/src/os_cpu/linux_ppc/vm
|
||||
src/hotspot/os_cpu/linux_s390 : hotspot/src/os_cpu/linux_s390/vm
|
||||
src/hotspot/os_cpu/linux_x86 : hotspot/src/os_cpu/linux_x86/vm
|
||||
src/hotspot/os_cpu/linux_zero : hotspot/src/os_cpu/linux_zero/vm
|
||||
src/hotspot/os_cpu/windows_x86 : hotspot/src/os_cpu/windows_x86/vm
|
||||
src/hotspot : hotspot/src
|
||||
src/utils/IdealGraphVisualizer : hotspot/src/share/tools/IdealGraphVisualizer
|
||||
src/utils/LogCompilation : hotspot/src/share/tools/LogCompilation
|
||||
src/utils/hsdis : hotspot/src/share/tools/hsdis
|
||||
src/utils/reorder : jdk/make/non-build-utils/reorder
|
||||
src/utils/src/build : jdk/make/non-build-utils/src/build
|
||||
make/BuildNashorn.gmk : nashorn/make/BuildNashorn.gmk
|
||||
make/CompileDemos.gmk : jdk/make/CompileDemos.gmk
|
||||
make/CompileInterimLangtools.gmk : langtools/make/CompileInterim.gmk
|
||||
make/CompileModuleTools.gmk : jdk/make/CompileModuleTools.gmk
|
||||
make/CompileToolsHotspot.gmk : hotspot/make/CompileTools.gmk
|
||||
make/CompileToolsJdk.gmk : jdk/make/CompileTools.gmk
|
||||
make/CopyInterimCLDRConverter.gmk : jdk/make/CopyInterimCLDRConverter.gmk
|
||||
make/GenerateModuleSummary.gmk : jdk/make/GenerateModuleSummary.gmk
|
||||
make/ModuleTools.gmk : jdk/make/ModuleTools.gmk
|
||||
make/ToolsJdk.gmk : jdk/make/Tools.gmk
|
||||
make/ToolsLangtools.gmk : langtools/make/Tools.gmk
|
||||
make/UnpackSecurity.gmk : jdk/make/UnpackSecurity.gmk
|
||||
make/autoconf : common/autoconf
|
||||
make/conf : common/conf
|
||||
make/copy : jdk/make/copy
|
||||
make/copy/Copy-java.corba.gmk : corba/make/copy/Copy-java.corba.gmk
|
||||
make/corba : corba/make
|
||||
make/data : jdk/make/data
|
||||
make/gendata : jdk/make/gendata
|
||||
make/gendata/Gendata-jdk.compiler.gmk : langtools/make/gendata/Gendata-jdk.compiler.gmk
|
||||
make/gensrc : jdk/make/gensrc
|
||||
make/gensrc/Gensrc-java.corba.gmk : corba/make/gensrc/Gensrc-java.corba.gmk
|
||||
make/gensrc/Gensrc-jdk.compiler.gmk : langtools/make/gensrc/Gensrc-jdk.compiler.gmk
|
||||
make/gensrc/Gensrc-jdk.hotspot.agent.gmk : hotspot/make/gensrc/Gensrc-jdk.hotspot.agent.gmk
|
||||
make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk : hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk
|
||||
make/gensrc/Gensrc-jdk.javadoc.gmk : langtools/make/gensrc/Gensrc-jdk.javadoc.gmk
|
||||
make/gensrc/Gensrc-jdk.jdeps.gmk : langtools/make/gensrc/Gensrc-jdk.jdeps.gmk
|
||||
make/gensrc/Gensrc-jdk.jshell.gmk : langtools/make/gensrc/Gensrc-jdk.jshell.gmk
|
||||
make/gensrc/GensrcCommonLangtools.gmk : langtools/make/gensrc/GensrcCommon.gmk
|
||||
make/hotspot : hotspot/make
|
||||
make/jdk : jdk/make
|
||||
make/langtools : langtools/make
|
||||
make/launcher : jdk/make/launcher
|
||||
make/lib : jdk/make/lib
|
||||
make/lib/Lib-jdk.hotspot.agent.gmk : hotspot/make/lib/Lib-jdk.hotspot.agent.gmk
|
||||
make/mapfiles : jdk/make/mapfiles
|
||||
make/mapfiles/libjsig : hotspot/make/mapfiles/libjsig
|
||||
make/mapfiles/libjvm_db : hotspot/make/mapfiles/libjvm_db
|
||||
make/mapfiles/libjvm_dtrace : hotspot/make/mapfiles/libjvm_dtrace
|
||||
make/mapfiles/libsaproc : hotspot/make/mapfiles/libsaproc
|
||||
make/nashorn : nashorn/make
|
||||
make/nb_native : common/nb_native
|
||||
make/scripts/addNotices.sh : jdk/make/scripts/addNotices.sh
|
||||
make/scripts/compare.sh : common/bin/compare.sh
|
||||
make/scripts/compare_exceptions.sh.incl : common/bin/compare_exceptions.sh.incl
|
||||
make/scripts/genExceptions.sh : jdk/make/scripts/genExceptions.sh
|
||||
make/scripts/hide_important_warnings_from_javac.sh : common/bin/hide_important_warnings_from_javac.sh
|
||||
make/scripts/logger.sh : common/bin/logger.sh
|
||||
make/src/native/fixpath.c : common/src/fixpath.c
|
||||
make/test/JtregNativeHotspot.gmk : hotspot/make/test/JtregNative.gmk
|
||||
make/test/JtregNativeJdk.gmk : jdk/make/test/JtregNative.gmk
|
||||
test/jdk : jdk/test
|
||||
test/langtools : langtools/test
|
||||
test/nashorn : nashorn/test
|
||||
test/jaxp : jaxp/test
|
||||
test/hotspot/gtest : hotspot/test/native
|
||||
test/hotspot/jtreg : hotspot/test
|
||||
bin : common/bin
|
||||
bin/nashorn : nashorn/bin
|
||||
doc : common/doc
|
||||
doc/nashorn : nashorn/docs
|
||||
@ -1,237 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
# Script for updating a patch file as per the shuffled/unshuffled source location.
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [-h|--help] [-v|--verbose] [-to9|-to10] [-r <repo>] <input_patch> <output_patch>"
|
||||
echo "where:"
|
||||
echo " -to9 create patches appropriate for a JDK 9 source tree"
|
||||
echo " When going to 9, the output patches will be suffixed with the"
|
||||
echo " repo name"
|
||||
echo " -to10 create patches appropriate for a JDK 10 source tree"
|
||||
echo " -r <repo> specify repo for source patch, set to 'top' for top repo"
|
||||
echo " <input_patch> is the input patch file, that needs shuffling/unshuffling"
|
||||
echo " <output_patch> is the updated patch file "
|
||||
echo " "
|
||||
exit 1
|
||||
}
|
||||
|
||||
SCRIPT_DIR=`dirname $0`
|
||||
UNSHUFFLE_LIST=$SCRIPT_DIR"/unshuffle_list.txt"
|
||||
|
||||
if [ ! -f "$UNSHUFFLE_LIST" ] ; then
|
||||
echo "FATAL: cannot find $UNSHUFFLE_LIST" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
vflag="false"
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case $1 in
|
||||
-h | --help )
|
||||
usage
|
||||
;;
|
||||
|
||||
-v | --verbose )
|
||||
vflag="true"
|
||||
;;
|
||||
|
||||
-r)
|
||||
repo="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
-to9)
|
||||
shuffle_to=9
|
||||
;;
|
||||
|
||||
-to10)
|
||||
shuffle_to=10
|
||||
;;
|
||||
|
||||
-*) # bad option
|
||||
usage
|
||||
;;
|
||||
|
||||
* ) # non option
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Make sure we have the right number of arguments
|
||||
if [ ! $# -eq 2 ] ; then
|
||||
echo "ERROR: Invalid number of arguments." >&2
|
||||
usage
|
||||
fi
|
||||
|
||||
# Check the given repo
|
||||
repos="top corba jaxp jaxws jdk langtools nashorn hotspot"
|
||||
found="false"
|
||||
if [ -n "$repo" ]; then
|
||||
for r in $repos ; do
|
||||
if [ $repo = "$r" ] ; then
|
||||
found="true"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if [ $found = "false" ] ; then
|
||||
echo "ERROR: Unknown repo: $repo. Should be one of [$repos]." >&2
|
||||
usage
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$shuffle_to" != "9" -a "$shuffle_to" != "10" ]; then
|
||||
echo "ERROR: Must pick either -to9 or -to10"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# When going to 10, a repo must be specified for the source patch
|
||||
if [ "$shuffle_to" = "10" -a -z "$repo" ]; then
|
||||
echo "ERROR: Must specify src repo for JDK 9 patch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check given input/output files
|
||||
input="$1"
|
||||
if [ "x$input" = "x-" ] ; then
|
||||
input="/dev/stdin"
|
||||
fi
|
||||
|
||||
if [ ! -f $input -a "x$input" != "x/dev/stdin" ] ; then
|
||||
echo "ERROR: Cannot find input patch file: $input" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
output="$2"
|
||||
if [ "x$output" = "x-" ] ; then
|
||||
output="/dev/stdout"
|
||||
fi
|
||||
base_output="$output"
|
||||
|
||||
if [ "$shuffle_to" = "10" ]; then
|
||||
if [ -f $output -a "x$output" != "x/dev/stdout" ] ; then
|
||||
echo "ERROR: Output patch already exists: $output" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
for r in $repos; do
|
||||
if [ -f "$output.$r" ]; then
|
||||
echo "ERROR: Output patch already exists: $output.$r" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
verbose() {
|
||||
if [ ${vflag} = "true" ] ; then
|
||||
echo "$@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
unshuffle() {
|
||||
line=$@
|
||||
verbose "Attempting to rewrite: \"$line\""
|
||||
|
||||
# Retrieve the file name
|
||||
path=
|
||||
if echo "$line" | egrep '^diff' > /dev/null ; then
|
||||
if ! echo "$line" | egrep '\-\-git' > /dev/null ; then
|
||||
echo "ERROR: Only git patches supported. Please use 'hg export --git ...'." >&2
|
||||
exit 1
|
||||
fi
|
||||
path="`echo "$line" | sed -e s@'diff --git a/'@@ -e s@' b/.*$'@@`"
|
||||
elif echo "$line" | egrep '^\-\-\-' > /dev/null ; then
|
||||
path="`echo "$line" | sed -e s@'--- a/'@@`"
|
||||
elif echo "$line" | egrep '^\+\+\+' > /dev/null ; then
|
||||
path="`echo "$line" | sed s@'+++ b/'@@`"
|
||||
fi
|
||||
verbose "Extracted path: \"$path\""
|
||||
|
||||
# Find the most specific matches in the shuffle list
|
||||
matches=
|
||||
if [ -n "$repo" -a "$repo" != "top" ]; then
|
||||
matchpath="$repo"/"$path"/x
|
||||
else
|
||||
matchpath="$path"/x
|
||||
fi
|
||||
while [ "$matchpath" != "" ] ; do
|
||||
matchpath="`echo $matchpath | sed s@'\(.*\)/.*$'@'\1'@`"
|
||||
|
||||
if [ "$shuffle_to" = "10" ] ; then
|
||||
pattern=": $matchpath$"
|
||||
else
|
||||
pattern="^$matchpath :"
|
||||
fi
|
||||
verbose "Attempting to find \"$matchpath\""
|
||||
matches=`egrep "$pattern" "$UNSHUFFLE_LIST"`
|
||||
if ! [ "x${matches}" = "x" ] ; then
|
||||
verbose "Got matches: [$matches]"
|
||||
break;
|
||||
fi
|
||||
|
||||
if ! echo "$matchpath" | egrep '.*/.*' > /dev/null ; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
# Rewrite the line, if we have a match
|
||||
if ! [ "x${matches}" = "x" ] ; then
|
||||
shuffled="${matches%% : *}"
|
||||
unshuffled="${matches#* : }"
|
||||
patch_suffix_9=""
|
||||
for r in $repos; do
|
||||
if [ "$unshuffled" != "${unshuffled#$r}" ]; then
|
||||
unshuffled="${unshuffled#$r\/}"
|
||||
patch_suffix_9=".$r"
|
||||
fi
|
||||
done
|
||||
verbose "shuffled: $shuffled"
|
||||
verbose "unshuffled: $unshuffled"
|
||||
verbose "patch_suffix_9: $patch_suffix_9"
|
||||
if [ "$shuffle_to" = "10" ] ; then
|
||||
newline="`echo "$line" | sed -e s@"$unshuffled"@"$shuffled"@g`"
|
||||
else
|
||||
newline="`echo "$line" | sed -e s@"$shuffled"@"$unshuffled"@g`"
|
||||
output=$base_output$patch_suffix_9
|
||||
verbose "Writing to $output"
|
||||
fi
|
||||
verbose "Rewriting to \"$newline\""
|
||||
echo "$newline" >> $output
|
||||
else
|
||||
echo "WARNING: no match found for $path"
|
||||
echo "$line" >> $output
|
||||
fi
|
||||
}
|
||||
|
||||
while IFS= read -r line
|
||||
do
|
||||
if echo "$line" | egrep '^diff|^\-\-\-|^\+\+\+' > /dev/null ; then
|
||||
unshuffle "$line"
|
||||
else
|
||||
printf "%s\n" "$line" >> $output
|
||||
fi
|
||||
done < "$input"
|
||||
@ -62,17 +62,22 @@ Help()
|
||||
echo "options:"
|
||||
echo "-c Specifies the company. Set to Oracle by default."
|
||||
echo "-y Specifies the copyright year. Set to current year by default."
|
||||
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."
|
||||
echo " as specified by -y. Overrides -b flag."
|
||||
echo "-h Print this help."
|
||||
echo
|
||||
}
|
||||
|
||||
full_year=false
|
||||
base_reference=master
|
||||
|
||||
# Process options
|
||||
while getopts "c:fhy:" option; do
|
||||
while getopts "b:c:fhy:" option; do
|
||||
case $option in
|
||||
b) # supplied base reference
|
||||
base_reference=${OPTARG}
|
||||
;;
|
||||
c) # supplied company year
|
||||
company=${OPTARG}
|
||||
;;
|
||||
@ -111,7 +116,7 @@ else
|
||||
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 'master..HEAD' --since="${year}-01-01T00:00:00Z" --until="${year}-12-31T23:59:59Z" --pretty=tformat:"%H")
|
||||
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}
|
||||
111
bin/update_pch.sh
Normal file
111
bin/update_pch.sh
Normal file
@ -0,0 +1,111 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
|
||||
# The output of this script may require some degree of human curation:
|
||||
# - Redundant headers, e.g. both x.hpp, x.inline.hpp are included;
|
||||
# - Headers relative to a non-default feature should be protected by an
|
||||
# appropriate 'if' clause to make sure all variants can build without
|
||||
# errors.
|
||||
|
||||
source_path="$(dirname ${0})"
|
||||
this_script_dir="$(cd -- "${source_path}" > /dev/null && pwd)"
|
||||
if test -z "${this_script_dir}"; then
|
||||
echo "Error: Could not determine location of this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Work in top directory
|
||||
cd $this_script_dir/..
|
||||
|
||||
# Time threshold for header compilation, if the time exceeds the
|
||||
# threshold the header will be precompiled.
|
||||
if [ -z "$MIN_MS" ]; then
|
||||
MIN_MS=100000
|
||||
fi
|
||||
|
||||
if [ -z "$CLEAN" ]; then
|
||||
CLEAN=true
|
||||
elif [ "$CLEAN" != "true" ] && [ "$CLEAN" != "false" ]; then
|
||||
echo "Expected either 'true' or 'false' for CLEAN"
|
||||
fi
|
||||
|
||||
# CBA_PATH should point to a valid ClangBuildAnalyzer executable.
|
||||
# Build steps:
|
||||
# git clone --depth 1 git@github.com:aras-p/ClangBuildAnalyzer.git
|
||||
# cd ClangBuildAnalyzer
|
||||
# make -f projects/make/Makefile
|
||||
if [ -z "$CBA_PATH" ]; then
|
||||
CBA_PATH="./ClangBuildAnalyzer/build/ClangBuildAnalyzer"
|
||||
fi
|
||||
|
||||
set -eux
|
||||
|
||||
PRECOMPILED_HPP="src/hotspot/share/precompiled/precompiled.hpp"
|
||||
CBA_CONFIG="ClangBuildAnalyzer.ini"
|
||||
TIMESTAMP="$(date +%Y%m%d-%H%M)"
|
||||
RUN_NAME="pch_update_$TIMESTAMP"
|
||||
CBA_OUTPUT="cba_out_$TIMESTAMP"
|
||||
|
||||
if [ "$CLEAN" = "true" ]; then
|
||||
trap 'rm -rf "build/'"$RUN_NAME"'" "$CBA_OUTPUT" "$CBA_CONFIG"' EXIT
|
||||
fi
|
||||
|
||||
sh configure --with-toolchain-type=clang \
|
||||
--with-conf-name="$RUN_NAME" \
|
||||
--disable-precompiled-headers \
|
||||
--with-extra-cxxflags="-ftime-trace" \
|
||||
--with-extra-cflags="-ftime-trace"
|
||||
|
||||
make clean CONF_NAME="$RUN_NAME"
|
||||
make hotspot CONF_NAME="$RUN_NAME"
|
||||
"$CBA_PATH" --all "./build/$RUN_NAME/hotspot/variant-server/libjvm/objs" \
|
||||
"$CBA_OUTPUT"
|
||||
|
||||
# Preserve license and comments on top
|
||||
cat "$PRECOMPILED_HPP" | awk '/^#include/ {exit} {print}' > "$PRECOMPILED_HPP.tmp"
|
||||
|
||||
if [ ! -f "$CBA_CONFIG" ]; then
|
||||
cat <<EOF > "$CBA_CONFIG"
|
||||
[counts]
|
||||
header=100
|
||||
headerChain=0
|
||||
template=0
|
||||
function=0
|
||||
fileCodegen=0
|
||||
fileParse=0
|
||||
|
||||
[misc]
|
||||
onlyRootHeaders=true
|
||||
EOF
|
||||
fi
|
||||
|
||||
"$CBA_PATH" --analyze "$CBA_OUTPUT" | \
|
||||
grep " ms: " | \
|
||||
# Keep the headers more expensive than ${1}ms
|
||||
awk -v x="$MIN_MS" '$1 < x { exit } { print $3 }' | \
|
||||
# Filter away non-hotspot headers
|
||||
grep hotspot/share | \
|
||||
awk -F "hotspot/share/" '{ printf "#include \"%s\"\n", $2 }' \
|
||||
>> "$PRECOMPILED_HPP.tmp"
|
||||
mv "$PRECOMPILED_HPP.tmp" "$PRECOMPILED_HPP"
|
||||
|
||||
java test/hotspot/jtreg/sources/SortIncludes.java --update "$PRECOMPILED_HPP"
|
||||
@ -50,6 +50,9 @@ id="toc-factoring-and-class-design">Factoring and Class Design</a></li>
|
||||
<li><a href="#commenting" id="toc-commenting">Commenting</a></li>
|
||||
<li><a href="#macros" id="toc-macros">Macros</a></li>
|
||||
<li><a href="#whitespace" id="toc-whitespace">Whitespace</a></li>
|
||||
<li><a href="#avoid-implicit-conversions-to-bool"
|
||||
id="toc-avoid-implicit-conversions-to-bool">Avoid implicit conversions
|
||||
to bool</a></li>
|
||||
<li><a href="#miscellaneous"
|
||||
id="toc-miscellaneous">Miscellaneous</a></li>
|
||||
</ul></li>
|
||||
@ -72,28 +75,78 @@ Standard Library</a></li>
|
||||
Deduction</a></li>
|
||||
<li><a href="#expression-sfinae" id="toc-expression-sfinae">Expression
|
||||
SFINAE</a></li>
|
||||
<li><a href="#trailing-return-type-syntax-for-functions"
|
||||
id="toc-trailing-return-type-syntax-for-functions">Trailing return type
|
||||
syntax for functions</a></li>
|
||||
<li><a href="#non-type-template-parameter-values"
|
||||
id="toc-non-type-template-parameter-values">Non-type template parameter
|
||||
values</a></li>
|
||||
<li><a href="#enum" id="toc-enum">enum</a></li>
|
||||
<li><a href="#alignas" id="toc-alignas">alignas</a></li>
|
||||
<li><a href="#thread_local" id="toc-thread_local">thread_local</a></li>
|
||||
<li><a href="#nullptr" id="toc-nullptr">nullptr</a></li>
|
||||
<li><a href="#atomic" id="toc-atomic"><atomic></a></li>
|
||||
<li><a href="#variable-templates-and-inline-variables"
|
||||
id="toc-variable-templates-and-inline-variables">Variable Templates and
|
||||
Inline Variables</a></li>
|
||||
<li><a href="#initializing-variables-with-static-storage-duration"
|
||||
id="toc-initializing-variables-with-static-storage-duration">Initializing
|
||||
variables with static storage duration</a></li>
|
||||
<li><a href="#uniform-initialization"
|
||||
id="toc-uniform-initialization">Uniform Initialization</a></li>
|
||||
<li><a href="#mandatory-copy-elision"
|
||||
id="toc-mandatory-copy-elision">Mandatory Copy Elision</a></li>
|
||||
<li><a href="#local-function-objects"
|
||||
id="toc-local-function-objects">Local Function Objects</a></li>
|
||||
<li><a href="#inheriting-constructors"
|
||||
id="toc-inheriting-constructors">Inheriting constructors</a></li>
|
||||
<li><a href="#attributes" id="toc-attributes">Attributes</a></li>
|
||||
<li><a href="#noexcept" id="toc-noexcept">noexcept</a></li>
|
||||
<li><a href="#enhanced-selection-statements"
|
||||
id="toc-enhanced-selection-statements">Enhanced selection
|
||||
statements</a></li>
|
||||
<li><a href="#expression-evaluation-order"
|
||||
id="toc-expression-evaluation-order">Expression Evaluation
|
||||
Order</a></li>
|
||||
<li><a href="#compatibility-with-c11"
|
||||
id="toc-compatibility-with-c11">Compatibility with C11</a></li>
|
||||
<li><a href="#additional-permitted-features"
|
||||
id="toc-additional-permitted-features">Additional Permitted
|
||||
Features</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#excluded-features" id="toc-excluded-features">Excluded
|
||||
Features</a>
|
||||
<ul>
|
||||
<li><a href="#structured-bindings"
|
||||
id="toc-structured-bindings">Structured Bindings</a></li>
|
||||
<li><a href="#file-system-library" id="toc-file-system-library">File
|
||||
System Library</a></li>
|
||||
<li><a href="#aggregate-extensions"
|
||||
id="toc-aggregate-extensions">Aggregate Extensions</a></li>
|
||||
<li><a href="#additional-excluded-features"
|
||||
id="toc-additional-excluded-features">Additional Excluded
|
||||
Features</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#undecided-features" id="toc-undecided-features">Undecided
|
||||
Features</a>
|
||||
<ul>
|
||||
<li><a href="#stdoptional"
|
||||
id="toc-stdoptional">std::optional<></a></li>
|
||||
<li><a href="#stdbyte" id="toc-stdbyte">std::byte</a></li>
|
||||
<li><a href="#string-views" id="toc-string-views">String Views</a></li>
|
||||
<li><a href="#substring-and-subsequence-searching"
|
||||
id="toc-substring-and-subsequence-searching">Substring and Subsequence
|
||||
Searching</a></li>
|
||||
<li><a href="#new-and-delete-with-over-aligned-data"
|
||||
id="toc-new-and-delete-with-over-aligned-data"><code>new</code> and
|
||||
<code>delete</code> with Over-Aligned Data</a></li>
|
||||
<li><a href="#stdto_chars-and-stdfrom_chars"
|
||||
id="toc-stdto_chars-and-stdfrom_chars"><code>std::to_chars()</code> and
|
||||
<code>std::from_chars</code></a></li>
|
||||
<li><a href="#stdlaunder"
|
||||
id="toc-stdlaunder"><code>std::launder()</code></a></li>
|
||||
<li><a href="#additional-undecided-features"
|
||||
id="toc-additional-undecided-features">Additional Undecided
|
||||
Features</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
@ -209,6 +262,16 @@ lines of code. Name what you must repeat.</p></li>
|
||||
attribute, the change should be done with a "setter" accessor matched to
|
||||
the simple "getter".</p></li>
|
||||
</ul>
|
||||
<h4 id="conventions-for-lock-free-code">Conventions for Lock-free
|
||||
Code</h4>
|
||||
<p>Sometimes variables are accessed concurrently without appropriate
|
||||
synchronization context, such as a held mutex or at a safepoint. In such
|
||||
cases the variable should be declared <code>volatile</code> and it
|
||||
should NOT be accessed as a normal C++ lvalue. Rather, access should be
|
||||
performed via functions from <code>Atomic</code>, such as
|
||||
<code>Atomic::load</code>, <code>Atomic::store</code>, etc.</p>
|
||||
<p>This special formulation makes it more clear to maintainers that the
|
||||
variable is accessed concurrently in a lock-free manner.</p>
|
||||
<h3 id="source-files">Source Files</h3>
|
||||
<ul>
|
||||
<li><p>All source files must have a globally unique basename. The build
|
||||
@ -408,22 +471,25 @@ adjust new lines horizontally to be consistent with that organization.
|
||||
(E.g., trailing backslashes on long macro definitions often
|
||||
align.)</p></li>
|
||||
</ul>
|
||||
<h3 id="miscellaneous">Miscellaneous</h3>
|
||||
<ul>
|
||||
<li><p>Use the <a href="https://en.cppreference.com/w/cpp/language/raii"
|
||||
title="Resource Acquisition Is Initialization">Resource Acquisition Is
|
||||
Initialization</a> (RAII) design pattern to manage bracketed critical
|
||||
sections. See class <code>ResourceMark</code> for an example.</p></li>
|
||||
<li><p>Avoid implicit conversions to <code>bool</code>.</p>
|
||||
<h3 id="avoid-implicit-conversions-to-bool">Avoid implicit conversions
|
||||
to bool</h3>
|
||||
<ul>
|
||||
<li>Use <code>bool</code> for boolean values.</li>
|
||||
<li>Do not use ints or pointers as (implicit) booleans with
|
||||
<code>&&</code>, <code>||</code>, <code>if</code>,
|
||||
<code>while</code>. Instead, compare explicitly, i.e.
|
||||
<code>if (x != 0)</code> or <code>if (ptr != nullptr)</code>, etc.</li>
|
||||
<li>Do not use declarations in <em>condition</em> forms, i.e. don't use
|
||||
<code>if (T v = value) { ... }</code>.</li>
|
||||
</ul></li>
|
||||
<li>Do not use non-boolean declarations in <em>condition</em> forms,
|
||||
i.e. don't use <code>if (T v = value) { ... }</code>. But see <a
|
||||
href="#enhanced-selection-statements">Enhanced selection
|
||||
statements</a>.</li>
|
||||
</ul>
|
||||
<h3 id="miscellaneous">Miscellaneous</h3>
|
||||
<ul>
|
||||
<li><p>Use the <a href="https://en.cppreference.com/w/cpp/language/raii"
|
||||
title="Resource Acquisition Is Initialization">Resource Acquisition Is
|
||||
Initialization</a> (RAII) design pattern to manage bracketed critical
|
||||
sections. See class <code>ResourceMark</code> for an example.</p></li>
|
||||
<li><p>Use functions from globalDefinitions.hpp and related files when
|
||||
performing bitwise operations on integers. Do not code directly as C
|
||||
operators, unless they are extremely simple. (Examples:
|
||||
@ -435,16 +501,16 @@ default case. It is ok to have an empty default with comment.</p></li>
|
||||
</ul>
|
||||
<h2 id="use-of-c-features">Use of C++ Features</h2>
|
||||
<p>HotSpot was originally written in a subset of the C++98/03 language.
|
||||
More recently, support for C++14 is provided, though again, HotSpot only
|
||||
More recently, support for C++17 is provided, though again, HotSpot only
|
||||
uses a subset. (Backports to JDK versions lacking support for more
|
||||
recent Standards must of course stick with the original C++98/03
|
||||
subset.)</p>
|
||||
<p>This section describes that subset. Features from the C++98/03
|
||||
language may be used unless explicitly excluded here. Features from
|
||||
C++11 and C++14 may be explicitly permitted or explicitly excluded, and
|
||||
discussed accordingly here. There is a third category, undecided
|
||||
features, about which HotSpot developers have not yet reached a
|
||||
consensus, or perhaps have not discussed at all. Use of these features
|
||||
C++11, C++14, and C++17 may be explicitly permitted or explicitly
|
||||
excluded, and discussed accordingly here. There is a third category,
|
||||
undecided features, about which HotSpot developers have not yet reached
|
||||
a consensus, or perhaps have not discussed at all. Use of these features
|
||||
is also excluded.</p>
|
||||
<p>(The use of some features may not be immediately obvious and may slip
|
||||
in anyway, since the compiler will accept them. The code review process
|
||||
@ -453,9 +519,9 @@ is the main defense against this.)</p>
|
||||
provide more extensive discussion or rationale for limitations. Features
|
||||
that don't have their own subsection are listed in omnibus feature
|
||||
sections for permitted, excluded, and undecided features.</p>
|
||||
<p>Lists of new features for C++11 and C++14, along with links to their
|
||||
descriptions, can be found in the online documentation for some of the
|
||||
compilers and libraries. The C++14 Standard is the definitive
|
||||
<p>Lists of new features for C++11, C++14, and C++17, along with links
|
||||
to their descriptions, can be found in the online documentation for some
|
||||
of the compilers and libraries. The C++17 Standard is the definitive
|
||||
description.</p>
|
||||
<ul>
|
||||
<li><a href="https://gcc.gnu.org/projects/cxx-status.html">C++ Standards
|
||||
@ -652,12 +718,42 @@ href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf">n1984</
|
||||
For local variables, this can be used to make the code clearer by
|
||||
eliminating type information that is obvious or irrelevant. Excessive
|
||||
use can make code much harder to understand.</p></li>
|
||||
<li><p>Function return type deduction (<a
|
||||
<li><p><code>auto</code> for non-type template parameters (<a
|
||||
href="http://wg21.link/p0127r2">p0127r2</a>)<br> <code>auto</code> may
|
||||
be used as a placeholder for the type of a non-type template parameter.
|
||||
The type is deduced from the value provided in a template
|
||||
instantiation.</p></li>
|
||||
</ul>
|
||||
<p><a name="function-return-type-deduction"></a> * Function return type
|
||||
deduction (<a
|
||||
href="https://isocpp.org/files/papers/N3638.html">n3638</a>)<br> Only
|
||||
use if the function body has a very small number of <code>return</code>
|
||||
statements, and generally relatively little other code.</p></li>
|
||||
statements, and generally relatively little other code.</p>
|
||||
<ul>
|
||||
<li>Class template argument deduction (<a
|
||||
href="http://wg21.link/n3602">n3602</a>, <a
|
||||
href="http://wg21.link/p0091r3">p0091r3</a>)<br> The template arguments
|
||||
of a class template may be deduced from the arguments to a constructor.
|
||||
This is similar to ordinary function argument deduction, though partial
|
||||
deduction with only <em>some</em> template arguments explicitly provided
|
||||
is not permitted for class template argument deduction. Deduction guides
|
||||
may be used to provide additional control over the deduction. As with
|
||||
<code>auto</code> variable declarations, excessive use can make code
|
||||
harder to understand, because explicit type information is lacking. But
|
||||
it can also remove the need to be explicit about types that are either
|
||||
obvious, or that are very hard to write. For example, these allow the
|
||||
addition of a scope-guard mechanism with nice syntax; something like
|
||||
this</li>
|
||||
</ul>
|
||||
<pre><code> ScopeGuard guard{[&]{ ... cleanup code ... }};</code></pre>
|
||||
<ul>
|
||||
<li><p>Also see <a href="#lambdaexpressions">lambda
|
||||
expressions</a>.</p></li>
|
||||
<li><p><code>decltype(auto)</code> should be avoided, whether for
|
||||
variables, for non-type template parameters, or for function return
|
||||
types. There are subtle and complex differences between this placeholder
|
||||
type and <code>auto</code>. Any use would need very careful
|
||||
explanation.</p></li>
|
||||
</ul>
|
||||
<h3 id="expression-sfinae">Expression SFINAE</h3>
|
||||
<p><a href="https://en.cppreference.com/w/cpp/language/sfinae"
|
||||
@ -682,6 +778,53 @@ class="uri">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468</a><br>
|
||||
<a
|
||||
href="https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html"
|
||||
class="uri">https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html</a></p>
|
||||
<h3 id="trailing-return-type-syntax-for-functions">Trailing return type
|
||||
syntax for functions</h3>
|
||||
<p>A function's return type may be specified after the parameters and
|
||||
qualifiers (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm">n2541</a>).
|
||||
In such a declaration the normal return type is <code>auto</code> and
|
||||
the return type is indicated by <code>-></code> followed by the type.
|
||||
Although both use <code>auto</code> in the "normal" leading return type
|
||||
position, this differs from <a
|
||||
href="#function-return-type-deduction">function return type
|
||||
deduction</a>, in that the return type is explicit rather than deduced,
|
||||
but specified in a trailing position.</p>
|
||||
<p>Use of trailing return types is permitted. However, the normal,
|
||||
leading position for the return type is preferred. A trailing return
|
||||
type should only be used where it provides some benefit. Such benefits
|
||||
usually arise because a trailing return type is in a different scope
|
||||
than a leading return type.</p>
|
||||
<ul>
|
||||
<li><p>If the function identifier is a nested name specifier, then the
|
||||
trailing return type occurs in the nested scope. This may permit simpler
|
||||
naming in the return type because of the different name lookup
|
||||
context.</p></li>
|
||||
<li><p>The trailing return type is in the scope of the parameters,
|
||||
making their types accessible via <code>decltype</code>. For
|
||||
example</p></li>
|
||||
</ul>
|
||||
<pre><code>template<typename T, typename U> auto add(T t, U u) -> decltype(t + u);</code></pre>
|
||||
<p>rather than</p>
|
||||
<pre><code>template<typename T, typename U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);</code></pre>
|
||||
<ul>
|
||||
<li>Complex calculated leading return types may obscure the normal
|
||||
syntactic boundaries, making it more difficult for a reader to find the
|
||||
function name and parameters. This is particularly common in cases where
|
||||
the return type is being used for <a
|
||||
href="https://en.cppreference.com/w/cpp/language/sfinae"
|
||||
title="Substitution Failure Is Not An Error">SFINAE</a>. A trailing
|
||||
return type may be preferable in such situations.</li>
|
||||
</ul>
|
||||
<h3 id="non-type-template-parameter-values">Non-type template parameter
|
||||
values</h3>
|
||||
<p>C++17 extended the arguments permitted for non-type template
|
||||
parameters (<a href="http://wg21.link/n4268">n4268</a>). The kinds of
|
||||
values (the parameter types) aren't changed. However, the values can now
|
||||
be the result of arbitrary constant expressions (with a few restrictions
|
||||
on the result), rather than a much more limited and restrictive set of
|
||||
expressions. In particular, the argument for a pointer or reference type
|
||||
parameter can now be the result of a constexpr function.</p>
|
||||
<h3 id="enum">enum</h3>
|
||||
<p>Where appropriate, <em>scoped-enums</em> should be used. (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf">n2347</a>)</p>
|
||||
@ -795,6 +938,41 @@ differ from what the Java compilers implement.</p>
|
||||
"conservative" memory ordering, which may differ from (may be stronger
|
||||
than) sequentially consistent. There are algorithms in HotSpot that are
|
||||
believed to rely on that ordering.</p>
|
||||
<h3 id="variable-templates-and-inline-variables">Variable Templates and
|
||||
Inline Variables</h3>
|
||||
<p>The use of variable templates (including static data member
|
||||
templates) (<a href="https://wg21.link/N3651">N3651</a>) is permitted.
|
||||
They provide parameterized variables and constants in a simple and
|
||||
direct form, instead of requiring the use of various workarounds.</p>
|
||||
<p>Variables with static storage duration and variable templates may be
|
||||
declared <code>inline</code> (<a
|
||||
href="https://wg21.link/p0386r2">p0386r2</a>), and this usage is
|
||||
permitted. This has similar effects as for declaring a function inline:
|
||||
it can be defined, identically, in multiple translation units, must be
|
||||
defined in every translation unit in which it is <a
|
||||
href="https://en.cppreference.com/w/cpp/language/definition"
|
||||
title="One Definition Rule">ODR used</a>, and the behavior of the
|
||||
program is as if there is exactly one variable.</p>
|
||||
<p>Declaring a variable inline allows the complete definition to be in a
|
||||
header file, rather than having a declaration in a header and the
|
||||
definition in a .cpp file. The guidance on <a
|
||||
href="#initializing-variables-with-static-storage-duration">initialization</a>
|
||||
of such variables still applies. Inline variables with dynamic
|
||||
initializations can make initialization order problems worse. The few
|
||||
ordering constraints that exist for non-inline variables don't apply, as
|
||||
there isn't a single program-designated translation unit containing the
|
||||
definition.</p>
|
||||
<p>A <code>constexpr</code> static data member or static data member
|
||||
template is implicitly <code>inline</code>. As a consequence, an <a
|
||||
href="https://en.cppreference.com/w/cpp/language/definition"
|
||||
title="One Definition Rule">ODR use</a> of such a member doesn't require
|
||||
a definition in some .cpp file. (This is a change from pre-C++17.
|
||||
Beginning with C++17, such a definition is considered a duplicate
|
||||
definition, and is deprecated.)</p>
|
||||
<p>Declaring a <code>thread_local</code> variable template or
|
||||
<code>inline</code> variable is forbidden in HotSpot code. <a
|
||||
href="#thread_local">The use of <code>thread_local</code></a> is already
|
||||
heavily restricted.</p>
|
||||
<h3
|
||||
id="initializing-variables-with-static-storage-duration">Initializing
|
||||
variables with static storage duration</h3>
|
||||
@ -846,6 +1024,45 @@ initialization</a></li>
|
||||
<p>Although related, the use of <code>std::initializer_list</code>
|
||||
remains forbidden, as part of the avoidance of the C++ Standard Library
|
||||
in HotSpot code.</p>
|
||||
<h3 id="mandatory-copy-elision">Mandatory Copy Elision</h3>
|
||||
<p><a href="https://en.wikipedia.org/wiki/Copy_elision">Copy elision</a>
|
||||
(or <a
|
||||
href="https://cn.cppreference.com/w/cpp/language/copy_elision.html">here</a>)
|
||||
is a compiler optimization used to avoid potentially expensive copies in
|
||||
certain situations. It is critical to making practical the performance
|
||||
of return by value or pass by value. It is also unusual in not following
|
||||
the as-if rule for optimizations - copy elision can be applied even if
|
||||
doing so bypasses side-effects of copying/moving the object. The C++
|
||||
standard explicitly permits this.</p>
|
||||
<p>However, because it's an optional optimization, the relevant
|
||||
copy/move constructor must be available and accessible, in case the
|
||||
compiler chooses to not apply the optimization even in a situation where
|
||||
permitted.</p>
|
||||
<p>C++17 changed some cases of copy elision so that there is never a
|
||||
copy/move in these cases (<a
|
||||
href="http://wg21.link/p0135r1">p0135r1</a>). The interesting cases
|
||||
involve a function that returns an unnamed temporary object, and
|
||||
constructors. In such cases the object being initialized from the
|
||||
temporary is always direct initialized, with no copy/move ever involved;
|
||||
see <a href="https://en.wikipedia.org/wiki/Copy_elision#RVO"
|
||||
title="Return Value Optimization">RVO</a> and more specifically <a
|
||||
href="https://cn.cppreference.com/w/cpp/language/copy_elision.html"
|
||||
title="Unnamed Return Value Optimization">URVO</a>.</p>
|
||||
<p>Since this is now standard behavior it can't be avoided in the
|
||||
covered situations. This could change the behavior of code that relied
|
||||
on side effects by constructors, but that's both uncommon and was
|
||||
already problematic because of the previous optional copy elision. But
|
||||
HotSpot code can, and should, explicitly take advantage of this newly
|
||||
required behavior where it makes sense to do so.</p>
|
||||
<p>For example, it may be beneficial to delay construction of the result
|
||||
of a function until the return statement, rather than having a local
|
||||
variable that is modified into the desired state and then returned.
|
||||
(Though <a href="https://en.wikipedia.org/wiki/Copy_elision#NRVO"
|
||||
title="Named Return Value Optimization">NRVO</a> may apply in that
|
||||
case.)</p>
|
||||
<p>It is also now possible to define a factory function for a class that
|
||||
is neither movable nor copyable, if it can be written in a way that
|
||||
makes use of this feature.</p>
|
||||
<h3 id="local-function-objects">Local Function Objects</h3>
|
||||
<ul>
|
||||
<li>Local function objects, including lambda expressions, may be
|
||||
@ -918,6 +1135,13 @@ href="https://en.wikipedia.org/wiki/Partial_application"
|
||||
title="Partial Application">partial application</a>. Again here, lambdas
|
||||
are typically much simpler and less verbose than function object
|
||||
classes.</p>
|
||||
<p>A lambda is a constexpr function if either the parameter declaration
|
||||
clause is followed by <code>constexpr</code>, or it satisfies the
|
||||
requirements for a constexpr function (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0170r1.pdf">p0170r1</a>).
|
||||
Thus, using a lambda to package up some computation doesn't incur
|
||||
unnecessary overhead or prevent use in a context required to be
|
||||
compile-time evaluated (such as an array size).</p>
|
||||
<p>Because of these benefits, lambda expressions are permitted in
|
||||
HotSpot code, with some restrictions and usage guidance. An anonymous
|
||||
lambda is one which is passed directly as an argument. A named lambda is
|
||||
@ -965,6 +1189,18 @@ making the captured value unaffected by modifications to the outer
|
||||
variable. But this only applies to captured auto variables, not member
|
||||
variables, and is inconsistent with referential transparency.</p></li>
|
||||
</ul></li>
|
||||
<li><p>By-value capture of <code>this</code> (using a capture list like
|
||||
<code>[*this]</code> (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r3.html">p0018r3</a>))
|
||||
is also not permitted. One of the motivating use-cases is when the
|
||||
lifetime of the lambda exceeds the lifetime of the object for the
|
||||
containing member function. That is, we have an upward lambda that is
|
||||
capturing <code>this</code> of the enclosing method. But again, that
|
||||
use-case doesn't apply if only downward lambdas are used. Another
|
||||
use-case is when we simply want the lambda to be operating on a copy of
|
||||
<code>this</code> for some reason. This is sufficiently uncommon that it
|
||||
can be handled by manual copying, so readers don't need to understand
|
||||
this rare syntax.</p></li>
|
||||
<li><p>Non-capturing lambdas (with an empty capture list -
|
||||
<code>[]</code>) have limited utility. There are cases where no captures
|
||||
are required (pure functions, for example), but if the function is small
|
||||
@ -974,14 +1210,15 @@ href="https://isocpp.org/files/papers/N3649.html">N3649</a>) are not
|
||||
permitted. Capture initializers inherently increase the complexity of
|
||||
the capture list, and provide little benefit over an additional in-scope
|
||||
local variable.</p></li>
|
||||
</ul>
|
||||
<p>The use of <code>mutable</code> lambda expressions is forbidden
|
||||
<li><p>The use of <code>mutable</code> lambda expressions is forbidden
|
||||
because there don't seem to be many, if any, good use-cases for them in
|
||||
HotSpot. A lambda expression needs to be mutable in order to modify a
|
||||
by-value captured value. But with only downward lambdas, such usage
|
||||
seems likely to be rare and complicated. It is better to use a function
|
||||
object class in any such cases that arise, rather than requiring all
|
||||
HotSpot developers to understand this relatively obscure feature.</p>
|
||||
HotSpot developers to understand this relatively obscure
|
||||
feature.</p></li>
|
||||
</ul>
|
||||
<p>While it is possible to directly invoke an anonymous lambda
|
||||
expression, that feature should not be used, as such a form can be
|
||||
confusing to readers. Instead, name the lambda and call it by name.</p>
|
||||
@ -1099,23 +1336,12 @@ href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">n2540</
|
||||
<p>C++11 provides simple syntax allowing a class to inherit the
|
||||
constructors of a base class. Unfortunately there are a number of
|
||||
problems with the original specification, and C++17 contains significant
|
||||
revisions (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html"
|
||||
title="p0136r1">p0136r1</a> opens with a list of 8 Core Issues). Since
|
||||
HotSpot doesn't support use of C++17, use of inherited constructors
|
||||
could run into those problems. Such uses might also change behavior in a
|
||||
future HotSpot update to use C++17 or later, potentially in subtle ways
|
||||
that could lead to hard to diagnose problems. Because of this, HotSpot
|
||||
code must not use inherited constructors.</p>
|
||||
<p>Note that gcc7 provides the <code>-fnew-inheriting-ctors</code>
|
||||
option to use the <a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html"
|
||||
title="p0136r1">p0136r1</a> semantics. This is enabled by default when
|
||||
using C++17 or later. It is also enabled by default for
|
||||
<code>fabi-version=11</code> (introduced by gcc7) or higher when using
|
||||
C++11/14, as the change is considered a Defect Report that applies to
|
||||
those versions. Earlier versions of gcc don't have that option, and
|
||||
other supported compilers may not have anything similar.</p>
|
||||
revisions (<a href="http:/wg21.link/p0136r1" title="p0136r1">p0136r1</a>
|
||||
opens with a list of 8 Core Issues). Although those issues have been
|
||||
addressed, the benefits from this feature are small compared to the
|
||||
complexity. Because of this, HotSpot code must not use inherited
|
||||
constructors.</p>
|
||||
<p><a href="http://wg21.link/p0195r0">p0195r0</a></p>
|
||||
<h3 id="attributes">Attributes</h3>
|
||||
<p>The use of some attributes (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf">n2761</a>)
|
||||
@ -1131,9 +1357,17 @@ those cases HotSpot has a preferred location.</p>
|
||||
beginning of the function's declaration, rather than between the
|
||||
function name and the parameter list.</li>
|
||||
</ul>
|
||||
<p><a href="http://wg21.link/p0068r0">p0068r0</a> is the initial
|
||||
proposal for the attributes added by C++17.)</p>
|
||||
<p>Only the following attributes are permitted:</p>
|
||||
<ul>
|
||||
<li><code>[[noreturn]]</code></li>
|
||||
<li><code>[[nodiscard]]</code> (<a
|
||||
href="http://wg21.link/p0189r1">p0189r1</a>)</li>
|
||||
<li><code>[[maybe_unused]]</code> (<a
|
||||
href="http://wg21.link/p0212r1">p0212r1</a>)</li>
|
||||
<li><code>[[fallthrough]]</code> (<a
|
||||
href="http://wg21.link/p0188">p0188r1</a>)</li>
|
||||
</ul>
|
||||
<p>The following attributes are expressly forbidden:</p>
|
||||
<ul>
|
||||
@ -1141,6 +1375,23 @@ function name and the parameter list.</li>
|
||||
<code>memory_order_consume</code>.</li>
|
||||
<li><code>[[deprecated]]</code> - Not relevant in HotSpot code.</li>
|
||||
</ul>
|
||||
<p>Direct use of non-standard (and presumably scoped) attributes in
|
||||
shared code is also forbidden. Using such would depend on the C++17
|
||||
feature that an attribute not recognized by the implementation is
|
||||
ignored (<a href="http://wg21.link/p0283r2">p0283r2</a>). If such an
|
||||
attribute is needed in shared code, the well-established technique of
|
||||
providing an <code>ATTRIBUTE_XXX</code> macro with per-compiler
|
||||
definitions (sometimes empty) should be used. Compilers may warn about
|
||||
unrecognized attributes (whether by name or by location), in order to
|
||||
report typos or misuse. Disabling such warnings globally would not be
|
||||
desirable.</p>
|
||||
<p>The use of <code>using</code> directives in attribute lists is also
|
||||
forbidden. (<a href="http://wg21.link/p0028r0">p0028r0</a>) (<a
|
||||
href="http://wg21.link/p0028r4">p0028r4</a>) We don't generally use
|
||||
scoped attributes in attribute lists with other attributes. Rather, uses
|
||||
of scoped attributes (which are implementation defined) are generally
|
||||
hidden behind a portability macro that includes the surrounding
|
||||
brackets.</p>
|
||||
<h3 id="noexcept">noexcept</h3>
|
||||
<p>Use of <code>noexcept</code> exception specifications (<a
|
||||
href="http://wg21.link/n3050">n3050</a>) are permitted with restrictions
|
||||
@ -1190,9 +1441,72 @@ Standard Library facilities.</p></li>
|
||||
functions not declared <code>noexcept</code>. So HotSpot code doesn't
|
||||
ever need to check, either with conditional exception specifications or
|
||||
with <code>noexcept</code> expressions.</p>
|
||||
<p>The exception specification is part of the type of a function (<a
|
||||
href="http://wg21.link/p0012r1">p0012r1</a>. This likely has little
|
||||
impact on HotSpot code, since the use of <code>noexcept</code> is
|
||||
expected to be rare.</p>
|
||||
<p>Dynamic exception specifications were deprecated in C++11. C++17
|
||||
removed all but <code>throw()</code>, with that remaining a deprecated
|
||||
equivalent to <code>noexcept</code>.</p>
|
||||
<h3 id="enhanced-selection-statements">Enhanced selection
|
||||
statements</h3>
|
||||
<p>C++17 modified the <em>condition</em> part of <code>if</code> and
|
||||
<code>switch</code> statements, permitting an <em>init-statement</em> to
|
||||
be included (<a href="http://wg21.link/p0305r1">p0305r1</a>).</p>
|
||||
<p>Use of this feature is permitted. (However, complex uses may
|
||||
interfere with readability.) Limiting the scope of a variable involved
|
||||
in the condition, while also making the value available to the
|
||||
statement's body, can improve readability. The alternative method of
|
||||
scope-limiting by introducing a nested scope isn't very popular and is
|
||||
rarely used.</p>
|
||||
<p>This new syntax is in addition to the <em>condition</em> being a
|
||||
declaration with a <em>brace-or-equal-initializer</em>. For an
|
||||
<code>if</code> statement this new sytax gains that benefit without
|
||||
violating the long-standing guidance against using <a
|
||||
href="#avoid-implicit-conversions-to-bool">implicit conversions to
|
||||
<code>bool</code></a>, which still stands.</p>
|
||||
<p>For example, uses of Unified Logging sometimes explicitly check
|
||||
whether a <code>LogTarget</code> is enabled. Instead of</p>
|
||||
<pre><code> LogTarget(...) lt;
|
||||
if (lt.is_enabled()) {
|
||||
LogStream log(lt);
|
||||
... use log ...
|
||||
}
|
||||
... lt is accessible but probably not needed here ...</code></pre>
|
||||
<p>using this feature one could write</p>
|
||||
<pre><code> if (LogTarget(...) lt; lt.is_enabled()) {
|
||||
LogStream log(lt);
|
||||
... use log ...
|
||||
}</code></pre>
|
||||
<p>C++17 also added compile-time <code>if</code> statements (<a
|
||||
href="http://wg21.link/p0292r2">p0292r2</a>). Use of
|
||||
<code>if constexpr</code> is permitted. This feature can replace and
|
||||
(sometimes vastly) simplify many uses of <a
|
||||
href="https://en.cppreference.com/w/cpp/language/sfinae"
|
||||
title="Substitution Failure Is Not An Error">SFINAE</a>. The same
|
||||
declaration and initialization guidance for the <em>condition</em> part
|
||||
apply here as for ordinary <code>if</code> statements.</p>
|
||||
<h3 id="expression-evaluation-order">Expression Evaluation Order</h3>
|
||||
<p>C++17 tightened up the evaluation order for some kinds of
|
||||
subexpressions (<a href="http://wg21.link/p0138r2">p0138r2</a>). Note,
|
||||
however, that the Alternate Evaluation Order for Function Calls
|
||||
alternative in that paper was adopted, rather than the strict left to
|
||||
right order of evaluation for function call arguments that was proposed
|
||||
in the main body of the paper.</p>
|
||||
<p>The primary purpose of this change seems to be to make certain kinds
|
||||
of call chaining well defined. That's not a style widely used in
|
||||
HotSpot. In general it is better to continue to avoid questions in this
|
||||
area by isolating operations with side effects from other statements. In
|
||||
particular, continue to avoid modifying a value in an expression where
|
||||
it is also used.</p>
|
||||
<h3 id="compatibility-with-c11">Compatibility with C11</h3>
|
||||
<p>C++17 refers to C11 rather than C99. This means that C11 libraries
|
||||
and functions may be used in HotSpot. There may be limitations because
|
||||
of differing levels of compatibility among various compilers and
|
||||
versions of those compilers.</p>
|
||||
<p>Note that the C parts of the JDK have been built with C11 selected
|
||||
for some time (<a
|
||||
href="https://bugs.openjdk.org/browse/JDK-8292008">JDK-8292008</a>).</p>
|
||||
<h3 id="additional-permitted-features">Additional Permitted
|
||||
Features</h3>
|
||||
<ul>
|
||||
@ -1208,8 +1522,10 @@ href="https://isocpp.org/files/papers/n3778.html">n3778</a>)</p></li>
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf">n2242</a>)
|
||||
(<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf">n2555</a>)</p></li>
|
||||
<li><p>Static assertions (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html">n1720</a>)</p></li>
|
||||
<li><p>Static assertions (<a href="http://wg21.link/n1720">n1720</a>)
|
||||
(<a href="http://wg21.link/n3928">n3928</a>)<br> Both the original
|
||||
(C++11) two-argument form and the new (C++17) single-argument form are
|
||||
permitted.</p></li>
|
||||
<li><p><code>decltype</code> (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">n2343</a>)
|
||||
(<a
|
||||
@ -1251,8 +1567,62 @@ href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html">n2930<
|
||||
href="https://en.cppreference.com/w/cpp/language/range-for">range-for</a>)</p></li>
|
||||
<li><p>Unrestricted Unions (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf">n2544</a>)</p></li>
|
||||
<li><p>Preprocessor Condition <code>__has_include</code> (<a
|
||||
href="http://wg21.link/p0061r0">p0061r0</a>) (<a
|
||||
href="http://wg21.link/p0061r1">p0061r1</a>)</p></li>
|
||||
<li><p>Hexadecimal Floating-Point Literals (<a
|
||||
href="http://wg21.link/p0245r1">p0245r1</a>)</p></li>
|
||||
<li><p>Construction Rules for <code>enum class</code> Values (<a
|
||||
href="http://wg21.link/p0138r2">p0138r2</a>)</p></li>
|
||||
<li><p>Allow <code>typename</code> in template template parameter (<a
|
||||
href="http://wg21.link/n4051">n4051</a>) — template template parameters
|
||||
are barely used (if at all) in HotSpot, but there's no reason to
|
||||
artificially disallow this syntactic regularization in any such
|
||||
uses.</p></li>
|
||||
</ul>
|
||||
<h3 id="excluded-features">Excluded Features</h3>
|
||||
<h2 id="excluded-features">Excluded Features</h2>
|
||||
<h3 id="structured-bindings">Structured Bindings</h3>
|
||||
<p>The use of structured bindings <a
|
||||
href="http://wg21.link/p0217r3">p0217r3</a> is forbidden. Preferred
|
||||
approaches for handling functions with multiple return values
|
||||
include</p>
|
||||
<ul>
|
||||
<li><p>Return a named class/struct intended for that purpose, with named
|
||||
and typed members/accessors.</p></li>
|
||||
<li><p>Return a value along with out parameters (usually pointers,
|
||||
sometimes references).</p></li>
|
||||
<li><p>Designate a sentinel "failure" value in the normal return value
|
||||
type, with some out of band location for additional information. For
|
||||
example, this is the model typically used with <code>errno</code>, where
|
||||
a function returns a normal result, or -1 to indicate an error, with
|
||||
additional error information in <code>errno</code>.</p></li>
|
||||
</ul>
|
||||
<p>There is a strong preference for names and explicit types, as opposed
|
||||
to offsets and implicit types. For example, there are folks who strongly
|
||||
dislike that some of the Standard Library functions return
|
||||
<code>std::pair</code> because <code>first</code> and
|
||||
<code>second</code> members don't carry any useful information.</p>
|
||||
<h3 id="file-system-library">File System Library</h3>
|
||||
<p>The use of the File System library is forbidden. HotSpot doesn't do
|
||||
very much with files, and already has adequate mechanisms for its needs.
|
||||
Rewriting in terms of this new library doesn't provide any obviously
|
||||
significant benefits. Having a mix of the existing usage and uses of
|
||||
this new library would be confusing.</p>
|
||||
<p><a href="http://wg21.link/n4100">n4100</a> <a
|
||||
href="http://wg21.link/p0218r0">p0218r0</a> <a
|
||||
href="http://wg21.link/p0219r1">p0219r1</a> <a
|
||||
href="http://wg21.link/p0317r1">p0317r1</a> <a
|
||||
href="http://wg21.link/p0392r0">p0392r0</a> <a
|
||||
href="http://wg21.link/p0430r2">p0430r2</a> <a
|
||||
href="http://wg21.link/p0492r2">p0492r2</a> <a
|
||||
href="http://wg21.link/p1164r1">p1164r1</a></p>
|
||||
<h3 id="aggregate-extensions">Aggregate Extensions</h3>
|
||||
<p>Aggregates with base classes are forbidden. C++17 allows aggregate
|
||||
initialization for classes with base classes (<a
|
||||
href="https://wg21.link/p0017r1">p0017r1</a>). HotSpot makes very little
|
||||
use of aggregate classes, preferring explicit constructors even for very
|
||||
simple classes.</p>
|
||||
<h3 id="additional-excluded-features">Additional Excluded Features</h3>
|
||||
<ul>
|
||||
<li><p>New string and character literals</p>
|
||||
<ul>
|
||||
@ -1285,22 +1655,236 @@ useful.</p></li>
|
||||
operator overloading is used, ensure the semantics conform to the normal
|
||||
expected behavior of the operation.</p></li>
|
||||
<li><p>Avoid most implicit conversion constructors and (implicit or
|
||||
explicit) conversion operators. (Note that conversion to
|
||||
<code>bool</code> isn't needed in HotSpot code because of the "no
|
||||
implicit boolean" guideline.)</p></li>
|
||||
explicit) conversion operators. Conversion to <code>bool</code>
|
||||
operators aren't needed because of the <a
|
||||
href="#avoid-implicit-conversions-to-bool">no implicit boolean</a>
|
||||
guideline.)</p></li>
|
||||
<li><p>Avoid <code>goto</code> statements.</p></li>
|
||||
<li><p>Attributes for namespaces and enumerators (<a
|
||||
href="http://wg21.link/n4266">n4266</a> — The only applicable attribute
|
||||
is <a href="#attributes"><code>[[deprecated]]</code></a>, which is
|
||||
forbidden.</p></li>
|
||||
<li><p>Variadic <code>using</code> declarations (<a
|
||||
href="http://wg21.link/p0195r2">p0195r2</a>)</p></li>
|
||||
<li><p><code>std::variant<></code> (<a
|
||||
href="http://wg21.link/p0088r3">p0088r3</a>) — Even if more of the C++
|
||||
Standard Library is permitted, this class will remain forbidded. Invalid
|
||||
accesses are indicated by throwing exceptions.</p></li>
|
||||
<li><p><code>std::any</code> (<a
|
||||
href="http://wg21.link/p0220r1">p0220r1</a>) — Even if more of the C++
|
||||
Standard Library is permitted, this class will remain forbidden. It may
|
||||
require allocation, and always uses the standard allocator. It requires
|
||||
<a href="https://en.wikipedia.org/wiki/Run-time_type_information"
|
||||
title="Runtime Type Information">RTTI</a>.</p></li>
|
||||
<li><p><code>std::as_const()</code> (<a
|
||||
href="http://wg21.link/p0007r1">p0007r1</a>) — If sufficiently useful,
|
||||
HotSpot could add such a function. It would likely be added to
|
||||
globalDefinitions.hpp, where there are already some similar small
|
||||
utilities.</p></li>
|
||||
<li><p><code>std::clamp()</code> (<a
|
||||
href="http://wg21.link/p002501">p002501</a>) — This function is already
|
||||
provided in globalDefinitions.hpp.</p></li>
|
||||
<li><p>Parallel STL Algorithms (<a
|
||||
href="http://wg21.link/p0024r2">p0024r2</a>) — Even if more of the C++
|
||||
Standard Library is permitted, these will remain forbidden. They are
|
||||
built on the standard C++ threading mechanisms. HotSpot doesn't use
|
||||
those mechanisms, instead providing and using its own.</p></li>
|
||||
<li><p>Cache Line Sizes <a href="http://wg21.link/p0154r1">p0154r1</a> —
|
||||
HotSpot has its own mechanisms for this, using values like
|
||||
<code>DEFAULT_CACHE_LINE_SIZE</code>. The platform-specific
|
||||
implementation of the HotSpot mechanisms might use these library
|
||||
functions, but there is no reason to move away from the current
|
||||
approach. Quoting from <a href="https://www.cppstd17.com"
|
||||
title="C++17: The Complete Guide">JOSUTTIS</a>: "... if you know better,
|
||||
use specific values, but using these values is better than any assumed
|
||||
fixed size for code supporting multiple platforms."</p></li>
|
||||
<li><p><code>register</code> storage class removal <a
|
||||
href="http://wg21.link/p0001r1">p0001r1</a> — The <code>register</code>
|
||||
storage class has been removed. <code>register</code> is still a
|
||||
keyword, so still can't be used for normal purposes. Also, this doesn't
|
||||
affect the use of <code>register</code> for gcc-style extended asm code;
|
||||
that's a different syntactic element with a different meaning.</p></li>
|
||||
<li><p>Value of <code>__cplusplus</code> — Testing whether
|
||||
<code>__cplusplus</code> is defined or not is permitted, and indeed
|
||||
required. But the value should not need to be examined. The value is
|
||||
changed with each revision of the Standard. But we build HotSpot and
|
||||
(most of) the rest of the JDK with a specifically selected version of
|
||||
the Standard. The value of <code>__cplusplus</code> should be known and
|
||||
unchanging until we change the project's build configuration again. So
|
||||
examining the value shouldn't ever be necessary.</p></li>
|
||||
<li><p>Removal of <code>++</code> for <code>bool</code> (<a
|
||||
href="http://wg21.link/p0003r1">p0003r1</a>)</p></li>
|
||||
<li><p>Removal of trigraphs (<a
|
||||
href="http://wg21.link/n4086">n4086</a>)</p></li>
|
||||
</ul>
|
||||
<h3 id="undecided-features">Undecided Features</h3>
|
||||
<h2 id="undecided-features">Undecided Features</h2>
|
||||
<p>This list is incomplete; it serves to explicitly call out some
|
||||
features that have not yet been discussed.</p>
|
||||
<p>Some features are undecided (so implicitly forbidden) because we
|
||||
don't expect to use them at all. This might be reconsidered if someone
|
||||
finds a good use case.</p>
|
||||
<p>Some Standard Library features are undecided (so implicitly
|
||||
forbidden) because, while this Style Guide forbids the use of such, they
|
||||
may be sufficiently useful that we want to permit them anyway. Doing so
|
||||
may require some idiomatic mechanism for addressing things like
|
||||
<code>assert</code> incompatibility, incompatibility with HotSpot's
|
||||
<code>FORBID_C_FUNCTION</code> mechanism, and the like.</p>
|
||||
<h3 id="stdoptional">std::optional<></h3>
|
||||
<p>It is undecided whether to permit the use of
|
||||
<code>std::optional<></code> (<a
|
||||
href="http://wg21.link/p0220r1">p0220r1</a>). It may be sufficiently
|
||||
useful that it should be permitted despite the usual prohibition against
|
||||
using Standard Library facilities. Use of the <code>value()</code>
|
||||
member function must be forbidden, as it reports an invalid access by
|
||||
throwing an exception.</p>
|
||||
<h3 id="stdbyte">std::byte</h3>
|
||||
<p>It is undecided whether to permit the use of the
|
||||
<code>std::byte</code> type (<a
|
||||
href="http://wg21.link/p0298r3">p0298r3</a>). It may be sufficiently
|
||||
useful that it should be permitted despite the usual prohibition against
|
||||
using Standard Library facilities.</p>
|
||||
<p>It has been suggested that changing the HotSpot <code>address</code>
|
||||
type to use <code>std::byte</code> has some benefits. That is,
|
||||
replace</p>
|
||||
<pre><code>typedef u_char* address;
|
||||
typedef const u_char* const_address;</code></pre>
|
||||
<pre><code>using address = std::byte*;
|
||||
using const_address = const std::byte*;</code></pre>
|
||||
<p>in globalDefinitions.hpp.</p>
|
||||
<p>A specific benefit that was mentioned is that it might improve the
|
||||
horrible way that gdb handles our current definition of the
|
||||
<code>address</code> type.</p>
|
||||
<pre><code>#include <cstddef>
|
||||
|
||||
typedef unsigned char* address;
|
||||
typedef std::byte* address_b;
|
||||
|
||||
int main() {
|
||||
|
||||
char* mem;
|
||||
|
||||
address addr = (address)mem;
|
||||
address_b addr_b = (address_b)mem;
|
||||
|
||||
return 0;
|
||||
}</code></pre>
|
||||
<pre><code>(gdb) p addr
|
||||
$1 = (address) 0x7ffff7fe4fa0 <dl_main> "\363\017\036\372Uf\017\357\300H\211\345AWI\211\377AVAUATSH\201\354\210\002"
|
||||
(gdb) p addr_b
|
||||
$2 = (address_b) 0x7ffff7fe4fa0 <dl_main></code></pre>
|
||||
<p>This needs to be explored. Some folks have said they will do so.</p>
|
||||
<h3 id="string-views">String Views</h3>
|
||||
<p>It is undecided whether to permit the use of
|
||||
<code>std::string_view</code> (<a
|
||||
href="http://wg21.link/p0220r1">p0220r1</a>).</p>
|
||||
<p>HotSpot doesn't use <code>std::string</code>, but uses
|
||||
<code>char*</code> strings a lot. Wrapping such in a
|
||||
<code>std::string_view</code> to enable the use of various algorithms
|
||||
could be useful. But since HotSpot also doesn't permit use of
|
||||
<code><algorithm></code> and the like, that only gets the limited
|
||||
set of algorithms provided by the view class directly.</p>
|
||||
<p>There is also the issue of <code>NUL</code> termination; string views
|
||||
are not necessarily <code>NUL</code> terminated. Moreover, if one goes
|
||||
to the work of making one that is <code>NUL</code> terminated, that
|
||||
terminator is included in the size.</p>
|
||||
<p>There are other caveats. Permitting use of string views would require
|
||||
discussion of those.</p>
|
||||
<h3 id="substring-and-subsequence-searching">Substring and Subsequence
|
||||
Searching</h3>
|
||||
<p>In addition to simple substring searching, the Standard Library now
|
||||
includes Boyer-Moore and Boyer-Moore-Horspool searchers, in case someone
|
||||
wants to search really large texts. That seems an unlikely use-case for
|
||||
HotSpot. See <a href="http://wg21.link/p0220r1">p0220r1</a>.</p>
|
||||
<h3 id="new-and-delete-with-over-aligned-data"><code>new</code> and
|
||||
<code>delete</code> with Over-Aligned Data</h3>
|
||||
<p>It is undecided whether to permit the use of dynamic allocation of
|
||||
overaligned types (<a href="http://wg21.link/n3396">n3396</a>).</p>
|
||||
<p>HotSpot currently only has a couple of over-aligned types that are
|
||||
dynamically allocated. These are handled manually, not going through
|
||||
<code>new</code> expressions, as that couldn't work before C++17.</p>
|
||||
<p>One of the ways an over-aligned type might arise is by aligning a
|
||||
data member. This might be done to avoid destructive interference for
|
||||
concurrent accesses. But HotSpot uses a different approach, using
|
||||
explicit padding. Again, this is in part because <code>new</code> and
|
||||
<code>delete</code> of overaligned types didn't work. But we might
|
||||
prefer to continue this approach.</p>
|
||||
<p>We would need to add <code>operator new</code> overloads to
|
||||
<code>CHeapObj<></code> and possibly in other places in order to
|
||||
support this. However, it has been suggested that implementing it
|
||||
(efficiently) on top of NMT might be difficult. Note that
|
||||
<code>posix_memalign</code> / <code>_aligned_malloc</code> don't help
|
||||
here, because of NMT's use of malloc headers.</p>
|
||||
<p>If we don't support it we may want to add <code>operator new</code>
|
||||
overloads that are deleted, to prevent attempted uses.</p>
|
||||
<p>Alignment usage in non-HotSpot parts of the OpenJDK:</p>
|
||||
<ul>
|
||||
<li><p><code>alignas</code> used once in harfbuzz, to align a
|
||||
variable.</p></li>
|
||||
<li><p>libpipewire has <code>#define SPA_ALIGNED</code> macro using gcc
|
||||
<code>aligned</code> attribute, but doesn't use it.</p></li>
|
||||
<li><p>libsleef has <code>#define ALIGNED</code> macro using gcc
|
||||
<code>aligned</code> attribute. It is not used for class or member
|
||||
declarations.</p></li>
|
||||
</ul>
|
||||
<h3 id="stdto_chars-and-stdfrom_chars"><code>std::to_chars()</code> and
|
||||
<code>std::from_chars</code></h3>
|
||||
<p>It is undecided whether to permit the use of
|
||||
<code>std::to_chars()</code> and <code>std::from_chars()</code> (<a
|
||||
href="http://wg21.link/p0067r5">p0067r5</a>).</p>
|
||||
<p>These functions provide low-level conversions between character
|
||||
sequences and numeric values. This seems like a good candidate for use
|
||||
in HotSpot, potentially replacing various clumsy or less performant
|
||||
alternatives. There is no memory allocation. Parsing failures are
|
||||
indicated via error codes rather than exceptions. Various other nice for
|
||||
HotSpot properties.</p>
|
||||
<p>Note that the published C++17 Standard puts these in
|
||||
<code><utility></code>, but a defect report moved them to
|
||||
<code><charconv></code>. This also needs
|
||||
<code><system_error></code>.</p>
|
||||
<p>This would require upgrading the minimum gcc version to 11.1 for
|
||||
floating point conversion support. The minimum Visual Studio version is
|
||||
already sufficient. The minimum clang version requirement hasn't been
|
||||
determined yet.</p>
|
||||
<h3 id="stdlaunder"><code>std::launder()</code></h3>
|
||||
<p>It is undecided whether to permit the use of
|
||||
<code>std::launder()</code> (<a
|
||||
href="http://wg21.link/p0137r1">p0137r1</a>).</p>
|
||||
<p>Change to permitted if we discover a place where we need it. Or maybe
|
||||
we should just permit it, but hope we don't need it.</p>
|
||||
<p>Also, C++20 revised the relevant part of Object Lifetime in a way
|
||||
that seems more permissive and with less need of laundering. We don't
|
||||
know if implementations of prior versions take advantage of the
|
||||
difference.</p>
|
||||
<p>See Object Lifetime: C++17 6.8/8, C++20 6.7.3/8</p>
|
||||
<h3 id="additional-undecided-features">Additional Undecided
|
||||
Features</h3>
|
||||
<ul>
|
||||
<li><p>Trailing return type syntax for functions (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm">n2541</a>)</p></li>
|
||||
<li><p>Variable templates (<a
|
||||
href="https://isocpp.org/files/papers/N3651.pdf">n3651</a>)</p></li>
|
||||
<li><p>Member initializers and aggregates (<a
|
||||
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html">n3653</a>)</p></li>
|
||||
<li><p>Rvalue references and move semantics</p></li>
|
||||
<li><p>Shorthand for nested namespaces (<a
|
||||
href="http://wg21.link/n4230">n4230</a>) — HotSpot makes very little use
|
||||
of namespaces, so this seemingly innocuous feature probably isn't useful
|
||||
to us.</p></li>
|
||||
<li><p>Direct list initialization with <code>auto</code> (<a
|
||||
href="http://wg21.link/n3681">n3681</a>) — This change fixed some issues
|
||||
with direct list initialization and <code>auto</code>. But we don't use
|
||||
that feature much, if at all. And perhaps shouldn't be using
|
||||
it.</p></li>
|
||||
<li><p>UTF-8 Character Literals (<a
|
||||
href="http://wg21.link/n4267">n4267</a>) — Do we have a use-case for
|
||||
this?</p></li>
|
||||
<li><p>Fold Expressions (<a href="http://wg21.link/n4295">n4295</a>) —
|
||||
Provides a simple way to apply operators to a parameter pack. HotSpot
|
||||
doesn't use variadic templates very much. That makes it questionable
|
||||
that developers should need to know about this feature. But if someone
|
||||
does come up with a good use-case, it's likely that the alternatives are
|
||||
significantly worse, because pack manipulation without this can be
|
||||
complicated.</p></li>
|
||||
<li><p><code>std::invoke<>()</code> (<a
|
||||
href="http://wg21.link/n4169">n4169</a>)</p></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -135,6 +135,17 @@ lines of code. Name what you must repeat.
|
||||
change should be done with a "setter" accessor matched to the simple
|
||||
"getter".
|
||||
|
||||
#### Conventions for Lock-free Code
|
||||
|
||||
Sometimes variables are accessed concurrently without appropriate synchronization
|
||||
context, such as a held mutex or at a safepoint. In such cases the variable should
|
||||
be declared `volatile` and it should NOT be accessed as a normal C++ lvalue. Rather,
|
||||
access should be performed via functions from `Atomic`, such as `Atomic::load`,
|
||||
`Atomic::store`, etc.
|
||||
|
||||
This special formulation makes it more clear to maintainers that the variable is
|
||||
accessed concurrently in a lock-free manner.
|
||||
|
||||
### Source Files
|
||||
|
||||
* All source files must have a globally unique basename. The build
|
||||
@ -366,20 +377,22 @@ adjust new lines horizontally to be consistent with that
|
||||
organization. (E.g., trailing backslashes on long macro definitions
|
||||
often align.)
|
||||
|
||||
### Avoid implicit conversions to bool
|
||||
|
||||
* Use `bool` for boolean values.
|
||||
* Do not use ints or pointers as (implicit) booleans with `&&`, `||`,
|
||||
`if`, `while`. Instead, compare explicitly, i.e. `if (x != 0)` or
|
||||
`if (ptr != nullptr)`, etc.
|
||||
* Do not use non-boolean declarations in _condition_ forms, i.e. don't use
|
||||
`if (T v = value) { ... }`. But see
|
||||
[Enhanced selection statements](#enhanced-selection-statements).
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* Use the [Resource Acquisition Is Initialization][RAII] (RAII)
|
||||
design pattern to manage bracketed critical
|
||||
sections. See class `ResourceMark` for an example.
|
||||
|
||||
* Avoid implicit conversions to `bool`.
|
||||
* Use `bool` for boolean values.
|
||||
* Do not use ints or pointers as (implicit) booleans with `&&`, `||`,
|
||||
`if`, `while`. Instead, compare explicitly, i.e. `if (x != 0)` or
|
||||
`if (ptr != nullptr)`, etc.
|
||||
* Do not use declarations in _condition_ forms, i.e. don't use
|
||||
`if (T v = value) { ... }`.
|
||||
|
||||
* Use functions from globalDefinitions.hpp and related files when
|
||||
performing bitwise
|
||||
operations on integers. Do not code directly as C operators, unless
|
||||
@ -391,18 +404,17 @@ they are extremely simple. (Examples: `align_up`, `is_power_of_2`,
|
||||
* Always enumerate all cases in a switch statement or provide a default
|
||||
case. It is ok to have an empty default with comment.
|
||||
|
||||
|
||||
## Use of C++ Features
|
||||
|
||||
HotSpot was originally written in a subset of the C++98/03 language.
|
||||
More recently, support for C++14 is provided, though again,
|
||||
More recently, support for C++17 is provided, though again,
|
||||
HotSpot only uses a subset. (Backports to JDK versions lacking
|
||||
support for more recent Standards must of course stick with the
|
||||
original C++98/03 subset.)
|
||||
|
||||
This section describes that subset. Features from the C++98/03
|
||||
language may be used unless explicitly excluded here. Features from
|
||||
C++11 and C++14 may be explicitly permitted or explicitly excluded,
|
||||
C++11, C++14, and C++17 may be explicitly permitted or explicitly excluded,
|
||||
and discussed accordingly here. There is a third category, undecided
|
||||
features, about which HotSpot developers have not yet reached a
|
||||
consensus, or perhaps have not discussed at all. Use of these
|
||||
@ -417,9 +429,9 @@ more extensive discussion or rationale for limitations. Features that
|
||||
don't have their own subsection are listed in omnibus feature sections
|
||||
for permitted, excluded, and undecided features.
|
||||
|
||||
Lists of new features for C++11 and C++14, along with links to their
|
||||
Lists of new features for C++11, C++14, and C++17, along with links to their
|
||||
descriptions, can be found in the online documentation for some of the
|
||||
compilers and libraries. The C++14 Standard is the definitive
|
||||
compilers and libraries. The C++17 Standard is the definitive
|
||||
description.
|
||||
|
||||
* [C++ Standards Support in GCC](https://gcc.gnu.org/projects/cxx-status.html)
|
||||
@ -624,13 +636,41 @@ For local variables, this can be used to make the code clearer by
|
||||
eliminating type information that is obvious or irrelevant. Excessive
|
||||
use can make code much harder to understand.
|
||||
|
||||
* `auto` for non-type template parameters
|
||||
([p0127r2](http://wg21.link/p0127r2))<br>
|
||||
`auto` may be used as a placeholder for the type of a non-type template
|
||||
parameter. The type is deduced from the value provided in a template
|
||||
instantiation.
|
||||
|
||||
<a name="function-return-type-deduction"></a>
|
||||
* Function return type deduction
|
||||
([n3638](https://isocpp.org/files/papers/N3638.html))<br>
|
||||
Only use if the function body has a very small number of `return`
|
||||
statements, and generally relatively little other code.
|
||||
|
||||
* Class template argument deduction
|
||||
([n3602](http://wg21.link/n3602), [p0091r3](http://wg21.link/p0091r3))<br>
|
||||
The template arguments of a class template may be deduced from the arguments
|
||||
to a constructor. This is similar to ordinary function argument deduction,
|
||||
though partial deduction with only _some_ template arguments explicitly
|
||||
provided is not permitted for class template argument deduction. Deduction
|
||||
guides may be used to provide additional control over the deduction. As with
|
||||
`auto` variable declarations, excessive use can make code harder to
|
||||
understand, because explicit type information is lacking. But it can also
|
||||
remove the need to be explicit about types that are either obvious, or that
|
||||
are very hard to write. For example, these allow the addition of a scope-guard
|
||||
mechanism with nice syntax; something like this
|
||||
```
|
||||
ScopeGuard guard{[&]{ ... cleanup code ... }};
|
||||
```
|
||||
|
||||
* Also see [lambda expressions](#lambdaexpressions).
|
||||
|
||||
* `decltype(auto)` should be avoided, whether for variables, for non-type
|
||||
template parameters, or for function return types. There are subtle and
|
||||
complex differences between this placeholder type and `auto`. Any use would
|
||||
need very careful explanation.
|
||||
|
||||
### Expression SFINAE
|
||||
|
||||
[Substitution Failure Is Not An Error][SFINAE] (SFINAE)
|
||||
@ -652,6 +692,52 @@ Here are a few closely related example bugs:<br>
|
||||
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95468><br>
|
||||
<https://developercommunity.visualstudio.com/content/problem/396562/sizeof-deduced-type-is-sometimes-not-a-constant-ex.html>
|
||||
|
||||
### Trailing return type syntax for functions
|
||||
|
||||
A function's return type may be specified after the parameters and qualifiers
|
||||
([n2541](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm)).
|
||||
In such a declaration the normal return type is `auto` and the return type is
|
||||
indicated by `->` followed by the type. Although both use `auto` in the
|
||||
"normal" leading return type position, this differs from
|
||||
[function return type deduction](#function-return-type-deduction),
|
||||
in that the return type is explicit rather than deduced, but specified in a
|
||||
trailing position.
|
||||
|
||||
Use of trailing return types is permitted. However, the normal, leading
|
||||
position for the return type is preferred. A trailing return type should only
|
||||
be used where it provides some benefit. Such benefits usually arise because a
|
||||
trailing return type is in a different scope than a leading return type.
|
||||
|
||||
* If the function identifier is a nested name specifier, then the trailing
|
||||
return type occurs in the nested scope. This may permit simpler naming in the
|
||||
return type because of the different name lookup context.
|
||||
|
||||
* The trailing return type is in the scope of the parameters, making their
|
||||
types accessible via `decltype`. For example
|
||||
```
|
||||
template<typename T, typename U> auto add(T t, U u) -> decltype(t + u);
|
||||
```
|
||||
rather than
|
||||
```
|
||||
template<typename T, typename U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
|
||||
```
|
||||
|
||||
* Complex calculated leading return types may obscure the normal syntactic
|
||||
boundaries, making it more difficult for a reader to find the function name and
|
||||
parameters. This is particularly common in cases where the return type is
|
||||
being used for [SFINAE]. A trailing return type may be preferable in such
|
||||
situations.
|
||||
|
||||
### Non-type template parameter values
|
||||
|
||||
C++17 extended the arguments permitted for non-type template parameters
|
||||
([n4268](http://wg21.link/n4268)). The kinds of values (the parameter types)
|
||||
aren't changed. However, the values can now be the result of arbitrary
|
||||
constant expressions (with a few restrictions on the result), rather than a
|
||||
much more limited and restrictive set of expressions. In particular, the
|
||||
argument for a pointer or reference type parameter can now be the result of a
|
||||
constexpr function.
|
||||
|
||||
### enum
|
||||
|
||||
Where appropriate, _scoped-enums_ should be used.
|
||||
@ -770,6 +856,39 @@ ordering, which may differ from (may be stronger than) sequentially
|
||||
consistent. There are algorithms in HotSpot that are believed to rely
|
||||
on that ordering.
|
||||
|
||||
### Variable Templates and Inline Variables
|
||||
|
||||
The use of variable templates (including static data member templates)
|
||||
([N3651](https://wg21.link/N3651)) is permitted. They provide parameterized
|
||||
variables and constants in a simple and direct form, instead of requiring the
|
||||
use of various workarounds.
|
||||
|
||||
Variables with static storage duration and variable templates may be declared
|
||||
`inline` ([p0386r2](https://wg21.link/p0386r2)), and this usage is
|
||||
permitted. This has similar effects as for declaring a function inline: it can
|
||||
be defined, identically, in multiple translation units, must be defined in
|
||||
every translation unit in which it is [ODR used][ODR], and the behavior of the
|
||||
program is as if there is exactly one variable.
|
||||
|
||||
Declaring a variable inline allows the complete definition to be in a header
|
||||
file, rather than having a declaration in a header and the definition in a
|
||||
.cpp file. The guidance on
|
||||
[initialization](#initializing-variables-with-static-storage-duration) of such
|
||||
variables still applies. Inline variables with dynamic initializations can
|
||||
make initialization order problems worse. The few ordering constraints
|
||||
that exist for non-inline variables don't apply, as there isn't a single
|
||||
program-designated translation unit containing the definition.
|
||||
|
||||
A `constexpr` static data member or static data member template
|
||||
is implicitly `inline`. As a consequence, an
|
||||
[ODR use][ODR] of such a member doesn't require a definition in some .cpp
|
||||
file. (This is a change from pre-C++17. Beginning with C++17, such a
|
||||
definition is considered a duplicate definition, and is deprecated.)
|
||||
|
||||
Declaring a `thread_local` variable template or `inline` variable is forbidden
|
||||
in HotSpot code. [The use of `thread_local`](#thread_local) is already
|
||||
heavily restricted.
|
||||
|
||||
### Initializing variables with static storage duration
|
||||
|
||||
Variables with static storage duration and _dynamic initialization_
|
||||
@ -813,6 +932,53 @@ Some relevant sections from cppreference.com:
|
||||
Although related, the use of `std::initializer_list` remains forbidden, as
|
||||
part of the avoidance of the C++ Standard Library in HotSpot code.
|
||||
|
||||
### Mandatory Copy Elision
|
||||
|
||||
[Copy elision](https://en.wikipedia.org/wiki/Copy_elision)
|
||||
(or [here](https://cn.cppreference.com/w/cpp/language/copy_elision.html))
|
||||
is a compiler optimization used to avoid potentially expensive copies in
|
||||
certain situations. It is critical to making practical the performance of
|
||||
return by value or pass by value. It is also unusual in not following the
|
||||
as-if rule for optimizations - copy elision can be applied even if doing so
|
||||
bypasses side-effects of copying/moving the object. The C++ standard
|
||||
explicitly permits this.
|
||||
|
||||
However, because it's an optional optimization, the relevant copy/move
|
||||
constructor must be available and accessible, in case the compiler chooses to
|
||||
not apply the optimization even in a situation where permitted.
|
||||
|
||||
C++17 changed some cases of copy elision so that there is never a copy/move in
|
||||
these cases ([p0135r1](http://wg21.link/p0135r1)). The interesting cases
|
||||
involve a function that returns an unnamed temporary object, and constructors.
|
||||
In such cases the object being initialized from the temporary is always direct
|
||||
initialized, with no copy/move ever involved; see [RVO] and more specifically
|
||||
[URVO].
|
||||
|
||||
Since this is now standard behavior it can't be avoided in the covered
|
||||
situations. This could change the behavior of code that relied on side effects
|
||||
by constructors, but that's both uncommon and was already problematic because
|
||||
of the previous optional copy elision. But HotSpot code can, and should,
|
||||
explicitly take advantage of this newly required behavior where it makes sense
|
||||
to do so.
|
||||
|
||||
For example, it may be beneficial to delay construction of the result of a
|
||||
function until the return statement, rather than having a local variable that
|
||||
is modified into the desired state and then returned. (Though [NRVO] may apply
|
||||
in that case.)
|
||||
|
||||
It is also now possible to define a factory function for a class that is
|
||||
neither movable nor copyable, if it can be written in a way that makes use of
|
||||
this feature.
|
||||
|
||||
[RVO]: https://en.wikipedia.org/wiki/Copy_elision#RVO
|
||||
"Return Value Optimization"
|
||||
|
||||
[NRVO]: https://en.wikipedia.org/wiki/Copy_elision#NRVO
|
||||
"Named Return Value Optimization"
|
||||
|
||||
[URVO]: https://cn.cppreference.com/w/cpp/language/copy_elision.html
|
||||
"Unnamed Return Value Optimization"
|
||||
|
||||
### Local Function Objects
|
||||
|
||||
* Local function objects, including lambda expressions, may be used.
|
||||
@ -881,6 +1047,12 @@ Another use for local functions is [partial application][PARTIALAPP]. Again
|
||||
here, lambdas are typically much simpler and less verbose than function
|
||||
object classes.
|
||||
|
||||
A lambda is a constexpr function if either the parameter declaration clause is
|
||||
followed by `constexpr`, or it satisfies the requirements for a constexpr
|
||||
function ([p0170r1]). Thus, using a lambda to package up some computation
|
||||
doesn't incur unnecessary overhead or prevent use in a context required to be
|
||||
compile-time evaluated (such as an array size).
|
||||
|
||||
Because of these benefits, lambda expressions are permitted in HotSpot code,
|
||||
with some restrictions and usage guidance. An anonymous lambda is one which
|
||||
is passed directly as an argument. A named lambda is the value of a
|
||||
@ -932,6 +1104,17 @@ the most part they don't apply to HotSpot code, given other usage restrictions.
|
||||
applies to captured auto variables, not member variables, and is
|
||||
inconsistent with referential transparency.
|
||||
|
||||
* By-value capture of `this` (using a capture list like `[*this]` ([p0018r3]))
|
||||
is also not permitted. One of the motivating use-cases is when the lifetime of
|
||||
the lambda exceeds the lifetime of the object for the containing member
|
||||
function. That is, we have an upward lambda that is capturing `this` of the
|
||||
enclosing method. But again, that use-case doesn't apply if only downward
|
||||
lambdas are used.
|
||||
Another use-case is when we simply want the lambda to be operating on a copy
|
||||
of `this` for some reason. This is sufficiently uncommon that it can be
|
||||
handled by manual copying, so readers don't need to understand this rare
|
||||
syntax.
|
||||
|
||||
* Non-capturing lambdas (with an empty capture list - `[]`) have limited
|
||||
utility. There are cases where no captures are required (pure functions,
|
||||
for example), but if the function is small and simple then that's obvious
|
||||
@ -941,7 +1124,7 @@ anyway.
|
||||
Capture initializers inherently increase the complexity of the capture list,
|
||||
and provide little benefit over an additional in-scope local variable.
|
||||
|
||||
The use of `mutable` lambda expressions is forbidden because there don't
|
||||
* The use of `mutable` lambda expressions is forbidden because there don't
|
||||
seem to be many, if any, good use-cases for them in HotSpot. A lambda
|
||||
expression needs to be mutable in order to modify a by-value captured value.
|
||||
But with only downward lambdas, such usage seems likely to be rare and
|
||||
@ -1088,21 +1271,12 @@ Do not use _inheriting constructors_
|
||||
C++11 provides simple syntax allowing a class to inherit the constructors of a
|
||||
base class. Unfortunately there are a number of problems with the original
|
||||
specification, and C++17 contains significant revisions ([p0136r1] opens with
|
||||
a list of 8 Core Issues). Since HotSpot doesn't support use of C++17, use of
|
||||
inherited constructors could run into those problems. Such uses might also
|
||||
change behavior in a future HotSpot update to use C++17 or later, potentially
|
||||
in subtle ways that could lead to hard to diagnose problems. Because of this,
|
||||
HotSpot code must not use inherited constructors.
|
||||
a list of 8 Core Issues). Although those issues have been addressed, the
|
||||
benefits from this feature are small compared to the complexity. Because of
|
||||
this, HotSpot code must not use inherited constructors.
|
||||
|
||||
Note that gcc7 provides the `-fnew-inheriting-ctors` option to use the
|
||||
[p0136r1] semantics. This is enabled by default when using C++17 or later.
|
||||
It is also enabled by default for `fabi-version=11` (introduced by gcc7) or
|
||||
higher when using C++11/14, as the change is considered a Defect Report that
|
||||
applies to those versions. Earlier versions of gcc don't have that option,
|
||||
and other supported compilers may not have anything similar.
|
||||
|
||||
[p0136r1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html
|
||||
"p0136r1"
|
||||
[p0136r1]: http:/wg21.link/p0136r1 "p0136r1"
|
||||
[p0195r0](http://wg21.link/p0195r0)
|
||||
|
||||
### Attributes
|
||||
|
||||
@ -1121,15 +1295,39 @@ preferred location.
|
||||
function's declaration, rather than between the function name and the parameter
|
||||
list.
|
||||
|
||||
[p0068r0](http://wg21.link/p0068r0) is the initial proposal for the attributes
|
||||
added by C++17.)
|
||||
|
||||
Only the following attributes are permitted:
|
||||
|
||||
* `[[noreturn]]`
|
||||
* `[[nodiscard]]` ([p0189r1](http://wg21.link/p0189r1))
|
||||
* `[[maybe_unused]]` ([p0212r1](http://wg21.link/p0212r1))
|
||||
* `[[fallthrough]]` ([p0188r1](http://wg21.link/p0188))
|
||||
|
||||
The following attributes are expressly forbidden:
|
||||
|
||||
* `[[carries_dependency]]` - Related to `memory_order_consume`.
|
||||
* `[[deprecated]]` - Not relevant in HotSpot code.
|
||||
|
||||
Direct use of non-standard (and presumably scoped) attributes in shared code
|
||||
is also forbidden. Using such would depend on the C++17 feature that an
|
||||
attribute not recognized by the implementation is ignored
|
||||
([p0283r2](http://wg21.link/p0283r2)). If such an attribute is needed in
|
||||
shared code, the well-established technique of providing an `ATTRIBUTE_XXX`
|
||||
macro with per-compiler definitions (sometimes empty) should be
|
||||
used. Compilers may warn about unrecognized attributes (whether by name or by
|
||||
location), in order to report typos or misuse. Disabling such warnings
|
||||
globally would not be desirable.
|
||||
|
||||
The use of `using` directives in attribute lists is also forbidden.
|
||||
([p0028r0](http://wg21.link/p0028r0))
|
||||
([p0028r4](http://wg21.link/p0028r4))
|
||||
We don't generally use scoped attributes in attribute lists with other
|
||||
attributes. Rather, uses of scoped attributes (which are implementation
|
||||
defined) are generally hidden behind a portability macro that includes the
|
||||
surrounding brackets.
|
||||
|
||||
### noexcept
|
||||
|
||||
Use of `noexcept` exception specifications
|
||||
@ -1178,9 +1376,79 @@ HotSpot code can assume no exceptions will ever be thrown, even from functions
|
||||
not declared `noexcept`. So HotSpot code doesn't ever need to check, either
|
||||
with conditional exception specifications or with `noexcept` expressions.
|
||||
|
||||
The exception specification is part of the type of a function
|
||||
([p0012r1](http://wg21.link/p0012r1). This likely has little impact on HotSpot
|
||||
code, since the use of `noexcept` is expected to be rare.
|
||||
|
||||
Dynamic exception specifications were deprecated in C++11. C++17 removed all
|
||||
but `throw()`, with that remaining a deprecated equivalent to `noexcept`.
|
||||
|
||||
### Enhanced selection statements
|
||||
|
||||
C++17 modified the _condition_ part of `if` and `switch` statements, permitting
|
||||
an _init-statement_ to be included
|
||||
([p0305r1](http://wg21.link/p0305r1)).
|
||||
|
||||
Use of this feature is permitted. (However, complex uses may interfere with
|
||||
readability.) Limiting the scope of a variable involved in the condition,
|
||||
while also making the value available to the statement's body, can improve
|
||||
readability. The alternative method of scope-limiting by introducing a nested
|
||||
scope isn't very popular and is rarely used.
|
||||
|
||||
This new syntax is in addition to the _condition_ being a declaration with a
|
||||
_brace-or-equal-initializer_. For an `if` statement this new sytax gains that
|
||||
benefit without violating the long-standing guidance against using
|
||||
[implicit conversions to `bool`](#avoid-implicit-conversions-to-bool),
|
||||
which still stands.
|
||||
|
||||
For example, uses of Unified Logging sometimes explicitly check whether a
|
||||
`LogTarget` is enabled. Instead of
|
||||
```
|
||||
LogTarget(...) lt;
|
||||
if (lt.is_enabled()) {
|
||||
LogStream log(lt);
|
||||
... use log ...
|
||||
}
|
||||
... lt is accessible but probably not needed here ...
|
||||
```
|
||||
using this feature one could write
|
||||
```
|
||||
if (LogTarget(...) lt; lt.is_enabled()) {
|
||||
LogStream log(lt);
|
||||
... use log ...
|
||||
}
|
||||
```
|
||||
|
||||
C++17 also added compile-time `if` statements
|
||||
([p0292r2](http://wg21.link/p0292r2)). Use of `if constexpr` is
|
||||
permitted. This feature can replace and (sometimes vastly) simplify many uses
|
||||
of [SFINAE]. The same declaration and initialization guidance for the
|
||||
_condition_ part apply here as for ordinary `if` statements.
|
||||
|
||||
### Expression Evaluation Order
|
||||
|
||||
C++17 tightened up the evaluation order for some kinds of subexpressions
|
||||
([p0138r2](http://wg21.link/p0138r2)). Note, however, that the Alternate
|
||||
Evaluation Order for Function Calls alternative in that paper was adopted,
|
||||
rather than the strict left to right order of evaluation for function call
|
||||
arguments that was proposed in the main body of the paper.
|
||||
|
||||
The primary purpose of this change seems to be to make certain kinds of call
|
||||
chaining well defined. That's not a style widely used in HotSpot. In general
|
||||
it is better to continue to avoid questions in this area by isolating
|
||||
operations with side effects from other statements. In particular, continue to
|
||||
avoid modifying a value in an expression where it is also used.
|
||||
|
||||
### Compatibility with C11
|
||||
|
||||
C++17 refers to C11 rather than C99. This means that C11 libraries and
|
||||
functions may be used in HotSpot. There may be limitations because of
|
||||
differing levels of compatibility among various compilers and versions of
|
||||
those compilers.
|
||||
|
||||
Note that the C parts of the JDK have been built with C11 selected for some
|
||||
time ([JDK-8292008](https://bugs.openjdk.org/browse/JDK-8292008)).
|
||||
|
||||
### Additional Permitted Features
|
||||
|
||||
* `alignof`
|
||||
@ -1198,7 +1466,10 @@ but `throw()`, with that remaining a deprecated equivalent to `noexcept`.
|
||||
([n2555](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf))
|
||||
|
||||
* Static assertions
|
||||
([n1720](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html))
|
||||
([n1720](http://wg21.link/n1720))
|
||||
([n3928](http://wg21.link/n3928))<br>
|
||||
Both the original (C++11) two-argument form and the new (C++17)
|
||||
single-argument form are permitted.
|
||||
|
||||
* `decltype`
|
||||
([n2343](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf))
|
||||
@ -1245,7 +1516,72 @@ but `throw()`, with that remaining a deprecated equivalent to `noexcept`.
|
||||
* Unrestricted Unions
|
||||
([n2544](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf))
|
||||
|
||||
### Excluded Features
|
||||
* Preprocessor Condition `__has_include`
|
||||
([p0061r0](http://wg21.link/p0061r0))
|
||||
([p0061r1](http://wg21.link/p0061r1))
|
||||
|
||||
* Hexadecimal Floating-Point Literals
|
||||
([p0245r1](http://wg21.link/p0245r1))
|
||||
|
||||
* Construction Rules for `enum class` Values
|
||||
([p0138r2](http://wg21.link/p0138r2))
|
||||
|
||||
* Allow `typename` in template template parameter
|
||||
([n4051](http://wg21.link/n4051)) — template template parameters are
|
||||
barely used (if at all) in HotSpot, but there's no reason to artificially
|
||||
disallow this syntactic regularization in any such uses.
|
||||
|
||||
## Excluded Features
|
||||
|
||||
### Structured Bindings
|
||||
|
||||
The use of structured bindings [p0217r3](http://wg21.link/p0217r3) is
|
||||
forbidden. Preferred approaches for handling functions with multiple return
|
||||
values include
|
||||
|
||||
* Return a named class/struct intended for that purpose, with named and typed
|
||||
members/accessors.
|
||||
|
||||
* Return a value along with out parameters (usually pointers, sometimes
|
||||
references).
|
||||
|
||||
* Designate a sentinel "failure" value in the normal return value type, with
|
||||
some out of band location for additional information. For example, this is
|
||||
the model typically used with `errno`, where a function returns a normal
|
||||
result, or -1 to indicate an error, with additional error information in
|
||||
`errno`.
|
||||
|
||||
There is a strong preference for names and explicit types, as opposed to
|
||||
offsets and implicit types. For example, there are folks who strongly dislike
|
||||
that some of the Standard Library functions return `std::pair` because `first`
|
||||
and `second` members don't carry any useful information.
|
||||
|
||||
### File System Library
|
||||
|
||||
The use of the File System library is forbidden. HotSpot doesn't do very much
|
||||
with files, and already has adequate mechanisms for its needs. Rewriting in
|
||||
terms of this new library doesn't provide any obviously significant
|
||||
benefits. Having a mix of the existing usage and uses of this new library
|
||||
would be confusing.
|
||||
|
||||
[n4100](http://wg21.link/n4100)
|
||||
[p0218r0](http://wg21.link/p0218r0)
|
||||
[p0219r1](http://wg21.link/p0219r1)
|
||||
[p0317r1](http://wg21.link/p0317r1)
|
||||
[p0392r0](http://wg21.link/p0392r0)
|
||||
[p0430r2](http://wg21.link/p0430r2)
|
||||
[p0492r2](http://wg21.link/p0492r2)
|
||||
[p1164r1](http://wg21.link/p1164r1)
|
||||
|
||||
### Aggregate Extensions
|
||||
|
||||
Aggregates with base classes are forbidden. C++17 allows aggregate
|
||||
initialization for classes with base classes
|
||||
([p0017r1](https://wg21.link/p0017r1)). HotSpot makes very little use of
|
||||
aggregate classes, preferring explicit constructors even for very simple
|
||||
classes.
|
||||
|
||||
### Additional Excluded Features
|
||||
|
||||
* New string and character literals
|
||||
* New character types
|
||||
@ -1281,27 +1617,277 @@ operator overloading is used, ensure the semantics conform to the
|
||||
normal expected behavior of the operation.
|
||||
|
||||
* Avoid most implicit conversion constructors and (implicit or explicit)
|
||||
conversion operators. (Note that conversion to `bool` isn't needed
|
||||
in HotSpot code because of the "no implicit boolean" guideline.)
|
||||
conversion operators. Conversion to `bool` operators aren't needed
|
||||
because of the
|
||||
[no implicit boolean](#avoid-implicit-conversions-to-bool)
|
||||
guideline.)
|
||||
|
||||
* Avoid `goto` statements.
|
||||
|
||||
### Undecided Features
|
||||
* Attributes for namespaces and enumerators
|
||||
([n4266](http://wg21.link/n4266) —
|
||||
The only applicable attribute is [`[[deprecated]]`](#attributes), which is
|
||||
forbidden.
|
||||
|
||||
* Variadic `using` declarations
|
||||
([p0195r2](http://wg21.link/p0195r2))
|
||||
|
||||
* `std::variant<>`
|
||||
([p0088r3](http://wg21.link/p0088r3)) —
|
||||
Even if more of the C++ Standard Library is permitted, this class will remain
|
||||
forbidded. Invalid accesses are indicated by throwing exceptions.
|
||||
|
||||
* `std::any`
|
||||
([p0220r1](http://wg21.link/p0220r1)) —
|
||||
Even if more of the C++ Standard Library is permitted, this class will remain
|
||||
forbidden. It may require allocation, and always uses the standard
|
||||
allocator. It requires [RTTI].
|
||||
|
||||
* `std::as_const()`
|
||||
([p0007r1](http://wg21.link/p0007r1)) —
|
||||
If sufficiently useful, HotSpot could add such a function. It would likely be
|
||||
added to globalDefinitions.hpp, where there are already some similar small
|
||||
utilities.
|
||||
|
||||
* `std::clamp()`
|
||||
([p002501](http://wg21.link/p002501)) —
|
||||
This function is already provided in globalDefinitions.hpp.
|
||||
|
||||
* Parallel STL Algorithms
|
||||
([p0024r2](http://wg21.link/p0024r2)) —
|
||||
Even if more of the C++ Standard Library is permitted, these will remain
|
||||
forbidden. They are built on the standard C++ threading mechanisms. HotSpot
|
||||
doesn't use those mechanisms, instead providing and using its own.
|
||||
|
||||
* Cache Line Sizes
|
||||
[p0154r1](http://wg21.link/p0154r1) —
|
||||
HotSpot has its own mechanisms for this, using values like
|
||||
`DEFAULT_CACHE_LINE_SIZE`. The platform-specific implementation of the HotSpot
|
||||
mechanisms might use these library functions, but there is no reason to move
|
||||
away from the current approach. Quoting from [JOSUTTIS]: "... if you know better,
|
||||
use specific values, but using these values is better than any assumed fixed
|
||||
size for code supporting multiple platforms."
|
||||
|
||||
* `register` storage class removal
|
||||
[p0001r1](http://wg21.link/p0001r1) —
|
||||
The `register` storage class has been removed. `register` is still a keyword,
|
||||
so still can't be used for normal purposes. Also, this doesn't affect the use
|
||||
of `register` for gcc-style extended asm code; that's a different syntactic
|
||||
element with a different meaning.
|
||||
|
||||
* Value of `__cplusplus` —
|
||||
Testing whether `__cplusplus` is defined or not is permitted, and indeed
|
||||
required. But the value should not need to be examined. The value is changed
|
||||
with each revision of the Standard. But we build HotSpot and (most of) the
|
||||
rest of the JDK with a specifically selected version of the Standard. The
|
||||
value of `__cplusplus` should be known and unchanging until we change the
|
||||
project's build configuration again. So examining the value shouldn't ever be
|
||||
necessary.
|
||||
|
||||
* Removal of `++` for `bool`
|
||||
([p0003r1](http://wg21.link/p0003r1))
|
||||
|
||||
* Removal of trigraphs
|
||||
([n4086](http://wg21.link/n4086))
|
||||
|
||||
## Undecided Features
|
||||
|
||||
This list is incomplete; it serves to explicitly call out some
|
||||
features that have not yet been discussed.
|
||||
|
||||
Some features are undecided (so implicitly forbidden) because we don't expect
|
||||
to use them at all. This might be reconsidered if someone finds a good use
|
||||
case.
|
||||
|
||||
Some Standard Library features are undecided (so implicitly forbidden)
|
||||
because, while this Style Guide forbids the use of such, they may be
|
||||
sufficiently useful that we want to permit them anyway. Doing so may require
|
||||
some idiomatic mechanism for addressing things like `assert` incompatibility,
|
||||
incompatibility with HotSpot's `FORBID_C_FUNCTION` mechanism, and the like.
|
||||
|
||||
### std::optional<>
|
||||
|
||||
It is undecided whether to permit the use of `std::optional<>`
|
||||
([p0220r1](http://wg21.link/p0220r1)). It may be sufficiently useful that it
|
||||
should be permitted despite the usual prohibition against using Standard
|
||||
Library facilities. Use of the `value()` member function must be forbidden, as
|
||||
it reports an invalid access by throwing an exception.
|
||||
|
||||
### std::byte
|
||||
|
||||
It is undecided whether to permit the use of the `std::byte` type
|
||||
([p0298r3](http://wg21.link/p0298r3)). It may be sufficiently useful that it
|
||||
should be permitted despite the usual prohibition against using Standard
|
||||
Library facilities.
|
||||
|
||||
It has been suggested that changing the HotSpot `address` type to use
|
||||
`std::byte` has some benefits. That is, replace
|
||||
```
|
||||
typedef u_char* address;
|
||||
typedef const u_char* const_address;
|
||||
```
|
||||
```
|
||||
using address = std::byte*;
|
||||
using const_address = const std::byte*;
|
||||
```
|
||||
in globalDefinitions.hpp.
|
||||
|
||||
A specific benefit that was mentioned is that it might improve the horrible
|
||||
way that gdb handles our current definition of the `address` type.
|
||||
```
|
||||
#include <cstddef>
|
||||
|
||||
typedef unsigned char* address;
|
||||
typedef std::byte* address_b;
|
||||
|
||||
int main() {
|
||||
|
||||
char* mem;
|
||||
|
||||
address addr = (address)mem;
|
||||
address_b addr_b = (address_b)mem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
(gdb) p addr
|
||||
$1 = (address) 0x7ffff7fe4fa0 <dl_main> "\363\017\036\372Uf\017\357\300H\211\345AWI\211\377AVAUATSH\201\354\210\002"
|
||||
(gdb) p addr_b
|
||||
$2 = (address_b) 0x7ffff7fe4fa0 <dl_main>
|
||||
```
|
||||
|
||||
This needs to be explored. Some folks have said they will do so.
|
||||
|
||||
### String Views
|
||||
|
||||
It is undecided whether to permit the use of `std::string_view`
|
||||
([p0220r1](http://wg21.link/p0220r1)).
|
||||
|
||||
HotSpot doesn't use `std::string`, but uses `char*` strings a lot. Wrapping
|
||||
such in a `std::string_view` to enable the use of various algorithms could be
|
||||
useful. But since HotSpot also doesn't permit use of `<algorithm>` and the
|
||||
like, that only gets the limited set of algorithms provided by the view class
|
||||
directly.
|
||||
|
||||
There is also the issue of `NUL` termination; string views are not necessarily
|
||||
`NUL` terminated. Moreover, if one goes to the work of making one that is
|
||||
`NUL` terminated, that terminator is included in the size.
|
||||
|
||||
There are other caveats. Permitting use of string views would require
|
||||
discussion of those.
|
||||
|
||||
### Substring and Subsequence Searching
|
||||
|
||||
In addition to simple substring searching, the Standard Library now includes
|
||||
Boyer-Moore and Boyer-Moore-Horspool searchers, in case someone wants to
|
||||
search really large texts. That seems an unlikely use-case for HotSpot. See
|
||||
[p0220r1](http://wg21.link/p0220r1).
|
||||
|
||||
### `new` and `delete` with Over-Aligned Data
|
||||
|
||||
It is undecided whether to permit the use of dynamic allocation of overaligned
|
||||
types ([n3396](http://wg21.link/n3396)).
|
||||
|
||||
HotSpot currently only has a couple of over-aligned types that are dynamically
|
||||
allocated. These are handled manually, not going through `new` expressions, as
|
||||
that couldn't work before C++17.
|
||||
|
||||
One of the ways an over-aligned type might arise is by aligning a data member.
|
||||
This might be done to avoid destructive interference for concurrent accesses.
|
||||
But HotSpot uses a different approach, using explicit padding. Again, this is
|
||||
in part because `new` and `delete` of overaligned types didn't work. But we
|
||||
might prefer to continue this approach.
|
||||
|
||||
We would need to add `operator new` overloads to `CHeapObj<>` and possibly in
|
||||
other places in order to support this. However, it has been suggested that
|
||||
implementing it (efficiently) on top of NMT might be difficult. Note that
|
||||
`posix_memalign` / `_aligned_malloc` don't help here, because of NMT's use of
|
||||
malloc headers.
|
||||
|
||||
If we don't support it we may want to add `operator new` overloads that are
|
||||
deleted, to prevent attempted uses.
|
||||
|
||||
Alignment usage in non-HotSpot parts of the OpenJDK:
|
||||
|
||||
* `alignas` used once in harfbuzz, to align a variable.
|
||||
|
||||
* libpipewire has `#define SPA_ALIGNED` macro using gcc `aligned` attribute,
|
||||
but doesn't use it.
|
||||
|
||||
* libsleef has `#define ALIGNED` macro using gcc `aligned` attribute. It is
|
||||
not used for class or member declarations.
|
||||
|
||||
### `std::to_chars()` and `std::from_chars`
|
||||
|
||||
It is undecided whether to permit the use of `std::to_chars()` and
|
||||
`std::from_chars()` ([p0067r5](http://wg21.link/p0067r5)).
|
||||
|
||||
These functions provide low-level conversions between character sequences and
|
||||
numeric values. This seems like a good candidate for use in HotSpot,
|
||||
potentially replacing various clumsy or less performant alternatives. There is
|
||||
no memory allocation. Parsing failures are indicated via error codes rather
|
||||
than exceptions. Various other nice for HotSpot properties.
|
||||
|
||||
Note that the published C++17 Standard puts these in `<utility>`, but a defect
|
||||
report moved them to `<charconv>`. This also needs `<system_error>`.
|
||||
|
||||
This would require upgrading the minimum gcc version to 11.1 for floating
|
||||
point conversion support. The minimum Visual Studio version is already
|
||||
sufficient. The minimum clang version requirement hasn't been determined yet.
|
||||
|
||||
### `std::launder()`
|
||||
|
||||
It is undecided whether to permit the use of `std::launder()`
|
||||
([p0137r1](http://wg21.link/p0137r1)).
|
||||
|
||||
Change to permitted if we discover a place where we need it. Or maybe we
|
||||
should just permit it, but hope we don't need it.
|
||||
|
||||
Also, C++20 revised the relevant part of Object Lifetime in a way that seems
|
||||
more permissive and with less need of laundering. We don't know if
|
||||
implementations of prior versions take advantage of the difference.
|
||||
|
||||
See Object Lifetime: C++17 6.8/8, C++20 6.7.3/8
|
||||
|
||||
### Additional Undecided Features
|
||||
|
||||
* Trailing return type syntax for functions
|
||||
([n2541](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm))
|
||||
|
||||
* Variable templates
|
||||
([n3651](https://isocpp.org/files/papers/N3651.pdf))
|
||||
|
||||
* Member initializers and aggregates
|
||||
([n3653](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html))
|
||||
|
||||
* Rvalue references and move semantics
|
||||
|
||||
* Shorthand for nested namespaces
|
||||
([n4230](http://wg21.link/n4230)) —
|
||||
HotSpot makes very little use of namespaces, so this seemingly innocuous
|
||||
feature probably isn't useful to us.
|
||||
|
||||
* Direct list initialization with `auto`
|
||||
([n3681](http://wg21.link/n3681)) —
|
||||
This change fixed some issues with direct list initialization and `auto`. But
|
||||
we don't use that feature much, if at all. And perhaps shouldn't be using it.
|
||||
|
||||
* UTF-8 Character Literals
|
||||
([n4267](http://wg21.link/n4267)) —
|
||||
Do we have a use-case for this?
|
||||
|
||||
* Fold Expressions
|
||||
([n4295](http://wg21.link/n4295)) —
|
||||
Provides a simple way to apply operators to a parameter pack. HotSpot doesn't
|
||||
use variadic templates very much. That makes it questionable that developers
|
||||
should need to know about this feature. But if someone does come up with a
|
||||
good use-case, it's likely that the alternatives are significantly worse,
|
||||
because pack manipulation without this can be complicated.
|
||||
|
||||
* `std::invoke<>()`
|
||||
([n4169](http://wg21.link/n4169))
|
||||
|
||||
|
||||
|
||||
[ADL]: https://en.cppreference.com/w/cpp/language/adl
|
||||
"Argument Dependent Lookup"
|
||||
|
||||
@ -1319,3 +1905,6 @@ features that have not yet been discussed.
|
||||
|
||||
[PARTIALAPP]: https://en.wikipedia.org/wiki/Partial_application
|
||||
"Partial Application"
|
||||
|
||||
[JOSUTTIS]: https://www.cppstd17.com
|
||||
"C++17: The Complete Guide"
|
||||
|
||||
@ -398,7 +398,8 @@ TEST_OPTS keywords.</p>
|
||||
<h4 id="jobs">JOBS</h4>
|
||||
<p>Currently only applies to JTReg.</p>
|
||||
<h4 id="timeout_factor">TIMEOUT_FACTOR</h4>
|
||||
<p>Currently only applies to JTReg.</p>
|
||||
<p>Currently only applies to <a href="#timeout_factor-1">JTReg
|
||||
-timeoutFactor</a>.</p>
|
||||
<h4 id="java_options">JAVA_OPTIONS</h4>
|
||||
<p>Applies to JTReg, GTest and Micro.</p>
|
||||
<h4 id="vm_options">VM_OPTIONS</h4>
|
||||
@ -444,8 +445,12 @@ otherwise it defaults to JOBS, except for Hotspot, where the default is
|
||||
<em>number of CPU cores/2</em>, but never more than <em>memory size in
|
||||
GB/2</em>.</p>
|
||||
<h4 id="timeout_factor-1">TIMEOUT_FACTOR</h4>
|
||||
<p>The timeout factor (<code>-timeoutFactor</code>).</p>
|
||||
<p>Defaults to 4.</p>
|
||||
<p>The <code>TIMEOUT_FACTOR</code> is forwarded to JTReg framework
|
||||
itself (<code>-timeoutFactor</code>). Also, some test cases that
|
||||
programmatically wait a certain amount of time will apply this factor.
|
||||
If we run in forced compilation mode (<code>-Xcomp</code>), the build
|
||||
system will automatically adjust this factor to compensate for less
|
||||
performance. Defaults to 1.</p>
|
||||
<h4 id="failure_handler_timeout">FAILURE_HANDLER_TIMEOUT</h4>
|
||||
<p>Sets the argument <code>-timeoutHandlerTimeout</code> for JTReg. The
|
||||
default value is 0. This is only valid if the failure handler is
|
||||
|
||||
@ -324,7 +324,7 @@ Currently only applies to JTReg.
|
||||
|
||||
#### TIMEOUT_FACTOR
|
||||
|
||||
Currently only applies to JTReg.
|
||||
Currently only applies to [JTReg -timeoutFactor](#timeout_factor-1).
|
||||
|
||||
#### JAVA_OPTIONS
|
||||
|
||||
@ -383,9 +383,11 @@ never more than *memory size in GB/2*.
|
||||
|
||||
#### TIMEOUT_FACTOR
|
||||
|
||||
The timeout factor (`-timeoutFactor`).
|
||||
|
||||
Defaults to 4.
|
||||
The `TIMEOUT_FACTOR` is forwarded to JTReg framework itself
|
||||
(`-timeoutFactor`). Also, some test cases that programmatically wait a
|
||||
certain amount of time will apply this factor. If we run in forced
|
||||
compilation mode (`-Xcomp`), the build system will automatically
|
||||
adjust this factor to compensate for less performance. Defaults to 1.
|
||||
|
||||
#### FAILURE_HANDLER_TIMEOUT
|
||||
|
||||
|
||||
@ -301,7 +301,7 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
$(call LogWarn, Signing $(JDK_BUNDLE_NAME))
|
||||
$(CODESIGN) -s "$(MACOSX_CODESIGN_IDENTITY)" \
|
||||
--timestamp --options runtime --deep --force \
|
||||
$(JDK_MACOSX_BUNDLE_DIR_SIGNED)/$(JDK_MACOSX_BUNDLE_TOP_DIR) $(LOG_DEBUG)
|
||||
$(JDK_MACOSX_BUNDLE_DIR_SIGNED)/$(JDK_MACOSX_BUNDLE_TOP_SUBDIR) $(LOG_DEBUG)
|
||||
$(TOUCH) $@
|
||||
|
||||
$(eval $(call SetupBundleFile, BUILD_JDK_BUNDLE, \
|
||||
@ -330,7 +330,7 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
$(call LogWarn, Signing $(JRE_BUNDLE_NAME))
|
||||
$(CODESIGN) -s "$(MACOSX_CODESIGN_IDENTITY)" \
|
||||
--timestamp --options runtime --deep --force \
|
||||
$(JRE_MACOSX_BUNDLE_DIR_SIGNED)/$(JRE_MACOSX_BUNDLE_TOP_DIR) $(LOG_DEBUG)
|
||||
$(JRE_MACOSX_BUNDLE_DIR_SIGNED)/$(JRE_MACOSX_BUNDLE_TOP_SUBDIR) $(LOG_DEBUG)
|
||||
$(TOUCH) $@
|
||||
|
||||
$(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \
|
||||
|
||||
@ -257,6 +257,7 @@ $(eval $(call SetupExecute, create_$(JMOD_FILE), \
|
||||
WARN := Creating $(INTERIM_MSG)$(JMOD_FILE), \
|
||||
DEPS := $(DEPS), \
|
||||
OUTPUT_FILE := $(JMODS_DIR)/$(JMOD_FILE), \
|
||||
WORKING_DIR := $(WORKSPACE_ROOT), \
|
||||
SUPPORT_DIR := $(JMODS_SUPPORT_DIR), \
|
||||
PRE_COMMAND := $(RM) $(JMODS_DIR)/$(JMOD_FILE) $(JMODS_SUPPORT_DIR)/$(JMOD_FILE), \
|
||||
COMMAND := $(JMOD) $(JMOD_SMALL_FLAGS) create --module-version $(VERSION_SHORT) \
|
||||
|
||||
@ -509,7 +509,7 @@ define SetupRunGtestTestBody
|
||||
$$(call LogWarn)
|
||||
$$(call LogWarn, Running test '$$($1_TEST)')
|
||||
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/gtest, ( \
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/gtest, \
|
||||
$$(CD) $$($1_TEST_SUPPORT_DIR) && \
|
||||
$$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/$$($1_VARIANT)/gtestLauncher \
|
||||
-jdk $(JDK_UNDER_TEST) $$($1_GTEST_FILTER) \
|
||||
@ -520,7 +520,7 @@ define SetupRunGtestTestBody
|
||||
> >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) \
|
||||
&& $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
|| $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
))
|
||||
)
|
||||
|
||||
$1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt
|
||||
|
||||
@ -644,7 +644,7 @@ define SetupRunMicroTestBody
|
||||
$$(call LogWarn)
|
||||
$$(call LogWarn, Running test '$$($1_TEST)')
|
||||
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/micro, ( \
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/micro, \
|
||||
$$(CD) $$(TEST_IMAGE_DIR) && \
|
||||
$$(FIXPATH) $$($1_MICRO_TEST_JDK)/bin/java $$($1_MICRO_JAVA_OPTIONS) \
|
||||
-jar $$($1_MICRO_BENCHMARKS_JAR) \
|
||||
@ -655,7 +655,7 @@ define SetupRunMicroTestBody
|
||||
> >($(TEE) $$($1_TEST_RESULTS_DIR)/micro.txt) \
|
||||
&& $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
|| $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
))
|
||||
)
|
||||
|
||||
$1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/micro.txt
|
||||
|
||||
@ -758,34 +758,34 @@ define SetupAOTBody
|
||||
ifeq ($$($1_TRAINING), onestep)
|
||||
|
||||
$$(call LogWarn, AOT: Create AOT cache $$($1_AOT_JDK_CACHE) in one step with flags: $$($1_VM_OPTIONS)) \
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), \
|
||||
cd $$($1_AOT_JDK_OUTPUT_DIR); \
|
||||
$(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \
|
||||
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \
|
||||
-Xlog:class+load,aot,aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
-Xlog:class+load$$(COMMA)aot$$(COMMA)aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
-XX:AOTMode=record -XX:AOTCacheOutput=$$($1_AOT_JDK_CACHE) \
|
||||
TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \
|
||||
))
|
||||
)
|
||||
|
||||
else
|
||||
|
||||
$$(call LogWarn, AOT: Create cache configuration) \
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), \
|
||||
cd $$($1_AOT_JDK_OUTPUT_DIR); \
|
||||
$(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \
|
||||
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \
|
||||
-Xlog:class+load,aot,aot+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
-Xlog:class+load$$(COMMA)aot$$(COMMA)aot+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
-XX:AOTMode=record -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) \
|
||||
TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \
|
||||
))
|
||||
)
|
||||
|
||||
$$(call LogWarn, AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS))
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
|
||||
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), \
|
||||
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \
|
||||
$$($1_VM_OPTIONS) -Xlog:aot,aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
$$($1_VM_OPTIONS) -Xlog:aot$$(COMMA)aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
|
||||
-XX:ExtraSharedClassListFile=$(JDK_UNDER_TEST)/lib/classlist \
|
||||
-XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \
|
||||
))
|
||||
)
|
||||
|
||||
endif
|
||||
|
||||
@ -946,7 +946,8 @@ define SetupRunJtregTestBody
|
||||
JTREG_ALL_OPTIONS := $$(JTREG_JAVA_OPTIONS) $$(JTREG_VM_OPTIONS)
|
||||
|
||||
JTREG_AUTO_PROBLEM_LISTS :=
|
||||
JTREG_AUTO_TIMEOUT_FACTOR := 4
|
||||
# Please reach consensus before changing this. It was not easy changing it to a `1`.
|
||||
JTREG_AUTO_TIMEOUT_FACTOR := 1
|
||||
|
||||
ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), )
|
||||
JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt
|
||||
@ -1084,9 +1085,9 @@ define SetupRunJtregTestBody
|
||||
$$(call LogWarn, Running test '$$($1_TEST)')
|
||||
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR) \
|
||||
$$($1_TEST_TMP_DIR))
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/jtreg, ( \
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/jtreg, \
|
||||
$$(COV_ENVIRONMENT) $$($1_COMMAND_LINE) \
|
||||
))
|
||||
)
|
||||
|
||||
$1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/text/stats.txt
|
||||
|
||||
@ -1203,12 +1204,12 @@ define SetupRunSpecialTestBody
|
||||
$$(call LogWarn)
|
||||
$$(call LogWarn, Running test '$$($1_TEST)')
|
||||
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/test-execution, ( \
|
||||
$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/test-execution, \
|
||||
$$($1_TEST_COMMAND_LINE) \
|
||||
> >($(TEE) $$($1_TEST_RESULTS_DIR)/test-output.txt) \
|
||||
&& $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
|| $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
||||
))
|
||||
)
|
||||
|
||||
# We can not parse the various "special" tests.
|
||||
parse-test-$1: run-test-$1
|
||||
|
||||
@ -111,7 +111,7 @@ else ifeq ($(call isTargetOs, aix), true)
|
||||
INFO := Generating export list for $(notdir $(lib)), \
|
||||
DEPS := $(lib), \
|
||||
OUTPUT_FILE := $(lib).exp, \
|
||||
COMMAND := ( $(AR) $(ARFLAGS) -w $(lib) | $(GREP) -v '^\.' | $(AWK) '{print $$1}' | $(SORT) -u > $(lib).exp ), \
|
||||
COMMAND := $(AR) $(ARFLAGS) -w $(lib) | $(GREP) -v '^\.' | $(AWK) '{print $$1}' | $(SORT) -u > $(lib).exp, \
|
||||
)) \
|
||||
$(eval STATIC_LIB_EXPORT_FILES += $(lib).exp) \
|
||||
)
|
||||
|
||||
@ -130,6 +130,9 @@ TOOL_PUBLICSUFFIXLIST = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_clas
|
||||
TOOL_FIXUPPANDOC = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
build.tools.fixuppandoc.Main
|
||||
|
||||
TOOL_VARHANDLEGUARDMETHODGENERATOR = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
build.tools.methodhandle.VarHandleGuardMethodGenerator
|
||||
|
||||
################################################################################
|
||||
|
||||
# Executable javascript filter for man page generation using pandoc.
|
||||
|
||||
@ -81,8 +81,8 @@ SLEEF_CMAKE_FILE := toolchains/$(OPENJDK_TARGET_CPU)-$(SLEEF_TOOLCHAIN_TYPE).cma
|
||||
$(eval $(call SetupExecute, sleef_native_config, \
|
||||
INFO := Configuring native sleef build, \
|
||||
OUTPUT_DIR := $(SLEEF_NATIVE_BUILD_DIR), \
|
||||
COMMAND := cd $(SLEEF_SOURCE_DIR) && $(CMAKE) -S . -B \
|
||||
$(SLEEF_NATIVE_BUILD_DIR), \
|
||||
WORKING_DIR := $(SLEEF_SOURCE_DIR), \
|
||||
COMMAND := $(CMAKE) -S . -B $(SLEEF_NATIVE_BUILD_DIR), \
|
||||
))
|
||||
|
||||
TARGETS := $(sleef_native_config)
|
||||
@ -91,8 +91,8 @@ $(eval $(call SetupExecute, sleef_native_build, \
|
||||
INFO := Building native sleef, \
|
||||
DEPS := $(sleef_native_config), \
|
||||
OUTPUT_DIR := $(SLEEF_NATIVE_BUILD_DIR), \
|
||||
COMMAND := cd $(SLEEF_SOURCE_DIR) && $(CMAKE) --build \
|
||||
$(SLEEF_NATIVE_BUILD_DIR) -j, \
|
||||
WORKING_DIR := $(SLEEF_SOURCE_DIR), \
|
||||
COMMAND := $(CMAKE) --build $(SLEEF_NATIVE_BUILD_DIR) -j, \
|
||||
))
|
||||
|
||||
TARGETS := $(sleef_native_build)
|
||||
@ -101,8 +101,8 @@ $(eval $(call SetupExecute, sleef_cross_config, \
|
||||
INFO := Configuring cross-compiling sleef build, \
|
||||
DEPS := $(sleef_native_build), \
|
||||
OUTPUT_DIR := $(SLEEF_CROSS_BUILD_DIR), \
|
||||
COMMAND := cd $(SLEEF_SOURCE_DIR) && $(CMAKE) -S . -B \
|
||||
$(SLEEF_CROSS_BUILD_DIR) \
|
||||
WORKING_DIR := $(SLEEF_SOURCE_DIR), \
|
||||
COMMAND := $(CMAKE) -S . -B $(SLEEF_CROSS_BUILD_DIR) \
|
||||
-DCMAKE_C_COMPILER=$(CC) \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$(SLEEF_CMAKE_FILE) \
|
||||
-DNATIVE_BUILD_DIR=$(SLEEF_NATIVE_BUILD_DIR) \
|
||||
@ -116,8 +116,8 @@ $(eval $(call SetupExecute, sleef_cross_build, \
|
||||
INFO := Building cross-compiling sleef, \
|
||||
DEPS := $(sleef_cross_config), \
|
||||
OUTPUT_DIR := $(SLEEF_NATIVE_BUILD_DIR), \
|
||||
COMMAND := cd $(SLEEF_SOURCE_DIR) && $(CMAKE) --build \
|
||||
$(SLEEF_CROSS_BUILD_DIR) -j, \
|
||||
WORKING_DIR := $(SLEEF_SOURCE_DIR), \
|
||||
COMMAND := $(CMAKE) --build $(SLEEF_CROSS_BUILD_DIR) -j, \
|
||||
))
|
||||
|
||||
TARGETS := $(sleef_cross_build)
|
||||
|
||||
@ -210,17 +210,8 @@ AC_DEFUN([BASIC_SETUP_XCODE_SYSROOT],
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_ERROR([The xcodebuild tool in the devkit reports an error: $XCODEBUILD_OUTPUT])
|
||||
fi
|
||||
elif test "x$TOOLCHAIN_PATH" != x; then
|
||||
UTIL_LOOKUP_PROGS(XCODEBUILD, xcodebuild, $TOOLCHAIN_PATH)
|
||||
if test "x$XCODEBUILD" != x; then
|
||||
XCODEBUILD_OUTPUT=`"$XCODEBUILD" -version 2>&1`
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_WARN([Ignoring the located xcodebuild tool $XCODEBUILD due to an error: $XCODEBUILD_OUTPUT])
|
||||
XCODEBUILD=
|
||||
fi
|
||||
fi
|
||||
else
|
||||
UTIL_LOOKUP_PROGS(XCODEBUILD, xcodebuild)
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(XCODEBUILD, xcodebuild)
|
||||
if test "x$XCODEBUILD" != x; then
|
||||
XCODEBUILD_OUTPUT=`"$XCODEBUILD" -version 2>&1`
|
||||
if test $? -ne 0; then
|
||||
@ -348,21 +339,11 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
|
||||
|
||||
# You can force the sysroot if the sysroot encoded into the compiler tools
|
||||
# is not correct.
|
||||
AC_ARG_WITH(sys-root, [AS_HELP_STRING([--with-sys-root],
|
||||
[alias for --with-sysroot for backwards compatibility])],
|
||||
[SYSROOT=$with_sys_root]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(sysroot, [AS_HELP_STRING([--with-sysroot],
|
||||
[use this directory as sysroot])],
|
||||
[SYSROOT=$with_sysroot]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([tools-dir], [AS_HELP_STRING([--with-tools-dir],
|
||||
[alias for --with-toolchain-path for backwards compatibility])],
|
||||
[UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_tools_dir)]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([toolchain-path], [AS_HELP_STRING([--with-toolchain-path],
|
||||
[prepend these directories when searching for toolchain binaries (compilers etc)])],
|
||||
[UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],$with_toolchain_path)]
|
||||
@ -371,6 +352,9 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
|
||||
AC_ARG_WITH([xcode-path], [AS_HELP_STRING([--with-xcode-path],
|
||||
[set up toolchain on Mac OS using a path to an Xcode installation])])
|
||||
|
||||
UTIL_DEPRECATED_ARG_WITH(sys-root)
|
||||
UTIL_DEPRECATED_ARG_WITH(tools-dir)
|
||||
|
||||
if test "x$with_xcode_path" != x; then
|
||||
if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
|
||||
UTIL_PREPEND_TO_PATH([TOOLCHAIN_PATH],
|
||||
|
||||
@ -207,29 +207,14 @@ AC_DEFUN([BASIC_CHECK_GNU_MAKE],
|
||||
UTIL_SETUP_TOOL(MAKE,
|
||||
[
|
||||
# Try our hardest to locate a correct version of GNU make
|
||||
UTIL_LOOKUP_PROGS(CHECK_GMAKE, gmake)
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(CHECK_GMAKE, gmake)
|
||||
BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH])
|
||||
|
||||
if test "x$FOUND_MAKE" = x; then
|
||||
UTIL_LOOKUP_PROGS(CHECK_MAKE, make)
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(CHECK_MAKE, make)
|
||||
BASIC_CHECK_MAKE_VERSION("$CHECK_MAKE", [make in PATH])
|
||||
fi
|
||||
|
||||
if test "x$FOUND_MAKE" = x; then
|
||||
if test "x$TOOLCHAIN_PATH" != x; then
|
||||
# We have a toolchain path, check that as well before giving up.
|
||||
OLD_PATH=$PATH
|
||||
PATH=$TOOLCHAIN_PATH:$PATH
|
||||
UTIL_LOOKUP_PROGS(CHECK_TOOLSDIR_GMAKE, gmake)
|
||||
BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_GMAKE", [gmake in tools-dir])
|
||||
if test "x$FOUND_MAKE" = x; then
|
||||
UTIL_LOOKUP_PROGS(CHECK_TOOLSDIR_MAKE, make)
|
||||
BASIC_CHECK_MAKE_VERSION("$CHECK_TOOLSDIR_MAKE", [make in tools-dir])
|
||||
fi
|
||||
PATH=$OLD_PATH
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$FOUND_MAKE" = x; then
|
||||
AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.])
|
||||
fi
|
||||
|
||||
@ -162,12 +162,7 @@ AC_DEFUN([BPERF_SETUP_CCACHE],
|
||||
# Check if ccache is available
|
||||
CCACHE_AVAILABLE=true
|
||||
|
||||
OLD_PATH="$PATH"
|
||||
if test "x$TOOLCHAIN_PATH" != x; then
|
||||
PATH=$TOOLCHAIN_PATH:$PATH
|
||||
fi
|
||||
UTIL_LOOKUP_PROGS(CCACHE, ccache)
|
||||
PATH="$OLD_PATH"
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(CCACHE, ccache)
|
||||
|
||||
AC_MSG_CHECKING([if ccache is available])
|
||||
if test "x$TOOLCHAIN_TYPE" != "xgcc" && test "x$TOOLCHAIN_TYPE" != "xclang"; then
|
||||
|
||||
@ -110,4 +110,4 @@ $MV $OUTPUTDIR/compare.log $OUTPUTDIR/compare.log.old 2> /dev/null
|
||||
|
||||
export SCRIPT_DIR="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
|
||||
|
||||
$BASH $TOPDIR/make/scripts/logger.sh $OUTPUTDIR/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
|
||||
$BASH $TOPDIR/make/scripts/compare-logger.sh $OUTPUTDIR/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
|
||||
|
||||
@ -221,6 +221,9 @@ JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER
|
||||
# LeakSanitizer
|
||||
JDKOPT_SETUP_LEAK_SANITIZER
|
||||
|
||||
# Setup static analyzer
|
||||
JDKOPT_SETUP_STATIC_ANALYZER
|
||||
|
||||
# Fallback linker
|
||||
# This needs to go before 'LIB_DETERMINE_DEPENDENCIES'
|
||||
JDKOPT_SETUP_FALLBACK_LINKER
|
||||
|
||||
@ -597,11 +597,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
|
||||
# CXXFLAGS C++ language level for all of JDK, including Hotspot.
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
LANGSTD_CXXFLAGS="-std=c++14"
|
||||
LANGSTD_CXXFLAGS="-std=c++17"
|
||||
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
LANGSTD_CXXFLAGS="-std:c++14"
|
||||
LANGSTD_CXXFLAGS="-std:c++17"
|
||||
else
|
||||
AC_MSG_ERROR([Cannot enable C++14 for this toolchain])
|
||||
AC_MSG_ERROR([Cannot enable C++17 for this toolchain])
|
||||
fi
|
||||
TOOLCHAIN_CFLAGS_JDK_CXXONLY="$TOOLCHAIN_CFLAGS_JDK_CXXONLY $LANGSTD_CXXFLAGS"
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM $LANGSTD_CXXFLAGS"
|
||||
|
||||
@ -74,7 +74,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
# Clang needs the lld linker to work correctly
|
||||
BASIC_LDFLAGS="-fuse-ld=lld -Wl,--exclude-libs,ALL"
|
||||
if test "x$CXX_IS_USER_SUPPLIED" = xfalse && test "x$CC_IS_USER_SUPPLIED" = xfalse; then
|
||||
UTIL_REQUIRE_PROGS(LLD, lld, $TOOLCHAIN_PATH:$PATH)
|
||||
UTIL_REQUIRE_TOOLCHAIN_PROGS(LLD, lld)
|
||||
fi
|
||||
fi
|
||||
if test "x$OPENJDK_TARGET_OS" = xaix; then
|
||||
|
||||
@ -320,12 +320,16 @@ AC_DEFUN([FLAGS_SETUP_TOOLCHAIN_CONTROL],
|
||||
[
|
||||
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
CC_OUT_OPTION=-Fo
|
||||
if test "x$OPENJDK_TARGET_CPU" != xaarch64; then
|
||||
AS_NON_ASM_EXTENSION_OPTION=-Ta
|
||||
fi
|
||||
else
|
||||
# The option used to specify the target .o,.a or .so file.
|
||||
# When compiling, how to specify the to be created object file.
|
||||
CC_OUT_OPTION='-o$(SPACE)'
|
||||
fi
|
||||
AC_SUBST(CC_OUT_OPTION)
|
||||
AC_SUBST(AS_NON_ASM_EXTENSION_OPTION)
|
||||
|
||||
# Generate make dependency files
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
|
||||
@ -479,6 +479,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
|
||||
AC_SUBST(ASAN_ENABLED)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Static analyzer
|
||||
#
|
||||
AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_ANALYZER],
|
||||
[
|
||||
UTIL_ARG_ENABLE(NAME: static-analyzer, DEFAULT: false, RESULT: STATIC_ANALYZER_ENABLED,
|
||||
DESC: [enable the GCC static analyzer],
|
||||
CHECK_AVAILABLE: [
|
||||
AC_MSG_CHECKING([if static analyzer is available])
|
||||
if test "x$TOOLCHAIN_TYPE" = "xgcc"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
],
|
||||
IF_ENABLED: [
|
||||
STATIC_ANALYZER_CFLAGS="-fanalyzer -Wno-analyzer-fd-leak"
|
||||
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $STATIC_ANALYZER_CFLAGS"
|
||||
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $STATIC_ANALYZER_CFLAGS"
|
||||
])
|
||||
AC_SUBST(STATIC_ANALYZER_ENABLED)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# LeakSanitizer
|
||||
|
||||
@ -492,6 +492,7 @@ CXX_VERSION_NUMBER := @CXX_VERSION_NUMBER@
|
||||
HOTSPOT_TOOLCHAIN_TYPE := @HOTSPOT_TOOLCHAIN_TYPE@
|
||||
|
||||
CC_OUT_OPTION := @CC_OUT_OPTION@
|
||||
AS_NON_ASM_EXTENSION_OPTION := @AS_NON_ASM_EXTENSION_OPTION@
|
||||
|
||||
# Flags used for overriding the default opt setting for a C/C++ source file.
|
||||
C_O_FLAG_HIGHEST_JVM := @C_O_FLAG_HIGHEST_JVM@
|
||||
@ -897,12 +898,14 @@ JDK_MACOSX_BUNDLE_DIR = $(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR)
|
||||
JRE_MACOSX_BUNDLE_DIR = $(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR)
|
||||
JDK_MACOSX_BUNDLE_DIR_SIGNED = $(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR_SIGNED)
|
||||
JRE_MACOSX_BUNDLE_DIR_SIGNED = $(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR_SIGNED)
|
||||
JDK_MACOSX_BUNDLE_TOP_DIR = jdk-$(VERSION_NUMBER).jdk
|
||||
JRE_MACOSX_BUNDLE_TOP_DIR = jre-$(VERSION_NUMBER).jre
|
||||
JDK_MACOSX_CONTENTS_SUBDIR = $(JDK_MACOSX_BUNDLE_TOP_DIR)/Contents
|
||||
JRE_MACOSX_CONTENTS_SUBDIR = $(JRE_MACOSX_BUNDLE_TOP_DIR)/Contents
|
||||
JDK_MACOSX_BUNDLE_TOP_SUBDIR = jdk-$(VERSION_NUMBER).jdk
|
||||
JRE_MACOSX_BUNDLE_TOP_SUBDIR = jre-$(VERSION_NUMBER).jre
|
||||
JDK_MACOSX_CONTENTS_SUBDIR = $(JDK_MACOSX_BUNDLE_TOP_SUBDIR)/Contents
|
||||
JRE_MACOSX_CONTENTS_SUBDIR = $(JRE_MACOSX_BUNDLE_TOP_SUBDIR)/Contents
|
||||
JDK_MACOSX_CONTENTS_DIR = $(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_CONTENTS_SUBDIR)
|
||||
JRE_MACOSX_CONTENTS_DIR = $(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_CONTENTS_SUBDIR)
|
||||
JDK_MACOSX_BUNDLE_TOP_DIR = $(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_BUNDLE_TOP_SUBDIR)
|
||||
JRE_MACOSX_BUNDLE_TOP_DIR = $(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_BUNDLE_TOP_SUBDIR)
|
||||
|
||||
# Bundle names
|
||||
ifneq ($(VERSION_BUILD), )
|
||||
|
||||
@ -276,9 +276,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
ORG_CFLAGS="$CFLAGS"
|
||||
ORG_CXXFLAGS="$CXXFLAGS"
|
||||
|
||||
# autoconf magic only relies on PATH, so update it if tools dir is specified
|
||||
OLD_PATH="$PATH"
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
|
||||
if test "x$XCODEBUILD" != x; then
|
||||
XCODE_VERSION_OUTPUT=`"$XCODEBUILD" -version 2> /dev/null | $HEAD -n 1`
|
||||
@ -300,9 +297,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
fi
|
||||
AC_SUBST(TOOLCHAIN_VERSION)
|
||||
|
||||
# Finally prepend TOOLCHAIN_PATH to the PATH, to allow --with-tools-dir to
|
||||
# override all other locations.
|
||||
if test "x$TOOLCHAIN_PATH" != x; then
|
||||
# For the microsoft toolchain the toolchain path needs to be added to the
|
||||
# normal path, or the compiler will not work in some situations in later
|
||||
# configure checks.
|
||||
if test "x$TOOLCHAIN_TYPE" = "xmicrosoft" && test "x$TOOLCHAIN_PATH" != x; then
|
||||
export PATH=$TOOLCHAIN_PATH:$PATH
|
||||
fi
|
||||
])
|
||||
@ -310,13 +308,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
# Restore path, etc
|
||||
AC_DEFUN_ONCE([TOOLCHAIN_POST_DETECTION],
|
||||
[
|
||||
# Restore old path, except for the microsoft toolchain, which requires the
|
||||
# toolchain path to remain in place. Otherwise the compiler will not work in
|
||||
# some situations in later configure checks.
|
||||
if test "x$TOOLCHAIN_TYPE" != "xmicrosoft"; then
|
||||
PATH="$OLD_PATH"
|
||||
fi
|
||||
|
||||
# Restore the flags to the user specified values.
|
||||
# This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2"
|
||||
CFLAGS="$ORG_CFLAGS"
|
||||
|
||||
@ -458,17 +458,18 @@ AC_DEFUN([UTIL_LOOKUP_PROGS],
|
||||
|
||||
################################################################################
|
||||
# Call UTIL_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool. This will look
|
||||
# first for cross-compilation tools.
|
||||
# first for tools using the cross-compilation prefix, and then for tools without
|
||||
# this prefix. For each of these name variants, it will look first in the
|
||||
# toolchain path, and then in the normal path.
|
||||
# $1: variable to set
|
||||
# $2: executable name (or list of names) to look for
|
||||
# $3: [path]
|
||||
AC_DEFUN([UTIL_LOOKUP_TOOLCHAIN_PROGS],
|
||||
[
|
||||
if test "x$ac_tool_prefix" = x; then
|
||||
UTIL_LOOKUP_PROGS($1, $2, $3)
|
||||
UTIL_LOOKUP_PROGS($1, $2, [$TOOLCHAIN_PATH:$PATH])
|
||||
else
|
||||
prefixed_names=$(for name in $2; do echo ${ac_tool_prefix}${name} $name; done)
|
||||
UTIL_LOOKUP_PROGS($1, $prefixed_names, $3)
|
||||
UTIL_LOOKUP_PROGS($1, $prefixed_names, [$TOOLCHAIN_PATH:$PATH])
|
||||
fi
|
||||
])
|
||||
|
||||
@ -497,10 +498,9 @@ AC_DEFUN([UTIL_REQUIRE_PROGS],
|
||||
# Like UTIL_LOOKUP_PROGS but fails if no tool was found.
|
||||
# $1: variable to set
|
||||
# $2: executable name (or list of names) to look for
|
||||
# $3: [path]
|
||||
AC_DEFUN([UTIL_REQUIRE_TOOLCHAIN_PROGS],
|
||||
[
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS($1, $2, $3)
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS($1, $2)
|
||||
UTIL_CHECK_NONEMPTY($1)
|
||||
])
|
||||
|
||||
|
||||
@ -45,6 +45,9 @@ ifeq ($(INCLUDE), true)
|
||||
# e.g. a simple sed replacement on the input file. If the operations are
|
||||
# unrelated to the main COMMAND, this is not a suitable solution.
|
||||
#
|
||||
# Before execution, the current working directory is changed to SUPPORT_DIR.
|
||||
# This can be overridden with WORKING_DIR.
|
||||
#
|
||||
# If your command outputs a variety of files, or if it's really a single file
|
||||
# but you don't really care about the output from the perspective, you can just
|
||||
# supply an OUTPUT_DIR. You are supposed to make sure the command creates files
|
||||
@ -75,9 +78,12 @@ ifeq ($(INCLUDE), true)
|
||||
# OUTPUT_DIR : The directory that will contain the result from the command
|
||||
# OUTPUT_FILE : Use this if the command results in a single output file
|
||||
# SUPPORT_DIR : Where to store generated support files
|
||||
# WORKING_DIR : Directory to cd to before executing the command
|
||||
# INFO : Message to display at LOG=info level when running command (optional)
|
||||
# WARN : Message to display at LOG=warn level when running command (optional)
|
||||
# DEPS : Dependencies for the execution to take place
|
||||
# DRYRUN : Set to true to perform everything but executing the command \
|
||||
# (defaults to false, primarily intended for debugging)
|
||||
#
|
||||
|
||||
# Setup make rules for copying files, with an option to do more complex
|
||||
@ -133,6 +139,10 @@ define SetupExecuteBody
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($$($1_WORKING_DIR), )
|
||||
$1_WORKING_DIR := $$($1_SUPPORT_DIR)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_INFO)$$($1_WARN), )
|
||||
# If neither info nor warn is provided, add basic info text.
|
||||
$1_INFO := Running commands for $1
|
||||
@ -147,14 +157,19 @@ define SetupExecuteBody
|
||||
ifneq ($$($1_INFO), )
|
||||
$$(call LogInfo, $$($1_INFO))
|
||||
endif
|
||||
$$(call MakeDir, $$($1_SUPPORT_DIR) $$($1_OUTPUT_DIR))
|
||||
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_pre, \
|
||||
$$($1_PRE_COMMAND))
|
||||
cd $$($1_WORKING_DIR) && $$($1_PRE_COMMAND))
|
||||
$$(TOUCH) $$@
|
||||
|
||||
$$($1_EXEC_RESULT): $$($1_PRE_MARKER)
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
$$($1_COMMAND))
|
||||
ifneq ($$($1_DRYRUN), true)
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
|
||||
else
|
||||
$$(call LogWarn, DRYRUN enabled for $1, not actually running command)
|
||||
$$(TOUCH) $$@
|
||||
endif
|
||||
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
|
||||
$$(TOUCH) $$@
|
||||
endif
|
||||
@ -168,9 +183,14 @@ define SetupExecuteBody
|
||||
ifneq ($$($1_INFO), )
|
||||
$$(call LogInfo, $$($1_INFO))
|
||||
endif
|
||||
$$(call MakeDir, $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
$$($1_COMMAND))
|
||||
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
|
||||
ifneq ($$($1_DRYRUN), true)
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
|
||||
else
|
||||
$$(call LogWarn, DRYRUN enabled for $1, not actually running command)
|
||||
$$(TOUCH) $$@
|
||||
endif
|
||||
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
|
||||
$$(TOUCH) $$@
|
||||
endif
|
||||
@ -182,7 +202,7 @@ define SetupExecuteBody
|
||||
|
||||
$$($1_FINAL_RESULT): $$($1_EXEC_RESULT)
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_post, \
|
||||
$$($1_POST_COMMAND))
|
||||
cd $$($1_WORKING_DIR) && $$($1_POST_COMMAND))
|
||||
$$(TOUCH) $$@
|
||||
|
||||
$1 += $$($1_FINAL_RESULT)
|
||||
|
||||
@ -284,6 +284,12 @@ else
|
||||
LogCmdlines =
|
||||
endif
|
||||
|
||||
# Check if the command line contains redirection, that is <, > or >>,
|
||||
# and if so, return a value that is interpreted as true in a make $(if)
|
||||
# construct.
|
||||
is_redirect = \
|
||||
$(if $(filter < > >>, $1), true)
|
||||
|
||||
################################################################################
|
||||
# ExecuteWithLog will run a command and log the output appropriately. This is
|
||||
# meant to be used by commands that do "real" work, like a compilation.
|
||||
@ -291,21 +297,23 @@ endif
|
||||
# of the build in case of failure. The command line itself is stored in a file,
|
||||
# and also logged to stdout if the LOG=cmdlines option has been given.
|
||||
#
|
||||
# NOTE: If the command redirects stdout, the caller needs to wrap it in a
|
||||
# subshell (by adding parentheses around it), otherwise the redirect to the
|
||||
# subshell tee process will create a race condition where the target file may
|
||||
# not be fully written when the make recipe is done.
|
||||
#
|
||||
# Param 1 - The path to base the name of the log file / command line file on
|
||||
# Param 2 - The command to run
|
||||
ExecuteWithLog = \
|
||||
$(call LogCmdlines, Executing: [$(strip $2)]) \
|
||||
$(call LogCmdlines, Executing: \
|
||||
[$(if $(call is_redirect, $2),$(LEFT_PAREN) )$(strip $2)$(if $(call \
|
||||
is_redirect, $2), $(RIGHT_PAREN))]) \
|
||||
$(call MakeDir, $(dir $(strip $1)) $(MAKESUPPORT_OUTPUTDIR)/failure-logs) \
|
||||
$(call WriteFile, $2, $(strip $1).cmdline) \
|
||||
( $(RM) $(strip $1).log && $(strip $2) > >($(TEE) -a $(strip $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \
|
||||
( $(RM) $(strip $1).log && \
|
||||
$(if $(call is_redirect, $2),$(LEFT_PAREN) )$(strip $2)$(if $(call \
|
||||
is_redirect, $2), $(RIGHT_PAREN)) \
|
||||
> >($(TEE) -a $(strip $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \
|
||||
( exitcode=$(DOLLAR)? && \
|
||||
$(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).log && \
|
||||
$(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).cmdline && \
|
||||
$(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst \
|
||||
/,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).log && \
|
||||
$(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst \
|
||||
/,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).cmdline && \
|
||||
exit $(DOLLAR)exitcode ) )
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -27,10 +27,15 @@
|
||||
# MakeIncludeEnd.gmk should be included last of all in all include files
|
||||
################################################################################
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
|
||||
CUSTOM_POST_NAME := $(subst .gmk,-post.gmk, $(THIS_INCLUDE))
|
||||
$(eval $(call IncludeCustomExtension, $(CUSTOM_POST_NAME)))
|
||||
ifneq ($(INCLUDE_GUARD_$(THIS_INCLUDE)), true)
|
||||
# This was the first time this file was included. Prevent future inclusion.
|
||||
INCLUDE_GUARD_$(THIS_INCLUDE) := true
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
|
||||
CUSTOM_POST_NAME := $(subst .gmk,-post.gmk, $(THIS_INCLUDE))
|
||||
$(eval $(call IncludeCustomExtension, $(CUSTOM_POST_NAME)))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Pop our helper name off the stack
|
||||
|
||||
@ -70,7 +70,6 @@ INCLUDE_STACK := $(THIS_INCLUDE) $(INCLUDE_STACK)
|
||||
|
||||
# Setup an automatic include guard
|
||||
ifneq ($(INCLUDE_GUARD_$(THIS_INCLUDE)), true)
|
||||
INCLUDE_GUARD_$(THIS_INCLUDE) := true
|
||||
INCLUDE := true
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
|
||||
@ -109,7 +109,7 @@ define ProcessMarkdown
|
||||
$$(call LogInfo, Post-processing markdown file $2)
|
||||
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$($1_$2_TARGET_DIR))
|
||||
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post, \
|
||||
( $$($1_POST_PROCESS) $$($1_$2_PANDOC_OUTPUT) > $$($1_$2_OUTPUT_FILE) ) )
|
||||
$$($1_POST_PROCESS) $$($1_$2_PANDOC_OUTPUT) > $$($1_$2_OUTPUT_FILE) )
|
||||
endif
|
||||
|
||||
$1 += $$($1_$2_OUTPUT_FILE)
|
||||
|
||||
@ -55,6 +55,42 @@ uppercase = \
|
||||
$(uppercase_result) \
|
||||
)
|
||||
|
||||
lowercase_table := A,a B,b C,c D,d E,e F,f G,g H,h I,i J,j K,k L,l M,m N,n O,o \
|
||||
P,p Q,q R,r S,s T,t U,u V,v W,w X,x Y,y Z,z
|
||||
|
||||
lowercase_internal = \
|
||||
$(if $(strip $1), $$(subst $(firstword $1), $(call lowercase_internal, \
|
||||
$(wordlist 2, $(words $1), $1), $2)), $2)
|
||||
|
||||
# Convert a string to lower case. Works only on a-z.
|
||||
# $1 - The string to convert
|
||||
lowercase = \
|
||||
$(strip \
|
||||
$(eval lowercase_result := $(call lowercase_internal, $(lowercase_table), $1)) \
|
||||
$(lowercase_result) \
|
||||
)
|
||||
|
||||
lowercase_letters := a b c d e f g h i j k l m n o p q r s t u v w x y z
|
||||
uppercase_letters := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|
||||
|
||||
titlecase_internal = \
|
||||
$(strip $(or \
|
||||
$(strip $(foreach l, $(lowercase_letters) $(uppercase_letters), \
|
||||
$(if $(filter $l%, $1), \
|
||||
$(call uppercase, $l)$(call lowercase, $(patsubst $l%,%,$1))))), \
|
||||
$1))
|
||||
|
||||
# Convert a string to Title Case. Works only on a-z.
|
||||
# $1 - The string to convert
|
||||
titlecase = \
|
||||
$(strip $(foreach w, $1, $(call titlecase_internal, $w)))
|
||||
|
||||
# Returns the first character of a string. Works only on a-z.
|
||||
# $1 - The string to extract the first character from
|
||||
firstchar = \
|
||||
$(strip $(foreach l, $(lowercase_letters) $(uppercase_letters), \
|
||||
$(if $(filter $l%, $(firstword $1)), $l)))
|
||||
|
||||
################################################################################
|
||||
# Creates a sequence of increasing numbers (inclusive).
|
||||
# Param 1 - starting number
|
||||
|
||||
228
make/common/modules/GensrcStreamPreProcessing.gmk
Normal file
228
make/common/modules/GensrcStreamPreProcessing.gmk
Normal file
@ -0,0 +1,228 @@
|
||||
#
|
||||
# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
include MakeIncludeStart.gmk
|
||||
ifeq ($(INCLUDE), true)
|
||||
|
||||
################################################################################
|
||||
# This file defines macros that sets up rules for running the spp.Spp build tool
|
||||
################################################################################
|
||||
|
||||
include Execute.gmk
|
||||
include $(TOPDIR)/make/ToolsJdk.gmk
|
||||
|
||||
NON_BYTE_NUMBER_TYPES := char short int long float double
|
||||
NUMBER_TYPES := byte $(NON_BYTE_NUMBER_TYPES)
|
||||
PRIMITIVE_TYPES := boolean $(NUMBER_TYPES)
|
||||
|
||||
################################################################################
|
||||
# The Conv function converts a type given as first argument (as a normal Java
|
||||
# native type name), into one of several corresponding strings, depending on
|
||||
# the aspect given in the second argument
|
||||
#
|
||||
# The implementation dispatches the call to one of several Conv_<aspect> macros.
|
||||
#
|
||||
# arg $1: the type to convert
|
||||
# arg $2: the aspect to convert for
|
||||
# arg $3: byte order (only needed for certain aspects)
|
||||
#
|
||||
Conv = \
|
||||
$(strip $(call Conv_$(strip $2),$(strip $1),$(strip $3)))
|
||||
|
||||
################################################################################
|
||||
# Conv_<aspect> implementations
|
||||
|
||||
# Return a single letter representing the type (lowercase first letter)
|
||||
Conv_x = \
|
||||
$(call firstchar, $1)
|
||||
|
||||
# Return capitalized type name
|
||||
Conv_Type = \
|
||||
$(call titlecase, $1)
|
||||
|
||||
# Return the full descriptive name of the type, e.g. int -> integer
|
||||
Conv_fulltype = \
|
||||
$(if $(filter char, $1), \
|
||||
character, \
|
||||
$(if $(filter int, $1), \
|
||||
integer, \
|
||||
$1 \
|
||||
) \
|
||||
)
|
||||
|
||||
# Return the capitalized full descriptive name of the type, e.g. int -> Integer
|
||||
Conv_Fulltype = \
|
||||
$(call titlecase, $(call Conv_fulltype, $1))
|
||||
|
||||
# Return log2 bits per value (0-3)
|
||||
Conv_LBPV = \
|
||||
$(if $(filter byte, $1), \
|
||||
0, \
|
||||
$(if $(filter char short, $1), \
|
||||
1, \
|
||||
$(if $(filter int float, $1), \
|
||||
2, \
|
||||
$(if $(filter long double, $1), \
|
||||
3))))
|
||||
|
||||
# Return float or int category
|
||||
Conv_category = \
|
||||
$(if $(filter float double, $1), \
|
||||
floatingPointType, \
|
||||
integralType \
|
||||
)
|
||||
|
||||
# Return stream information for char
|
||||
Conv_streams = \
|
||||
$(if $(filter char, $1), streamableType)
|
||||
|
||||
# Return stream type information for char
|
||||
Conv_streamtype = \
|
||||
$(if $(filter char, $1), int)
|
||||
|
||||
# Return capitalized stream type information for char
|
||||
Conv_Streamtype = \
|
||||
$(if $(filter char, $1), Int)
|
||||
|
||||
# Return article to use for type in English text
|
||||
Conv_a = \
|
||||
$(if $(filter int, $1), an, a)
|
||||
|
||||
# Return capitalized article to use for type in English text
|
||||
Conv_A = \
|
||||
$(if $(filter int, $1), An, A)
|
||||
|
||||
# Return integer type with same size as the type
|
||||
Conv_memtype = \
|
||||
$(if $(filter float, $1), int, $(if $(filter double, $1), long, $1))
|
||||
|
||||
# Return capitalized integer type with same size as the type
|
||||
Conv_Memtype = \
|
||||
$(call titlecase, $(call Conv, $1, memtype))
|
||||
|
||||
# Return capitalized full descriptive name for integer type with same size as the type
|
||||
Conv_FullMemtype = \
|
||||
$(call Conv, $(call Conv, $1, memtype), Fulltype)
|
||||
|
||||
# Return Type or Memtype depending on byte order
|
||||
# arg $2: BYTE_ORDER
|
||||
Conv_Swaptype = \
|
||||
$(if $(filter U, $2), \
|
||||
$(call Conv, $1, Type), \
|
||||
$(call Conv, $1, Memtype))
|
||||
|
||||
# Return fromBits method name for floating types, depending on byte order
|
||||
# arg $2: BYTE_ORDER
|
||||
Conv_fromBits = \
|
||||
$(if $(filter float double, $1), \
|
||||
$(if $(filter U, $2), , \
|
||||
$(call Conv, $1, Type).$(call Conv, $1, memtype)BitsTo$(call Conv, $1, Type)))
|
||||
|
||||
# Return toBits method name for floating types, depending on byte order
|
||||
# arg $2: BYTE_ORDER
|
||||
Conv_toBits = \
|
||||
$(if $(filter float double, $1), \
|
||||
$(if $(filter U, $2), , \
|
||||
$(call Conv, $1, Type).$1ToRaw$(call Conv, $(call Conv, $1, memtype), Type)Bits))
|
||||
|
||||
# Return swap method name, depending on byte order
|
||||
# arg $2: BYTE_ORDER
|
||||
Conv_swap = \
|
||||
$(if $(filter S, $2), Bits.swap)
|
||||
|
||||
# Return word describing the number of bytes required by type
|
||||
Conv_nbytes = \
|
||||
$(if $(filter 0, $(call Conv, $1, LBPV)), one, \
|
||||
$(if $(filter 1, $(call Conv, $1, LBPV)), two, \
|
||||
$(if $(filter 2, $(call Conv, $1, LBPV)), four, \
|
||||
$(if $(filter 3, $(call Conv, $1, LBPV)), eight))))
|
||||
|
||||
# Return word describing the number of bytes required by type, minus one
|
||||
Conv_nbytesButOne = \
|
||||
$(if $(filter 0, $(call Conv, $1, LBPV)), zero, \
|
||||
$(if $(filter 1, $(call Conv, $1, LBPV)), one, \
|
||||
$(if $(filter 2, $(call Conv, $1, LBPV)), three, \
|
||||
$(if $(filter 3, $(call Conv, $1, LBPV)), seven))))
|
||||
|
||||
################################################################################
|
||||
# Setup make rules that runs the spp.Spp build tool on an input file.
|
||||
#
|
||||
# Parameter 1 is the name of the rule. This name is used as variable prefix,
|
||||
# and the targets generated are listed in a variable by that name.
|
||||
#
|
||||
# Remaining parameters are named arguments. These include:
|
||||
# BEGIN_END Set to true to exclude everything outside #begin/#end (default: false)
|
||||
# SUBST_EMPTY_LINES Set to false to not generate empty lines for removed lines (default: true)
|
||||
# SOURCE_FILE The input file to process (required)
|
||||
# OUTPUT_FILE The output file (required)
|
||||
# INFO Override default message to print (optional)
|
||||
# KEYS One or more keys to control the generation (optional)
|
||||
# REPLACEMENTS one or more text replacement patterns, using the syntax:
|
||||
# VAR=VALUE [VAR=VALUE] ...
|
||||
#
|
||||
SetupStreamPreProcessing = $(NamedParamsMacroTemplate)
|
||||
define SetupStreamPreProcessingBody
|
||||
# Verify arguments
|
||||
ifeq ($$($1_SOURCE_FILE), )
|
||||
$$(error Must specify SOURCE_FILE (in $1))
|
||||
endif
|
||||
ifeq ($$($1_OUTPUT_FILE), )
|
||||
$$(error Must specify OUTPUT_FILE (in $1))
|
||||
endif
|
||||
|
||||
$1_COMMAND_LINE :=
|
||||
ifeq ($$($1_BEGIN_END), true)
|
||||
$1_COMMAND_LINE += -be
|
||||
endif
|
||||
|
||||
ifeq ($$($1_SUBST_EMPTY_LINES), false)
|
||||
$1_COMMAND_LINE += -nel
|
||||
endif
|
||||
|
||||
$1_COMMAND_LINE += $$(foreach k, $$($1_KEYS), -K$$k)
|
||||
$1_COMMAND_LINE += $$(subst $$$$(SPACE), ,$$(foreach d, $$($1_REPLACEMENTS), -D$$d))
|
||||
|
||||
$1_COMMAND_LINE += -i$$($1_SOURCE_FILE) -o$$($1_OUTPUT_FILE).tmp
|
||||
|
||||
ifeq ($$($1_INFO), )
|
||||
$1_INFO := Preprocessing $$(notdir $$($1_SOURCE_FILE)) for $(MODULE)
|
||||
endif
|
||||
|
||||
$$(eval $$(call SetupExecute, RUN_SPP_$1, \
|
||||
INFO := $$($1_INFO), \
|
||||
DEPS := $$($1_SOURCE_FILE) $$(BUILD_TOOLS_JDK), \
|
||||
OUTPUT_FILE := $$($1_OUTPUT_FILE), \
|
||||
COMMAND := $$(TOOL_SPP) $$($1_COMMAND_LINE), \
|
||||
PRE_COMMAND := $$(RM) $$($1_OUTPUT_FILE).tmp $$($1_OUTPUT_FILE), \
|
||||
POST_COMMAND := $$(MV) $$($1_OUTPUT_FILE).tmp $$($1_OUTPUT_FILE), \
|
||||
))
|
||||
|
||||
$1 += $$(RUN_SPP_$1)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
endif # include guard
|
||||
include MakeIncludeEnd.gmk
|
||||
@ -155,12 +155,6 @@ define CreateCompiledNativeFileBody
|
||||
endif
|
||||
$1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
|
||||
-include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
|
||||
else ifeq ($(TOOLCHAIN_TYPE), microsoft)
|
||||
ifeq ($(OPENJDK_TARGET_CPU), aarch64)
|
||||
$1_NON_ASM_EXTENSION_FLAG :=
|
||||
else
|
||||
$1_NON_ASM_EXTENSION_FLAG := "-Ta"
|
||||
endif
|
||||
endif
|
||||
else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
|
||||
# Compile as a C++ or Objective-C++ file
|
||||
@ -242,7 +236,7 @@ define CreateCompiledNativeFileBody
|
||||
# For assembler calls just create empty dependency lists
|
||||
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
|
||||
$$($1_COMPILER) $$($1_FLAGS) \
|
||||
$(CC_OUT_OPTION)$$($1_OBJ) $$($1_NON_ASM_EXTENSION_FLAG) $$($1_SRC_FILE))) \
|
||||
$(CC_OUT_OPTION)$$($1_OBJ) $(AS_NON_ASM_EXTENSION_OPTION) $$($1_SRC_FILE))) \
|
||||
| $(TR) -d '\r' | $(GREP) -v -e "Assembling:" || test "$$$$?" = "1" ; \
|
||||
$(ECHO) > $$($1_DEPS_FILE) ; \
|
||||
$(ECHO) > $$($1_DEPS_TARGETS_FILE)
|
||||
|
||||
@ -113,9 +113,10 @@ define CreateDynamicLibraryOrExecutableMicrosoft
|
||||
$$(CHMOD) +x $$($1_TARGET)
|
||||
endif
|
||||
ifneq ($$($1_MANIFEST), )
|
||||
$$($1_MT) -nologo -manifest $$($1_MANIFEST) \
|
||||
-identity:"$$($1_NAME).exe, version=$$($1_MANIFEST_VERSION)" \
|
||||
-outputresource:$$@;#1
|
||||
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_mt, \
|
||||
$$($1_MT) -nologo -manifest $$($1_MANIFEST) \
|
||||
-identity:"$$($1_NAME).exe$$(COMMA) version=$$($1_MANIFEST_VERSION)" \
|
||||
'-outputresource:$$($1_TARGET);$$(HASH)1')
|
||||
endif
|
||||
ifneq ($(SIGNING_HOOK), )
|
||||
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_call_signing_hook, \
|
||||
|
||||
@ -47,8 +47,9 @@ ifeq ($(call check-jvm-feature, dtrace), true)
|
||||
$(call LogInfo, Generating dtrace header file $(@F))
|
||||
$(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR))
|
||||
$(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, \
|
||||
($(CPP) $(DTRACE_CPP_FLAGS) $(SYSROOT_CFLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d))
|
||||
$(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d)
|
||||
$(CPP) $(DTRACE_CPP_FLAGS) $(SYSROOT_CFLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d)
|
||||
$(call ExecuteWithLog, $@, \
|
||||
$(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d)
|
||||
|
||||
# Process all .d files in DTRACE_SOURCE_DIR. They are:
|
||||
# hotspot_jni.d hotspot.d hs_private.d
|
||||
|
||||
@ -62,13 +62,13 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \
|
||||
DISABLED_WARNINGS_gcc := format-nonliteral maybe-uninitialized undef \
|
||||
unused-result zero-as-null-pointer-constant, \
|
||||
DISABLED_WARNINGS_clang := format-nonliteral undef unused-result, \
|
||||
DISABLED_WARNINGS_microsoft := 4530, \
|
||||
DEFAULT_CFLAGS := false, \
|
||||
CFLAGS := $(JVM_CFLAGS) \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googletest \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include, \
|
||||
CFLAGS_windows := -EHsc, \
|
||||
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
|
||||
OPTIMIZATION := $(JVM_OPTIMIZATION), \
|
||||
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
|
||||
@ -98,7 +98,6 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include \
|
||||
$(addprefix -I, $(GTEST_TEST_SRC)), \
|
||||
CFLAGS_windows := -EHsc, \
|
||||
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
|
||||
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc) \
|
||||
undef stringop-overflow, \
|
||||
@ -110,7 +109,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
|
||||
self-assign-overloaded, \
|
||||
DISABLED_WARNINGS_clang_test_g1ServiceThread.cpp := delete-abstract-non-virtual-dtor, \
|
||||
DISABLED_WARNINGS_clang_test_logDecorations.cpp := missing-field-initializers, \
|
||||
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft), \
|
||||
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft) 4530, \
|
||||
LD_SET_ORIGIN := false, \
|
||||
DEFAULT_LDFLAGS := false, \
|
||||
LDFLAGS := $(JVM_LDFLAGS), \
|
||||
|
||||
@ -97,11 +97,13 @@ CFLAGS_VM_VERSION := \
|
||||
|
||||
DISABLED_WARNINGS_gcc := array-bounds comment delete-non-virtual-dtor \
|
||||
empty-body format-zero-length implicit-fallthrough int-in-bool-context \
|
||||
invalid-offsetof \
|
||||
maybe-uninitialized missing-field-initializers \
|
||||
shift-negative-value unknown-pragmas unused-but-set-variable \
|
||||
unused-local-typedefs unused-variable
|
||||
|
||||
DISABLED_WARNINGS_clang := delete-non-abstract-non-virtual-dtor missing-braces \
|
||||
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
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure ccls
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure clangd
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure RTags
|
||||
|
||||
@ -79,6 +79,7 @@ class Bundle {
|
||||
"NumberElements/nan",
|
||||
"NumberElements/currencyDecimal",
|
||||
"NumberElements/currencyGroup",
|
||||
"NumberElements/lenientMinusSigns",
|
||||
};
|
||||
|
||||
private static final String[] TIME_PATTERN_KEYS = {
|
||||
|
||||
@ -844,6 +844,26 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
|
||||
});
|
||||
break;
|
||||
|
||||
// Lenient parsing
|
||||
case "parseLenients":
|
||||
if ("lenient".equals(attributes.getValue("level"))) {
|
||||
pushKeyContainer(qName, attributes, attributes.getValue("scope"));
|
||||
} else {
|
||||
pushIgnoredContainer(qName);
|
||||
}
|
||||
break;
|
||||
|
||||
case "parseLenient":
|
||||
// Use only the lenient minus sign for now
|
||||
if (currentContainer instanceof KeyContainer kc
|
||||
&& kc.getKey().equals("number")
|
||||
&& attributes.getValue("sample").equals("-")) {
|
||||
pushStringEntry(qName, attributes, currentNumberingSystem + "NumberElements/lenientMinusSigns");
|
||||
} else {
|
||||
pushIgnoredContainer(qName);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// treat anything else as a container
|
||||
pushContainer(qName, attributes);
|
||||
@ -1150,6 +1170,14 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
|
||||
currentStyle = "";
|
||||
putIfEntry();
|
||||
break;
|
||||
case "parseLenient":
|
||||
if (currentContainer instanceof StringEntry se) {
|
||||
// Convert to a simple concatenation of lenient minuses
|
||||
// e.g. "[\--﹣ ‐‑ ‒ – −⁻₋ ➖]" -> "--﹣‐‑‒–−⁻₋➖" for the root locale
|
||||
put(se.getKey(), se.getValue().replaceAll("[\\[\\]\\\\ ]", ""));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
putIfEntry();
|
||||
}
|
||||
|
||||
@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package build.tools.methodhandle;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.classfile.TypeKind;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A helper program to generate the VarHandleGuards class with a set of
|
||||
* static guard methods each of which corresponds to a particular shape and
|
||||
* performs a type check of the symbolic type descriptor with the VarHandle
|
||||
* type descriptor before linking/invoking to the underlying operation as
|
||||
* characterized by the operation member name on the VarForm of the
|
||||
* VarHandle.
|
||||
* <p>
|
||||
* The generated class essentially encapsulates pre-compiled LambdaForms,
|
||||
* one for each method, for the most common set of method signatures.
|
||||
* This reduces static initialization costs, footprint costs, and circular
|
||||
* dependencies that may arise if a class is generated per LambdaForm.
|
||||
* <p>
|
||||
* A maximum of L*T*S methods will be generated where L is the number of
|
||||
* access modes kinds (or unique operation signatures) and T is the number
|
||||
* of variable types and S is the number of shapes (such as instance field,
|
||||
* static field, or array access).
|
||||
* If there are 4 unique operation signatures, 5 basic types (Object, int,
|
||||
* long, float, double), and 3 shapes then a maximum of 60 methods will be
|
||||
* generated. However, the number is likely to be less since there may
|
||||
* be duplicate signatures.
|
||||
* <p>
|
||||
* Each method is annotated with @LambdaForm.Compiled to inform the runtime
|
||||
* that such methods should be treated as if a method of a class that is the
|
||||
* result of compiling a LambdaForm. Annotation of such methods is
|
||||
* important for correct evaluation of certain assertions and method return
|
||||
* type profiling in HotSpot.
|
||||
*
|
||||
* @see java.lang.invoke.GenerateJLIClassesHelper
|
||||
*/
|
||||
public final class VarHandleGuardMethodGenerator {
|
||||
|
||||
static final String CLASS_HEADER = """
|
||||
/*
|
||||
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.vm.annotation.AOTSafeClassInitializer;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Hidden;
|
||||
|
||||
// This file is generated by build.tools.methodhandle.VarHandleGuardMethodGenerator.
|
||||
// Do not edit!
|
||||
@AOTSafeClassInitializer
|
||||
final class VarHandleGuards {
|
||||
""";
|
||||
|
||||
static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
|
||||
|
||||
static final String GUARD_METHOD_TEMPLATE =
|
||||
"""
|
||||
@ForceInline
|
||||
@LambdaForm.Compiled
|
||||
@Hidden
|
||||
static final <METHOD> throws Throwable {
|
||||
boolean direct = handle.checkAccessModeThenIsDirect(ad);
|
||||
if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) {
|
||||
<RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>
|
||||
} else {
|
||||
MethodHandle mh = handle.getMethodHandle(ad.mode);
|
||||
<RETURN>mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);
|
||||
}
|
||||
}""";
|
||||
|
||||
static final String GUARD_METHOD_TEMPLATE_V =
|
||||
"""
|
||||
@ForceInline
|
||||
@LambdaForm.Compiled
|
||||
@Hidden
|
||||
static final <METHOD> throws Throwable {
|
||||
boolean direct = handle.checkAccessModeThenIsDirect(ad);
|
||||
if (direct && handle.vform.methodType_table[ad.type] == ad.symbolicMethodTypeErased) {
|
||||
MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);
|
||||
} else if (direct && handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodTypeErased) {
|
||||
MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);
|
||||
} else {
|
||||
MethodHandle mh = handle.getMethodHandle(ad.mode);
|
||||
mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);
|
||||
}
|
||||
}""";
|
||||
|
||||
// A template for deriving the operations
|
||||
// could be supported by annotating VarHandle directly with the
|
||||
// operation kind and shape
|
||||
interface VarHandleTemplate {
|
||||
Object get();
|
||||
|
||||
void set(Object value);
|
||||
|
||||
boolean compareAndSet(Object actualValue, Object expectedValue);
|
||||
|
||||
Object compareAndExchange(Object actualValue, Object expectedValue);
|
||||
|
||||
Object getAndUpdate(Object value);
|
||||
}
|
||||
|
||||
record HandleType(Class<?> receiver, Class<?>... intermediates) {
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
if (args.length != 1) {
|
||||
System.err.println("Usage: java VarHandleGuardMethodGenerator VarHandleGuards.java");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
Path outputFile = Path.of(args[0]);
|
||||
|
||||
try (PrintWriter pw = new PrintWriter(Files.newBufferedWriter(
|
||||
outputFile,
|
||||
StandardCharsets.UTF_8,
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING))) {
|
||||
print(pw);
|
||||
}
|
||||
}
|
||||
|
||||
public static void print(PrintWriter pw) {
|
||||
pw.println(CLASS_HEADER);
|
||||
|
||||
// Declare the stream of shapes
|
||||
List<HandleType> hts = List.of(
|
||||
// Object->T
|
||||
new HandleType(Object.class),
|
||||
|
||||
// <static>->T
|
||||
new HandleType(null),
|
||||
|
||||
// Array[index]->T
|
||||
new HandleType(Object.class, int.class),
|
||||
|
||||
// MS[base]->T
|
||||
new HandleType(Object.class, long.class),
|
||||
|
||||
// MS[base][offset]->T
|
||||
new HandleType(Object.class, long.class, long.class)
|
||||
);
|
||||
|
||||
// The 5 JVM calling convention types
|
||||
List<Class<?>> basicTypes = List.of(Object.class, int.class, long.class, float.class, double.class);
|
||||
|
||||
Stream.of(VarHandleTemplate.class.getMethods()).<MethodType>
|
||||
mapMulti((m, sink) -> {
|
||||
for (var ht : hts) {
|
||||
for (var bt : basicTypes) {
|
||||
sink.accept(generateMethodType(m, ht.receiver, bt, ht.intermediates));
|
||||
}
|
||||
}
|
||||
}).
|
||||
distinct().
|
||||
map(VarHandleGuardMethodGenerator::generateMethod).
|
||||
forEach(pw::println);
|
||||
|
||||
pw.println("}");
|
||||
}
|
||||
|
||||
static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
Class<?> returnType = m.getReturnType() == Object.class
|
||||
? value : m.getReturnType();
|
||||
|
||||
List<Class<?>> params = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
params.add(receiver);
|
||||
Collections.addAll(params, intermediates);
|
||||
for (var p : m.getParameters()) {
|
||||
params.add(value);
|
||||
}
|
||||
return MethodType.methodType(returnType, params);
|
||||
}
|
||||
|
||||
static String generateMethod(MethodType mt) {
|
||||
Class<?> returnType = mt.returnType();
|
||||
|
||||
var params = new LinkedHashMap<String, String>();
|
||||
params.put("handle", className(VarHandle.class));
|
||||
for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
params.put("arg" + i, className(mt.parameterType(i)));
|
||||
}
|
||||
params.put("ad", "VarHandle.AccessDescriptor");
|
||||
|
||||
// Generate method signature line
|
||||
String RETURN = className(returnType);
|
||||
String NAME = "guard";
|
||||
String SIGNATURE = getSignature(mt);
|
||||
String PARAMS = params.entrySet().stream().
|
||||
map(e -> e.getValue() + " " + e.getKey()).
|
||||
collect(Collectors.joining(", "));
|
||||
String METHOD = GUARD_METHOD_SIG_TEMPLATE.
|
||||
replace("<RETURN>", RETURN).
|
||||
replace("<NAME>", NAME).
|
||||
replace("<SIGNATURE>", SIGNATURE).
|
||||
replace("<PARAMS>", PARAMS);
|
||||
|
||||
// Generate method
|
||||
params.remove("ad");
|
||||
|
||||
List<String> LINK_TO_STATIC_ARGS = new ArrayList<>(params.keySet());
|
||||
LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)");
|
||||
|
||||
List<String> LINK_TO_INVOKER_ARGS = new ArrayList<>(params.keySet());
|
||||
LINK_TO_INVOKER_ARGS.set(0, LINK_TO_INVOKER_ARGS.get(0) + ".asDirect()");
|
||||
|
||||
RETURN = returnType == void.class
|
||||
? ""
|
||||
: returnType == Object.class
|
||||
? "return "
|
||||
: "return (" + returnType.getName() + ") ";
|
||||
|
||||
String RESULT_ERASED = returnType == void.class
|
||||
? ""
|
||||
: returnType != Object.class
|
||||
? "return (" + returnType.getName() + ") "
|
||||
: "Object r = ";
|
||||
|
||||
String RETURN_ERASED = returnType != Object.class
|
||||
? ""
|
||||
: "\n return ad.returnType.cast(r);";
|
||||
|
||||
String template = returnType == void.class
|
||||
? GUARD_METHOD_TEMPLATE_V
|
||||
: GUARD_METHOD_TEMPLATE;
|
||||
return template.
|
||||
replace("<METHOD>", METHOD).
|
||||
replace("<NAME>", NAME).
|
||||
replaceAll("<RETURN>", RETURN).
|
||||
replace("<RESULT_ERASED>", RESULT_ERASED).
|
||||
replace("<RETURN_ERASED>", RETURN_ERASED).
|
||||
replaceAll("<LINK_TO_STATIC_ARGS>", String.join(", ", LINK_TO_STATIC_ARGS)).
|
||||
replace("<LINK_TO_INVOKER_ARGS>", String.join(", ", LINK_TO_INVOKER_ARGS))
|
||||
.indent(4);
|
||||
}
|
||||
|
||||
static String className(Class<?> c) {
|
||||
String n = c.getCanonicalName();
|
||||
if (n == null)
|
||||
throw new IllegalArgumentException("Not representable in source code: " + c);
|
||||
if (!c.isPrimitive() && c.getPackageName().equals("java.lang")) {
|
||||
n = n.substring("java.lang.".length());
|
||||
} else if (c.getPackageName().equals("java.lang.invoke")) {
|
||||
n = n.substring("java.lang.invoke.".length());
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static String getSignature(MethodType m) {
|
||||
StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
|
||||
|
||||
for (int i = 0; i < m.parameterCount(); i++) {
|
||||
Class<?> pt = m.parameterType(i);
|
||||
sb.append(getCharType(pt));
|
||||
}
|
||||
|
||||
sb.append('_').append(getCharType(m.returnType()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static char getCharType(Class<?> pt) {
|
||||
return TypeKind.from(pt).upperBound().descriptorString().charAt(0);
|
||||
}
|
||||
}
|
||||
@ -26,6 +26,8 @@
|
||||
################################################################################
|
||||
|
||||
include GensrcCommon.gmk
|
||||
include GensrcProperties.gmk
|
||||
include GensrcStreamPreProcessing.gmk
|
||||
|
||||
include gensrc/GensrcBuffer.gmk
|
||||
include gensrc/GensrcCharacterData.gmk
|
||||
@ -71,8 +73,6 @@ TARGETS += $(CLDR_GEN_DONE)
|
||||
|
||||
################################################################################
|
||||
|
||||
include GensrcProperties.gmk
|
||||
|
||||
$(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \
|
||||
SRC_DIRS := $(MODULE_SRC)/share/classes/sun/launcher/resources, \
|
||||
CLASS := ListResourceBundle, \
|
||||
|
||||
@ -28,363 +28,222 @@ ifeq ($(INCLUDE), true)
|
||||
|
||||
################################################################################
|
||||
|
||||
GENSRC_BUFFER :=
|
||||
BUFFER_INPUT_DIR := $(MODULE_SRC)/share/classes/java/nio
|
||||
BUFFER_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio
|
||||
|
||||
GENSRC_BUFFER_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio
|
||||
################################################################################
|
||||
# Helper method to setup generation of bin snippets.
|
||||
# Will add the generated snippet file name to $1_BIN_SNIPPET_FILES.
|
||||
#
|
||||
# arg $1: $1 as passed into SetupGenBuffer
|
||||
# arg $2: type for this bin snippet
|
||||
define SetupGenBufferBinSnippets
|
||||
$1_$2_TMP := $$(BUFFER_OUTPUT_DIR)/$1.java.bin-snippet.$2
|
||||
|
||||
GENSRC_BUFFER_SRC := $(MODULE_SRC)/share/classes/java/nio
|
||||
|
||||
###
|
||||
|
||||
$(GENSRC_BUFFER_DST)/_the.buffer.dir:
|
||||
$(call LogInfo, Generating buffer classes)
|
||||
$(call MakeDir, $(@D))
|
||||
$(TOUCH) $@
|
||||
|
||||
define fixRw
|
||||
$1_RW := $2
|
||||
$1_rwkey := rw
|
||||
ifeq (R, $2)
|
||||
$1_rwkey := ro
|
||||
endif
|
||||
endef
|
||||
|
||||
define typesAndBits
|
||||
# param 1 target
|
||||
# param 2 type
|
||||
# param 3 BO
|
||||
$1_a := a
|
||||
$1_A := A
|
||||
|
||||
$1_type := $2
|
||||
|
||||
ifeq ($2, byte)
|
||||
$1_x := b
|
||||
$1_Type := Byte
|
||||
$1_fulltype := byte
|
||||
$1_Fulltype := Byte
|
||||
$1_category := integralType
|
||||
$1_LBPV := 0
|
||||
endif
|
||||
|
||||
ifeq ($2, char)
|
||||
$1_x := c
|
||||
$1_Type := Char
|
||||
$1_fulltype := character
|
||||
$1_Fulltype := Character
|
||||
$1_category := integralType
|
||||
$1_streams := streamableType
|
||||
$1_streamtype := int
|
||||
$1_Streamtype := Int
|
||||
$1_LBPV := 1
|
||||
endif
|
||||
|
||||
ifeq ($2, short)
|
||||
$1_x := s
|
||||
$1_Type := Short
|
||||
$1_fulltype := short
|
||||
$1_Fulltype := Short
|
||||
$1_category := integralType
|
||||
$1_LBPV := 1
|
||||
endif
|
||||
|
||||
ifeq ($2, int)
|
||||
$1_a := an
|
||||
$1_A := An
|
||||
$1_x := i
|
||||
$1_Type := Int
|
||||
$1_fulltype := integer
|
||||
$1_Fulltype := Integer
|
||||
$1_category := integralType
|
||||
$1_LBPV := 2
|
||||
endif
|
||||
|
||||
ifeq ($2, long)
|
||||
$1_x := l
|
||||
$1_Type := Long
|
||||
$1_fulltype := long
|
||||
$1_Fulltype := Long
|
||||
$1_category := integralType
|
||||
$1_LBPV := 3
|
||||
endif
|
||||
|
||||
ifeq ($2, float)
|
||||
$1_x := f
|
||||
$1_Type := Float
|
||||
$1_fulltype := float
|
||||
$1_Fulltype := Float
|
||||
$1_category := floatingPointType
|
||||
$1_LBPV := 2
|
||||
endif
|
||||
|
||||
ifeq ($2, double)
|
||||
$1_x := d
|
||||
$1_Type := Double
|
||||
$1_fulltype := double
|
||||
$1_Fulltype := Double
|
||||
$1_category := floatingPointType
|
||||
$1_LBPV := 3
|
||||
endif
|
||||
|
||||
$1_Swaptype := $$($1_Type)
|
||||
$1_memtype := $2
|
||||
$1_Memtype := $$($1_Type)
|
||||
|
||||
ifeq ($2, float)
|
||||
$1_memtype := int
|
||||
$1_Memtype := Int
|
||||
ifneq ($3, U)
|
||||
$1_Swaptype := Int
|
||||
$1_fromBits := Float.intBitsToFloat
|
||||
$1_toBits := Float.floatToRawIntBits
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($2, double)
|
||||
$1_memtype := long
|
||||
$1_Memtype := Long
|
||||
ifneq ($3, U)
|
||||
$1_Swaptype := Long
|
||||
$1_fromBits := Double.longBitsToDouble
|
||||
$1_toBits := Double.doubleToRawLongBits
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($3, S)
|
||||
$1_swap := Bits.swap
|
||||
endif
|
||||
endef
|
||||
|
||||
define genBinOps
|
||||
# param 1 target
|
||||
# param 2 type
|
||||
# param 3 BO
|
||||
# param 4 RW
|
||||
# param 5 nbytes
|
||||
# param 6 nbytesButOne
|
||||
$(call typesAndBits,$1,$2,$3)
|
||||
$(call fixRw,$1,$4)
|
||||
$1_nbytes := $5
|
||||
$1_nbytesButOne := $6
|
||||
$1_CMD := $(TOOL_SPP) \
|
||||
-Dtype=$$($1_type) \
|
||||
-DType=$$($1_Type) \
|
||||
-Dfulltype=$$($1_fulltype) \
|
||||
-Dmemtype=$$($1_memtype) \
|
||||
-DMemtype=$$($1_Memtype) \
|
||||
-DfromBits=$$($1_fromBits) \
|
||||
-DtoBits=$$($1_toBits) \
|
||||
-DLG_BYTES_PER_VALUE=$$($1_LBPV) \
|
||||
-DBYTES_PER_VALUE="(1 << $$($1_LBPV))" \
|
||||
-Dnbytes=$$($1_nbytes) \
|
||||
-DnbytesButOne=$$($1_nbytesButOne) \
|
||||
-DRW=$$($1_RW) \
|
||||
-K$$($1_rwkey) \
|
||||
-Da=$$($1_a) \
|
||||
-be
|
||||
endef
|
||||
|
||||
define SetupGenBuffer
|
||||
# param 1 is for output file
|
||||
# param 2 is template dependency
|
||||
# param 3-9 are named args.
|
||||
# type :=
|
||||
# BIN :=
|
||||
# RW := Mutability (R)ead-only (W)ritable
|
||||
# BO := (U)nswapped/(S)wapped/(L)ittle/(B)ig
|
||||
#
|
||||
$(if $3,$1_$(strip $3))
|
||||
$(if $4,$1_$(strip $4))
|
||||
$(if $5,$1_$(strip $5))
|
||||
$(if $6,$1_$(strip $6))
|
||||
$(if $7,$1_$(strip $7))
|
||||
$(if $8,$1_$(strip $8))
|
||||
$(if $9,$1_$(strip $9))
|
||||
$(if $(10),$1_$(strip $(10)))
|
||||
$(if $(11),$1_$(strip $(11)))
|
||||
$(if $(12),$1_$(strip $(12)))
|
||||
$(if $(13),$1_$(strip $(13)))
|
||||
$(if $(14),$1_$(strip $(14)))
|
||||
$(foreach i,3 4 5 6 7 8 9 10 11 12 13 14 15,$(if $($i),$1_$(strip $($i)))$(NEWLINE))
|
||||
$(call LogSetupMacroEntry,SetupGenBuffer($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15))
|
||||
$(if $(16),$(error Internal makefile error: Too many arguments to SetupGenBuffer, please update GensrcBuffer.gmk))
|
||||
|
||||
$(call fixRw,$1,$$($1_RW))
|
||||
$(call typesAndBits,$1,$$($1_type),$$($1_BO))
|
||||
|
||||
$1_DST := $(GENSRC_BUFFER_DST)/$1.java
|
||||
$1_SRC := $(GENSRC_BUFFER_SRC)/$(strip $2).java.template
|
||||
$1_SRC_BIN := $(GENSRC_BUFFER_SRC)/$(strip $2)-bin.java.template
|
||||
|
||||
$1_DEP := $$($1_SRC)
|
||||
ifneq ($$($1_BIN), 1)
|
||||
$1_DEP := $$($1_SRC)
|
||||
$1_OUT := $$($1_DST)
|
||||
$1_$2_LBPV := $$(call Conv, $2, LBPV)
|
||||
ifeq ($$($1_READ_ONLY), true)
|
||||
$1_$2_RW_KEYS := ro
|
||||
$1_$2_RW_REPLACEMENT := R
|
||||
else
|
||||
$1_DEP += $$($1_SRC) $$($1_SRC_BIN)
|
||||
$1_OUT := $(GENSRC_BUFFER_DST)/$1.binop.0.java
|
||||
$1_$2_RW_KEYS := rw
|
||||
$1_$2_RW_REPLACEMENT :=
|
||||
endif
|
||||
|
||||
ifeq ($$($1_BIN), 1)
|
||||
$(call genBinOps,$1_char,char,$$($1_BO),$$($1_RW),two,one)
|
||||
$(call genBinOps,$1_short,short,$$($1_BO),$$($1_RW),two,one)
|
||||
$(call genBinOps,$1_int,int,$$($1_BO),$$($1_RW),four,three)
|
||||
$(call genBinOps,$1_long,long,$$($1_BO),$$($1_RW),eight,seven)
|
||||
$(call genBinOps,$1_float,float,$$($1_BO),$$($1_RW),four,three)
|
||||
$(call genBinOps,$1_double,double,$$($1_BO),$$($1_RW),eight,seven)
|
||||
endif
|
||||
|
||||
$$($1_DST): $$($1_DEP) $(GENSRC_BUFFER_DST)/_the.buffer.dir
|
||||
$(RM) $$($1_OUT).tmp
|
||||
$(TOOL_SPP) -i$$($1_SRC) -o$$($1_OUT).tmp \
|
||||
-K$$($1_type) \
|
||||
-K$$($1_category) \
|
||||
-K$$($1_streams) \
|
||||
-Dtype=$$($1_type) \
|
||||
-DType=$$($1_Type) \
|
||||
-Dfulltype=$$($1_fulltype) \
|
||||
-DFulltype=$$($1_Fulltype) \
|
||||
-Dstreamtype=$$($1_streamtype) \
|
||||
-DStreamtype=$$($1_Streamtype) \
|
||||
-Dx=$$($1_x) \
|
||||
-Dmemtype=$$($1_memtype) \
|
||||
-DMemtype=$$($1_Memtype) \
|
||||
-DSwaptype=$$($1_Swaptype) \
|
||||
-DfromBits=$$($1_fromBits) \
|
||||
-DtoBits=$$($1_toBits) \
|
||||
-DLG_BYTES_PER_VALUE=$$($1_LBPV) \
|
||||
-DBYTES_PER_VALUE="(1 << $$($1_LBPV))" \
|
||||
-DBO=$$($1_BO) \
|
||||
-Dswap=$$($1_swap) \
|
||||
-DRW=$$($1_RW) \
|
||||
-K$$($1_rwkey) \
|
||||
-Da=$$($1_a) \
|
||||
-DA=$$($1_A) \
|
||||
-Kbo$$($1_BO)
|
||||
$(MV) $$($1_OUT).tmp $$($1_OUT)
|
||||
# Do the extra bin thing
|
||||
ifeq ($$($1_BIN), 1)
|
||||
$(SED) -e '/#BIN/,$$$$d' < $$($1_OUT) > $$($1_DST).tmp
|
||||
$(RM) $$($1_OUT)
|
||||
$$($1_char_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$$($1_short_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$$($1_int_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$$($1_long_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$$($1_float_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$$($1_double_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp
|
||||
$(ECHO) "}" >> $$($1_DST).tmp
|
||||
mv $$($1_DST).tmp $$($1_DST)
|
||||
endif
|
||||
|
||||
GENSRC_BUFFER += $$($1_DST)
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_BUFFER_BIN_$1_$2, \
|
||||
SOURCE_FILE := $$(BUFFER_INPUT_DIR)/$$($1_TEMPLATE)-bin.java.template, \
|
||||
OUTPUT_FILE := $$($1_$2_TMP), \
|
||||
INFO := Generating buffer class bin snippets for $1 ($2), \
|
||||
BEGIN_END := true, \
|
||||
KEYS := \
|
||||
$$($1_$2_RW_KEYS), \
|
||||
REPLACEMENTS := \
|
||||
type=$2 \
|
||||
RW=$$($1_$2_RW_REPLACEMENT) \
|
||||
LG_BYTES_PER_VALUE=$$($1_$2_LBPV) \
|
||||
BYTES_PER_VALUE="(1$$$$(SPACE)<<$$$$(SPACE)$$($1_$2_LBPV))" \
|
||||
a=$$(call Conv, $2, a) \
|
||||
fulltype=$$(call Conv, $2, fulltype) \
|
||||
memtype=$$(call Conv, $2, memtype) \
|
||||
Memtype=$$(call Conv, $2, Memtype) \
|
||||
nbytes=$$(call Conv, $2, nbytes) \
|
||||
nbytesButOne=$$(call Conv, $2, nbytesButOne) \
|
||||
Type=$$(call Conv, $2, Type) \
|
||||
fromBits=$$(call Conv, $2, fromBits, $$($1_BYTE_ORDER)) \
|
||||
toBits=$$(call Conv, $2, toBits, $$($1_BYTE_ORDER)), \
|
||||
))
|
||||
TARGETS += $$(GEN_BUFFER_$1_$2)
|
||||
|
||||
$1_BIN_SNIPPET_FILES += $$($1_$2_TMP)
|
||||
endef
|
||||
|
||||
###
|
||||
|
||||
X_BUF := X-Buffer
|
||||
|
||||
$(eval $(call SetupGenBuffer,ByteBuffer, $(X_BUF), type := byte, BIN := 1))
|
||||
$(eval $(call SetupGenBuffer,CharBuffer, $(X_BUF), type := char))
|
||||
$(eval $(call SetupGenBuffer,ShortBuffer, $(X_BUF), type := short))
|
||||
$(eval $(call SetupGenBuffer,IntBuffer, $(X_BUF), type := int))
|
||||
$(eval $(call SetupGenBuffer,LongBuffer, $(X_BUF), type := long))
|
||||
$(eval $(call SetupGenBuffer,FloatBuffer, $(X_BUF), type := float))
|
||||
$(eval $(call SetupGenBuffer,DoubleBuffer,$(X_BUF), type := double))
|
||||
|
||||
# Buffers whose contents are heap-allocated
|
||||
################################################################################
|
||||
# Setup make rules that creates a generated buffer class java source file,
|
||||
# according to specifications provided.
|
||||
#
|
||||
HEAP_X_BUF := Heap-X-Buffer
|
||||
|
||||
$(eval $(call SetupGenBuffer,HeapByteBuffer, $(HEAP_X_BUF), type := byte))
|
||||
$(eval $(call SetupGenBuffer,HeapByteBufferR, $(HEAP_X_BUF), type := byte, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapCharBuffer, $(HEAP_X_BUF), type := char))
|
||||
$(eval $(call SetupGenBuffer,HeapCharBufferR, $(HEAP_X_BUF), type := char, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapShortBuffer, $(HEAP_X_BUF), type := short))
|
||||
$(eval $(call SetupGenBuffer,HeapShortBufferR, $(HEAP_X_BUF), type := short, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapIntBuffer, $(HEAP_X_BUF), type := int))
|
||||
$(eval $(call SetupGenBuffer,HeapIntBufferR, $(HEAP_X_BUF), type := int, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapLongBuffer, $(HEAP_X_BUF), type := long))
|
||||
$(eval $(call SetupGenBuffer,HeapLongBufferR, $(HEAP_X_BUF), type := long, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapFloatBuffer, $(HEAP_X_BUF), type := float))
|
||||
$(eval $(call SetupGenBuffer,HeapFloatBufferR, $(HEAP_X_BUF), type := float, RW := R))
|
||||
$(eval $(call SetupGenBuffer,HeapDoubleBuffer, $(HEAP_X_BUF), type := double))
|
||||
$(eval $(call SetupGenBuffer,HeapDoubleBufferR,$(HEAP_X_BUF), type := double, RW := R))
|
||||
|
||||
# Direct byte buffer
|
||||
# Parameter 1 is the name of the rule. This name is used as variable prefix,
|
||||
# and the targets generated are listed in a variable by that name. The output
|
||||
# file name is also based on this.
|
||||
#
|
||||
DIRECT_X_BUF := Direct-X-Buffer
|
||||
|
||||
$(eval $(call SetupGenBuffer,DirectByteBuffer, $(DIRECT_X_BUF), type := byte, BIN := 1))
|
||||
$(eval $(call SetupGenBuffer,DirectByteBufferR,$(DIRECT_X_BUF), type := byte, BIN := 1, RW := R))
|
||||
|
||||
# Unswapped views of direct byte buffers
|
||||
# Remaining parameters are named arguments. These include:
|
||||
# TYPE The native type
|
||||
# TEMPLATE The base file name of the template to use
|
||||
# BYTE_ORDER (U)nswapped/(S)wapped/(L)ittle/(B)ig
|
||||
# READ_ONLY Set to true to generate read-only buffers (default: false)
|
||||
# GENERATE_BIN Set to true to generate bin snippets (default: false)
|
||||
#
|
||||
$(eval $(call SetupGenBuffer,DirectCharBufferU, $(DIRECT_X_BUF), type := char, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectCharBufferRU, $(DIRECT_X_BUF), type := char, RW := R, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectShortBufferU, $(DIRECT_X_BUF), type := short, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectShortBufferRU, $(DIRECT_X_BUF), type := short, RW := R, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectIntBufferU, $(DIRECT_X_BUF), type := int, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectIntBufferRU, $(DIRECT_X_BUF), type := int, RW := R, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectLongBufferU, $(DIRECT_X_BUF), type := long, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectLongBufferRU, $(DIRECT_X_BUF), type := long, RW := R, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectFloatBufferU, $(DIRECT_X_BUF), type := float, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectFloatBufferRU, $(DIRECT_X_BUF), type := float, RW := R, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectDoubleBufferU, $(DIRECT_X_BUF), type := double, BO := U))
|
||||
$(eval $(call SetupGenBuffer,DirectDoubleBufferRU,$(DIRECT_X_BUF), type := double, RW := R, BO := U))
|
||||
SetupGenBuffer = $(NamedParamsMacroTemplate)
|
||||
define SetupGenBufferBody
|
||||
$1_OUTPUT := $$(BUFFER_OUTPUT_DIR)/$1.java
|
||||
ifeq ($$($1_GENERATE_BIN), true)
|
||||
# After generating the buffer class, we need to do further post processing,
|
||||
# so output to a temporary file
|
||||
$1_REAL_OUTPUT := $$($1_OUTPUT)
|
||||
$1_OUTPUT := $$($1_OUTPUT).bin-snippet.tmp
|
||||
endif
|
||||
|
||||
# Swapped views of direct byte buffers
|
||||
$1_LBPV := $$(call Conv, $$($1_TYPE), LBPV)
|
||||
ifeq ($$($1_READ_ONLY), true)
|
||||
$1_RW_KEYS := ro
|
||||
$1_RW_REPLACEMENT := R
|
||||
else
|
||||
$1_RW_KEYS := rw
|
||||
$1_RW_REPLACEMENT :=
|
||||
endif
|
||||
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_BUFFER_$1, \
|
||||
SOURCE_FILE := $$(BUFFER_INPUT_DIR)/$$($1_TEMPLATE).java.template, \
|
||||
OUTPUT_FILE := $$($1_OUTPUT), \
|
||||
INFO := Generating buffer class $1.java, \
|
||||
KEYS := \
|
||||
$$($1_TYPE) \
|
||||
$$($1_RW_KEYS) \
|
||||
bo$$($1_BYTE_ORDER) \
|
||||
$$(call Conv, $$($1_TYPE), category) \
|
||||
$$(call Conv, $$($1_TYPE), streams), \
|
||||
REPLACEMENTS := \
|
||||
type=$$($1_TYPE) \
|
||||
BO=$$($1_BYTE_ORDER) \
|
||||
RW=$$($1_RW_REPLACEMENT) \
|
||||
LG_BYTES_PER_VALUE=$$($1_LBPV) \
|
||||
BYTES_PER_VALUE="(1$$$$(SPACE)<<$$$$(SPACE)$$($1_$2_LBPV))" \
|
||||
a=$$(call Conv, $$($1_TYPE), a) \
|
||||
A=$$(call Conv, $$($1_TYPE), A) \
|
||||
fulltype=$$(call Conv, $$($1_TYPE), fulltype) \
|
||||
Fulltype=$$(call Conv, $$($1_TYPE), Fulltype) \
|
||||
memtype=$$(call Conv, $$($1_TYPE), memtype) \
|
||||
Memtype=$$(call Conv, $$($1_TYPE), Memtype) \
|
||||
streamtype=$$(call Conv, $$($1_TYPE), streamtype) \
|
||||
Streamtype=$$(call Conv, $$($1_TYPE), Streamtype) \
|
||||
Type=$$(call Conv, $$($1_TYPE), Type) \
|
||||
x=$$(call Conv, $$($1_TYPE), x) \
|
||||
fromBits=$$(call Conv, $$($1_TYPE), fromBits, $$($1_BYTE_ORDER)) \
|
||||
toBits=$$(call Conv, $$($1_TYPE), toBits, $$($1_BYTE_ORDER)) \
|
||||
swap=$$(call Conv, $$($1_TYPE), swap, $$($1_BYTE_ORDER)) \
|
||||
Swaptype=$$(call Conv, $$($1_TYPE), Swaptype, $$($1_BYTE_ORDER)), \
|
||||
))
|
||||
TARGETS += $$(GEN_BUFFER_$1)
|
||||
$1 += $$(GEN_BUFFER_$1)
|
||||
|
||||
ifeq ($$($1_GENERATE_BIN), true)
|
||||
# Setup generation of snippet files, one for each non-byte type. This will
|
||||
# populate $1_BIN_SNIPPET_FILES.
|
||||
$1_BIN_SNIPPET_FILES :=
|
||||
$$(foreach t, $$(NON_BYTE_NUMBER_TYPES), \
|
||||
$$(eval $$(call SetupGenBufferBinSnippets,$1,$$t)) \
|
||||
)
|
||||
|
||||
# Inject these snippets in the file generated by GEN_BUFFER_$1
|
||||
$$($1_REAL_OUTPUT): $$($1_OUTPUT) $$($1_BIN_SNIPPET_FILES)
|
||||
$$(call LogInfo, Concatenating buffer class bin snippets for $1)
|
||||
# Delete everything from the line containing #BIN and below
|
||||
$$(SED) -e '/#BIN/,$$$$d' < $$($1_OUTPUT) > $$($1_REAL_OUTPUT).tmp
|
||||
$$(CAT) $$($1_BIN_SNIPPET_FILES) >> $$($1_REAL_OUTPUT).tmp
|
||||
$$(ECHO) "}" >> $$($1_REAL_OUTPUT).tmp
|
||||
$$(MV) $$($1_REAL_OUTPUT).tmp $$($1_REAL_OUTPUT)
|
||||
|
||||
TARGETS += $$($1_REAL_OUTPUT)
|
||||
$1 += $$($1_REAL_OUTPUT)
|
||||
endif
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
# Helper method to setup generation of all buffer classes, for a given
|
||||
# modifiability state (read-only or not)
|
||||
#
|
||||
$(eval $(call SetupGenBuffer,DirectCharBufferS, $(DIRECT_X_BUF), type := char, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectCharBufferRS, $(DIRECT_X_BUF), type := char, RW := R, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectShortBufferS, $(DIRECT_X_BUF), type := short, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectShortBufferRS, $(DIRECT_X_BUF), type := short, RW := R, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectIntBufferS, $(DIRECT_X_BUF), type := int, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectIntBufferRS, $(DIRECT_X_BUF), type := int, RW := R, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectLongBufferS, $(DIRECT_X_BUF), type := long, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectLongBufferRS, $(DIRECT_X_BUF), type := long, RW := R, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectFloatBufferS, $(DIRECT_X_BUF), type := float, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectFloatBufferRS, $(DIRECT_X_BUF), type := float, RW := R, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectDoubleBufferS, $(DIRECT_X_BUF), type := double, BO := S))
|
||||
$(eval $(call SetupGenBuffer,DirectDoubleBufferRS,$(DIRECT_X_BUF), type := double, RW := R, BO := S))
|
||||
# arg $1: READ_ONLY argument, true or false
|
||||
# arg $2: Modifiability marker for class name (R or empty)
|
||||
define SetupGenerateBuffersWithRO
|
||||
ifeq ($1, false)
|
||||
# The basic buffer classes are not generated in READ_ONLY versions
|
||||
$$(eval $$(call SetupGenBuffer, ByteBuffer, \
|
||||
TYPE := byte, \
|
||||
TEMPLATE := X-Buffer, \
|
||||
GENERATE_BIN := true, \
|
||||
))
|
||||
TARGETS += $$(ByteBuffer)
|
||||
|
||||
# Big-endian views of byte buffers
|
||||
#
|
||||
BYTE_X_BUF := ByteBufferAs-X-Buffer
|
||||
$$(foreach t, $$(NON_BYTE_NUMBER_TYPES), \
|
||||
$$(eval $$(call SetupGenBuffer, $$(call titlecase, $$t)Buffer, \
|
||||
TYPE := $$t, \
|
||||
TEMPLATE := X-Buffer, \
|
||||
)) \
|
||||
$$(eval TARGETS += $$($$(call titlecase, $$t)Buffer)) \
|
||||
)
|
||||
endif
|
||||
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsCharBufferB, $(BYTE_X_BUF), type := char, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsCharBufferRB, $(BYTE_X_BUF), type := char, RW := R, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsShortBufferB, $(BYTE_X_BUF), type := short, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsShortBufferRB, $(BYTE_X_BUF), type := short, RW := R, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsIntBufferB, $(BYTE_X_BUF), type := int, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsIntBufferRB, $(BYTE_X_BUF), type := int, RW := R, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsLongBufferB, $(BYTE_X_BUF), type := long, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsLongBufferRB, $(BYTE_X_BUF), type := long, RW := R, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsFloatBufferB, $(BYTE_X_BUF), type := float, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsFloatBufferRB, $(BYTE_X_BUF), type := float, RW := R, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsDoubleBufferB, $(BYTE_X_BUF), type := double, BO := B))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsDoubleBufferRB,$(BYTE_X_BUF), type := double, RW := R, BO := B))
|
||||
# Buffers whose contents are heap-allocated, one for every type
|
||||
$$(foreach t, $$(NUMBER_TYPES), \
|
||||
$$(eval $$(call SetupGenBuffer, Heap$$(call titlecase, $$t)Buffer$2, \
|
||||
TYPE := $$t, \
|
||||
TEMPLATE := Heap-X-Buffer, \
|
||||
READ_ONLY := $1, \
|
||||
)) \
|
||||
$$(eval TARGETS += $$(Heap$$(call titlecase, $$t)Buffer$2)) \
|
||||
)
|
||||
|
||||
# Little-endian views of byte buffers
|
||||
#
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsCharBufferL, $(BYTE_X_BUF), type := char, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsCharBufferRL, $(BYTE_X_BUF), type := char, RW := R, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsShortBufferL, $(BYTE_X_BUF), type := short, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsShortBufferRL, $(BYTE_X_BUF), type := short, RW := R, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsIntBufferL, $(BYTE_X_BUF), type := int, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsIntBufferRL, $(BYTE_X_BUF), type := int, RW := R, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsLongBufferL, $(BYTE_X_BUF), type := long, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsLongBufferRL, $(BYTE_X_BUF), type := long, RW := R, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsFloatBufferL, $(BYTE_X_BUF), type := float, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsFloatBufferRL, $(BYTE_X_BUF), type := float, RW := R, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsDoubleBufferL, $(BYTE_X_BUF), type := double, BO := L))
|
||||
$(eval $(call SetupGenBuffer,ByteBufferAsDoubleBufferRL,$(BYTE_X_BUF), type := double, RW := R, BO := L))
|
||||
# Treat byte special for DirectByteBuffer classes
|
||||
$$(eval $$(call SetupGenBuffer, DirectByteBuffer$2, \
|
||||
TEMPLATE := Direct-X-Buffer, \
|
||||
TYPE := byte, \
|
||||
GENERATE_BIN := true, \
|
||||
READ_ONLY := $1, \
|
||||
))
|
||||
TARGETS += $$(DirectByteBuffer$2)
|
||||
|
||||
###
|
||||
# Generate Swapped and Unswapped views of the direct byte buffers, each for
|
||||
# every non-byte type
|
||||
$$(foreach b, U S, \
|
||||
$$(foreach t, $$(NON_BYTE_NUMBER_TYPES), \
|
||||
$$(eval $$(call SetupGenBuffer, Direct$$(call titlecase, $$t)Buffer$2$$b, \
|
||||
TYPE := $$t, \
|
||||
TEMPLATE := Direct-X-Buffer, \
|
||||
BYTE_ORDER := $$b, \
|
||||
READ_ONLY := $1, \
|
||||
)) \
|
||||
$$(eval TARGETS += $$(Direct$$(call titlecase, $$t)Buffer$2$$b)) \
|
||||
) \
|
||||
)
|
||||
|
||||
$(GENSRC_BUFFER): $(BUILD_TOOLS_JDK)
|
||||
# Generate Big and Little endian views of the direct byte buffers, each for
|
||||
# every non-byte type
|
||||
$$(foreach b, B L, \
|
||||
$$(foreach t, $$(NON_BYTE_NUMBER_TYPES), \
|
||||
$$(eval $$(call SetupGenBuffer, ByteBufferAs$$(call titlecase, $$t)Buffer$2$$b, \
|
||||
TYPE := $$t, \
|
||||
TEMPLATE := ByteBufferAs-X-Buffer, \
|
||||
BYTE_ORDER := $$b, \
|
||||
READ_ONLY := $1, \
|
||||
)) \
|
||||
$$(eval TARGETS += $$(ByteBufferAs$$(call titlecase, $$t)Buffer$2$$b)) \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
TARGETS += $(GENSRC_BUFFER)
|
||||
################################################################################
|
||||
# Generate buffers in both read-write and read-only variants for all buffers
|
||||
|
||||
$(eval $(call SetupGenerateBuffersWithRO,false,))
|
||||
$(eval $(call SetupGenerateBuffersWithRO,true,R))
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -28,91 +28,74 @@ ifeq ($(INCLUDE), true)
|
||||
|
||||
################################################################################
|
||||
|
||||
GENSRC_CHARSETCODER :=
|
||||
|
||||
GENSRC_CHARSETCODER_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio/charset
|
||||
|
||||
GENSRC_CHARSETCODER_SRC := $(MODULE_SRC)/share/classes/java/nio
|
||||
|
||||
GENSRC_CHARSETCODER_TEMPLATE := $(GENSRC_CHARSETCODER_SRC)/charset/Charset-X-Coder.java.template
|
||||
CHARSETCODER_INPUT := $(MODULE_SRC)/share/classes/java/nio/charset/Charset-X-Coder.java.template
|
||||
CHARSETCODER_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio/charset
|
||||
|
||||
################################################################################
|
||||
|
||||
$(GENSRC_CHARSETCODER_DST)/CharsetDecoder.java: $(GENSRC_CHARSETCODER_TEMPLATE)
|
||||
$(call MakeTargetDir)
|
||||
$(RM) $@.tmp
|
||||
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/gensrc/java.base/_charset_decoder, \
|
||||
$(TOOL_SPP) -i$< -o$@.tmp \
|
||||
-Kdecoder \
|
||||
-DA='A' \
|
||||
-Da='a' \
|
||||
-DCode='Decode' \
|
||||
-Dcode='decode' \
|
||||
-DitypesPhrase='bytes in a specific charset' \
|
||||
-DotypesPhrase='sixteen-bit Unicode characters' \
|
||||
-Ditype='byte' \
|
||||
-Dotype='character' \
|
||||
-DItype='Byte' \
|
||||
-DOtype='Char' \
|
||||
-Dcoder='decoder' \
|
||||
-DCoder='Decoder' \
|
||||
-Dcoding='decoding' \
|
||||
-DOtherCoder='Encoder' \
|
||||
-DreplTypeName='string' \
|
||||
-DdefaultRepl='"\\uFFFD"' \
|
||||
-DdefaultReplName='<code>"\\uFFFD"<\/code>' \
|
||||
-DreplType='String' \
|
||||
-DreplFQType='java.lang.String' \
|
||||
-DreplLength='length()' \
|
||||
-DItypesPerOtype='CharsPerByte' \
|
||||
-DnotLegal='not legal for this charset' \
|
||||
-Dotypes-per-itype='chars-per-byte' \
|
||||
-DoutSequence='Unicode character')
|
||||
$(MV) $@.tmp $@
|
||||
$(eval $(call SetupStreamPreProcessing, GEN_CHARSETDECODER, \
|
||||
SOURCE_FILE := $(CHARSETCODER_INPUT), \
|
||||
OUTPUT_FILE := $(CHARSETCODER_OUTPUT_DIR)/CharsetDecoder.java, \
|
||||
INFO := Generating CharsetDecoder.java, \
|
||||
KEYS := decoder, \
|
||||
REPLACEMENTS := \
|
||||
A='A' \
|
||||
a='a' \
|
||||
Code='Decode' \
|
||||
code='decode' \
|
||||
itypesPhrase='bytes$$(SPACE)in$$(SPACE)a$$(SPACE)specific$$(SPACE)charset' \
|
||||
otypesPhrase='sixteen-bit$$(SPACE)Unicode$$(SPACE)characters' \
|
||||
itype='byte' \
|
||||
otype='character' \
|
||||
Itype='Byte' \
|
||||
Otype='Char' \
|
||||
coder='decoder' \
|
||||
Coder='Decoder' \
|
||||
coding='decoding' \
|
||||
OtherCoder='Encoder' \
|
||||
replTypeName='string' \
|
||||
replType='String' \
|
||||
replFQType='java.lang.String' \
|
||||
replLength='length()' \
|
||||
ItypesPerOtype='CharsPerByte' \
|
||||
notLegal='not$$(SPACE)legal$$(SPACE)for$$(SPACE)this$$(SPACE)charset' \
|
||||
otypes-per-itype='chars-per-byte' \
|
||||
outSequence='Unicode$$(SPACE)character', \
|
||||
))
|
||||
|
||||
GENSRC_CHARSETCODER += $(GENSRC_CHARSETCODER_DST)/CharsetDecoder.java
|
||||
TARGETS += $(GEN_CHARSETDECODER)
|
||||
|
||||
################################################################################
|
||||
$(eval $(call SetupStreamPreProcessing, GEN_CHARSETENCODER, \
|
||||
SOURCE_FILE := $(CHARSETCODER_INPUT), \
|
||||
OUTPUT_FILE := $(CHARSETCODER_OUTPUT_DIR)/CharsetEncoder.java, \
|
||||
INFO := Generating CharsetEncoder.java, \
|
||||
KEYS := encoder, \
|
||||
REPLACEMENTS := \
|
||||
A='An' \
|
||||
a='an' \
|
||||
Code='Encode' \
|
||||
code='encode' \
|
||||
itypesPhrase='sixteen-bit$$(SPACE)Unicode$$(SPACE)characters' \
|
||||
otypesPhrase='bytes$$(SPACE)in$$(SPACE)a$$(SPACE)specific$$(SPACE)charset' \
|
||||
itype='character' \
|
||||
otype='byte' \
|
||||
Itype='Char' \
|
||||
Otype='Byte' \
|
||||
coder='encoder' \
|
||||
Coder='Encoder' \
|
||||
coding='encoding' \
|
||||
OtherCoder='Decoder' \
|
||||
replTypeName='byte$$(SPACE)array' \
|
||||
replType='byte[]' \
|
||||
replFQType='byte[]' \
|
||||
replLength='length' \
|
||||
ItypesPerOtype='BytesPerChar' \
|
||||
notLegal='not$$(SPACE)a$$(SPACE)legal$$(SPACE)sixteen-bit$$(SPACE)Unicode$$(SPACE)sequence' \
|
||||
otypes-per-itype='bytes-per-char' \
|
||||
outSequence='byte$$(SPACE)sequence$$(SPACE)in$$(SPACE)the$$(SPACE)given$$(SPACE)charset', \
|
||||
))
|
||||
|
||||
$(GENSRC_CHARSETCODER_DST)/CharsetEncoder.java: $(GENSRC_CHARSETCODER_TEMPLATE)
|
||||
$(call MakeTargetDir)
|
||||
$(RM) $@.tmp
|
||||
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/gensrc/java.base/_charset_encoder, \
|
||||
$(TOOL_SPP) -i$< -o$@.tmp \
|
||||
-Kencoder \
|
||||
-DA='An' \
|
||||
-Da='an' \
|
||||
-DCode='Encode' \
|
||||
-Dcode='encode' \
|
||||
-DitypesPhrase='sixteen-bit Unicode characters' \
|
||||
-DotypesPhrase='bytes in a specific charset' \
|
||||
-Ditype='character' \
|
||||
-Dotype='byte' \
|
||||
-DItype='Char' \
|
||||
-DOtype='Byte' \
|
||||
-Dcoder='encoder' \
|
||||
-DCoder='Encoder' \
|
||||
-Dcoding='encoding' \
|
||||
-DOtherCoder='Decoder' \
|
||||
-DreplTypeName='byte array' \
|
||||
-DdefaultRepl='new byte[] { (byte)'"'"\\?"'"' }' \
|
||||
-DdefaultReplName='<code>{<\/code>\ <code>(byte)'"'"\\?"'"'<\/code>\ <code>}<\/code>' \
|
||||
-DreplType='byte[]' \
|
||||
-DreplFQType='byte[]' \
|
||||
-DreplLength='length' \
|
||||
-DItypesPerOtype='BytesPerChar' \
|
||||
-DnotLegal='not a legal sixteen-bit Unicode sequence' \
|
||||
-Dotypes-per-itype='bytes-per-char' \
|
||||
-DoutSequence='byte sequence in the given charset')
|
||||
$(MV) $@.tmp $@
|
||||
|
||||
GENSRC_CHARSETCODER += $(GENSRC_CHARSETCODER_DST)/CharsetEncoder.java
|
||||
|
||||
################################################################################
|
||||
|
||||
$(GENSRC_CHARSETCODER): $(BUILD_TOOLS_JDK)
|
||||
|
||||
TARGETS += $(GENSRC_CHARSETCODER)
|
||||
TARGETS += $(GEN_CHARSETENCODER)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -28,144 +28,77 @@ ifeq ($(INCLUDE), true)
|
||||
|
||||
################################################################################
|
||||
|
||||
SCOPED_MEMORY_ACCESS_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/misc
|
||||
SCOPED_MEMORY_ACCESS_SRC_DIR := $(MODULE_SRC)/share/classes/jdk/internal/misc
|
||||
SCOPED_MEMORY_ACCESS_TEMPLATE := $(SCOPED_MEMORY_ACCESS_SRC_DIR)/X-ScopedMemoryAccess.java.template
|
||||
SCOPED_MEMORY_ACCESS_BIN_TEMPLATE := $(SCOPED_MEMORY_ACCESS_SRC_DIR)/X-ScopedMemoryAccess-bin.java.template
|
||||
SCOPED_MEMORY_ACCESS_DEST := $(SCOPED_MEMORY_ACCESS_GENSRC_DIR)/ScopedMemoryAccess.java
|
||||
SCOPED_INPUT_DIR := $(MODULE_SRC)/share/classes/jdk/internal/misc
|
||||
SCOPED_INPUT := $(SCOPED_INPUT_DIR)/X-ScopedMemoryAccess.java.template
|
||||
SCOPED_OUTPUT := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/misc/ScopedMemoryAccess.java
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating the ScopedMemoryAccess java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
define GenerateScopedOp
|
||||
# Helper method to setup generation of scoped snippets.
|
||||
# Will add the generated snippet file name to SCOPED_SNIPPET_FILES.
|
||||
#
|
||||
# arg $1: type for this snippet
|
||||
define SetupGenScopedSnippets
|
||||
$1_SCOPED_SNIPPET_FILE := $$(SCOPED_OUTPUT).snippet.$1
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
ifeq ($$($1_Type), Boolean)
|
||||
$1_type := boolean
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_KEYS := $1 CAS
|
||||
ifneq ($$(filter byte, $1),)
|
||||
$1_KEYS += byte
|
||||
endif
|
||||
ifneq ($$(filter float double, $1),)
|
||||
$1_KEYS += floatingPoint
|
||||
endif
|
||||
ifneq ($$(filter char short int long, $1),)
|
||||
$1_KEYS += Unaligned
|
||||
endif
|
||||
ifneq ($$(filter boolean byte char short, $1),)
|
||||
$1_KEYS += ShorterThanInt
|
||||
endif
|
||||
ifeq ($$(filter boolean, $1),)
|
||||
$1_KEYS += AtomicAdd
|
||||
endif
|
||||
ifeq ($$(filter float double, $1),)
|
||||
$1_KEYS += Bitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Byte)
|
||||
$1_type := byte
|
||||
$1_BoxType := $$($1_Type)
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_SCOPED_SNIPPET_$1, \
|
||||
SOURCE_FILE := $$(SCOPED_INPUT_DIR)/X-ScopedMemoryAccess-bin.java.template, \
|
||||
OUTPUT_FILE := $$($1_SCOPED_SNIPPET_FILE), \
|
||||
INFO := Generating snippets for ScopedMemoryAccess ($1), \
|
||||
SUBST_EMPTY_LINES := false, \
|
||||
KEYS := $$($1_KEYS), \
|
||||
REPLACEMENTS := \
|
||||
type=$1 \
|
||||
Type=$$(call Conv, $1, Type), \
|
||||
))
|
||||
TARGETS += $$(GEN_SCOPED_SNIPPET_$1)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -Kbyte
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
$1_type := short
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
$1_type := char
|
||||
$1_BoxType := Character
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
$1_type := int
|
||||
$1_BoxType := Integer
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Long)
|
||||
$1_type := long
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Float)
|
||||
$1_type := float
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := int
|
||||
$1_RawType := Int
|
||||
$1_RawBoxType := Integer
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Double)
|
||||
$1_type := double
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := long
|
||||
$1_RawType := Long
|
||||
$1_RawBoxType := Long
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Byte Short Char Int Long Float Double), )
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char Int Long), )
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char), )
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
SCOPED_SNIPPET_FILES += $$($1_SCOPED_SNIPPET_FILE)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating the ScopedMemoryAccess java class
|
||||
# Setup generation of snippet files, one for each primitive type. This will
|
||||
# populate SCOPED_SNIPPET_FILES.
|
||||
|
||||
SCOPE_MEMORY_ACCESS_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||
$(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \
|
||||
$(eval $(call GenerateScopedOp,BIN_$t,$t)))
|
||||
# SCOPED_TYPES is identical to PRIMITIVE_TYPES, but with a slightly different
|
||||
# order. Keep the original SCOPED_TYPES order for now to not change the
|
||||
# generated file.
|
||||
SCOPED_TYPES := boolean byte short char int long float double
|
||||
|
||||
$(SCOPED_MEMORY_ACCESS_DEST): $(BUILD_TOOLS_JDK) $(SCOPED_MEMORY_ACCESS_TEMPLATE) $(SCOPED_MEMORY_ACCESS_BIN_TEMPLATE)
|
||||
$(call MakeDir, $(SCOPED_MEMORY_ACCESS_GENSRC_DIR))
|
||||
$(CAT) $(SCOPED_MEMORY_ACCESS_TEMPLATE) > $(SCOPED_MEMORY_ACCESS_DEST)
|
||||
$(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \
|
||||
$(TOOL_SPP) -nel -K$(BIN_$t_type) -Dtype=$(BIN_$t_type) -DType=$(BIN_$t_Type) $(BIN_$t_ARGS) \
|
||||
-i$(SCOPED_MEMORY_ACCESS_BIN_TEMPLATE) -o$(SCOPED_MEMORY_ACCESS_DEST) ;)
|
||||
$(ECHO) "}" >> $(SCOPED_MEMORY_ACCESS_DEST)
|
||||
SCOPED_SNIPPET_FILES :=
|
||||
$(foreach t, $(SCOPED_TYPES), \
|
||||
$(eval $(call SetupGenScopedSnippets,$t)) \
|
||||
)
|
||||
|
||||
TARGETS += $(SCOPED_MEMORY_ACCESS_DEST)
|
||||
# Setup a rule for generating the ScopedMemoryAccess java class by incorporating
|
||||
# those snippets
|
||||
$(SCOPED_OUTPUT): $(SCOPED_INPUT) $(SCOPED_SNIPPET_FILES)
|
||||
$(call LogInfo, Concatenating snippets for ScopedMemoryAccess.java)
|
||||
$(CAT) $(SCOPED_INPUT) > $(SCOPED_OUTPUT).tmp
|
||||
$(CAT) $(SCOPED_SNIPPET_FILES) >> $(SCOPED_OUTPUT).tmp
|
||||
$(ECHO) "}" >> $(SCOPED_OUTPUT).tmp
|
||||
$(MV) $(SCOPED_OUTPUT).tmp $(SCOPED_OUTPUT)
|
||||
|
||||
TARGETS += $(SCOPED_OUTPUT)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -28,277 +28,144 @@ ifeq ($(INCLUDE), true)
|
||||
|
||||
################################################################################
|
||||
|
||||
GENSRC_VARHANDLES :=
|
||||
|
||||
VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
|
||||
VARHANDLES_SRC_DIR := $(MODULE_SRC)/share/classes/java/lang/invoke
|
||||
VARHANDLES_INPUT_DIR := $(MODULE_SRC)/share/classes/java/lang/invoke
|
||||
VARHANDLES_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandle java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
#
|
||||
# arg $1: type for this varhandle
|
||||
define GenerateVarHandle
|
||||
VARHANDLE_$1_type := $$(strip $$(if $$(filter reference, $1), Object, $1))
|
||||
VARHANDLE_$1_Type := $$(call Conv, $1, Type)
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Byte Short Char Int Long Float Double), )
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_KEYS := $$(VARHANDLE_$1_type) CAS
|
||||
ifneq ($$(filter byte short char, $1),)
|
||||
$1_KEYS += ShorterThanInt
|
||||
endif
|
||||
ifeq ($$(filter boolean reference, $1),)
|
||||
$1_KEYS += AtomicAdd
|
||||
endif
|
||||
ifeq ($$(filter float double reference, $1),)
|
||||
$1_KEYS += Bitwise
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char Int Long), )
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Byte Short Char), )
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
|
||||
ifeq ($$($1_Type), Reference)
|
||||
$$(eval $1_type := Object)
|
||||
else
|
||||
$$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
|
||||
endif
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(RM) $$@
|
||||
$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
|
||||
$$($1_ARGS) -i$$< -o$$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_VARHANDLE_$1, \
|
||||
SOURCE_FILE := $$(VARHANDLES_INPUT_DIR)/X-VarHandle.java.template, \
|
||||
OUTPUT_FILE := $$(VARHANDLES_OUTPUT_DIR)/VarHandle$$(VARHANDLE_$1_Type)s.java, \
|
||||
INFO := Generating VarHandle class for $1, \
|
||||
SUBST_EMPTY_LINES := false, \
|
||||
KEYS := $$($1_KEYS), \
|
||||
REPLACEMENTS := \
|
||||
type=$$(VARHANDLE_$1_type) \
|
||||
Type=$$(VARHANDLE_$1_Type), \
|
||||
))
|
||||
TARGETS += $$(GEN_VARHANDLE_$1)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandleByteArray java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
#
|
||||
# arg $1: type for this varhandle
|
||||
define GenerateVarHandleByteArray
|
||||
VARHANDLE_BYTEARRAY_$1_Type := $$(call Conv, $1, Type)
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
$1_type := short
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
$1_KEYS := $1
|
||||
ifneq ($$(filter int long float double, $1),)
|
||||
$1_KEYS += CAS
|
||||
endif
|
||||
ifneq ($$(filter float double, $1),)
|
||||
$1_KEYS += floatingPoint
|
||||
endif
|
||||
ifneq ($$(filter int long, $1),)
|
||||
$1_KEYS += AtomicAdd Bitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
$1_type := char
|
||||
$1_BoxType := Character
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
$1_type := int
|
||||
$1_BoxType := Integer
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Long)
|
||||
$1_type := long
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Float)
|
||||
$1_type := float
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := int
|
||||
$1_RawType := Int
|
||||
$1_RawBoxType := Integer
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Double)
|
||||
$1_type := double
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := long
|
||||
$1_RawType := Long
|
||||
$1_RawBoxType := Long
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(RM) $$@
|
||||
$(TOOL_SPP) -nel -K$$($1_type) \
|
||||
-Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
|
||||
-DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
|
||||
$$($1_ARGS) -i$$< -o$$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_VARHANDLE_BYTEARRAY_$1, \
|
||||
SOURCE_FILE := $$(VARHANDLES_INPUT_DIR)/X-VarHandleByteArrayView.java.template, \
|
||||
OUTPUT_FILE := $$(VARHANDLES_OUTPUT_DIR)/VarHandleByteArrayAs$$(VARHANDLE_BYTEARRAY_$1_Type)s.java, \
|
||||
INFO := Generating VarHandleByteArray class for $1, \
|
||||
SUBST_EMPTY_LINES := false, \
|
||||
KEYS := $$($1_KEYS), \
|
||||
REPLACEMENTS := \
|
||||
type=$1 \
|
||||
Type=$$(VARHANDLE_BYTEARRAY_$1_Type) \
|
||||
BoxType=$$(call Conv, $1, Fulltype) \
|
||||
rawType=$$(call Conv, $1, memtype) \
|
||||
RawType=$$(call Conv, $1, Memtype) \
|
||||
RawBoxType=$$(call Conv, $1, FullMemtype), \
|
||||
))
|
||||
TARGETS += $$(GEN_VARHANDLE_BYTEARRAY_$1)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a memory segment var handle view class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
# Setup a rule for generating a VarHandleMemorySegment java class
|
||||
#
|
||||
# arg $1: type for this varhandle
|
||||
define GenerateVarHandleMemorySegment
|
||||
VARHANDLE_SEGMENT_$1_Type := $$(call Conv, $1, Type)
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java
|
||||
|
||||
ifeq ($$($1_Type), Boolean)
|
||||
$1_type := boolean
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -Kbyte
|
||||
$1_ARGS += -KShorterThanInt
|
||||
$1_KEYS := $1
|
||||
ifneq ($$(filter int long float double, $1),)
|
||||
$1_KEYS += CAS
|
||||
endif
|
||||
ifneq ($$(filter boolean byte, $1),)
|
||||
$1_KEYS += byte
|
||||
endif
|
||||
ifneq ($$(filter float double, $1),)
|
||||
$1_KEYS += floatingPoint
|
||||
endif
|
||||
ifneq ($$(filter boolean byte short char, $1),)
|
||||
$1_KEYS += ShorterThanInt
|
||||
endif
|
||||
ifneq ($$(filter int long, $1),)
|
||||
$1_KEYS += AtomicAdd Bitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Byte)
|
||||
$1_type := byte
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -Kbyte
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
$1_type := short
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
$1_type := char
|
||||
$1_BoxType := Character
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
$1_type := int
|
||||
$1_BoxType := Integer
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Long)
|
||||
$1_type := long
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Float)
|
||||
$1_type := float
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := int
|
||||
$1_RawType := Int
|
||||
$1_RawBoxType := Integer
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Double)
|
||||
$1_type := double
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := long
|
||||
$1_RawType := Long
|
||||
$1_RawBoxType := Long
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleSegmentView.java.template $(BUILD_TOOLS_JDK)
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(RM) $$@
|
||||
$(TOOL_SPP) -nel -K$$($1_type) \
|
||||
-Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
|
||||
-DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
|
||||
$$($1_ARGS) -i$$< -o$$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
$$(eval $$(call SetupStreamPreProcessing, GEN_VARHANDLE_SEGMENT_$1, \
|
||||
SOURCE_FILE := $$(VARHANDLES_INPUT_DIR)/X-VarHandleSegmentView.java.template, \
|
||||
OUTPUT_FILE := $$(VARHANDLES_OUTPUT_DIR)/VarHandleSegmentAs$$(VARHANDLE_SEGMENT_$1_Type)s.java, \
|
||||
INFO := Generating VarHandleSegment class for $1, \
|
||||
SUBST_EMPTY_LINES := false, \
|
||||
KEYS := $$($1_KEYS), \
|
||||
REPLACEMENTS := \
|
||||
type=$1 \
|
||||
Type=$$(VARHANDLE_SEGMENT_$1_Type) \
|
||||
BoxType=$$(call Conv, $1, Fulltype) \
|
||||
rawType=$$(call Conv, $1, memtype) \
|
||||
RawType=$$(call Conv, $1, Memtype) \
|
||||
RawBoxType=$$(call Conv, $1, FullMemtype), \
|
||||
))
|
||||
TARGETS += $$(GEN_VARHANDLE_SEGMENT_$1)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
# Generate all VarHandle related classes
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Reference
|
||||
$(foreach t, $(VARHANDLES_TYPES), \
|
||||
$(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
|
||||
$(foreach t, $(PRIMITIVE_TYPES) reference, \
|
||||
$(eval $(call GenerateVarHandle,$t)) \
|
||||
)
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
|
||||
$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
|
||||
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
||||
$(foreach t, $(NON_BYTE_NUMBER_TYPES), \
|
||||
$(eval $(call GenerateVarHandleByteArray,$t)) \
|
||||
)
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_MEMORY_SEGMENT_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||
$(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \
|
||||
$(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t)))
|
||||
$(foreach t, $(PRIMITIVE_TYPES), \
|
||||
$(eval $(call GenerateVarHandleMemorySegment,$t)) \
|
||||
)
|
||||
|
||||
TARGETS += $(GENSRC_VARHANDLES)
|
||||
################################################################################
|
||||
|
||||
GENSRC_VARHANDLEGUARDS := $(VARHANDLES_OUTPUT_DIR)/VarHandleGuards.java
|
||||
|
||||
$(GENSRC_VARHANDLEGUARDS): $(BUILD_TOOLS_JDK)
|
||||
$(call LogInfo, Generating $@)
|
||||
$(call MakeTargetDir)
|
||||
$(TOOL_VARHANDLEGUARDMETHODGENERATOR) \
|
||||
$(GENSRC_VARHANDLEGUARDS)
|
||||
|
||||
TARGETS += $(GENSRC_VARHANDLEGUARDS)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGEAPPLAUNCHER, \
|
||||
-rpath @executable_path/../PlugIns/, \
|
||||
LIBS_macosx := -framework Cocoa, \
|
||||
LIBS_windows := msi.lib ole32.lib shell32.lib shlwapi.lib user32.lib, \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
LIBS_linux := $(LIBDL) $(LIBPTHREAD), \
|
||||
MANIFEST := $(JAVA_MANIFEST), \
|
||||
MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS) \
|
||||
))
|
||||
@ -97,7 +97,7 @@ ifeq ($(call isTargetOs, linux), true)
|
||||
DISABLED_WARNINGS_clang_JvmLauncherLib.c := format-nonliteral, \
|
||||
DISABLED_WARNINGS_clang_tstrings.cpp := format-nonliteral, \
|
||||
LD_SET_ORIGIN := false, \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
LIBS_linux := $(LIBDL) $(LIBPTHREAD), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBJPACKAGEAPPLAUNCHERAUX)
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
GREP=grep
|
||||
|
||||
#
|
||||
EXP="Note: Some input files use or override a deprecated API."
|
||||
EXP="${EXP}|Note: Recompile with -Xlint:deprecation for details."
|
||||
EXP="${EXP}|Note: Some input files use unchecked or unsafe operations."
|
||||
EXP="${EXP}|Note: Recompile with -Xlint:unchecked for details."
|
||||
EXP="${EXP}| warning"
|
||||
EXP="${EXP}|uses or overrides a deprecated API."
|
||||
EXP="${EXP}|uses unchecked or unsafe operations."
|
||||
#
|
||||
${GREP} --line-buffered -v -E "${EXP}"
|
||||
@ -138,6 +138,7 @@ ifneq ($(filter build-test-jdk-jtreg-native, $(MAKECMDGOALS)), )
|
||||
OUTPUT_DIR := $(BUILD_JDK_JTREG_OUTPUT_DIR), \
|
||||
EXCLUDE := $(BUILD_JDK_JTREG_EXCLUDE), \
|
||||
EXTRA_FILES := $(BUILD_JDK_JTREG_EXTRA_FILES), \
|
||||
LIBS := $(LIBPTHREAD), \
|
||||
))
|
||||
endif
|
||||
|
||||
|
||||
@ -4412,10 +4412,9 @@ operand immI8()
|
||||
%}
|
||||
|
||||
// 8 bit signed value (simm8), or #simm8 LSL 8.
|
||||
operand immI8_shift8()
|
||||
operand immIDupV()
|
||||
%{
|
||||
predicate((n->get_int() <= 127 && n->get_int() >= -128) ||
|
||||
(n->get_int() <= 32512 && n->get_int() >= -32768 && (n->get_int() & 0xff) == 0));
|
||||
predicate(Assembler::operand_valid_for_sve_dup_immediate((int64_t)n->get_int()));
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
@ -4424,10 +4423,9 @@ operand immI8_shift8()
|
||||
%}
|
||||
|
||||
// 8 bit signed value (simm8), or #simm8 LSL 8.
|
||||
operand immL8_shift8()
|
||||
operand immLDupV()
|
||||
%{
|
||||
predicate((n->get_long() <= 127 && n->get_long() >= -128) ||
|
||||
(n->get_long() <= 32512 && n->get_long() >= -32768 && (n->get_long() & 0xff) == 0));
|
||||
predicate(Assembler::operand_valid_for_sve_dup_immediate(n->get_long()));
|
||||
match(ConL);
|
||||
|
||||
op_cost(0);
|
||||
@ -4435,6 +4433,17 @@ operand immL8_shift8()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// 8 bit signed value (simm8), or #simm8 LSL 8.
|
||||
operand immHDupV()
|
||||
%{
|
||||
predicate(Assembler::operand_valid_for_sve_dup_immediate((int64_t)n->geth()));
|
||||
match(ConH);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// 8 bit integer valid for vector add sub immediate
|
||||
operand immBAddSubV()
|
||||
%{
|
||||
@ -5956,9 +5965,6 @@ attributes %{
|
||||
instruction_unit_size = 4; // An instruction is 4 bytes long
|
||||
instruction_fetch_unit_size = 64; // The processor fetches one line
|
||||
instruction_fetch_units = 1; // of 64 bytes
|
||||
|
||||
// List of nop instructions
|
||||
nops( MachNop );
|
||||
%}
|
||||
|
||||
// We don't use an actual pipeline model so don't care about resources
|
||||
@ -7077,18 +7083,16 @@ instruct loadConD(vRegD dst, immD con) %{
|
||||
%}
|
||||
|
||||
// Load Half Float Constant
|
||||
// The "ldr" instruction loads a 32-bit word from the constant pool into a
|
||||
// 32-bit register but only the bottom half will be populated and the top
|
||||
// 16 bits are zero.
|
||||
instruct loadConH(vRegF dst, immH con) %{
|
||||
match(Set dst con);
|
||||
format %{
|
||||
"ldrs $dst, [$constantaddress]\t# load from constant table: half float=$con\n\t"
|
||||
%}
|
||||
format %{ "mov rscratch1, $con\n\t"
|
||||
"fmov $dst, rscratch1"
|
||||
%}
|
||||
ins_encode %{
|
||||
__ ldrs(as_FloatRegister($dst$$reg), $constantaddress($con));
|
||||
__ movw(rscratch1, (uint32_t)$con$$constant);
|
||||
__ fmovs($dst$$FloatRegister, rscratch1);
|
||||
%}
|
||||
ins_pipe(fp_load_constant_s);
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Store Instructions
|
||||
|
||||
@ -4875,7 +4875,7 @@ instruct replicateB_imm8_gt128b(vReg dst, immI8 con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct replicateI_imm8_gt128b(vReg dst, immI8_shift8 con) %{
|
||||
instruct replicateI_imm8_gt128b(vReg dst, immIDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16 &&
|
||||
(Matcher::vector_element_basic_type(n) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n) == T_INT));
|
||||
@ -4898,7 +4898,7 @@ instruct replicateL_imm_128b(vReg dst, immL con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct replicateL_imm8_gt128b(vReg dst, immL8_shift8 con) %{
|
||||
instruct replicateL_imm8_gt128b(vReg dst, immLDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateL_imm8_gt128b $dst, $con\t# vector > 128 bits" %}
|
||||
@ -4909,19 +4909,27 @@ instruct replicateL_imm8_gt128b(vReg dst, immL8_shift8 con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Replicate a 16-bit half precision float value
|
||||
instruct replicateHF_imm(vReg dst, immH con) %{
|
||||
// Replicate an immediate 16-bit half precision float value
|
||||
instruct replicateHF_imm_le128b(vReg dst, immH con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) <= 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateHF_imm $dst, $con\t# replicate immediate half-precision float" %}
|
||||
format %{ "replicateHF_imm_le128b $dst, $con\t# vector <= 128 bits" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
|
||||
int imm = (int)($con$$constant) & 0xffff;
|
||||
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
|
||||
__ mov($dst$$FloatRegister, get_arrangement(this), imm);
|
||||
} else { // length_in_bytes must be > 16 and SVE should be enabled
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
__ sve_dup($dst$$FloatRegister, __ H, imm);
|
||||
}
|
||||
__ mov($dst$$FloatRegister, get_arrangement(this), imm);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Replicate a 16-bit half precision float which is within the limits
|
||||
// for the operand - immHDupV
|
||||
instruct replicateHF_imm8_gt128b(vReg dst, immHDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateHF_imm8_gt128b $dst, $con\t# vector > 128 bits" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
__ sve_dup($dst$$FloatRegister, __ H, (int)($con$$constant));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@ -3107,7 +3107,7 @@ instruct replicateB_imm8_gt128b(vReg dst, immI8 con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct replicateI_imm8_gt128b(vReg dst, immI8_shift8 con) %{
|
||||
instruct replicateI_imm8_gt128b(vReg dst, immIDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16 &&
|
||||
(Matcher::vector_element_basic_type(n) == T_SHORT ||
|
||||
Matcher::vector_element_basic_type(n) == T_INT));
|
||||
@ -3130,7 +3130,7 @@ instruct replicateL_imm_128b(vReg dst, immL con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct replicateL_imm8_gt128b(vReg dst, immL8_shift8 con) %{
|
||||
instruct replicateL_imm8_gt128b(vReg dst, immLDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateL_imm8_gt128b $dst, $con\t# vector > 128 bits" %}
|
||||
@ -3141,19 +3141,27 @@ instruct replicateL_imm8_gt128b(vReg dst, immL8_shift8 con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Replicate a 16-bit half precision float value
|
||||
instruct replicateHF_imm(vReg dst, immH con) %{
|
||||
// Replicate an immediate 16-bit half precision float value
|
||||
instruct replicateHF_imm_le128b(vReg dst, immH con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) <= 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateHF_imm $dst, $con\t# replicate immediate half-precision float" %}
|
||||
format %{ "replicateHF_imm_le128b $dst, $con\t# vector <= 128 bits" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
|
||||
int imm = (int)($con$$constant) & 0xffff;
|
||||
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
|
||||
__ mov($dst$$FloatRegister, get_arrangement(this), imm);
|
||||
} else { // length_in_bytes must be > 16 and SVE should be enabled
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
__ sve_dup($dst$$FloatRegister, __ H, imm);
|
||||
}
|
||||
__ mov($dst$$FloatRegister, get_arrangement(this), imm);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Replicate a 16-bit half precision float which is within the limits
|
||||
// for the operand - immHDupV
|
||||
instruct replicateHF_imm8_gt128b(vReg dst, immHDupV con) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n) > 16);
|
||||
match(Set dst (Replicate con));
|
||||
format %{ "replicateHF_imm8_gt128b $dst, $con\t# vector > 128 bits" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
__ sve_dup($dst$$FloatRegister, __ H, (int)($con$$constant));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@ -434,6 +434,11 @@ int Assembler::operand_valid_for_movi_immediate(uint64_t imm64, SIMD_Arrangement
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Assembler::operand_valid_for_sve_dup_immediate(int64_t imm) {
|
||||
return ((imm >= -128 && imm <= 127) ||
|
||||
(((imm & 0xff) == 0) && imm >= -32768 && imm <= 32512));
|
||||
}
|
||||
|
||||
bool Assembler::operand_valid_for_sve_logical_immediate(unsigned elembits, uint64_t imm) {
|
||||
return encode_sve_logical_immediate(elembits, imm) != 0xffffffff;
|
||||
}
|
||||
|
||||
@ -3814,7 +3814,11 @@ private:
|
||||
starti;
|
||||
assert(T != Q, "invalid size");
|
||||
int sh = 0;
|
||||
if (imm8 <= 127 && imm8 >= -128) {
|
||||
if (isFloat) {
|
||||
assert(T != B, "invalid size");
|
||||
assert((imm8 >> 8) == 0, "invalid immediate");
|
||||
sh = 0;
|
||||
} else if (imm8 <= 127 && imm8 >= -128) {
|
||||
sh = 0;
|
||||
} else if (T != B && imm8 <= 32512 && imm8 >= -32768 && (imm8 & 0xff) == 0) {
|
||||
sh = 1;
|
||||
@ -3824,7 +3828,7 @@ private:
|
||||
}
|
||||
int m = isMerge ? 1 : 0;
|
||||
f(0b00000101, 31, 24), f(T, 23, 22), f(0b01, 21, 20);
|
||||
prf(Pg, 16), f(isFloat ? 1 : 0, 15), f(m, 14), f(sh, 13), sf(imm8, 12, 5), rf(Zd, 0);
|
||||
prf(Pg, 16), f(isFloat ? 1 : 0, 15), f(m, 14), f(sh, 13), f(imm8 & 0xff, 12, 5), rf(Zd, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -3834,7 +3838,7 @@ public:
|
||||
}
|
||||
// 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<int8_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
|
||||
@ -4324,6 +4328,7 @@ public:
|
||||
static bool operand_valid_for_sve_add_sub_immediate(int64_t imm);
|
||||
static bool operand_valid_for_float_immediate(double imm);
|
||||
static int operand_valid_for_movi_immediate(uint64_t imm64, SIMD_Arrangement T);
|
||||
static bool operand_valid_for_sve_dup_immediate(int64_t imm);
|
||||
|
||||
void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
|
||||
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
|
||||
|
||||
@ -2585,11 +2585,6 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::emit_delay(LIR_OpDelay*) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) {
|
||||
__ lea(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no));
|
||||
}
|
||||
|
||||
@ -702,10 +702,10 @@ static void printbc(Method *m, intptr_t bcx) {
|
||||
if (m->validate_bci_from_bcp((address)bcx) < 0
|
||||
|| !m->contains((address)bcx)) {
|
||||
name = "???";
|
||||
snprintf(buf, sizeof buf, "(bad)");
|
||||
os::snprintf_checked(buf, sizeof buf, "(bad)");
|
||||
} else {
|
||||
int bci = m->bci_from((address)bcx);
|
||||
snprintf(buf, sizeof buf, "%d", bci);
|
||||
os::snprintf_checked(buf, sizeof buf, "%d", bci);
|
||||
name = Bytecodes::name(m->code_at(bci));
|
||||
}
|
||||
ResourceMark rm;
|
||||
|
||||
@ -275,7 +275,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::increment_patching_epoch() {
|
||||
Atomic::inc(&_patching_epoch);
|
||||
AtomicAccess::inc(&_patching_epoch);
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::clear_patching_epoch() {
|
||||
@ -331,13 +331,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
|
||||
__ ldr(rscratch2, thread_disarmed_and_epoch_addr);
|
||||
__ cmp(rscratch1, rscratch2);
|
||||
} else {
|
||||
assert(patching_type == NMethodPatchingType::conc_data_patch, "must be");
|
||||
// Subsequent loads of oops must occur after load of guard value.
|
||||
// BarrierSetNMethod::disarm sets guard with release semantics.
|
||||
__ membar(__ LoadLoad);
|
||||
Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()));
|
||||
__ ldrw(rscratch2, thread_disarmed_addr);
|
||||
__ cmpw(rscratch1, rscratch2);
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
__ br(condition, barrier_target);
|
||||
|
||||
|
||||
@ -39,8 +39,7 @@ class Node;
|
||||
|
||||
enum class NMethodPatchingType {
|
||||
stw_instruction_and_data_patch,
|
||||
conc_instruction_and_data_patch,
|
||||
conc_data_patch
|
||||
conc_instruction_and_data_patch
|
||||
};
|
||||
|
||||
class BarrierSetAssembler: public CHeapObj<mtGC> {
|
||||
|
||||
@ -58,8 +58,6 @@ static int entry_barrier_offset(nmethod* nm) {
|
||||
return -4 * (4 + slow_path_size(nm));
|
||||
case NMethodPatchingType::conc_instruction_and_data_patch:
|
||||
return -4 * (10 + slow_path_size(nm));
|
||||
case NMethodPatchingType::conc_data_patch:
|
||||
return -4 * (5 + slow_path_size(nm));
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
return 0;
|
||||
@ -114,11 +112,25 @@ public:
|
||||
}
|
||||
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_barrier(err_msg& msg) const;
|
||||
@ -181,7 +193,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
|
||||
}
|
||||
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
|
||||
if (!supports_entry_barrier(nm)) {
|
||||
return;
|
||||
}
|
||||
@ -198,7 +210,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
}
|
||||
|
||||
NativeNMethodBarrier barrier(nm);
|
||||
barrier.set_value(value);
|
||||
barrier.set_value(value, bit_mask);
|
||||
}
|
||||
|
||||
int BarrierSetNMethod::guard_value(nmethod* nm) {
|
||||
|
||||
@ -67,7 +67,7 @@ private:
|
||||
Register scratch, RegSet saved_regs);
|
||||
|
||||
public:
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
|
||||
|
||||
#ifdef COMPILER1
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
|
||||
|
||||
@ -2259,7 +2259,7 @@ void MacroAssembler::movptr(Register r, uintptr_t imm64) {
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIX64, (uint64_t)imm64);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "0x%" PRIX64, (uint64_t)imm64);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
@ -2317,7 +2317,7 @@ void MacroAssembler::mov_immediate64(Register dst, uint64_t imm64)
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIX64, imm64);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "0x%" PRIX64, imm64);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
@ -2430,7 +2430,7 @@ void MacroAssembler::mov_immediate32(Register dst, uint32_t imm32)
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIX32, imm32);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "0x%" PRIX32, imm32);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
@ -2902,11 +2902,11 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack, FpPushPopMode m
|
||||
{
|
||||
char buffer[48];
|
||||
if (mode == PushPopSVE) {
|
||||
snprintf(buffer, sizeof(buffer), "push_fp: %d SVE registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "push_fp: %d SVE registers", count);
|
||||
} else if (mode == PushPopNeon) {
|
||||
snprintf(buffer, sizeof(buffer), "push_fp: %d Neon registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "push_fp: %d Neon registers", count);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "push_fp: %d fp registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "push_fp: %d fp registers", count);
|
||||
}
|
||||
block_comment(buffer);
|
||||
}
|
||||
@ -3014,11 +3014,11 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack, FpPushPopMode mo
|
||||
{
|
||||
char buffer[48];
|
||||
if (mode == PushPopSVE) {
|
||||
snprintf(buffer, sizeof(buffer), "pop_fp: %d SVE registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "pop_fp: %d SVE registers", count);
|
||||
} else if (mode == PushPopNeon) {
|
||||
snprintf(buffer, sizeof(buffer), "pop_fp: %d Neon registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "pop_fp: %d Neon registers", count);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "pop_fp: %d fp registers", count);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "pop_fp: %d fp registers", count);
|
||||
}
|
||||
block_comment(buffer);
|
||||
}
|
||||
@ -5920,7 +5920,7 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
|
||||
{
|
||||
const char kind = (elem_size == 2) ? 'U' : 'L';
|
||||
char comment[64];
|
||||
snprintf(comment, sizeof comment, "array_equals%c{", kind);
|
||||
os::snprintf_checked(comment, sizeof comment, "array_equals%c{", kind);
|
||||
BLOCK_COMMENT(comment);
|
||||
}
|
||||
#endif
|
||||
@ -6118,7 +6118,7 @@ void MacroAssembler::string_equals(Register a1, Register a2,
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char comment[64];
|
||||
snprintf(comment, sizeof comment, "{string_equalsL");
|
||||
os::snprintf_checked(comment, sizeof comment, "{string_equalsL");
|
||||
BLOCK_COMMENT(comment);
|
||||
}
|
||||
#endif
|
||||
@ -6266,7 +6266,7 @@ address MacroAssembler::zero_words(Register base, uint64_t cnt)
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof buf, "zero_words (count = %" PRIu64 ") {", cnt);
|
||||
os::snprintf_checked(buf, sizeof buf, "zero_words (count = %" PRIu64 ") {", cnt);
|
||||
BLOCK_COMMENT(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "runtime/continuation.hpp"
|
||||
#include "runtime/continuationEntry.inline.hpp"
|
||||
#include "runtime/frame.inline.hpp"
|
||||
@ -10265,7 +10265,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
#if defined (LINUX) && !defined (__ARM_FEATURE_ATOMICS)
|
||||
|
||||
// ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX.
|
||||
// ARMv8.1 LSE versions of the atomic stubs used by AtomicAccess::PlatformXX.
|
||||
//
|
||||
// If LSE is in use, generate LSE versions of all the stubs. The
|
||||
// non-LSE versions are in atomic_aarch64.S.
|
||||
|
||||
@ -721,12 +721,12 @@ void VM_Version::initialize_cpu_information(void) {
|
||||
_no_of_cores = os::processor_count();
|
||||
_no_of_threads = _no_of_cores;
|
||||
_no_of_sockets = _no_of_cores;
|
||||
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64");
|
||||
os::snprintf_checked(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64");
|
||||
|
||||
int desc_len = snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
|
||||
int desc_len = os::snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
|
||||
get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len);
|
||||
desc_len = (int)strlen(_cpu_desc);
|
||||
snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _cpu_info_string);
|
||||
os::snprintf_checked(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _cpu_info_string);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@ -2638,9 +2638,6 @@ attributes %{
|
||||
instruction_unit_size = 4; // An instruction is 4 bytes long
|
||||
instruction_fetch_unit_size = 16; // The processor fetches one line
|
||||
instruction_fetch_units = 1; // of 16 bytes
|
||||
|
||||
// List of nop instructions
|
||||
nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
|
||||
%}
|
||||
|
||||
//----------RESOURCES----------------------------------------------------------
|
||||
@ -3284,18 +3281,18 @@ pipe_class loadPollP(iRegP poll) %{
|
||||
%}
|
||||
|
||||
pipe_class br(Universe br, label labl) %{
|
||||
single_instruction_with_delay_slot;
|
||||
single_instruction;
|
||||
BR : R;
|
||||
%}
|
||||
|
||||
pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
|
||||
single_instruction_with_delay_slot;
|
||||
single_instruction;
|
||||
cr : E(read);
|
||||
BR : R;
|
||||
%}
|
||||
|
||||
pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
|
||||
single_instruction_with_delay_slot;
|
||||
single_instruction;
|
||||
op1 : E(read);
|
||||
BR : R;
|
||||
MS : R;
|
||||
@ -3326,14 +3323,14 @@ pipe_class call(method meth) %{
|
||||
%}
|
||||
|
||||
pipe_class tail_call(Universe ignore, label labl) %{
|
||||
single_instruction; has_delay_slot;
|
||||
single_instruction;
|
||||
fixed_latency(100);
|
||||
BR : R(1);
|
||||
MS : R(1);
|
||||
%}
|
||||
|
||||
pipe_class ret(Universe ignore) %{
|
||||
single_instruction; has_delay_slot;
|
||||
single_instruction;
|
||||
BR : R(1);
|
||||
MS : R(1);
|
||||
%}
|
||||
@ -3376,14 +3373,6 @@ pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
|
||||
IALU : R(3)
|
||||
%}
|
||||
|
||||
// Perform a compare, then move conditionally in a branch delay slot.
|
||||
pipe_class min_max( iRegI src2, iRegI srcdst ) %{
|
||||
src2 : E(read);
|
||||
srcdst : E(read);
|
||||
IALU : R;
|
||||
BR : R;
|
||||
%}
|
||||
|
||||
// Define the class for the Nop node
|
||||
define %{
|
||||
MachNop = ialu_nop;
|
||||
@ -9056,7 +9045,7 @@ instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dum
|
||||
format %{ "MOV $zero,0\n"
|
||||
" MOV $temp,$cnt\n"
|
||||
"loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n"
|
||||
" STR.ge $zero,[$base+$temp]\t! delay slot"
|
||||
" STR.ge $zero,[$base+$temp]\n"
|
||||
" B.gt loop\t\t! Clearing loop\n" %}
|
||||
ins_encode %{
|
||||
__ mov($zero$$Register, 0);
|
||||
|
||||
@ -2552,11 +2552,6 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
|
||||
fatal("Type profiling not implemented on this platform");
|
||||
}
|
||||
|
||||
void LIR_Assembler::emit_delay(LIR_OpDelay*) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) {
|
||||
Address mon_addr = frame_map()->address_for_monitor_lock(monitor_no);
|
||||
__ add_slow(dst->as_pointer_register(), mon_addr.base(), mon_addr.disp());
|
||||
|
||||
@ -48,11 +48,25 @@ class NativeNMethodBarrier: public NativeInstruction {
|
||||
|
||||
public:
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
}
|
||||
|
||||
void verify() const;
|
||||
@ -115,7 +129,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
|
||||
}
|
||||
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
|
||||
if (!supports_entry_barrier(nm)) {
|
||||
return;
|
||||
}
|
||||
@ -123,7 +137,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
// Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier.
|
||||
// Symmetric "LDR; DMB ISHLD" is in the nmethod barrier.
|
||||
NativeNMethodBarrier* barrier = native_nmethod_barrier(nm);
|
||||
barrier->set_value(value);
|
||||
barrier->set_value(value, bit_mask);
|
||||
}
|
||||
|
||||
int BarrierSetNMethod::guard_value(nmethod* nm) {
|
||||
|
||||
@ -839,7 +839,7 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file,
|
||||
char buffer[64];
|
||||
#ifdef COMPILER1
|
||||
if (CommentedAssembly) {
|
||||
snprintf(buffer, sizeof(buffer), "verify_oop at %d", offset());
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "verify_oop at %d", offset());
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -421,7 +421,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
|
||||
// As per atomic.hpp the Atomic read-modify-write operations must be logically implemented as:
|
||||
// As per atomicAccess.hpp the atomic read-modify-write operations must be
|
||||
// logically implemented as:
|
||||
// <fence>; <op>; <membar StoreLoad|StoreStore>
|
||||
// But for load-linked/store-conditional based systems a fence here simply means
|
||||
// no load/store can be reordered with respect to the initial load-linked, so we have:
|
||||
@ -440,7 +441,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// be removed in the future.
|
||||
|
||||
// Implementation of atomic_add(jint add_value, volatile jint* dest)
|
||||
// used by Atomic::add(volatile jint* dest, jint add_value)
|
||||
// used by AtomicAccess::add(volatile jint* dest, jint add_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@ -492,7 +493,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Implementation of jint atomic_xchg(jint exchange_value, volatile jint* dest)
|
||||
// used by Atomic::add(volatile jint* dest, jint exchange_value)
|
||||
// used by AtomicAccess::add(volatile jint* dest, jint exchange_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@ -542,7 +543,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Implementation of jint atomic_cmpxchg(jint exchange_value, volatile jint *dest, jint compare_value)
|
||||
// used by Atomic::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
|
||||
// used by AtomicAccess::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@ -582,7 +583,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// Support for jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
|
||||
// Support for jlong AtomicAccess::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
|
||||
// reordered before by a wrapper to (jlong compare_value, jlong exchange_value, volatile jlong *dest)
|
||||
//
|
||||
// Arguments :
|
||||
|
||||
@ -362,7 +362,7 @@ void VM_Version::initialize_cpu_information(void) {
|
||||
_no_of_cores = os::processor_count();
|
||||
_no_of_threads = _no_of_cores;
|
||||
_no_of_sockets = _no_of_cores;
|
||||
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch);
|
||||
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
|
||||
os::snprintf_checked(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch);
|
||||
os::snprintf_checked(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ int AbstractInterpreter::size_activation(int max_stack,
|
||||
// It is also guaranteed to be walkable even though it is in a skeletal state
|
||||
//
|
||||
// is_top_frame == true:
|
||||
// We're processing the *oldest* interpreter frame!
|
||||
// We're processing the *youngest* interpreter frame on top of stack!
|
||||
//
|
||||
// pop_frame_extra_args:
|
||||
// If this is != 0 we are returning to a deoptimized frame by popping
|
||||
@ -131,8 +131,9 @@ void AbstractInterpreter::layout_activation(Method* method,
|
||||
#ifdef ASSERT
|
||||
if (caller->is_interpreted_frame()) {
|
||||
assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement");
|
||||
const int caller_abi_bytesize = (is_bottom_frame ? frame::top_ijava_frame_abi_size : frame::parent_ijava_frame_abi_size);
|
||||
intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (caller_abi_bytesize / Interpreter::stackElementSize);
|
||||
// If the bottom frame's caller was thawed then it has frame::java_abi (aka parent_ijava_frame_abi).
|
||||
// With an ordinary i2c call it would keep the larger frame::top_ijava_frame_abi
|
||||
intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (frame::parent_ijava_frame_abi_size / Interpreter::stackElementSize);
|
||||
assert(locals_base >= l2, "bad placement");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2747,11 +2747,6 @@ void LIR_Assembler::align_backward_branch_target() {
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::emit_delay(LIR_OpDelay* op) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) {
|
||||
// tmp must be unused
|
||||
assert(tmp->is_illegal(), "wasting a register if tmp is allocated");
|
||||
|
||||
@ -183,12 +183,9 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
|
||||
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||
assert_different_registers(tmp, R0);
|
||||
|
||||
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
|
||||
__ align(8); // must align the following block which requires atomic updates
|
||||
|
||||
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
|
||||
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
|
||||
true, true, false); // 2 instructions
|
||||
__ mtctr(tmp);
|
||||
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
|
||||
|
||||
// This is a compound instruction. Patching support is provided by NativeMovRegMem.
|
||||
// Actual patching is done in (platform-specific part of) BarrierSetNMethod.
|
||||
@ -198,6 +195,11 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
|
||||
__ ld(R0, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), R16_thread);
|
||||
__ cmpw(CR0, R0, tmp);
|
||||
|
||||
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
|
||||
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
|
||||
true, true, false); // 2 instructions
|
||||
__ mtctr(tmp);
|
||||
|
||||
__ bnectrl(CR0);
|
||||
|
||||
// Oops may have been changed. Make those updates observable.
|
||||
|
||||
@ -40,8 +40,7 @@ class Node;
|
||||
|
||||
enum class NMethodPatchingType {
|
||||
stw_instruction_and_data_patch,
|
||||
conc_instruction_and_data_patch,
|
||||
conc_data_patch
|
||||
conc_instruction_and_data_patch
|
||||
};
|
||||
|
||||
class BarrierSetAssembler: public CHeapObj<mtGC> {
|
||||
|
||||
@ -38,7 +38,7 @@ class NativeNMethodBarrier: public NativeInstruction {
|
||||
|
||||
NativeMovRegMem* get_patchable_instruction_handle() const {
|
||||
// Endianness is handled by NativeMovRegMem
|
||||
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address() + 3 * 4);
|
||||
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address());
|
||||
}
|
||||
|
||||
public:
|
||||
@ -47,7 +47,7 @@ public:
|
||||
return get_patchable_instruction_handle()->offset();
|
||||
}
|
||||
|
||||
void release_set_guard_value(int value) {
|
||||
void release_set_guard_value(int value, int bit_mask) {
|
||||
// Patching is not atomic.
|
||||
// Stale observations of the "armed" state is okay as invoking the barrier stub in that case has no
|
||||
// unwanted side effects. Disarming is thus a non-critical operation.
|
||||
@ -55,8 +55,37 @@ public:
|
||||
|
||||
OrderAccess::release(); // Release modified oops
|
||||
|
||||
// Set the guard value (naming of 'offset' function is misleading).
|
||||
get_patchable_instruction_handle()->set_offset(value);
|
||||
if (bit_mask == ~0) {
|
||||
// Set the guard value (naming of 'offset' function is misleading).
|
||||
get_patchable_instruction_handle()->set_offset(value);
|
||||
return;
|
||||
}
|
||||
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
|
||||
NativeMovRegMem* mov = get_patchable_instruction_handle();
|
||||
assert(align_up(mov->instruction_address(), sizeof(uint64_t)) ==
|
||||
align_down(mov->instruction_address(), sizeof(uint64_t)), "instruction not aligned");
|
||||
uint64_t *instr = (uint64_t*)mov->instruction_address();
|
||||
assert(NativeMovRegMem::instruction_size == sizeof(*instr), "must be");
|
||||
union {
|
||||
u_char buf[NativeMovRegMem::instruction_size];
|
||||
uint64_t u64;
|
||||
} new_mov_instr, old_mov_instr;
|
||||
new_mov_instr.u64 = old_mov_instr.u64 = AtomicAccess::load(instr);
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) return; // skip icache flush if nothing changed
|
||||
nativeMovRegMem_at(new_mov_instr.buf)->set_offset(new_value, false /* no icache flush */);
|
||||
// Swap in the new value
|
||||
uint64_t v = AtomicAccess::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_relaxed);
|
||||
if (v == old_mov_instr.u64) break;
|
||||
old_mov_instr.u64 = v;
|
||||
}
|
||||
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
|
||||
}
|
||||
|
||||
void verify() const {
|
||||
@ -66,12 +95,6 @@ public:
|
||||
|
||||
uint* current_instruction = reinterpret_cast<uint*>(get_barrier_start_address());
|
||||
|
||||
// calculate_address_from_global_toc (compound instruction)
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
|
||||
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
|
||||
|
||||
get_patchable_instruction_handle()->verify();
|
||||
current_instruction += 2;
|
||||
|
||||
@ -80,6 +103,12 @@ public:
|
||||
// cmpw (mnemonic)
|
||||
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
|
||||
|
||||
// calculate_address_from_global_toc (compound instruction)
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
|
||||
|
||||
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
|
||||
|
||||
// bnectrl (mnemonic) (weak check; not checking the exact type)
|
||||
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
|
||||
|
||||
@ -117,13 +146,13 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
// Thus, there's nothing to do here.
|
||||
}
|
||||
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
|
||||
if (!supports_entry_barrier(nm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeNMethodBarrier* barrier = get_nmethod_barrier(nm);
|
||||
barrier->release_set_guard_value(value);
|
||||
barrier->release_set_guard_value(value, bit_mask);
|
||||
}
|
||||
|
||||
int BarrierSetNMethod::guard_value(nmethod* nm) {
|
||||
|
||||
@ -69,7 +69,7 @@ private:
|
||||
Register preserve);
|
||||
|
||||
public:
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
|
||||
|
||||
/* ==== C1 stubs ==== */
|
||||
#ifdef COMPILER1
|
||||
|
||||
@ -347,7 +347,7 @@ void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer)
|
||||
// Finally patch out the jump.
|
||||
volatile juint *jump_addr = (volatile juint*)instr_addr;
|
||||
// Release not needed because caller uses invalidate_range after copying the remaining bytes.
|
||||
//Atomic::release_store(jump_addr, *((juint*)code_buffer));
|
||||
//AtomicAccess::release_store(jump_addr, *((juint*)code_buffer));
|
||||
*jump_addr = *((juint*)code_buffer); // atomically store code over branch instruction
|
||||
ICache::ppc64_flush_icache_bytes(instr_addr, NativeGeneralJump::instruction_size);
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
return ((*hi_ptr) << 16) | ((*lo_ptr) & 0xFFFF);
|
||||
}
|
||||
|
||||
void set_offset(intptr_t x) {
|
||||
void set_offset(intptr_t x, bool flush_icache = true) {
|
||||
#ifdef VM_LITTLE_ENDIAN
|
||||
short *hi_ptr = (short*)(addr_at(0));
|
||||
short *lo_ptr = (short*)(addr_at(4));
|
||||
@ -472,7 +472,9 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
#endif
|
||||
*hi_ptr = x >> 16;
|
||||
*lo_ptr = x & 0xFFFF;
|
||||
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
|
||||
if (flush_icache) {
|
||||
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
|
||||
}
|
||||
}
|
||||
|
||||
void add_offset_in_bytes(intptr_t radd_offset) {
|
||||
|
||||
@ -4920,10 +4920,6 @@ attributes %{
|
||||
|
||||
// ...in one line
|
||||
instruction_fetch_units = 1
|
||||
|
||||
// Unused, list one so that array generated by adlc is not empty.
|
||||
// Aix compiler chokes if _nop_count = 0.
|
||||
nops(fxNop);
|
||||
%}
|
||||
|
||||
//----------RESOURCES----------------------------------------------------------
|
||||
|
||||
@ -625,7 +625,7 @@ void VM_Version::initialize_cpu_information(void) {
|
||||
_no_of_cores = os::processor_count();
|
||||
_no_of_threads = _no_of_cores;
|
||||
_no_of_sockets = _no_of_cores;
|
||||
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64);
|
||||
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", cpu_info_string());
|
||||
os::snprintf_checked(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64);
|
||||
os::snprintf_checked(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", cpu_info_string());
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@ -912,6 +912,32 @@ protected:
|
||||
emit(insn);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static uint32_t encode_jal(Register Rd, const int32_t offset) {
|
||||
guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1101111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff));
|
||||
patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1));
|
||||
patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff));
|
||||
patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1));
|
||||
return insn;
|
||||
}
|
||||
|
||||
static uint32_t encode_jalr(Register Rd, Register Rs, const int32_t offset) {
|
||||
guarantee(is_simm12(offset), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1100111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 14, 12, 0b000);
|
||||
patch_reg((address)&insn, 15, Rs);
|
||||
int32_t val = offset & 0xfff;
|
||||
patch((address)&insn, 31, 20, val);
|
||||
return insn;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
enum barrier {
|
||||
@ -1988,6 +2014,7 @@ enum VectorMask {
|
||||
|
||||
// Vector Narrowing Integer Right Shift Instructions
|
||||
INSN(vnsra_wi, 0b1010111, 0b011, 0b101101);
|
||||
INSN(vnsrl_wi, 0b1010111, 0b011, 0b101100);
|
||||
|
||||
#undef INSN
|
||||
|
||||
|
||||
@ -1590,8 +1590,6 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
}
|
||||
}
|
||||
|
||||
void LIR_Assembler::emit_delay(LIR_OpDelay*) { Unimplemented(); }
|
||||
|
||||
void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) {
|
||||
__ la(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no));
|
||||
}
|
||||
|
||||
@ -2248,41 +2248,80 @@ static void float_to_float16_v_slow_path(C2_MacroAssembler& masm,
|
||||
#define __ masm.
|
||||
VectorRegister dst = stub.data<0>();
|
||||
VectorRegister src = stub.data<1>();
|
||||
VectorRegister tmp = stub.data<2>();
|
||||
VectorRegister vtmp = stub.data<2>();
|
||||
assert_different_registers(dst, src, vtmp);
|
||||
|
||||
__ bind(stub.entry());
|
||||
|
||||
// Active elements (NaNs) are marked in v0 mask register.
|
||||
// mul is already set to mf2 in float_to_float16_v.
|
||||
|
||||
// preserve the payloads of non-canonical NaNs.
|
||||
__ vnsra_wi(dst, src, 13, Assembler::v0_t);
|
||||
// Float (32 bits)
|
||||
// Bit: 31 30 to 23 22 to 0
|
||||
// +---+------------------+-----------------------------+
|
||||
// | S | Exponent | Mantissa (Fraction) |
|
||||
// +---+------------------+-----------------------------+
|
||||
// 1 bit 8 bits 23 bits
|
||||
//
|
||||
// Float (16 bits)
|
||||
// Bit: 15 14 to 10 9 to 0
|
||||
// +---+----------------+------------------+
|
||||
// | S | Exponent | Mantissa |
|
||||
// +---+----------------+------------------+
|
||||
// 1 bit 5 bits 10 bits
|
||||
const int fp_sign_bits = 1;
|
||||
const int fp32_bits = 32;
|
||||
const int fp32_mantissa_2nd_part_bits = 9;
|
||||
const int fp32_mantissa_3rd_part_bits = 4;
|
||||
const int fp16_exponent_bits = 5;
|
||||
const int fp16_mantissa_bits = 10;
|
||||
|
||||
// preserve the sign bit.
|
||||
__ vnsra_wi(tmp, src, 26, Assembler::v0_t);
|
||||
__ vsll_vi(tmp, tmp, 10, Assembler::v0_t);
|
||||
__ mv(t0, 0x3ff);
|
||||
__ vor_vx(tmp, tmp, t0, Assembler::v0_t);
|
||||
// preserve the sign bit and exponent, clear mantissa.
|
||||
__ vnsra_wi(dst, src, fp32_bits - fp_sign_bits - fp16_exponent_bits, Assembler::v0_t);
|
||||
__ vsll_vi(dst, dst, fp16_mantissa_bits, Assembler::v0_t);
|
||||
|
||||
// get the result by merging sign bit and payloads of preserved non-canonical NaNs.
|
||||
__ vand_vv(dst, dst, tmp, Assembler::v0_t);
|
||||
// Preserve high order bit of float NaN in the
|
||||
// binary16 result NaN (tenth bit); OR in remaining
|
||||
// bits into lower 9 bits of binary 16 significand.
|
||||
// | (doppel & 0x007f_e000) >> 13 // 10 bits
|
||||
// | (doppel & 0x0000_1ff0) >> 4 // 9 bits
|
||||
// | (doppel & 0x0000_000f)); // 4 bits
|
||||
//
|
||||
// Check j.l.Float.floatToFloat16 for more information.
|
||||
// 10 bits
|
||||
__ vnsrl_wi(vtmp, src, fp32_mantissa_2nd_part_bits + fp32_mantissa_3rd_part_bits, Assembler::v0_t);
|
||||
__ mv(t0, 0x3ff); // retain first part of mantissa in a float 32
|
||||
__ vand_vx(vtmp, vtmp, t0, Assembler::v0_t);
|
||||
__ vor_vv(dst, dst, vtmp, Assembler::v0_t);
|
||||
// 9 bits
|
||||
__ vnsrl_wi(vtmp, src, fp32_mantissa_3rd_part_bits, Assembler::v0_t);
|
||||
__ mv(t0, 0x1ff); // retain second part of mantissa in a float 32
|
||||
__ vand_vx(vtmp, vtmp, t0, Assembler::v0_t);
|
||||
__ vor_vv(dst, dst, vtmp, Assembler::v0_t);
|
||||
// 4 bits
|
||||
// Narrow shift is necessary to move data from 32 bits element to 16 bits element in vector register.
|
||||
__ vnsrl_wi(vtmp, src, 0, Assembler::v0_t);
|
||||
__ vand_vi(vtmp, vtmp, 0xf, Assembler::v0_t);
|
||||
__ vor_vv(dst, dst, vtmp, Assembler::v0_t);
|
||||
|
||||
__ j(stub.continuation());
|
||||
#undef __
|
||||
}
|
||||
|
||||
// j.l.Float.float16ToFloat
|
||||
void C2_MacroAssembler::float_to_float16_v(VectorRegister dst, VectorRegister src, VectorRegister vtmp,
|
||||
Register tmp, uint vector_length) {
|
||||
void C2_MacroAssembler::float_to_float16_v(VectorRegister dst, VectorRegister src,
|
||||
VectorRegister vtmp, Register tmp, uint vector_length) {
|
||||
assert_different_registers(dst, src, vtmp);
|
||||
|
||||
auto stub = C2CodeStub::make<VectorRegister, VectorRegister, VectorRegister>
|
||||
(dst, src, vtmp, 28, float_to_float16_v_slow_path);
|
||||
(dst, src, vtmp, 56, float_to_float16_v_slow_path);
|
||||
|
||||
// On riscv, NaN needs a special process as vfncvt_f_f_w does not work in that case.
|
||||
|
||||
vsetvli_helper(BasicType::T_FLOAT, vector_length, Assembler::m1);
|
||||
|
||||
// check whether there is a NaN.
|
||||
// replace v_fclass with vmseq_vv as performance optimization.
|
||||
// replace v_fclass with vmfne_vv as performance optimization.
|
||||
vmfne_vv(v0, src, src);
|
||||
vcpop_m(t0, v0);
|
||||
|
||||
|
||||
@ -217,7 +217,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::increment_patching_epoch() {
|
||||
Atomic::inc(&_patching_epoch);
|
||||
AtomicAccess::inc(&_patching_epoch);
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::clear_patching_epoch() {
|
||||
@ -241,10 +241,6 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
|
||||
__ lwu(t0, *guard);
|
||||
|
||||
switch (patching_type) {
|
||||
case NMethodPatchingType::conc_data_patch:
|
||||
// Subsequent loads of oops must occur after load of guard value.
|
||||
// BarrierSetNMethod::disarm sets guard with release semantics.
|
||||
__ membar(MacroAssembler::LoadLoad); // fall through to stw_instruction_and_data_patch
|
||||
case NMethodPatchingType::stw_instruction_and_data_patch:
|
||||
{
|
||||
// With STW patching, no data or instructions are updated concurrently,
|
||||
|
||||
@ -40,8 +40,7 @@ class Node;
|
||||
|
||||
enum class NMethodPatchingType {
|
||||
stw_instruction_and_data_patch,
|
||||
conc_instruction_and_data_patch,
|
||||
conc_data_patch
|
||||
conc_instruction_and_data_patch
|
||||
};
|
||||
|
||||
class BarrierSetAssembler: public CHeapObj<mtGC> {
|
||||
|
||||
@ -50,8 +50,6 @@ static int entry_barrier_offset(nmethod* nm) {
|
||||
switch (bs_asm->nmethod_patching_type()) {
|
||||
case NMethodPatchingType::stw_instruction_and_data_patch:
|
||||
return -4 * (4 + slow_path_size(nm));
|
||||
case NMethodPatchingType::conc_data_patch:
|
||||
return -4 * (5 + slow_path_size(nm));
|
||||
case NMethodPatchingType::conc_instruction_and_data_patch:
|
||||
return -4 * (15 + slow_path_size(nm));
|
||||
}
|
||||
@ -108,11 +106,25 @@ public:
|
||||
}
|
||||
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_barrier(err_msg& msg) const;
|
||||
@ -194,7 +206,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
|
||||
}
|
||||
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
|
||||
if (!supports_entry_barrier(nm)) {
|
||||
return;
|
||||
}
|
||||
@ -211,7 +223,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
|
||||
}
|
||||
|
||||
NativeNMethodBarrier barrier(nm);
|
||||
barrier.set_value(value);
|
||||
barrier.set_value(value, bit_mask);
|
||||
}
|
||||
|
||||
int BarrierSetNMethod::guard_value(nmethod* nm) {
|
||||
|
||||
@ -69,7 +69,7 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
|
||||
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
|
||||
|
||||
#ifdef COMPILER1
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
|
||||
|
||||
@ -2679,7 +2679,7 @@ void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset, Register
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIx64, uimm64);
|
||||
os::snprintf_checked(buffer, sizeof(buffer), "0x%" PRIx64, uimm64);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
@ -3402,6 +3402,8 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
|
||||
|
||||
void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) {
|
||||
assert(UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert_different_registers(dst, tmp);
|
||||
assert_different_registers(src, tmp);
|
||||
|
||||
if (CompressedKlassPointers::base() == nullptr) {
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
@ -3412,18 +3414,13 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register
|
||||
return;
|
||||
}
|
||||
|
||||
Register xbase = dst;
|
||||
if (dst == src) {
|
||||
xbase = tmp;
|
||||
}
|
||||
Register xbase = tmp;
|
||||
|
||||
assert_different_registers(src, xbase);
|
||||
mv(xbase, (uintptr_t)CompressedKlassPointers::base());
|
||||
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
Register t = src == dst ? dst : t0;
|
||||
assert_different_registers(t, xbase);
|
||||
shadd(dst, src, xbase, t, CompressedKlassPointers::shift());
|
||||
// dst = (src << shift) + xbase
|
||||
shadd(dst, src, xbase, dst /* temporary, dst != xbase */, CompressedKlassPointers::shift());
|
||||
} else {
|
||||
add(dst, xbase, src);
|
||||
}
|
||||
@ -5874,13 +5871,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) {
|
||||
// in cnt.
|
||||
//
|
||||
// NOTE: This is intended to be used in the zero_blocks() stub. If
|
||||
// you want to use it elsewhere, note that cnt must be >= CacheLineSize.
|
||||
// you want to use it elsewhere, note that cnt must be >= zicboz_block_size.
|
||||
void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tmp1, Register tmp2) {
|
||||
int zicboz_block_size = VM_Version::zicboz_block_size.value();
|
||||
Label initial_table_end, loop;
|
||||
|
||||
// Align base with cache line size.
|
||||
neg(tmp1, base);
|
||||
andi(tmp1, tmp1, CacheLineSize - 1);
|
||||
andi(tmp1, tmp1, zicboz_block_size - 1);
|
||||
|
||||
// tmp1: the number of bytes to be filled to align the base with cache line size.
|
||||
add(base, base, tmp1);
|
||||
@ -5890,16 +5888,16 @@ void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tm
|
||||
la(tmp1, initial_table_end);
|
||||
sub(tmp2, tmp1, tmp2);
|
||||
jr(tmp2);
|
||||
for (int i = -CacheLineSize + wordSize; i < 0; i += wordSize) {
|
||||
for (int i = -zicboz_block_size + wordSize; i < 0; i += wordSize) {
|
||||
sd(zr, Address(base, i));
|
||||
}
|
||||
bind(initial_table_end);
|
||||
|
||||
mv(tmp1, CacheLineSize / wordSize);
|
||||
mv(tmp1, zicboz_block_size / wordSize);
|
||||
bind(loop);
|
||||
cbo_zero(base);
|
||||
sub(cnt, cnt, tmp1);
|
||||
addi(base, base, CacheLineSize);
|
||||
addi(base, base, zicboz_block_size);
|
||||
bge(cnt, tmp1, loop);
|
||||
}
|
||||
|
||||
|
||||
@ -93,14 +93,60 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
|
||||
|
||||
void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) {}
|
||||
|
||||
void MethodHandles::verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) {
|
||||
BLOCK_COMMENT("verify_method {");
|
||||
__ verify_method_ptr(method);
|
||||
if (VerifyMethodHandles) {
|
||||
Label L_ok;
|
||||
assert_different_registers(method, t0, t1);
|
||||
const Register method_holder = t1;
|
||||
__ load_method_holder(method_holder, method);
|
||||
|
||||
switch (iid) {
|
||||
case vmIntrinsicID::_invokeBasic:
|
||||
// Require compiled LambdaForm class to be fully initialized.
|
||||
__ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset()));
|
||||
__ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
|
||||
__ mv(t1, InstanceKlass::fully_initialized);
|
||||
__ beq(t0, t1, L_ok);
|
||||
break;
|
||||
case vmIntrinsicID::_linkToStatic:
|
||||
__ clinit_barrier(method_holder, t0, &L_ok);
|
||||
break;
|
||||
|
||||
case vmIntrinsicID::_linkToVirtual:
|
||||
case vmIntrinsicID::_linkToSpecial:
|
||||
case vmIntrinsicID::_linkToInterface:
|
||||
// Class initialization check is too strong here. Just ensure that class initialization has been initiated.
|
||||
__ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset()));
|
||||
__ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
|
||||
__ mv(t1, InstanceKlass::being_initialized);
|
||||
__ bge(t0, t1, L_ok);
|
||||
|
||||
// init_state check failed, but it may be an abstract interface method
|
||||
__ lhu(t0, Address(method, Method::access_flags_offset()));
|
||||
__ test_bit(t1, t0, exact_log2(JVM_ACC_ABSTRACT));
|
||||
__ bnez(t1, L_ok);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid));
|
||||
}
|
||||
|
||||
// Method holder init state check failed for a concrete method.
|
||||
__ stop("Method holder klass is not initialized");
|
||||
__ BIND(L_ok);
|
||||
}
|
||||
BLOCK_COMMENT("} verify_method");
|
||||
}
|
||||
#endif //ASSERT
|
||||
|
||||
void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp,
|
||||
bool for_compiler_entry) {
|
||||
bool for_compiler_entry, vmIntrinsics::ID iid) {
|
||||
assert(method == xmethod, "interpreter calling convention");
|
||||
Label L_no_such_method;
|
||||
__ beqz(xmethod, L_no_such_method);
|
||||
__ verify_method_ptr(method);
|
||||
verify_method(_masm, method, iid);
|
||||
|
||||
if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) {
|
||||
Label run_compiled_code;
|
||||
@ -158,7 +204,7 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
|
||||
__ BIND(L);
|
||||
}
|
||||
|
||||
jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry);
|
||||
jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry, vmIntrinsics::_invokeBasic);
|
||||
BLOCK_COMMENT("} jump_to_lambda_form");
|
||||
}
|
||||
|
||||
@ -437,8 +483,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
|
||||
// After figuring out which concrete method to call, jump into it.
|
||||
// Note that this works in the interpreter with no data motion.
|
||||
// But the compiled version will require that r2_recv be shifted out.
|
||||
__ verify_method_ptr(xmethod);
|
||||
jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry);
|
||||
jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry, iid);
|
||||
if (iid == vmIntrinsics::_linkToInterface) {
|
||||
__ bind(L_incompatible_class_change_error);
|
||||
__ far_jump(RuntimeAddress(SharedRuntime::throw_IncompatibleClassChangeError_entry()));
|
||||
|
||||
@ -39,6 +39,8 @@ public:
|
||||
Register obj, vmClassID klass_id,
|
||||
const char* error_message = "wrong klass") NOT_DEBUG_RETURN;
|
||||
|
||||
static void verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) NOT_DEBUG_RETURN;
|
||||
|
||||
static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) {
|
||||
verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle),
|
||||
"reference is a MH");
|
||||
@ -49,7 +51,7 @@ public:
|
||||
// Similar to InterpreterMacroAssembler::jump_from_interpreted.
|
||||
// Takes care of special dispatch from single stepping too.
|
||||
static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp,
|
||||
bool for_compiler_entry);
|
||||
bool for_compiler_entry, vmIntrinsics::ID iid);
|
||||
|
||||
static void jump_to_lambda_form(MacroAssembler* _masm,
|
||||
Register recv, Register method_temp,
|
||||
|
||||
@ -28,11 +28,13 @@
|
||||
#include "code/compiledIC.hpp"
|
||||
#include "nativeInst_riscv.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/orderAccess.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Runtime1.hpp"
|
||||
@ -52,15 +54,15 @@ address NativeCall::destination() const {
|
||||
address addr = instruction_address();
|
||||
assert(NativeCall::is_at(addr), "unexpected code at call site");
|
||||
|
||||
address destination = MacroAssembler::target_addr_for_insn(addr);
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(addr);
|
||||
|
||||
CodeBlob* cb = CodeCache::find_blob(addr);
|
||||
assert(cb != nullptr && cb->is_nmethod(), "nmethod expected");
|
||||
nmethod *nm = (nmethod *)cb;
|
||||
assert(nm != nullptr, "Sanity");
|
||||
assert(nm->stub_contains(destination), "Sanity");
|
||||
assert(destination != nullptr, "Sanity");
|
||||
return stub_address_destination_at(destination);
|
||||
assert(nm->stub_contains(stub_addr), "Sanity");
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
|
||||
return stub_address_destination_at(stub_addr);
|
||||
}
|
||||
|
||||
address NativeCall::reloc_destination() {
|
||||
@ -89,6 +91,30 @@ void NativeCall::print() {
|
||||
tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(instruction_address()));
|
||||
}
|
||||
|
||||
void NativeCall::optimize_call(address dest, bool mt_safe) {
|
||||
// Skip over auipc + ld
|
||||
address jmp_ins_pc = instruction_address() + 2 * NativeInstruction::instruction_size;
|
||||
// Rutime calls may be unaligned, but they are never changed after relocation.
|
||||
assert(!mt_safe || is_aligned(jmp_ins_pc, NativeInstruction::instruction_size), "Must be naturally aligned: %p", jmp_ins_pc);
|
||||
// If reachable use JAL
|
||||
if (Assembler::reachable_from_branch_at(jmp_ins_pc, dest)) {
|
||||
int64_t distance = dest - jmp_ins_pc;
|
||||
uint32_t new_jal = Assembler::encode_jal(ra, distance);
|
||||
AtomicAccess::store((uint32_t *)jmp_ins_pc, new_jal);
|
||||
} else if (!MacroAssembler::is_jalr_at(jmp_ins_pc)) { // The jalr is always identical: jalr ra, 0(t1)
|
||||
uint32_t new_jalr = Assembler::encode_jalr(ra, t1, 0);
|
||||
AtomicAccess::store((uint32_t *)jmp_ins_pc, new_jalr);
|
||||
} else {
|
||||
// No change to instruction stream
|
||||
return;
|
||||
}
|
||||
// We changed instruction stream
|
||||
if (mt_safe) {
|
||||
// IC invalidate provides a leading full fence, it thus happens after we changed the instruction stream.
|
||||
ICache::invalidate_range(jmp_ins_pc, NativeInstruction::instruction_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
assert(NativeCall::is_at(instruction_address()), "unexpected code at call site");
|
||||
assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
|
||||
@ -96,15 +122,17 @@ bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
"concurrent code patching");
|
||||
|
||||
address stub_addr = stub_address();
|
||||
if (stub_addr != nullptr) {
|
||||
set_stub_address_destination_at(stub_addr, dest);
|
||||
return true;
|
||||
}
|
||||
assert(stub_addr != nullptr, "No stub?");
|
||||
set_stub_address_destination_at(stub_addr, dest); // release
|
||||
// optimize_call happens after we stored new address in addr stub.
|
||||
// patches jalr -> jal/jal -> jalr depending on dest
|
||||
optimize_call(dest, true);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCall::reloc_set_destination(address dest) {
|
||||
// The argument passed in is the address to the stub containing the destination
|
||||
bool NativeCall::reloc_set_destination(address stub_addr) {
|
||||
address call_addr = instruction_address();
|
||||
assert(NativeCall::is_at(call_addr), "unexpected code at call site");
|
||||
|
||||
@ -113,10 +141,12 @@ bool NativeCall::reloc_set_destination(address dest) {
|
||||
|
||||
if (code->is_nmethod()) {
|
||||
// TODO: Need to revisit this when porting the AOT features.
|
||||
assert(dest != nullptr, "Sanity");
|
||||
assert(dest == trampoline_stub_Relocation::get_trampoline_for(call_addr,
|
||||
code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, dest);
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
assert(stub_addr == trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); // patches auipc + ld to stub_addr
|
||||
|
||||
address dest = stub_address_destination_at(stub_addr);
|
||||
optimize_call(dest, false); // patches jalr -> jal/jal -> jalr depending on dest
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -142,9 +172,9 @@ address NativeCall::stub_address() {
|
||||
CodeBlob *code = CodeCache::find_blob(call_addr);
|
||||
assert(code != nullptr, "Could not find the containing code blob");
|
||||
|
||||
address dest = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(dest), "Sanity");
|
||||
return dest;
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(stub_addr), "Sanity");
|
||||
return stub_addr;
|
||||
}
|
||||
|
||||
bool NativeCall::is_at(address addr) {
|
||||
@ -160,6 +190,15 @@ bool NativeCall::is_at(address addr) {
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
if (MacroAssembler::is_auipc_at(addr) &&
|
||||
MacroAssembler::is_ld_at(addr + instr_size) &&
|
||||
MacroAssembler::is_jal_at(addr + 2 * instr_size) &&
|
||||
(MacroAssembler::extract_rd(addr) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rs1(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -156,6 +156,10 @@ class NativeCall: private NativeInstruction {
|
||||
static void set_stub_address_destination_at(address dest, address value);
|
||||
// return target address at stub
|
||||
static address stub_address_destination_at(address src);
|
||||
// We either have a jalr or jal depending on distance to old destination.
|
||||
// This method emits a new jal if new destination is within jal reach.
|
||||
// Otherwise restores the jalr which can reach any destination.
|
||||
void optimize_call(address dest, bool mt_safe = true);
|
||||
};
|
||||
|
||||
// An interface for accessing/manipulating native mov reg, imm instructions.
|
||||
|
||||
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