mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-11 11:59:38 +01:00
Compare commits
362 Commits
lbourges/J
...
jdk-26+15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d679087b0 | ||
|
|
0b3a303053 | ||
|
|
8ba0db0de8 | ||
|
|
7690a45f77 | ||
|
|
2826d17025 | ||
|
|
4cc75be80e | ||
|
|
eb9e04598d | ||
|
|
134c3ef41e | ||
|
|
7fcce27096 | ||
|
|
85996572b6 | ||
|
|
85715e1050 | ||
|
|
fdc11a1569 | ||
|
|
4e2a85f750 | ||
|
|
7a3025e3d7 | ||
|
|
af18ff8d7c | ||
|
|
34c3ac0316 | ||
|
|
5cd7721ad4 | ||
|
|
c968a672c0 | ||
|
|
385c132989 | ||
|
|
46ae1ee871 | ||
|
|
703d930e4d | ||
|
|
4d4e51c41f | ||
|
|
edae355e95 | ||
|
|
33244c8244 | ||
|
|
5c9f60dc5a | ||
|
|
1d3364b007 | ||
|
|
f3de386263 | ||
|
|
9e3fa3216f | ||
|
|
b7b01d6f56 | ||
|
|
2705e880b6 | ||
|
|
8ab8d02e40 | ||
|
|
af9b9050ec | ||
|
|
53b3e0567d | ||
|
|
8cd4e7d856 | ||
|
|
f96403986b | ||
|
|
24a734938e | ||
|
|
a12e9fcebd | ||
|
|
cc6d34b2fa | ||
|
|
b653ae92d5 | ||
|
|
f10c85fbc3 | ||
|
|
0632617670 | ||
|
|
a1ab12b772 | ||
|
|
a25dde6279 | ||
|
|
002f936ef2 | ||
|
|
4fc917c250 | ||
|
|
f51e442b0e | ||
|
|
cfb809344c | ||
|
|
e16c510071 | ||
|
|
67bb22f3d6 | ||
|
|
ecfba66d3d | ||
|
|
680bf75898 | ||
|
|
0aee7bf24d | ||
|
|
4ec63e8f5d | ||
|
|
81a1e8e136 | ||
|
|
56e37352d5 | ||
|
|
3e68d7d99f | ||
|
|
85441cec35 | ||
|
|
cb58e6560a | ||
|
|
55af9d8380 | ||
|
|
323b02016e | ||
|
|
48831c65b5 | ||
|
|
ab12fbfda2 | ||
|
|
6765a9d775 | ||
|
|
166ef5e7b1 | ||
|
|
bcff857ba0 | ||
|
|
03c54d4288 | ||
|
|
a272696813 | ||
|
|
5e423e034f | ||
|
|
bea2b029a7 | ||
|
|
051f39e12c | ||
|
|
fb1924d2e3 | ||
|
|
f9dc640ef0 | ||
|
|
b0ca9bf61e | ||
|
|
8a6b8751e1 | ||
|
|
14a40fd579 | ||
|
|
6bb15a542b | ||
|
|
e8c7d2aaf3 | ||
|
|
dbf4ffffe3 | ||
|
|
cdc8b5eb83 | ||
|
|
1ebe949507 | ||
|
|
b674a42553 | ||
|
|
3824c7cd06 | ||
|
|
4ab2b5bdb4 | ||
|
|
e2a503e26e | ||
|
|
c6c451ac39 | ||
|
|
a17058b5bb | ||
|
|
9cca4f7c76 | ||
|
|
9f4d5b2398 | ||
|
|
ceacf6f785 | ||
|
|
1e90af08ab | ||
|
|
33794d1614 | ||
|
|
124fcf1d9a | ||
|
|
0dad3f1ae8 | ||
|
|
e6fa8aae61 | ||
|
|
a2f8d3c4c2 | ||
|
|
0d7f8f83c7 | ||
|
|
40a602520b | ||
|
|
b7b64bb6c8 | ||
|
|
581070715a | ||
|
|
945aaf8932 | ||
|
|
1dc1d56f79 | ||
|
|
8520fd3f6a | ||
|
|
f90d520308 | ||
|
|
79a1a98cab | ||
|
|
e190355777 | ||
|
|
80873a09bf | ||
|
|
8c50bed867 | ||
|
|
53d4e928ef | ||
|
|
ab9f70dd5a | ||
|
|
986ecff5f9 | ||
|
|
1495dd94e9 | ||
|
|
222ae365c8 | ||
|
|
49fd6a0cb4 | ||
|
|
2527e9e58d | ||
|
|
a03302d41b | ||
|
|
62bc7b7c42 | ||
|
|
90a2db1ecb | ||
|
|
4d1dfabcb4 | ||
|
|
f4d73d2a3d | ||
|
|
11743b1ed3 | ||
|
|
ed62bda2e0 | ||
|
|
02dd21196e | ||
|
|
becc35f287 | ||
|
|
431f467246 | ||
|
|
8d236615b7 | ||
|
|
e3b36e3bab | ||
|
|
a40afdd08f | ||
|
|
d5935af228 | ||
|
|
3abaa83610 | ||
|
|
2a5f149bb8 | ||
|
|
3b2f3e53d7 | ||
|
|
6dda2f6fad | ||
|
|
7c70e73414 | ||
|
|
8c4090c2cf | ||
|
|
e268563a10 | ||
|
|
5052a7eee5 | ||
|
|
b50c11f907 | ||
|
|
991ac9e616 | ||
|
|
80fb7088a1 | ||
|
|
0d85f076cc | ||
|
|
c935d1ce1c | ||
|
|
48ba8ed243 | ||
|
|
ecf05ca541 | ||
|
|
444a8fa14e | ||
|
|
a029245a4e | ||
|
|
710354369e | ||
|
|
1feb9bd559 | ||
|
|
eea50fbc1b | ||
|
|
31847149c1 | ||
|
|
e66ed4d729 | ||
|
|
ef7872cc31 | ||
|
|
523bc77981 | ||
|
|
af532cc1b2 | ||
|
|
d19eab4f08 | ||
|
|
3fb9246af9 | ||
|
|
55e7af0560 | ||
|
|
efb81dafaf | ||
|
|
8f11d83a01 | ||
|
|
f58d612b61 | ||
|
|
b06459d3a8 | ||
|
|
99223eea03 | ||
|
|
5110d54d93 | ||
|
|
98af18921a | ||
|
|
7f0cd6488b | ||
|
|
fc77e7600f | ||
|
|
dacd9af9a0 | ||
|
|
56713817c0 | ||
|
|
fe4c7a0429 | ||
|
|
3ca44c8dea | ||
|
|
48f70d7ad8 | ||
|
|
a9f3cb23d1 | ||
|
|
d5d94db12a | ||
|
|
dbac620b99 | ||
|
|
a6e2a329a0 | ||
|
|
ba90ccc6a8 | ||
|
|
86f48ab559 | ||
|
|
12dc568b3d | ||
|
|
685da0323b | ||
|
|
2894240602 | ||
|
|
a668f437e4 | ||
|
|
2427c901b3 | ||
|
|
80ab094a75 | ||
|
|
bdc39818ce | ||
|
|
9339a6a232 | ||
|
|
12e6a0b6d0 | ||
|
|
0e7399318b | ||
|
|
f23c150709 | ||
|
|
d4ce630cea | ||
|
|
849570a94a | ||
|
|
d594ef3a3e | ||
|
|
ae9607725c | ||
|
|
937d61bfba | ||
|
|
86d6a2e05e | ||
|
|
a2da75a6b6 | ||
|
|
b8cdf31a2e | ||
|
|
05da2137f1 | ||
|
|
9f70965bb9 | ||
|
|
aaac8c0636 | ||
|
|
33d00a77f3 | ||
|
|
8c6d12250b | ||
|
|
452b052fe3 | ||
|
|
993babb326 | ||
|
|
8051aaf068 | ||
|
|
afa8e79ba1 | ||
|
|
22ae137400 | ||
|
|
79d8a34a92 | ||
|
|
8f864fd563 | ||
|
|
5c78c7cd83 | ||
|
|
b0f5b23ed2 | ||
|
|
a5a2340054 | ||
|
|
7469a274bb | ||
|
|
d06c66f7f5 | ||
|
|
ab1f2af4f0 | ||
|
|
57df267e42 | ||
|
|
443b172638 | ||
|
|
501e6aed44 | ||
|
|
075ddef831 | ||
|
|
bd4c0f4a7d | ||
|
|
f1c0b4ed72 | ||
|
|
b43c2c6635 | ||
|
|
79cea6dd17 | ||
|
|
1d53ac30f1 | ||
|
|
124575b4c2 | ||
|
|
32df2d17f3 | ||
|
|
19f0755c48 | ||
|
|
0ca38bdc4d | ||
|
|
b39c73696d | ||
|
|
88c3979367 | ||
|
|
aaff9dec24 | ||
|
|
0d54329304 | ||
|
|
1aca920f59 | ||
|
|
82289f6559 | ||
|
|
1ff73cb2ec | ||
|
|
69645fd4ba | ||
|
|
23670fd418 | ||
|
|
b426151a33 | ||
|
|
c755345177 | ||
|
|
c203e7093e | ||
|
|
2b44ed7070 | ||
|
|
6a480ad07a | ||
|
|
caaef3a04c | ||
|
|
173dedfb24 | ||
|
|
aae13af04b | ||
|
|
22d3a6dd34 | ||
|
|
28602f3d3e | ||
|
|
3641c32c11 | ||
|
|
2ae3ea2ad9 | ||
|
|
68abf76e90 | ||
|
|
5013d69d96 | ||
|
|
e38c6f9827 | ||
|
|
deec6aa76d | ||
|
|
e5ec464120 | ||
|
|
98e64cffff | ||
|
|
e7d2a52d35 | ||
|
|
0f7c0e956e | ||
|
|
e5077660c4 | ||
|
|
21efd25c11 | ||
|
|
a629424248 | ||
|
|
1a7ac16d23 | ||
|
|
63faa50428 | ||
|
|
040cc7aee0 | ||
|
|
d24449f696 | ||
|
|
45726a1f8b | ||
|
|
5cc8673841 | ||
|
|
57434c73ea | ||
|
|
28bd29f396 | ||
|
|
7fa501e398 | ||
|
|
d99fb09a20 | ||
|
|
1f0dfdbcca | ||
|
|
0b8ae26028 | ||
|
|
15601b4718 | ||
|
|
58e7581527 | ||
|
|
09aad0aea8 | ||
|
|
7b9969dc8f | ||
|
|
f28f618972 | ||
|
|
603526b55b | ||
|
|
c01b4fc348 | ||
|
|
ae0dac43c0 | ||
|
|
19882220ec | ||
|
|
e916ce8ce9 | ||
|
|
dba0d54505 | ||
|
|
f5f414f9fc | ||
|
|
e1c58f858a | ||
|
|
f0498c2aed | ||
|
|
8e44856992 | ||
|
|
558d06399c | ||
|
|
584137cf96 | ||
|
|
3468c6e5ef | ||
|
|
52747256bb | ||
|
|
11eccfc85f | ||
|
|
bdf9834b81 | ||
|
|
d757246823 | ||
|
|
cf70cb70bc | ||
|
|
fb651fd6d2 | ||
|
|
1548ac4f54 | ||
|
|
02fe095d29 | ||
|
|
a3fd4248b7 | ||
|
|
f61b247fe3 | ||
|
|
ed260e8cae | ||
|
|
f0e706698d | ||
|
|
9439d76309 | ||
|
|
b735ef99b2 | ||
|
|
5ede5b47d4 | ||
|
|
5febc4e3bb | ||
|
|
a7c0f4b845 | ||
|
|
c74c60fb8b | ||
|
|
78d50c0215 | ||
|
|
2e06a91765 | ||
|
|
ecab52c09b | ||
|
|
ed7d5fe840 | ||
|
|
be6c15ecb4 | ||
|
|
9041f4c47f | ||
|
|
3e60ab51fe | ||
|
|
5ca8d7c2a7 | ||
|
|
ebf5ae8435 | ||
|
|
e912977a66 | ||
|
|
1383b8ef87 | ||
|
|
51d710e3cc | ||
|
|
908f3c9697 | ||
|
|
169d145e99 | ||
|
|
70f3469310 | ||
|
|
9c338f6f87 | ||
|
|
4ffd2a8aa4 | ||
|
|
c220a6c7bb | ||
|
|
40bc083267 | ||
|
|
320235ccb8 | ||
|
|
b453eb63c6 | ||
|
|
506625b768 | ||
|
|
640b71da48 | ||
|
|
eca2032c06 | ||
|
|
95577ca97f | ||
|
|
55e7494dee | ||
|
|
3bbaa772b0 | ||
|
|
0858743dee | ||
|
|
884076f6e2 | ||
|
|
024292ac4d | ||
|
|
0755477c9a | ||
|
|
4ed268ff9a | ||
|
|
0b2d0817f1 | ||
|
|
999761d0f6 | ||
|
|
812434c420 | ||
|
|
626bea80ab | ||
|
|
4c80780f6a | ||
|
|
655dc516c2 | ||
|
|
f2f7a490c0 | ||
|
|
e04a310375 | ||
|
|
ec7361e082 | ||
|
|
a0053012a4 | ||
|
|
bad38a0f92 | ||
|
|
285adff24e | ||
|
|
c9ecedd226 | ||
|
|
2a16cc890b | ||
|
|
81c6ed3882 | ||
|
|
c1198bba0e | ||
|
|
a42ba1ff1a | ||
|
|
6e91ccd1c3 | ||
|
|
2b756ab1e8 | ||
|
|
ca753ebad6 | ||
|
|
190e113031 | ||
|
|
166ea12d73 | ||
|
|
e7ca8c7d55 | ||
|
|
f364fcab79 |
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"
|
||||
@@ -1451,10 +1451,10 @@ of a cross-compiling toolchain and a sysroot environment which can
|
||||
easily be used together with the <code>--with-devkit</code> configure
|
||||
option to cross compile the JDK. On Linux/x86_64, the following
|
||||
command:</p>
|
||||
<pre><code>bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64-linux-gnu && make</code></pre>
|
||||
<p>will configure and build the JDK for Linux/ppc64 assuming that
|
||||
<code><devkit-path></code> points to a Linux/x86_64 to Linux/ppc64
|
||||
devkit.</p>
|
||||
<pre><code>bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64le-linux-gnu && make</code></pre>
|
||||
<p>will configure and build the JDK for Linux/ppc64le assuming that
|
||||
<code><devkit-path></code> points to a Linux/x86_64 to
|
||||
Linux/ppc64le devkit.</p>
|
||||
<p>Devkits can be created from the <code>make/devkit</code> directory by
|
||||
executing:</p>
|
||||
<pre><code>make [ TARGETS="<TARGET_TRIPLET>+" ] [ BASE_OS=<OS> ] [ BASE_OS_VERSION=<VER> ]</code></pre>
|
||||
@@ -1481,10 +1481,10 @@ following targets are known to work:</p>
|
||||
<td>arm-linux-gnueabihf</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td>ppc64-linux-gnu</td>
|
||||
<td>ppc64le-linux-gnu</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td>ppc64le-linux-gnu</td>
|
||||
<td>riscv64-linux-gnu</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td>s390x-linux-gnu</td>
|
||||
|
||||
@@ -1258,11 +1258,11 @@ toolchain and a sysroot environment which can easily be used together with the
|
||||
following command:
|
||||
|
||||
```
|
||||
bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64-linux-gnu && make
|
||||
bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64le-linux-gnu && make
|
||||
```
|
||||
|
||||
will configure and build the JDK for Linux/ppc64 assuming that `<devkit-path>`
|
||||
points to a Linux/x86_64 to Linux/ppc64 devkit.
|
||||
will configure and build the JDK for Linux/ppc64le assuming that `<devkit-path>`
|
||||
points to a Linux/x86_64 to Linux/ppc64le devkit.
|
||||
|
||||
Devkits can be created from the `make/devkit` directory by executing:
|
||||
|
||||
@@ -1281,8 +1281,8 @@ at least the following targets are known to work:
|
||||
| x86_64-linux-gnu |
|
||||
| aarch64-linux-gnu |
|
||||
| arm-linux-gnueabihf |
|
||||
| ppc64-linux-gnu |
|
||||
| ppc64le-linux-gnu |
|
||||
| riscv64-linux-gnu |
|
||||
| s390x-linux-gnu |
|
||||
|
||||
`BASE_OS` must be one of `OL` for Oracle Enterprise Linux or `Fedora`. If the
|
||||
|
||||
@@ -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,77 @@ 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="#inline-variables" id="toc-inline-variables">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 +261,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 +470,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 +500,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 +518,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 +717,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 +777,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 +937,34 @@ 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="inline-variables">Inline Variables</h3>
|
||||
<p>Variables with static storage duration may be declared
|
||||
<code>inline</code> (<a href="https://wg21.link/p0386r2">p0386r2</a>).
|
||||
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 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 variable 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 <code>inline</code> is
|
||||
forbidden for 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 +1016,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 +1127,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 +1181,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 +1202,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 +1328,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 +1349,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 +1367,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 +1433,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 +1514,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 +1559,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 +1647,239 @@ 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>
|
||||
href="https://isocpp.org/files/papers/N3651.pdf">n3651</a>, <a
|
||||
href="http://wg21.link/p0127r2">p0127r2</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,32 @@ ordering, which may differ from (may be stronger than) sequentially
|
||||
consistent. There are algorithms in HotSpot that are believed to rely
|
||||
on that ordering.
|
||||
|
||||
### Inline Variables
|
||||
|
||||
Variables with static storage duration may be declared `inline`
|
||||
([p0386r2](https://wg21.link/p0386r2)). 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 is implicitly `inline`. As a consequence, an
|
||||
[ODR use][ODR] of such a variable 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 `inline` is forbidden for 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 +925,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 +1040,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 +1097,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 +1117,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 +1264,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 +1288,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 +1369,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 +1459,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 +1509,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 +1610,281 @@ 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))
|
||||
([n3651](https://isocpp.org/files/papers/N3651.pdf),
|
||||
[p0127r2](http://wg21.link/p0127r2))
|
||||
|
||||
* 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 +1902,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"
|
||||
@@ -940,7 +940,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
# ACLE and this flag are required to build the aarch64 SVE related functions in
|
||||
# libvectormath. Apple Silicon does not support SVE; use macOS as a proxy for
|
||||
# that check.
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_CPU" = "xlinux"; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_OS" = "xlinux"; then
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
AC_LANG_PUSH(C)
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
@@ -954,6 +954,17 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
$2SVE_CFLAGS="-march=armv8-a+sve"
|
||||
# Switching the initialization mode with gcc from 'pattern' to 'zero'
|
||||
# avoids the use of unsupported `__builtin_clear_padding` for variable
|
||||
# length aggregates
|
||||
if test "x$DEBUG_LEVEL" != xrelease && test "x$TOOLCHAIN_TYPE" = xgcc ; then
|
||||
INIT_ZERO_FLAG="-ftrivial-auto-var-init=zero"
|
||||
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_ZERO_FLAG],
|
||||
IF_TRUE: [
|
||||
$2SVE_CFLAGS="${$2SVE_CFLAGS} $INIT_ZERO_FLAG"
|
||||
]
|
||||
)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -115,7 +115,11 @@ AC_DEFUN([FLAGS_SETUP_ASFLAGS],
|
||||
# Force preprocessor to run, just to make sure
|
||||
BASIC_ASFLAGS="-x assembler-with-cpp"
|
||||
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
BASIC_ASFLAGS="-nologo -c"
|
||||
if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
|
||||
BASIC_ASFLAGS="-nologo"
|
||||
else
|
||||
BASIC_ASFLAGS="-nologo -c"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(BASIC_ASFLAGS)
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -655,8 +646,11 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE],
|
||||
if test "x$TOOLCHAIN_TYPE" != xmicrosoft; then
|
||||
AS="$CC -c"
|
||||
else
|
||||
if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then
|
||||
# On 64 bit windows, the assembler is "ml64.exe"
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
|
||||
# On Windows aarch64, the assembler is "armasm64.exe"
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(AS, armasm64)
|
||||
elif test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then
|
||||
# On Windows x64, the assembler is "ml64.exe"
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(AS, ml64)
|
||||
else
|
||||
# otherwise, the assembler is "ml.exe"
|
||||
|
||||
@@ -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
|
||||
@@ -236,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) -Ta $$($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, \
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#
|
||||
# make TARGETS="aarch64-linux-gnu" BASE_OS=Fedora
|
||||
# or
|
||||
# make TARGETS="arm-linux-gnueabihf ppc64-linux-gnu" BASE_OS=Fedora BASE_OS_VERSION=17
|
||||
# make TARGETS="arm-linux-gnueabihf ppc64le-linux-gnu" BASE_OS=Fedora BASE_OS_VERSION=17
|
||||
#
|
||||
# to build several devkits for a specific OS version at once.
|
||||
# You can find the final results under ../../build/devkit/result/<host>-to-<target>
|
||||
@@ -50,7 +50,7 @@
|
||||
# makefile again for cross compilation. Ex:
|
||||
#
|
||||
# PATH=$PWD/../../build/devkit/result/x86_64-linux-gnu-to-x86_64-linux-gnu/bin:$PATH \
|
||||
# make TARGETS="arm-linux-gnueabihf,ppc64-linux-gnu" BASE_OS=Fedora
|
||||
# make TARGETS="arm-linux-gnueabihf ppc64le-linux-gnu" BASE_OS=Fedora
|
||||
#
|
||||
# This is the makefile which iterates over all host and target platforms.
|
||||
#
|
||||
|
||||
@@ -69,15 +69,26 @@ else ifeq ($(BASE_OS), Fedora)
|
||||
ifeq ($(BASE_OS_VERSION), )
|
||||
BASE_OS_VERSION := $(DEFAULT_OS_VERSION)
|
||||
endif
|
||||
ifeq ($(filter aarch64 armhfp ppc64le riscv64 s390x x86_64, $(ARCH)), )
|
||||
$(error Only "aarch64 armhfp ppc64le riscv64 s390x x86_64" architectures are supported for Fedora, but "$(ARCH)" was requested)
|
||||
endif
|
||||
ifeq ($(ARCH), riscv64)
|
||||
ifeq ($(filter 38 39 40 41, $(BASE_OS_VERSION)), )
|
||||
$(error Only Fedora 38-41 are supported for "$(ARCH)", but Fedora $(BASE_OS_VERSION) was requested)
|
||||
endif
|
||||
BASE_URL := http://fedora.riscv.rocks/repos-dist/f$(BASE_OS_VERSION)/latest/$(ARCH)/Packages/
|
||||
else
|
||||
LATEST_ARCHIVED_OS_VERSION := 35
|
||||
ifeq ($(filter x86_64 armhfp, $(ARCH)), )
|
||||
LATEST_ARCHIVED_OS_VERSION := 36
|
||||
ifeq ($(filter aarch64 armhfp x86_64, $(ARCH)), )
|
||||
FEDORA_TYPE := fedora-secondary
|
||||
else
|
||||
FEDORA_TYPE := fedora/linux
|
||||
endif
|
||||
ifeq ($(ARCH), armhfp)
|
||||
ifneq ($(BASE_OS_VERSION), 36)
|
||||
$(error Fedora 36 is the last release supporting "armhfp", but $(BASE_OS) was requested)
|
||||
endif
|
||||
endif
|
||||
NOT_ARCHIVED := $(shell [ $(BASE_OS_VERSION) -gt $(LATEST_ARCHIVED_OS_VERSION) ] && echo true)
|
||||
ifeq ($(NOT_ARCHIVED),true)
|
||||
BASE_URL := https://dl.fedoraproject.org/pub/$(FEDORA_TYPE)/releases/$(BASE_OS_VERSION)/Everything/$(ARCH)/os/Packages/
|
||||
@@ -464,7 +475,7 @@ ifeq ($(ARCH), armhfp)
|
||||
$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard
|
||||
endif
|
||||
|
||||
ifneq ($(filter riscv64 ppc64 ppc64le s390x, $(ARCH)), )
|
||||
ifneq ($(filter riscv64 ppc64le s390x, $(ARCH)), )
|
||||
# We only support 64-bit on these platforms anyway
|
||||
CONFIG += --disable-multilib
|
||||
endif
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -922,8 +922,10 @@ public class GenerateJfrFiles {
|
||||
}
|
||||
out.write(" using JfrEvent<Event" + event.name
|
||||
+ ">::commit; // else commit() is hidden by overloaded versions in this class");
|
||||
printConstructor2(out, event, empty);
|
||||
printCommitMethod(out, event, empty);
|
||||
if (!event.fields.isEmpty()) {
|
||||
printConstructor2(out, event, empty);
|
||||
printCommitMethod(out, event, empty);
|
||||
}
|
||||
if (!empty) {
|
||||
printVerify(out, event.fields);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -3123,7 +3118,9 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
__ membar(__ AnyAny);
|
||||
if(!UseLSE) {
|
||||
__ membar(__ AnyAny);
|
||||
}
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -101,9 +101,12 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
|
||||
*hf.addr_at(frame::interpreter_frame_locals_offset) = locals_offset;
|
||||
return hf;
|
||||
} else {
|
||||
// We need to re-read fp out of the frame because it may be an oop and we might have
|
||||
// had a safepoint in finalize_freeze, after constructing f.
|
||||
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
|
||||
// For a compiled frame we need to re-read fp out of the frame because it may be an
|
||||
// oop and we might have had a safepoint in finalize_freeze, after constructing f.
|
||||
// For stub/native frames the value is not used while frozen, and will be constructed again
|
||||
// when thawing the frame (see ThawBase::new_stack_frame). We use a special bad address to
|
||||
// help with debugging, particularly when inspecting frames and identifying invalid accesses.
|
||||
fp = FKind::compiled ? *(intptr_t**)(f.sp() - frame::sender_sp_offset) : (intptr_t*)badAddressVal;
|
||||
|
||||
int fsize = FKind::size(f);
|
||||
sp = caller.unextended_sp() - fsize;
|
||||
@@ -192,6 +195,11 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
|
||||
intptr_t* fp_addr = sp - frame::sender_sp_offset;
|
||||
*fp_addr = badAddressVal;
|
||||
}
|
||||
|
||||
//////// Thaw
|
||||
|
||||
// Fast path
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -117,8 +115,22 @@ public:
|
||||
return Atomic::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) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = Atomic::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 = Atomic::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) {
|
||||
|
||||
@@ -172,9 +172,9 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm,
|
||||
|
||||
if (expand_call) {
|
||||
assert(pre_val != c_rarg1, "smashed arg");
|
||||
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread);
|
||||
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
|
||||
} else {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
|
||||
}
|
||||
|
||||
__ pop(saved, sp);
|
||||
@@ -753,7 +753,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss
|
||||
__ bind(runtime);
|
||||
__ push_call_clobbered_registers();
|
||||
__ load_parameter(0, pre_val);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
|
||||
__ pop_call_clobbered_registers();
|
||||
__ bind(done);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -6421,10 +6421,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value)
|
||||
|
||||
// Intrinsic for
|
||||
//
|
||||
// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray
|
||||
// return the number of characters copied.
|
||||
// - java/lang/StringUTF16.compress
|
||||
// return index of non-latin1 character if copy fails, otherwise 'len'.
|
||||
// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes char[] to byte[] in ISO-8859-1
|
||||
//
|
||||
// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1
|
||||
//
|
||||
// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len)
|
||||
// Encodes char[] to byte[] in ASCII
|
||||
//
|
||||
// This version always returns the number of characters copied, and does not
|
||||
// clobber the 'len' register. A successful copy will complete with the post-
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2426,13 +2426,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
Register hdr = op->hdr_opr()->as_pointer_register();
|
||||
Register lock = op->lock_opr()->as_pointer_register();
|
||||
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
if (op->info() != nullptr) {
|
||||
add_debug_info_for_null_check_here(op->info());
|
||||
__ null_check(obj);
|
||||
}
|
||||
__ b(*op->stub()->entry());
|
||||
} else if (op->code() == lir_lock) {
|
||||
if (op->code() == lir_lock) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
int null_check_offset = __ lock_object(hdr, obj, lock, *op->stub()->entry());
|
||||
if (op->info() != nullptr) {
|
||||
@@ -2558,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());
|
||||
|
||||
@@ -177,18 +177,16 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len,
|
||||
}
|
||||
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
|
||||
Label done, fast_lock, fast_lock_done;
|
||||
int null_check_offset = 0;
|
||||
|
||||
const Register tmp2 = Rtemp; // Rtemp should be free at c1 LIR level
|
||||
assert_different_registers(hdr, obj, disp_hdr, tmp2);
|
||||
|
||||
assert(BasicObjectLock::lock_offset() == 0, "adjust this code");
|
||||
const ByteSize obj_offset = BasicObjectLock::obj_offset();
|
||||
const int mark_offset = BasicLock::displaced_header_offset_in_bytes();
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
// save object being locked into the BasicObjectLock
|
||||
str(obj, Address(disp_hdr, obj_offset));
|
||||
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
@@ -199,95 +197,29 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
|
||||
b(slow_case, ne);
|
||||
}
|
||||
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
|
||||
lightweight_lock(obj /* obj */, t1, t2, t3, 1 /* savemask - save t1 */, slow_case);
|
||||
// Success: fall through
|
||||
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
// On MP platforms the next load could return a 'stale' value if the memory location has been modified by another thread.
|
||||
// That would be acceptable as ether CAS or slow case path is taken in that case.
|
||||
|
||||
// Must be the first instruction here, because implicit null check relies on it
|
||||
ldr(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
|
||||
|
||||
tst(hdr, markWord::unlocked_value);
|
||||
b(fast_lock, ne);
|
||||
|
||||
// Check for recursive locking
|
||||
// See comments in InterpreterMacroAssembler::lock_object for
|
||||
// explanations on the fast recursive locking check.
|
||||
// -1- test low 2 bits
|
||||
movs(tmp2, AsmOperand(hdr, lsl, 30));
|
||||
// -2- test (hdr - SP) if the low two bits are 0
|
||||
sub(tmp2, hdr, SP, eq);
|
||||
movs(tmp2, AsmOperand(tmp2, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK
|
||||
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8267042)
|
||||
str(tmp2, Address(disp_hdr, mark_offset));
|
||||
b(fast_lock_done, eq);
|
||||
// else need slow case
|
||||
b(slow_case);
|
||||
|
||||
|
||||
bind(fast_lock);
|
||||
// Save previous object header in BasicLock structure and update the header
|
||||
str(hdr, Address(disp_hdr, mark_offset));
|
||||
|
||||
cas_for_lock_acquire(hdr, disp_hdr, obj, tmp2, slow_case);
|
||||
|
||||
bind(fast_lock_done);
|
||||
}
|
||||
bind(done);
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
|
||||
lightweight_lock(obj, t1, t2, t3, 1 /* savemask - save t1 */, slow_case);
|
||||
// Success: fall through
|
||||
return null_check_offset;
|
||||
}
|
||||
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, disp_hdr, Rtemp);
|
||||
Register tmp2 = Rtemp;
|
||||
|
||||
assert(BasicObjectLock::lock_offset() == 0, "adjust this code");
|
||||
const ByteSize obj_offset = BasicObjectLock::obj_offset();
|
||||
const int mark_offset = BasicLock::displaced_header_offset_in_bytes();
|
||||
|
||||
Label done;
|
||||
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
|
||||
ldr(obj, Address(disp_hdr, obj_offset));
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
|
||||
lightweight_unlock(obj /* object */, t1, t2, t3, 1 /* savemask (save t1) */,
|
||||
slow_case);
|
||||
// Success: Fall through
|
||||
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
// Load displaced header and object from the lock
|
||||
ldr(hdr, Address(disp_hdr, mark_offset));
|
||||
// If hdr is null, we've got recursive locking and there's nothing more to do
|
||||
cbz(hdr, done);
|
||||
|
||||
// load object
|
||||
ldr(obj, Address(disp_hdr, obj_offset));
|
||||
|
||||
// Restore the object header
|
||||
cas_for_lock_release(disp_hdr, hdr, obj, tmp2, slow_case);
|
||||
}
|
||||
bind(done);
|
||||
lightweight_unlock(obj, t1, t2, t3, 1 /* savemask - save t1 */, slow_case);
|
||||
// Success: fall through
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
@@ -81,7 +81,7 @@ void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratc
|
||||
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
||||
assert_different_registers(Roop, Rbox, Rscratch, Rscratch2);
|
||||
|
||||
Label fast_lock, done;
|
||||
Label done;
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(Rscratch, Roop);
|
||||
@@ -90,43 +90,10 @@ void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratc
|
||||
b(done, ne);
|
||||
}
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
|
||||
lightweight_lock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
||||
1 /* savemask (save t1) */, done);
|
||||
|
||||
// Success: set Z
|
||||
cmp(Roop, Roop);
|
||||
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
|
||||
tst(Rmark, markWord::unlocked_value);
|
||||
b(fast_lock, ne);
|
||||
|
||||
// Check for recursive lock
|
||||
// See comments in InterpreterMacroAssembler::lock_object for
|
||||
// explanations on the fast recursive locking check.
|
||||
// -1- test low 2 bits
|
||||
movs(Rscratch, AsmOperand(Rmark, lsl, 30));
|
||||
// -2- test (hdr - SP) if the low two bits are 0
|
||||
sub(Rscratch, Rmark, SP, eq);
|
||||
movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK
|
||||
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
|
||||
str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
b(done);
|
||||
|
||||
bind(fast_lock);
|
||||
str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
}
|
||||
lightweight_lock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
||||
1 /* savemask (save t1) */, done);
|
||||
|
||||
cmp(Roop, Roop); // Success: set Z
|
||||
bind(done);
|
||||
|
||||
// At this point flags are set as follows:
|
||||
@@ -140,29 +107,12 @@ void C2_MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscra
|
||||
|
||||
Label done;
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_unlock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
||||
1 /* savemask (save t1) */, done);
|
||||
|
||||
lightweight_unlock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
||||
1 /* savemask (save t1) */, done);
|
||||
cmp(Roop, Roop); // Success: Set Z
|
||||
// Fall through
|
||||
|
||||
cmp(Roop, Roop); // Success: Set Z
|
||||
// Fall through
|
||||
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
// Find the lock address and load the displaced header from the stack.
|
||||
ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
// If hdr is null, we've got recursive locking and there's nothing more to do
|
||||
cmp(Rmark, 0);
|
||||
b(done, eq);
|
||||
|
||||
// Restore the object header
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_release(Rbox, Rmark, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
}
|
||||
bind(done);
|
||||
|
||||
// At this point flags are set as follows:
|
||||
|
||||
@@ -60,6 +60,10 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
@@ -51,8 +51,22 @@ public:
|
||||
return Atomic::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) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = Atomic::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 = Atomic::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) {
|
||||
|
||||
@@ -888,105 +888,30 @@ void InterpreterMacroAssembler::set_do_not_unlock_if_synchronized(bool flag, Reg
|
||||
void InterpreterMacroAssembler::lock_object(Register Rlock) {
|
||||
assert(Rlock == R1, "the second argument");
|
||||
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), Rlock);
|
||||
} else {
|
||||
Label done;
|
||||
const Register Robj = R2;
|
||||
const Register Rmark = R3;
|
||||
assert_different_registers(Robj, Rmark, Rlock, R0, Rtemp);
|
||||
|
||||
const Register Robj = R2;
|
||||
const Register Rmark = R3;
|
||||
assert_different_registers(Robj, Rmark, Rlock, R0, Rtemp);
|
||||
Label done, slow_case;
|
||||
|
||||
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
|
||||
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
|
||||
const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes();
|
||||
// Load object pointer
|
||||
ldr(Robj, Address(Rlock, BasicObjectLock::obj_offset()));
|
||||
|
||||
Label already_locked, slow_case;
|
||||
|
||||
// Load object pointer
|
||||
ldr(Robj, Address(Rlock, obj_offset));
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(R0, Robj);
|
||||
ldrb(R0, Address(R0, Klass::misc_flags_offset()));
|
||||
tst(R0, KlassFlags::_misc_is_value_based_class);
|
||||
b(slow_case, ne);
|
||||
}
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_lock(Robj, R0 /* t1 */, Rmark /* t2 */, Rtemp /* t3 */, 0 /* savemask */, slow_case);
|
||||
b(done);
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
// On MP platforms the next load could return a 'stale' value if the memory location has been modified by another thread.
|
||||
// That would be acceptable as ether CAS or slow case path is taken in that case.
|
||||
// Exception to that is if the object is locked by the calling thread, then the recursive test will pass (guaranteed as
|
||||
// loads are satisfied from a store queue if performed on the same processor).
|
||||
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "must be");
|
||||
ldr(Rmark, Address(Robj, oopDesc::mark_offset_in_bytes()));
|
||||
|
||||
// Test if object is already locked
|
||||
tst(Rmark, markWord::unlocked_value);
|
||||
b(already_locked, eq);
|
||||
|
||||
// Save old object->mark() into BasicLock's displaced header
|
||||
str(Rmark, Address(Rlock, mark_offset));
|
||||
|
||||
cas_for_lock_acquire(Rmark, Rlock, Robj, Rtemp, slow_case);
|
||||
|
||||
b(done);
|
||||
|
||||
// If we got here that means the object is locked by ether calling thread or another thread.
|
||||
bind(already_locked);
|
||||
// Handling of locked objects: recursive locks and slow case.
|
||||
|
||||
// Fast check for recursive lock.
|
||||
//
|
||||
// Can apply the optimization only if this is a stack lock
|
||||
// allocated in this thread. For efficiency, we can focus on
|
||||
// recently allocated stack locks (instead of reading the stack
|
||||
// base and checking whether 'mark' points inside the current
|
||||
// thread stack):
|
||||
// 1) (mark & 3) == 0
|
||||
// 2) SP <= mark < SP + os::pagesize()
|
||||
//
|
||||
// Warning: SP + os::pagesize can overflow the stack base. We must
|
||||
// neither apply the optimization for an inflated lock allocated
|
||||
// just above the thread stack (this is why condition 1 matters)
|
||||
// nor apply the optimization if the stack lock is inside the stack
|
||||
// of another thread. The latter is avoided even in case of overflow
|
||||
// because we have guard pages at the end of all stacks. Hence, if
|
||||
// we go over the stack base and hit the stack of another thread,
|
||||
// this should not be in a writeable area that could contain a
|
||||
// stack lock allocated by that thread. As a consequence, a stack
|
||||
// lock less than page size away from SP is guaranteed to be
|
||||
// owned by the current thread.
|
||||
//
|
||||
// Note: assuming SP is aligned, we can check the low bits of
|
||||
// (mark-SP) instead of the low bits of mark. In that case,
|
||||
// assuming page size is a power of 2, we can merge the two
|
||||
// conditions into a single test:
|
||||
// => ((mark - SP) & (3 - os::pagesize())) == 0
|
||||
|
||||
// (3 - os::pagesize()) cannot be encoded as an ARM immediate operand.
|
||||
// Check independently the low bits and the distance to SP.
|
||||
// -1- test low 2 bits
|
||||
movs(R0, AsmOperand(Rmark, lsl, 30));
|
||||
// -2- test (mark - SP) if the low two bits are 0
|
||||
sub(R0, Rmark, SP, eq);
|
||||
movs(R0, AsmOperand(R0, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK: store 0 into lock record
|
||||
str(R0, Address(Rlock, mark_offset), eq);
|
||||
|
||||
b(done, eq);
|
||||
}
|
||||
|
||||
bind(slow_case);
|
||||
|
||||
// Call the runtime routine for slow case
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), Rlock);
|
||||
bind(done);
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(R0, Robj);
|
||||
ldrb(R0, Address(R0, Klass::misc_flags_offset()));
|
||||
tst(R0, KlassFlags::_misc_is_value_based_class);
|
||||
b(slow_case, ne);
|
||||
}
|
||||
|
||||
lightweight_lock(Robj, R0 /* t1 */, Rmark /* t2 */, Rtemp /* t3 */, 0 /* savemask */, slow_case);
|
||||
b(done);
|
||||
|
||||
bind(slow_case);
|
||||
|
||||
// Call the runtime routine for slow case
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), Rlock);
|
||||
bind(done);
|
||||
}
|
||||
|
||||
// Unlocks an object. Used in monitorexit bytecode and remove_activation.
|
||||
@@ -997,65 +922,39 @@ void InterpreterMacroAssembler::lock_object(Register Rlock) {
|
||||
void InterpreterMacroAssembler::unlock_object(Register Rlock) {
|
||||
assert(Rlock == R0, "the first argument");
|
||||
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), Rlock);
|
||||
} else {
|
||||
Label done, slow_case;
|
||||
Label done, slow_case;
|
||||
|
||||
const Register Robj = R2;
|
||||
const Register Rmark = R3;
|
||||
assert_different_registers(Robj, Rmark, Rlock, Rtemp);
|
||||
const Register Robj = R2;
|
||||
const Register Rmark = R3;
|
||||
assert_different_registers(Robj, Rmark, Rlock, Rtemp);
|
||||
|
||||
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
|
||||
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
|
||||
const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes();
|
||||
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
|
||||
const Register Rzero = zero_register(Rtemp);
|
||||
|
||||
const Register Rzero = zero_register(Rtemp);
|
||||
// Load oop into Robj
|
||||
ldr(Robj, Address(Rlock, obj_offset));
|
||||
|
||||
// Load oop into Robj
|
||||
ldr(Robj, Address(Rlock, obj_offset));
|
||||
// Free entry
|
||||
str(Rzero, Address(Rlock, obj_offset));
|
||||
|
||||
// Free entry
|
||||
str(Rzero, Address(Rlock, obj_offset));
|
||||
// Check for non-symmetric locking. This is allowed by the spec and the interpreter
|
||||
// must handle it.
|
||||
ldr(Rtemp, Address(Rthread, JavaThread::lock_stack_top_offset()));
|
||||
sub(Rtemp, Rtemp, oopSize);
|
||||
ldr(Rtemp, Address(Rthread, Rtemp));
|
||||
cmpoop(Rtemp, Robj);
|
||||
b(slow_case, ne);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_unlock(Robj /* obj */, Rlock /* t1 */, Rmark /* t2 */, Rtemp /* t3 */,
|
||||
1 /* savemask (save t1) */, slow_case);
|
||||
b(done);
|
||||
|
||||
// Check for non-symmetric locking. This is allowed by the spec and the interpreter
|
||||
// must handle it.
|
||||
ldr(Rtemp, Address(Rthread, JavaThread::lock_stack_top_offset()));
|
||||
sub(Rtemp, Rtemp, oopSize);
|
||||
ldr(Rtemp, Address(Rthread, Rtemp));
|
||||
cmpoop(Rtemp, Robj);
|
||||
b(slow_case, ne);
|
||||
bind(slow_case);
|
||||
// Call the runtime routine for slow case.
|
||||
str(Robj, Address(Rlock, obj_offset)); // restore obj
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), Rlock);
|
||||
|
||||
lightweight_unlock(Robj /* obj */, Rlock /* t1 */, Rmark /* t2 */, Rtemp /* t3 */,
|
||||
1 /* savemask (save t1) */, slow_case);
|
||||
|
||||
b(done);
|
||||
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
// Load the old header from BasicLock structure
|
||||
ldr(Rmark, Address(Rlock, mark_offset));
|
||||
|
||||
// Test for recursion (zero mark in BasicLock)
|
||||
cbz(Rmark, done);
|
||||
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
|
||||
cas_for_lock_release(Rlock, Rmark, Robj, Rtemp, slow_case, allow_fallthrough_on_failure);
|
||||
|
||||
b(done, eq);
|
||||
|
||||
}
|
||||
bind(slow_case);
|
||||
|
||||
// Call the runtime routine for slow case.
|
||||
str(Robj, Address(Rlock, obj_offset)); // restore obj
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), Rlock);
|
||||
|
||||
bind(done);
|
||||
}
|
||||
bind(done);
|
||||
}
|
||||
|
||||
// Test ImethodDataPtr. If it is null, continue at the specified label
|
||||
|
||||
@@ -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
|
||||
@@ -1758,7 +1758,6 @@ void MacroAssembler::read_polling_page(Register dest, relocInfo::relocType rtype
|
||||
// - Success: fallthrough
|
||||
// - Error: break to slow, Z cleared.
|
||||
void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, Register t3, unsigned savemask, Label& slow) {
|
||||
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
|
||||
assert_different_registers(obj, t1, t2, t3);
|
||||
|
||||
#ifdef ASSERT
|
||||
@@ -1816,7 +1815,6 @@ void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, Re
|
||||
// - Success: fallthrough
|
||||
// - Error: break to slow, Z cleared.
|
||||
void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2, Register t3, unsigned savemask, Label& slow) {
|
||||
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
|
||||
assert_different_registers(obj, t1, t2, t3);
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
@@ -1139,41 +1139,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Remember the handle for the unlocking code
|
||||
__ mov(sync_handle, R1);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
log_trace(fastlock)("SharedRuntime lock fast");
|
||||
__ lightweight_lock(sync_obj /* object */, disp_hdr /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
0x7 /* savemask */, slow_lock);
|
||||
log_trace(fastlock)("SharedRuntime lock fast");
|
||||
__ lightweight_lock(sync_obj /* object */, disp_hdr /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
0x7 /* savemask */, slow_lock);
|
||||
// Fall through to lock_done
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
const Register mark = tmp;
|
||||
// On MP platforms the next load could return a 'stale' value if the memory location has been modified by another thread.
|
||||
// That would be acceptable as either CAS or slow case path is taken in that case
|
||||
|
||||
__ ldr(mark, Address(sync_obj, oopDesc::mark_offset_in_bytes()));
|
||||
__ sub(disp_hdr, FP, lock_slot_fp_offset);
|
||||
__ tst(mark, markWord::unlocked_value);
|
||||
__ b(fast_lock, ne);
|
||||
|
||||
// Check for recursive lock
|
||||
// See comments in InterpreterMacroAssembler::lock_object for
|
||||
// explanations on the fast recursive locking check.
|
||||
// Check independently the low bits and the distance to SP
|
||||
// -1- test low 2 bits
|
||||
__ movs(Rtemp, AsmOperand(mark, lsl, 30));
|
||||
// -2- test (hdr - SP) if the low two bits are 0
|
||||
__ sub(Rtemp, mark, SP, eq);
|
||||
__ movs(Rtemp, AsmOperand(Rtemp, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK
|
||||
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8267042)
|
||||
__ str(Rtemp, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
|
||||
__ b(lock_done, eq);
|
||||
__ b(slow_lock);
|
||||
|
||||
__ bind(fast_lock);
|
||||
__ str(mark, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
|
||||
|
||||
__ cas_for_lock_acquire(mark, disp_hdr, sync_obj, Rtemp, slow_lock);
|
||||
}
|
||||
__ bind(lock_done);
|
||||
}
|
||||
|
||||
@@ -1226,21 +1195,11 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
Label slow_unlock, unlock_done;
|
||||
if (method->is_synchronized()) {
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
log_trace(fastlock)("SharedRuntime unlock fast");
|
||||
__ lightweight_unlock(sync_obj, R2 /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
7 /* savemask */, slow_unlock);
|
||||
// Fall through
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
// See C1_MacroAssembler::unlock_object() for more comments
|
||||
__ ldr(sync_obj, Address(sync_handle));
|
||||
log_trace(fastlock)("SharedRuntime unlock fast");
|
||||
__ lightweight_unlock(sync_obj, R2 /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
7 /* savemask */, slow_unlock);
|
||||
// Fall through
|
||||
|
||||
// See C1_MacroAssembler::unlock_object() for more comments
|
||||
__ ldr(R2, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
|
||||
__ cbz(R2, unlock_done);
|
||||
|
||||
__ cas_for_lock_release(disp_hdr, R2, sync_obj, Rtemp, slow_unlock);
|
||||
}
|
||||
__ bind(unlock_done);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -228,11 +228,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
||||
if (method()->is_synchronized()) {
|
||||
monitor_address(0, FrameMap::R4_opr);
|
||||
stub = new MonitorExitStub(FrameMap::R4_opr, true, 0);
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
__ b(*stub->entry());
|
||||
} else {
|
||||
__ unlock_object(R5, R6, R4, *stub->entry());
|
||||
}
|
||||
__ unlock_object(R5, R6, R4, *stub->entry());
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
|
||||
@@ -2618,44 +2614,20 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
// Obj may not be an oop.
|
||||
if (op->code() == lir_lock) {
|
||||
MonitorEnterStub* stub = (MonitorEnterStub*)op->stub();
|
||||
if (LockingMode != LM_MONITOR) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
// Add debug info for NullPointerException only if one is possible.
|
||||
if (op->info() != nullptr) {
|
||||
if (!os::zero_page_read_protected() || !ImplicitNullChecks) {
|
||||
explicit_null_check(obj, op->info());
|
||||
} else {
|
||||
add_debug_info_for_null_check_here(op->info());
|
||||
}
|
||||
}
|
||||
__ lock_object(hdr, obj, lock, op->scratch_opr()->as_register(), *op->stub()->entry());
|
||||
} else {
|
||||
// always do slow locking
|
||||
// note: The slow locking code could be inlined here, however if we use
|
||||
// slow locking, speed doesn't matter anyway and this solution is
|
||||
// simpler and requires less duplicated code - additionally, the
|
||||
// slow locking code is the same in either case which simplifies
|
||||
// debugging.
|
||||
if (op->info() != nullptr) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
// Add debug info for NullPointerException only if one is possible.
|
||||
if (op->info() != nullptr) {
|
||||
if (!os::zero_page_read_protected() || !ImplicitNullChecks) {
|
||||
explicit_null_check(obj, op->info());
|
||||
} else {
|
||||
add_debug_info_for_null_check_here(op->info());
|
||||
__ null_check(obj);
|
||||
}
|
||||
__ b(*op->stub()->entry());
|
||||
}
|
||||
__ lock_object(hdr, obj, lock, op->scratch_opr()->as_register(), *op->stub()->entry());
|
||||
} else {
|
||||
assert (op->code() == lir_unlock, "Invalid code, expected lir_unlock");
|
||||
if (LockingMode != LM_MONITOR) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
__ unlock_object(hdr, obj, lock, *op->stub()->entry());
|
||||
} else {
|
||||
// always do slow unlocking
|
||||
// note: The slow unlocking code could be inlined here, however if we use
|
||||
// slow unlocking, speed doesn't matter anyway and this solution is
|
||||
// simpler and requires less duplicated code - additionally, the
|
||||
// slow unlocking code is the same in either case which simplifies
|
||||
// debugging.
|
||||
__ b(*op->stub()->entry());
|
||||
}
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
__ unlock_object(hdr, obj, lock, *op->stub()->entry());
|
||||
}
|
||||
__ bind(*op->stub()->continuation());
|
||||
}
|
||||
@@ -2775,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");
|
||||
|
||||
@@ -82,59 +82,13 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox
|
||||
// Save object being locked into the BasicObjectLock...
|
||||
std(Roop, in_bytes(BasicObjectLock::obj_offset()), Rbox);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_lock(Rbox, Roop, Rmark, Rscratch, slow_int);
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(Rscratch, Roop);
|
||||
lbz(Rscratch, in_bytes(Klass::misc_flags_offset()), Rscratch);
|
||||
testbitdi(CR0, R0, Rscratch, exact_log2(KlassFlags::_misc_is_value_based_class));
|
||||
bne(CR0, slow_int);
|
||||
}
|
||||
|
||||
// ... and mark it unlocked.
|
||||
ori(Rmark, Rmark, markWord::unlocked_value);
|
||||
|
||||
// Save unlocked object header into the displaced header location on the stack.
|
||||
std(Rmark, BasicLock::displaced_header_offset_in_bytes(), Rbox);
|
||||
|
||||
// Compare object markWord with Rmark and if equal exchange Rscratch with object markWord.
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "cas must take a zero displacement");
|
||||
cmpxchgd(/*flag=*/CR0,
|
||||
/*current_value=*/Rscratch,
|
||||
/*compare_value=*/Rmark,
|
||||
/*exchange_value=*/Rbox,
|
||||
/*where=*/Roop/*+0==mark_offset_in_bytes*/,
|
||||
MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
|
||||
MacroAssembler::cmpxchgx_hint_acquire_lock(),
|
||||
noreg,
|
||||
&cas_failed,
|
||||
/*check without membar and ldarx first*/true);
|
||||
// If compare/exchange succeeded we found an unlocked object and we now have locked it
|
||||
// hence we are done.
|
||||
} else {
|
||||
assert(false, "Unhandled LockingMode:%d", LockingMode);
|
||||
}
|
||||
lightweight_lock(Rbox, Roop, Rmark, Rscratch, slow_int);
|
||||
b(done);
|
||||
|
||||
bind(slow_int);
|
||||
b(slow_case); // far
|
||||
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
bind(cas_failed);
|
||||
// We did not find an unlocked object so see if this is a recursive case.
|
||||
sub(Rscratch, Rscratch, R1_SP);
|
||||
load_const_optimized(R0, (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
|
||||
and_(R0/*==0?*/, Rscratch, R0);
|
||||
std(R0/*==0, perhaps*/, BasicLock::displaced_header_offset_in_bytes(), Rbox);
|
||||
bne(CR0, slow_int);
|
||||
}
|
||||
|
||||
bind(done);
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
inc_held_monitor_count(Rmark /*tmp*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,43 +100,17 @@ void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rb
|
||||
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
|
||||
assert(mark_addr.disp() == 0, "cas must take a zero displacement");
|
||||
|
||||
if (LockingMode != LM_LIGHTWEIGHT) {
|
||||
// Test first if it is a fast recursive unlock.
|
||||
ld(Rmark, BasicLock::displaced_header_offset_in_bytes(), Rbox);
|
||||
cmpdi(CR0, Rmark, 0);
|
||||
beq(CR0, done);
|
||||
}
|
||||
|
||||
// Load object.
|
||||
ld(Roop, in_bytes(BasicObjectLock::obj_offset()), Rbox);
|
||||
verify_oop(Roop, FILE_AND_LINE);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_unlock(Roop, Rmark, slow_int);
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
// Check if it is still a light weight lock, this is is true if we see
|
||||
// the stack address of the basicLock in the markWord of the object.
|
||||
cmpxchgd(/*flag=*/CR0,
|
||||
/*current_value=*/R0,
|
||||
/*compare_value=*/Rbox,
|
||||
/*exchange_value=*/Rmark,
|
||||
/*where=*/Roop,
|
||||
MacroAssembler::MemBarRel,
|
||||
MacroAssembler::cmpxchgx_hint_release_lock(),
|
||||
noreg,
|
||||
&slow_int);
|
||||
} else {
|
||||
assert(false, "Unhandled LockingMode:%d", LockingMode);
|
||||
}
|
||||
lightweight_unlock(Roop, Rmark, slow_int);
|
||||
b(done);
|
||||
bind(slow_int);
|
||||
b(slow_case); // far
|
||||
|
||||
// Done
|
||||
bind(done);
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
dec_held_monitor_count(Rmark /*tmp*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -334,6 +334,9 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
|
||||
}
|
||||
|
||||
//////// Thaw
|
||||
|
||||
// Fast path
|
||||
|
||||
@@ -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 = Atomic::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 = Atomic::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) {
|
||||
|
||||
@@ -311,7 +311,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm
|
||||
}
|
||||
|
||||
// Invoke runtime.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, R16_thread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
|
||||
|
||||
// Restore to-be-preserved registers.
|
||||
if (!preserve_gp_registers && preloaded_mode && pre_val->is_volatile()) {
|
||||
@@ -966,7 +966,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss
|
||||
__ push_frame_reg_args(nbytes_save, R11_tmp1);
|
||||
|
||||
// Invoke runtime.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), R0_pre_val, R16_thread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), R0_pre_val);
|
||||
|
||||
// Restore to-be-preserved registers.
|
||||
__ pop_frame();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -946,121 +946,20 @@ void InterpreterMacroAssembler::leave_jfr_critical_section() {
|
||||
// object - Address of the object to be locked.
|
||||
//
|
||||
void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
call_VM_preemptable(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
|
||||
} else {
|
||||
// template code (for LM_LEGACY):
|
||||
//
|
||||
// markWord displaced_header = obj->mark().set_unlocked();
|
||||
// monitor->lock()->set_displaced_header(displaced_header);
|
||||
// if (Atomic::cmpxchg(/*addr*/obj->mark_addr(), /*cmp*/displaced_header, /*ex=*/monitor) == displaced_header) {
|
||||
// // We stored the monitor address into the object's mark word.
|
||||
// } else if (THREAD->is_lock_owned((address)displaced_header))
|
||||
// // Simple recursive case.
|
||||
// monitor->lock()->set_displaced_header(nullptr);
|
||||
// } else {
|
||||
// // Slow path.
|
||||
// InterpreterRuntime::monitorenter(THREAD, monitor);
|
||||
// }
|
||||
const Register header = R7_ARG5;
|
||||
const Register tmp = R8_ARG6;
|
||||
|
||||
const Register header = R7_ARG5;
|
||||
const Register object_mark_addr = R8_ARG6;
|
||||
const Register current_header = R9_ARG7;
|
||||
const Register tmp = R10_ARG8;
|
||||
Label done, slow_case;
|
||||
|
||||
Label count_locking, done, slow_case, cas_failed;
|
||||
assert_different_registers(header, tmp);
|
||||
|
||||
assert_different_registers(header, object_mark_addr, current_header, tmp);
|
||||
lightweight_lock(monitor, object, header, tmp, slow_case);
|
||||
b(done);
|
||||
|
||||
// markWord displaced_header = obj->mark().set_unlocked();
|
||||
bind(slow_case);
|
||||
call_VM_preemptable(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_lock(monitor, object, header, tmp, slow_case);
|
||||
b(done);
|
||||
} else if (LockingMode == LM_LEGACY) {
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(tmp, object);
|
||||
lbz(tmp, in_bytes(Klass::misc_flags_offset()), tmp);
|
||||
testbitdi(CR0, R0, tmp, exact_log2(KlassFlags::_misc_is_value_based_class));
|
||||
bne(CR0, slow_case);
|
||||
}
|
||||
|
||||
// Load markWord from object into header.
|
||||
ld(header, oopDesc::mark_offset_in_bytes(), object);
|
||||
|
||||
// Set displaced_header to be (markWord of object | UNLOCK_VALUE).
|
||||
ori(header, header, markWord::unlocked_value);
|
||||
|
||||
// monitor->lock()->set_displaced_header(displaced_header);
|
||||
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
|
||||
const int mark_offset = lock_offset +
|
||||
BasicLock::displaced_header_offset_in_bytes();
|
||||
|
||||
// Initialize the box (Must happen before we update the object mark!).
|
||||
std(header, mark_offset, monitor);
|
||||
|
||||
// if (Atomic::cmpxchg(/*addr*/obj->mark_addr(), /*cmp*/displaced_header, /*ex=*/monitor) == displaced_header) {
|
||||
|
||||
// Store stack address of the BasicObjectLock (this is monitor) into object.
|
||||
addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes());
|
||||
|
||||
// Must fence, otherwise, preceding store(s) may float below cmpxchg.
|
||||
// CmpxchgX sets CR0 to cmpX(current, displaced).
|
||||
cmpxchgd(/*flag=*/CR0,
|
||||
/*current_value=*/current_header,
|
||||
/*compare_value=*/header, /*exchange_value=*/monitor,
|
||||
/*where=*/object_mark_addr,
|
||||
MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
|
||||
MacroAssembler::cmpxchgx_hint_acquire_lock(),
|
||||
noreg,
|
||||
&cas_failed,
|
||||
/*check without membar and ldarx first*/true);
|
||||
|
||||
// If the compare-and-exchange succeeded, then we found an unlocked
|
||||
// object and we have now locked it.
|
||||
b(count_locking);
|
||||
bind(cas_failed);
|
||||
|
||||
// } else if (THREAD->is_lock_owned((address)displaced_header))
|
||||
// // Simple recursive case.
|
||||
// monitor->lock()->set_displaced_header(nullptr);
|
||||
|
||||
// We did not see an unlocked object so try the fast recursive case.
|
||||
|
||||
// Check if owner is self by comparing the value in the markWord of object
|
||||
// (current_header) with the stack pointer.
|
||||
sub(current_header, current_header, R1_SP);
|
||||
|
||||
assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
|
||||
load_const_optimized(tmp, ~(os::vm_page_size()-1) | markWord::lock_mask_in_place);
|
||||
|
||||
and_(R0/*==0?*/, current_header, tmp);
|
||||
// If condition is true we are done and hence we can store 0 in the displaced
|
||||
// header indicating it is a recursive lock.
|
||||
bne(CR0, slow_case);
|
||||
std(R0/*==0!*/, mark_offset, monitor);
|
||||
b(count_locking);
|
||||
}
|
||||
|
||||
// } else {
|
||||
// // Slow path.
|
||||
// InterpreterRuntime::monitorenter(THREAD, monitor);
|
||||
|
||||
// None of the above fast optimizations worked so we have to get into the
|
||||
// slow case of monitor enter.
|
||||
bind(slow_case);
|
||||
call_VM_preemptable(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
|
||||
// }
|
||||
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
b(done);
|
||||
align(32, 12);
|
||||
bind(count_locking);
|
||||
inc_held_monitor_count(current_header /*tmp*/);
|
||||
}
|
||||
bind(done);
|
||||
}
|
||||
bind(done);
|
||||
}
|
||||
|
||||
// Unlocks an object. Used in monitorexit bytecode and remove_activation.
|
||||
@@ -1071,95 +970,34 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
|
||||
//
|
||||
// Throw IllegalMonitorException if object is not locked by current thread.
|
||||
void InterpreterMacroAssembler::unlock_object(Register monitor) {
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor);
|
||||
} else {
|
||||
const Register object = R7_ARG5;
|
||||
const Register header = R8_ARG6;
|
||||
const Register current_header = R10_ARG8;
|
||||
|
||||
// template code (for LM_LEGACY):
|
||||
//
|
||||
// if ((displaced_header = monitor->displaced_header()) == nullptr) {
|
||||
// // Recursive unlock. Mark the monitor unlocked by setting the object field to null.
|
||||
// monitor->set_obj(nullptr);
|
||||
// } else if (Atomic::cmpxchg(obj->mark_addr(), monitor, displaced_header) == monitor) {
|
||||
// // We swapped the unlocked mark in displaced_header into the object's mark word.
|
||||
// monitor->set_obj(nullptr);
|
||||
// } else {
|
||||
// // Slow path.
|
||||
// InterpreterRuntime::monitorexit(monitor);
|
||||
// }
|
||||
Label free_slot;
|
||||
Label slow_case;
|
||||
|
||||
const Register object = R7_ARG5;
|
||||
const Register header = R8_ARG6;
|
||||
const Register object_mark_addr = R9_ARG7;
|
||||
const Register current_header = R10_ARG8;
|
||||
assert_different_registers(object, header, current_header);
|
||||
|
||||
Label free_slot;
|
||||
Label slow_case;
|
||||
// The object address from the monitor is in object.
|
||||
ld(object, in_bytes(BasicObjectLock::obj_offset()), monitor);
|
||||
|
||||
assert_different_registers(object, header, object_mark_addr, current_header);
|
||||
lightweight_unlock(object, header, slow_case);
|
||||
|
||||
if (LockingMode != LM_LIGHTWEIGHT) {
|
||||
// Test first if we are in the fast recursive case.
|
||||
ld(header, in_bytes(BasicObjectLock::lock_offset()) +
|
||||
BasicLock::displaced_header_offset_in_bytes(), monitor);
|
||||
b(free_slot);
|
||||
|
||||
// If the displaced header is zero, we have a recursive unlock.
|
||||
cmpdi(CR0, header, 0);
|
||||
beq(CR0, free_slot); // recursive unlock
|
||||
}
|
||||
bind(slow_case);
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor);
|
||||
|
||||
// } else if (Atomic::cmpxchg(obj->mark_addr(), monitor, displaced_header) == monitor) {
|
||||
// // We swapped the unlocked mark in displaced_header into the object's mark word.
|
||||
// monitor->set_obj(nullptr);
|
||||
Label done;
|
||||
b(done); // Monitor register may be overwritten! Runtime has already freed the slot.
|
||||
|
||||
// If we still have a lightweight lock, unlock the object and be done.
|
||||
|
||||
// The object address from the monitor is in object.
|
||||
ld(object, in_bytes(BasicObjectLock::obj_offset()), monitor);
|
||||
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
lightweight_unlock(object, header, slow_case);
|
||||
} else {
|
||||
addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes());
|
||||
|
||||
// We have the displaced header in displaced_header. If the lock is still
|
||||
// lightweight, it will contain the monitor address and we'll store the
|
||||
// displaced header back into the object's mark word.
|
||||
// CmpxchgX sets CR0 to cmpX(current, monitor).
|
||||
cmpxchgd(/*flag=*/CR0,
|
||||
/*current_value=*/current_header,
|
||||
/*compare_value=*/monitor, /*exchange_value=*/header,
|
||||
/*where=*/object_mark_addr,
|
||||
MacroAssembler::MemBarRel,
|
||||
MacroAssembler::cmpxchgx_hint_release_lock(),
|
||||
noreg,
|
||||
&slow_case);
|
||||
}
|
||||
b(free_slot);
|
||||
|
||||
// } else {
|
||||
// // Slow path.
|
||||
// InterpreterRuntime::monitorexit(monitor);
|
||||
|
||||
// The lock has been converted into a heavy lock and hence
|
||||
// we need to get into the slow case.
|
||||
bind(slow_case);
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor);
|
||||
// }
|
||||
|
||||
Label done;
|
||||
b(done); // Monitor register may be overwritten! Runtime has already freed the slot.
|
||||
|
||||
// Exchange worked, do monitor->set_obj(nullptr);
|
||||
align(32, 12);
|
||||
bind(free_slot);
|
||||
li(R0, 0);
|
||||
std(R0, in_bytes(BasicObjectLock::obj_offset()), monitor);
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
dec_held_monitor_count(current_header /*tmp*/);
|
||||
}
|
||||
bind(done);
|
||||
}
|
||||
// Do monitor->set_obj(nullptr);
|
||||
align(32, 12);
|
||||
bind(free_slot);
|
||||
li(R0, 0);
|
||||
std(R0, in_bytes(BasicObjectLock::obj_offset()), monitor);
|
||||
bind(done);
|
||||
}
|
||||
|
||||
// Load compiled (i2c) or interpreter entry when calling from interpreted and
|
||||
|
||||
@@ -2671,238 +2671,6 @@ address MacroAssembler::emit_trampoline_stub(int destination_toc_offset,
|
||||
}
|
||||
|
||||
// "The box" is the space on the stack where we copy the object mark.
|
||||
void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box,
|
||||
Register temp, Register displaced_header, Register current_header) {
|
||||
assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_lock_lightweight");
|
||||
assert_different_registers(oop, box, temp, displaced_header, current_header);
|
||||
Label object_has_monitor;
|
||||
Label cas_failed;
|
||||
Label success, failure;
|
||||
|
||||
// Load markWord from object into displaced_header.
|
||||
ld(displaced_header, oopDesc::mark_offset_in_bytes(), oop);
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
||||
load_klass(temp, oop);
|
||||
lbz(temp, in_bytes(Klass::misc_flags_offset()), temp);
|
||||
testbitdi(flag, R0, temp, exact_log2(KlassFlags::_misc_is_value_based_class));
|
||||
bne(flag, failure);
|
||||
}
|
||||
|
||||
// Handle existing monitor.
|
||||
// The object has an existing monitor iff (mark & monitor_value) != 0.
|
||||
andi_(temp, displaced_header, markWord::monitor_value);
|
||||
bne(CR0, object_has_monitor);
|
||||
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
// Set NE to indicate 'failure' -> take slow-path.
|
||||
crandc(flag, Assembler::equal, flag, Assembler::equal);
|
||||
b(failure);
|
||||
} else {
|
||||
assert(LockingMode == LM_LEGACY, "must be");
|
||||
// Set displaced_header to be (markWord of object | UNLOCK_VALUE).
|
||||
ori(displaced_header, displaced_header, markWord::unlocked_value);
|
||||
|
||||
// Load Compare Value application register.
|
||||
|
||||
// Initialize the box. (Must happen before we update the object mark!)
|
||||
std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box);
|
||||
|
||||
// Must fence, otherwise, preceding store(s) may float below cmpxchg.
|
||||
// Compare object markWord with mark and if equal exchange scratch1 with object markWord.
|
||||
cmpxchgd(/*flag=*/flag,
|
||||
/*current_value=*/current_header,
|
||||
/*compare_value=*/displaced_header,
|
||||
/*exchange_value=*/box,
|
||||
/*where=*/oop,
|
||||
MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
|
||||
MacroAssembler::cmpxchgx_hint_acquire_lock(),
|
||||
noreg,
|
||||
&cas_failed,
|
||||
/*check without membar and ldarx first*/true);
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
|
||||
// If the compare-and-exchange succeeded, then we found an unlocked
|
||||
// object and we have now locked it.
|
||||
b(success);
|
||||
|
||||
bind(cas_failed);
|
||||
// We did not see an unlocked object so try the fast recursive case.
|
||||
|
||||
// Check if the owner is self by comparing the value in the markWord of object
|
||||
// (current_header) with the stack pointer.
|
||||
sub(current_header, current_header, R1_SP);
|
||||
load_const_optimized(temp, ~(os::vm_page_size()-1) | markWord::lock_mask_in_place);
|
||||
|
||||
and_(R0/*==0?*/, current_header, temp);
|
||||
// If condition is true we are cont and hence we can store 0 as the
|
||||
// displaced header in the box, which indicates that it is a recursive lock.
|
||||
std(R0/*==0, perhaps*/, BasicLock::displaced_header_offset_in_bytes(), box);
|
||||
|
||||
if (flag != CR0) {
|
||||
mcrf(flag, CR0);
|
||||
}
|
||||
beq(CR0, success);
|
||||
b(failure);
|
||||
}
|
||||
|
||||
// Handle existing monitor.
|
||||
bind(object_has_monitor);
|
||||
|
||||
// Try to CAS owner (no owner => current thread's _monitor_owner_id).
|
||||
addi(temp, displaced_header, in_bytes(ObjectMonitor::owner_offset()) - markWord::monitor_value);
|
||||
Register thread_id = displaced_header;
|
||||
ld(thread_id, in_bytes(JavaThread::monitor_owner_id_offset()), R16_thread);
|
||||
cmpxchgd(/*flag=*/flag,
|
||||
/*current_value=*/current_header,
|
||||
/*compare_value=*/(intptr_t)0,
|
||||
/*exchange_value=*/thread_id,
|
||||
/*where=*/temp,
|
||||
MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
|
||||
MacroAssembler::cmpxchgx_hint_acquire_lock());
|
||||
|
||||
// Store a non-null value into the box.
|
||||
std(box, BasicLock::displaced_header_offset_in_bytes(), box);
|
||||
beq(flag, success);
|
||||
|
||||
// Check for recursive locking.
|
||||
cmpd(flag, current_header, thread_id);
|
||||
bne(flag, failure);
|
||||
|
||||
// Current thread already owns the lock. Just increment recursions.
|
||||
Register recursions = displaced_header;
|
||||
ld(recursions, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), temp);
|
||||
addi(recursions, recursions, 1);
|
||||
std(recursions, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), temp);
|
||||
|
||||
// flag == EQ indicates success, increment held monitor count if LM_LEGACY is enabled
|
||||
// flag == NE indicates failure
|
||||
bind(success);
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
inc_held_monitor_count(temp);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
// Check that unlocked label is reached with flag == EQ.
|
||||
Label flag_correct;
|
||||
beq(flag, flag_correct);
|
||||
stop("compiler_fast_lock_object: Flag != EQ");
|
||||
#endif
|
||||
bind(failure);
|
||||
#ifdef ASSERT
|
||||
// Check that slow_path label is reached with flag == NE.
|
||||
bne(flag, flag_correct);
|
||||
stop("compiler_fast_lock_object: Flag != NE");
|
||||
bind(flag_correct);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box,
|
||||
Register temp, Register displaced_header, Register current_header) {
|
||||
assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_unlock_lightweight");
|
||||
assert_different_registers(oop, box, temp, displaced_header, current_header);
|
||||
Label success, failure, object_has_monitor, not_recursive;
|
||||
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
// Find the lock address and load the displaced header from the stack.
|
||||
ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box);
|
||||
|
||||
// If the displaced header is 0, we have a recursive unlock.
|
||||
cmpdi(flag, displaced_header, 0);
|
||||
beq(flag, success);
|
||||
}
|
||||
|
||||
// Handle existing monitor.
|
||||
// The object has an existing monitor iff (mark & monitor_value) != 0.
|
||||
ld(current_header, oopDesc::mark_offset_in_bytes(), oop);
|
||||
andi_(R0, current_header, markWord::monitor_value);
|
||||
bne(CR0, object_has_monitor);
|
||||
|
||||
if (LockingMode == LM_MONITOR) {
|
||||
// Set NE to indicate 'failure' -> take slow-path.
|
||||
crandc(flag, Assembler::equal, flag, Assembler::equal);
|
||||
b(failure);
|
||||
} else {
|
||||
assert(LockingMode == LM_LEGACY, "must be");
|
||||
// Check if it is still a light weight lock, this is is true if we see
|
||||
// the stack address of the basicLock in the markWord of the object.
|
||||
// Cmpxchg sets flag to cmpd(current_header, box).
|
||||
cmpxchgd(/*flag=*/flag,
|
||||
/*current_value=*/current_header,
|
||||
/*compare_value=*/box,
|
||||
/*exchange_value=*/displaced_header,
|
||||
/*where=*/oop,
|
||||
MacroAssembler::MemBarRel,
|
||||
MacroAssembler::cmpxchgx_hint_release_lock(),
|
||||
noreg,
|
||||
&failure);
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
|
||||
b(success);
|
||||
}
|
||||
|
||||
// Handle existing monitor.
|
||||
bind(object_has_monitor);
|
||||
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
|
||||
addi(current_header, current_header, -(int)markWord::monitor_value); // monitor
|
||||
|
||||
ld(displaced_header, in_bytes(ObjectMonitor::recursions_offset()), current_header);
|
||||
addic_(displaced_header, displaced_header, -1);
|
||||
blt(CR0, not_recursive); // Not recursive if negative after decrement.
|
||||
|
||||
// Recursive unlock
|
||||
std(displaced_header, in_bytes(ObjectMonitor::recursions_offset()), current_header);
|
||||
if (flag == CR0) { // Otherwise, flag is already EQ, here.
|
||||
crorc(CR0, Assembler::equal, CR0, Assembler::equal); // Set CR0 EQ
|
||||
}
|
||||
b(success);
|
||||
|
||||
bind(not_recursive);
|
||||
|
||||
// Set owner to null.
|
||||
// Release to satisfy the JMM
|
||||
release();
|
||||
li(temp, 0);
|
||||
std(temp, in_bytes(ObjectMonitor::owner_offset()), current_header);
|
||||
// We need a full fence after clearing owner to avoid stranding.
|
||||
// StoreLoad achieves this.
|
||||
membar(StoreLoad);
|
||||
|
||||
// Check if the entry_list is empty.
|
||||
ld(temp, in_bytes(ObjectMonitor::entry_list_offset()), current_header);
|
||||
cmpdi(flag, temp, 0);
|
||||
beq(flag, success); // If so we are done.
|
||||
|
||||
// Check if there is a successor.
|
||||
ld(temp, in_bytes(ObjectMonitor::succ_offset()), current_header);
|
||||
cmpdi(flag, temp, 0);
|
||||
// Invert equal bit
|
||||
crnand(flag, Assembler::equal, flag, Assembler::equal);
|
||||
beq(flag, success); // If there is a successor we are done.
|
||||
|
||||
// Save the monitor pointer in the current thread, so we can try
|
||||
// to reacquire the lock in SharedRuntime::monitor_exit_helper().
|
||||
std(current_header, in_bytes(JavaThread::unlocked_inflated_monitor_offset()), R16_thread);
|
||||
b(failure); // flag == NE
|
||||
|
||||
// flag == EQ indicates success, decrement held monitor count if LM_LEGACY is enabled
|
||||
// flag == NE indicates failure
|
||||
bind(success);
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
dec_held_monitor_count(temp);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
// Check that unlocked label is reached with flag == EQ.
|
||||
Label flag_correct;
|
||||
beq(flag, flag_correct);
|
||||
stop("compiler_fast_unlock_object: Flag != EQ");
|
||||
#endif
|
||||
bind(failure);
|
||||
#ifdef ASSERT
|
||||
// Check that slow_path label is reached with flag == NE.
|
||||
bne(flag, flag_correct);
|
||||
stop("compiler_fast_unlock_object: Flag != NE");
|
||||
bind(flag_correct);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister flag, Register obj, Register box,
|
||||
Register tmp1, Register tmp2, Register tmp3) {
|
||||
assert_different_registers(obj, box, tmp1, tmp2, tmp3);
|
||||
@@ -4769,38 +4537,6 @@ void MacroAssembler::pop_cont_fastpath() {
|
||||
bind(done);
|
||||
}
|
||||
|
||||
// Note: Must preserve CR0 EQ (invariant).
|
||||
void MacroAssembler::inc_held_monitor_count(Register tmp) {
|
||||
assert(LockingMode == LM_LEGACY, "");
|
||||
ld(tmp, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
|
||||
#ifdef ASSERT
|
||||
Label ok;
|
||||
cmpdi(CR0, tmp, 0);
|
||||
bge_predict_taken(CR0, ok);
|
||||
stop("held monitor count is negativ at increment");
|
||||
bind(ok);
|
||||
crorc(CR0, Assembler::equal, CR0, Assembler::equal); // Restore CR0 EQ
|
||||
#endif
|
||||
addi(tmp, tmp, 1);
|
||||
std(tmp, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
|
||||
}
|
||||
|
||||
// Note: Must preserve CR0 EQ (invariant).
|
||||
void MacroAssembler::dec_held_monitor_count(Register tmp) {
|
||||
assert(LockingMode == LM_LEGACY, "");
|
||||
ld(tmp, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
|
||||
#ifdef ASSERT
|
||||
Label ok;
|
||||
cmpdi(CR0, tmp, 0);
|
||||
bgt_predict_taken(CR0, ok);
|
||||
stop("held monitor count is <= 0 at decrement");
|
||||
bind(ok);
|
||||
crorc(CR0, Assembler::equal, CR0, Assembler::equal); // Restore CR0 EQ
|
||||
#endif
|
||||
addi(tmp, tmp, -1);
|
||||
std(tmp, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
|
||||
}
|
||||
|
||||
// Function to flip between unlocked and locked state (fast locking).
|
||||
// Branches to failed if the state is not as expected with CR0 NE.
|
||||
// Falls through upon success with CR0 EQ.
|
||||
@@ -4842,7 +4578,6 @@ void MacroAssembler::atomically_flip_locked_state(bool is_unlock, Register obj,
|
||||
// - obj: the object to be locked
|
||||
// - t1, t2: temporary register
|
||||
void MacroAssembler::lightweight_lock(Register box, Register obj, Register t1, Register t2, Label& slow) {
|
||||
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
|
||||
assert_different_registers(box, obj, t1, t2, R0);
|
||||
|
||||
Label push;
|
||||
@@ -4899,7 +4634,6 @@ void MacroAssembler::lightweight_lock(Register box, Register obj, Register t1, R
|
||||
// - obj: the object to be unlocked
|
||||
// - t1: temporary register
|
||||
void MacroAssembler::lightweight_unlock(Register obj, Register t1, Label& slow) {
|
||||
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
|
||||
assert_different_registers(obj, t1);
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
@@ -697,8 +697,6 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
void push_cont_fastpath();
|
||||
void pop_cont_fastpath();
|
||||
void inc_held_monitor_count(Register tmp);
|
||||
void dec_held_monitor_count(Register tmp);
|
||||
void atomically_flip_locked_state(bool is_unlock, Register obj, Register tmp, Label& failed, int semantics);
|
||||
void lightweight_lock(Register box, Register obj, Register t1, Register t2, Label& slow);
|
||||
void lightweight_unlock(Register obj, Register t1, Label& slow);
|
||||
@@ -715,12 +713,6 @@ class MacroAssembler: public Assembler {
|
||||
enum { trampoline_stub_size = 6 * 4 };
|
||||
address emit_trampoline_stub(int destination_toc_offset, int insts_call_instruction_offset, Register Rtoc = noreg);
|
||||
|
||||
void compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
void compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
void compiler_fast_lock_lightweight_object(ConditionRegister flag, Register oop, Register box,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user