Compare commits
272 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23f4810c46 | |||
| 569e78080b | |||
| 043aeaf02a | |||
| 2b451131a5 | |||
| d1ea6ea22d | |||
| 26b5708c47 | |||
| 77a71c5b09 | |||
| 52e5504627 | |||
| 2407eb0522 | |||
| 67cb53d088 | |||
| 44cb9cad26 | |||
| 4f4030a423 | |||
| d85e410c19 | |||
| d407ef6510 | |||
| ba44656b97 | |||
| 847b107df8 | |||
| e6ddb39635 | |||
| 17244c699a | |||
| 2aafda1968 | |||
| a2870d6b49 | |||
| 17accf4a06 | |||
| 8f87fdce0b | |||
| 5d93242028 | |||
| 4141534e4a | |||
| 7fe71a7813 | |||
| 52a923f20c | |||
| f489598d43 | |||
| 85f5bf3f41 | |||
| faf6df5462 | |||
| 735afd93bb | |||
| 156eb767f1 | |||
| ed31023fc5 | |||
| f7c9fef914 | |||
| 2a232d0210 | |||
| 1cd186c7f7 | |||
| 0a64358aa8 | |||
| 727d41d288 | |||
| e8adc1f816 | |||
| 2313f8e4eb | |||
| 288822a5c2 | |||
| f993f90c86 | |||
| 303686684c | |||
| 3183a13f66 | |||
| 5350ce1059 | |||
| 7d3452b37e | |||
| 528f93f8cb | |||
| f36c33c86d | |||
| f68cba3d2f | |||
| f1ee1b4a3d | |||
| 218e82c875 | |||
| 82bdef1639 | |||
| 4df04a2543 | |||
| fd30ae988b | |||
| 61acdf6512 | |||
| f9b91a7836 | |||
| 4bc86a26db | |||
| 02c78bb47e | |||
| dbf787c6b7 | |||
| e122f4dd0d | |||
| 29908148f8 | |||
| b48f51932f | |||
| d316d3f74f | |||
| 2e99ed6422 | |||
| 3e5094ed12 | |||
| 360b6af1b1 | |||
| 47ed1a8d17 | |||
| 7ed72d943b | |||
| 43531064c2 | |||
| 942b21772a | |||
| 61c5245bf7 | |||
| b11b1f1186 | |||
| 4882559ae3 | |||
| d0fe8f7ede | |||
| 9f7b9887cb | |||
| 47efe3c794 | |||
| bdfe05b595 | |||
| c3aaa8751a | |||
| 58270b757c | |||
| ced3f13f4e | |||
| 2f74e14334 | |||
| e365b7d69c | |||
| 2b28c28384 | |||
| bf726e8217 | |||
| 3c6ef5e27a | |||
| 8d5c005642 | |||
| ca182912a3 | |||
| 2131584add | |||
| f779ad64ac | |||
| 0ba4141cb1 | |||
| e8db14f584 | |||
| 433d2ec534 | |||
| 44454633eb | |||
| f10fbe1fb4 | |||
| 258fcf9f5e | |||
| 682fd7846c | |||
| 5efaa9970a | |||
| a1b43c3046 | |||
| 5e12ff9ff6 | |||
| e6f8450d95 | |||
| cc65836d00 | |||
| d21e73dee3 | |||
| b03b6f54c5 | |||
| 5a684e3196 | |||
| 4b544f93ad | |||
| 25a4e26320 | |||
| 3d4e049194 | |||
| bca1e6e9c3 | |||
| 695e36b003 | |||
| 16458b60c9 | |||
| 1512d889de | |||
| 54206943a1 | |||
| 3798dcf75b | |||
| 2b7eee4a4c | |||
| 87d50425fc | |||
| 802d9c23dc | |||
| fa00b24954 | |||
| 2bff4174e5 | |||
| 1b9a11682d | |||
| 65aea48588 | |||
| 94a301a70e | |||
| 937e19e86a | |||
| 930d724923 | |||
| 28879d3d03 | |||
| 48d394a245 | |||
| 898fcff037 | |||
| 5855fd2f65 | |||
| c0815e40b6 | |||
| 7ec3fa5f0a | |||
| e3a4c28409 | |||
| 6e4e966d9b | |||
| e4cb86df2b | |||
| 4be4826ddb | |||
| 14b9f53bb3 | |||
| 000569da60 | |||
| c597384ad6 | |||
| b8f2c7387f | |||
| 72e5ad3d21 | |||
| c927291ecf | |||
| feaa654b1b | |||
| 5db1dfe5c8 | |||
| a49856bb04 | |||
| 4c7c009dd6 | |||
| 04dcaa3412 | |||
| 4c5e901c96 | |||
| a306f88a84 | |||
| a355edbbe4 | |||
| 91a979430e | |||
| aa36799acb | |||
| 919f5faa46 | |||
| f682f07007 | |||
| 0756ecb214 | |||
| f7ce3a1b5f | |||
| 18dc186a8f | |||
| 6f493b4d2e | |||
| 01d7554b87 | |||
| 9949ee3163 | |||
| d7eeacf2a0 | |||
| 91afdaff80 | |||
| 1ba841410b | |||
| b00e0dae9b | |||
| 7e738f0d90 | |||
| 4719ed671a | |||
| c28142e7c1 | |||
| 6df01178c0 | |||
| faebec63a9 | |||
| 005f3a392f | |||
| 5730e908c6 | |||
| 976207df1f | |||
| d0ea6686eb | |||
| 9c0f41e997 | |||
| 45cc515f45 | |||
| c2c44a061a | |||
| e1071797a4 | |||
| b75e35cb94 | |||
| e883dec6be | |||
| c41add8d3e | |||
| 075ebb4ee5 | |||
| 15d42c6d77 | |||
| 58007c0bcc | |||
| c82070e635 | |||
| 0bc3705948 | |||
| c7f014ed49 | |||
| ca89cd06d3 | |||
| eb26865c36 | |||
| 3ba2e748d6 | |||
| 73df06c80c | |||
| 60e9222fe1 | |||
| 76e464bcd5 | |||
| 0fbae8050b | |||
| 90e81c2bee | |||
| 2425584849 | |||
| 64155dfac0 | |||
| 729f4f9b16 | |||
| 11cdafb821 | |||
| f8ba02f229 | |||
| 60930a3e19 | |||
| 58c9fbc93d | |||
| e8dda2b675 | |||
| a7dc011ac4 | |||
| 1cb1267ce8 | |||
| 3db3c06218 | |||
| c16462b3b4 | |||
| 9ca7b24421 | |||
| 2c13c66cf9 | |||
| cf00f96fd4 | |||
| 5271448b3a | |||
| 21c985f2d7 | |||
| c85c5cb50e | |||
| ef291d2d5d | |||
| ff538c7f56 | |||
| e2eaa2ecf3 | |||
| 3eb3e0dcb0 | |||
| 35dabb1a5f | |||
| 84aa295227 | |||
| 4e59c63ec5 | |||
| 850f904a84 | |||
| 11df28916a | |||
| aeffce7c22 | |||
| 44aad0786b | |||
| 10fea86002 | |||
| 02d7281b93 | |||
| 15dd96f7a6 | |||
| d13769d6c1 | |||
| 5f43345d6e | |||
| 0f535aeb0a | |||
| e0ad4a6696 | |||
| 5c1865a4fc | |||
| 9e843f56ec | |||
| 5abd18426d | |||
| e172e6a4e3 | |||
| 7603e96fa2 | |||
| 8b92af7d4a | |||
| ec7432331b | |||
| fc3e3e26c5 | |||
| 781f2b2f81 | |||
| 4ea8979b93 | |||
| 56f2f7a3af | |||
| a2d272a02a | |||
| 063f970f0f | |||
| 3355a9d3fa | |||
| 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 |
@@ -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"
|
||||
@@ -23,9 +23,19 @@
|
||||
# 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
|
||||
# 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
|
||||
+73
-26
@@ -75,6 +75,9 @@ 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>
|
||||
@@ -83,8 +86,9 @@ values</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="#variable-templates-and-inline-variables"
|
||||
id="toc-variable-templates-and-inline-variables">Variable Templates and
|
||||
Inline Variables</a></li>
|
||||
<li><a href="#initializing-variables-with-static-storage-duration"
|
||||
id="toc-initializing-variables-with-static-storage-duration">Initializing
|
||||
variables with static storage duration</a></li>
|
||||
@@ -719,11 +723,14 @@ 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>
|
||||
<li><p>Function return type deduction (<a
|
||||
</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>
|
||||
<li><p>Class template argument deduction (<a
|
||||
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.
|
||||
@@ -736,7 +743,7 @@ 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</p></li>
|
||||
this</li>
|
||||
</ul>
|
||||
<pre><code> ScopeGuard guard{[&]{ ... cleanup code ... }};</code></pre>
|
||||
<ul>
|
||||
@@ -771,6 +778,44 @@ 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
|
||||
@@ -893,12 +938,18 @@ 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
|
||||
<h3 id="variable-templates-and-inline-variables">Variable Templates and
|
||||
Inline Variables</h3>
|
||||
<p>The use of variable templates (including static data member
|
||||
templates) (<a href="https://wg21.link/N3651">N3651</a>) is permitted.
|
||||
They provide parameterized variables and constants in a simple and
|
||||
direct form, instead of requiring the use of various workarounds.</p>
|
||||
<p>Variables with static storage duration and variable templates may be
|
||||
declared <code>inline</code> (<a
|
||||
href="https://wg21.link/p0386r2">p0386r2</a>), and this usage is
|
||||
permitted. This has similar effects as for declaring a function inline:
|
||||
it can be defined, identically, in multiple translation units, must be
|
||||
defined in every translation unit in which it is <a
|
||||
href="https://en.cppreference.com/w/cpp/language/definition"
|
||||
title="One Definition Rule">ODR used</a>, and the behavior of the
|
||||
program is as if there is exactly one variable.</p>
|
||||
@@ -911,16 +962,17 @@ 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
|
||||
<p>A <code>constexpr</code> static data member or static data member
|
||||
template is implicitly <code>inline</code>. As a consequence, an <a
|
||||
href="https://en.cppreference.com/w/cpp/language/definition"
|
||||
title="One Definition Rule">ODR use</a> of such a 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>
|
||||
title="One Definition Rule">ODR use</a> of such a member doesn't require
|
||||
a definition in some .cpp file. (This is a change from pre-C++17.
|
||||
Beginning with C++17, such a definition is considered a duplicate
|
||||
definition, and is deprecated.)</p>
|
||||
<p>Declaring a <code>thread_local</code> variable template or
|
||||
<code>inline</code> variable is forbidden in HotSpot code. <a
|
||||
href="#thread_local">The use of <code>thread_local</code></a> is already
|
||||
heavily restricted.</p>
|
||||
<h3
|
||||
id="initializing-variables-with-static-storage-duration">Initializing
|
||||
variables with static storage duration</h3>
|
||||
@@ -1807,11 +1859,6 @@ difference.</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>, <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>
|
||||
|
||||
+55
-18
@@ -642,6 +642,7 @@ use can make code much harder to understand.
|
||||
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`
|
||||
@@ -691,6 +692,42 @@ 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
|
||||
@@ -819,14 +856,19 @@ 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
|
||||
### Variable Templates and 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.
|
||||
The use of variable templates (including static data member templates)
|
||||
([N3651](https://wg21.link/N3651)) is permitted. They provide parameterized
|
||||
variables and constants in a simple and direct form, instead of requiring the
|
||||
use of various workarounds.
|
||||
|
||||
Variables with static storage duration and variable templates may be declared
|
||||
`inline` ([p0386r2](https://wg21.link/p0386r2)), and this usage is
|
||||
permitted. This has similar effects as for declaring a function inline: it can
|
||||
be defined, identically, in multiple translation units, must be defined in
|
||||
every translation unit in which it is [ODR used][ODR], and the behavior of the
|
||||
program is as if there is exactly one variable.
|
||||
|
||||
Declaring a variable inline allows the complete definition to be in a header
|
||||
file, rather than having a declaration in a header and the definition in a
|
||||
@@ -837,13 +879,15 @@ 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
|
||||
A `constexpr` static data member or static data member template
|
||||
is implicitly `inline`. As a consequence, an
|
||||
[ODR use][ODR] of such a member doesn't require a definition in some .cpp
|
||||
file. (This is a change from pre-C++17. Beginning with C++17, such a
|
||||
definition is considered a duplicate definition, and is deprecated.)
|
||||
|
||||
Declaring a `thread_local` variable `inline` is forbidden for HotSpot code.
|
||||
[The use of `thread_local`](#thread_local) is already heavily restricted.
|
||||
Declaring a `thread_local` variable template or `inline` variable is forbidden
|
||||
in HotSpot code. [The use of `thread_local`](#thread_local) is already
|
||||
heavily restricted.
|
||||
|
||||
### Initializing variables with static storage duration
|
||||
|
||||
@@ -1809,13 +1853,6 @@ 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),
|
||||
[p0127r2](http://wg21.link/p0127r2))
|
||||
|
||||
* Member initializers and aggregates
|
||||
([n3653](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html))
|
||||
|
||||
|
||||
+2
-2
@@ -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, \
|
||||
|
||||
@@ -114,7 +114,6 @@ ifeq ($(HSDIS_BACKEND), binutils)
|
||||
TOOLCHAIN_TYPE := gcc
|
||||
OPENJDK_TARGET_OS := linux
|
||||
OPENJDK_TARGET_OS_TYPE := unix
|
||||
CC_OUT_OPTION := -o$(SPACE)
|
||||
GENDEPS_FLAGS := -MMD -MF
|
||||
CFLAGS_DEBUG_SYMBOLS := -g
|
||||
DISABLED_WARNINGS :=
|
||||
|
||||
+4
-20
@@ -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
|
||||
|
||||
@@ -597,10 +597,9 @@ AC_DEFUN([BOOTJDK_SETUP_BUILD_JDK],
|
||||
AC_ARG_WITH(build-jdk, [AS_HELP_STRING([--with-build-jdk],
|
||||
[path to JDK of same version as is being built@<:@the newly built JDK@:>@])])
|
||||
|
||||
CREATE_BUILDJDK=false
|
||||
EXTERNAL_BUILDJDK=false
|
||||
BUILD_JDK_FOUND="no"
|
||||
EXTERNAL_BUILDJDK_PATH=""
|
||||
if test "x$with_build_jdk" != "x"; then
|
||||
BUILD_JDK_FOUND=no
|
||||
BOOTJDK_CHECK_BUILD_JDK([
|
||||
if test "x$with_build_jdk" != x; then
|
||||
BUILD_JDK=$with_build_jdk
|
||||
@@ -608,40 +607,15 @@ AC_DEFUN([BOOTJDK_SETUP_BUILD_JDK],
|
||||
AC_MSG_NOTICE([Found potential Build JDK using configure arguments])
|
||||
fi
|
||||
])
|
||||
EXTERNAL_BUILDJDK=true
|
||||
else
|
||||
if test "x$COMPILE_TYPE" = "xcross"; then
|
||||
BUILD_JDK="\$(BUILDJDK_OUTPUTDIR)/jdk"
|
||||
BUILD_JDK_FOUND=yes
|
||||
CREATE_BUILDJDK=true
|
||||
if test "x$BUILD_JDK_FOUND" != "xyes"; then
|
||||
AC_MSG_CHECKING([for Build JDK])
|
||||
AC_MSG_RESULT([yes, will build it for the host platform])
|
||||
else
|
||||
BUILD_JDK="\$(JDK_OUTPUTDIR)"
|
||||
BUILD_JDK_FOUND=yes
|
||||
AC_MSG_CHECKING([for Build JDK])
|
||||
AC_MSG_RESULT([yes, will use output dir])
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Could not find a suitable Build JDK])
|
||||
fi
|
||||
EXTERNAL_BUILDJDK_PATH="$BUILD_JDK"
|
||||
fi
|
||||
|
||||
# Since these tools do not yet exist, we cannot use UTIL_FIXUP_EXECUTABLE to
|
||||
# detect the need of fixpath
|
||||
JMOD="$BUILD_JDK/bin/jmod"
|
||||
UTIL_ADD_FIXPATH(JMOD)
|
||||
JLINK="$BUILD_JDK/bin/jlink"
|
||||
UTIL_ADD_FIXPATH(JLINK)
|
||||
AC_SUBST(JMOD)
|
||||
AC_SUBST(JLINK)
|
||||
|
||||
if test "x$BUILD_JDK_FOUND" != "xyes"; then
|
||||
AC_MSG_CHECKING([for Build JDK])
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Could not find a suitable Build JDK])
|
||||
fi
|
||||
|
||||
AC_SUBST(CREATE_BUILDJDK)
|
||||
AC_SUBST(BUILD_JDK)
|
||||
AC_SUBST(EXTERNAL_BUILDJDK)
|
||||
AC_SUBST(EXTERNAL_BUILDJDK_PATH)
|
||||
])
|
||||
|
||||
# The docs-reference JDK is used to run javadoc for the docs-reference targets.
|
||||
|
||||
@@ -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" "$@"
|
||||
|
||||
@@ -37,56 +37,25 @@ AC_DEFUN([FLAGS_SETUP_SHARED_LIBS],
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
# Default works for linux, might work on other platforms as well.
|
||||
SHARED_LIBRARY_FLAGS='-shared'
|
||||
# --disable-new-dtags forces use of RPATH instead of RUNPATH for rpaths.
|
||||
# This protects internal library dependencies within the JDK from being
|
||||
# overridden using LD_LIBRARY_PATH. See JDK-8326891 for more information.
|
||||
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1 -Wl,--disable-new-dtags'
|
||||
SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
|
||||
SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
# Linking is different on MacOSX
|
||||
SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0"
|
||||
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path$(or [$]1,/.)'
|
||||
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
|
||||
SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1'
|
||||
|
||||
elif test "x$OPENJDK_TARGET_OS" = xaix; then
|
||||
# Linking is different on aix
|
||||
SHARED_LIBRARY_FLAGS="-shared -Wl,-bM:SRE -Wl,-bnoentry"
|
||||
SET_EXECUTABLE_ORIGIN=""
|
||||
SET_SHARED_LIBRARY_ORIGIN=''
|
||||
SET_SHARED_LIBRARY_NAME=''
|
||||
|
||||
else
|
||||
# Default works for linux, might work on other platforms as well.
|
||||
SHARED_LIBRARY_FLAGS='-shared'
|
||||
SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1'
|
||||
if test "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
SET_EXECUTABLE_ORIGIN="$SET_EXECUTABLE_ORIGIN -Wl,--disable-new-dtags"
|
||||
fi
|
||||
SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
|
||||
|
||||
# arm specific settings
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xarm"; then
|
||||
# '-Wl,-z,origin' isn't used on arm.
|
||||
SET_SHARED_LIBRARY_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1'
|
||||
else
|
||||
SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
|
||||
fi
|
||||
fi
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
SHARED_LIBRARY_FLAGS="-dll"
|
||||
SET_EXECUTABLE_ORIGIN=''
|
||||
SET_SHARED_LIBRARY_ORIGIN=''
|
||||
SET_SHARED_LIBRARY_NAME=''
|
||||
fi
|
||||
|
||||
AC_SUBST(SET_EXECUTABLE_ORIGIN)
|
||||
AC_SUBST(SET_SHARED_LIBRARY_ORIGIN)
|
||||
AC_SUBST(SET_SHARED_LIBRARY_NAME)
|
||||
AC_SUBST(SHARED_LIBRARY_FLAGS)
|
||||
])
|
||||
|
||||
@@ -934,48 +903,6 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
IF_FALSE: [$2FDLIBM_CFLAGS=""])
|
||||
fi
|
||||
AC_SUBST($2FDLIBM_CFLAGS)
|
||||
|
||||
# Check whether the compiler supports the Arm C Language Extensions (ACLE)
|
||||
# for SVE. Set SVE_CFLAGS to -march=armv8-a+sve if it does.
|
||||
# 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_OS" = "xlinux"; then
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
AC_LANG_PUSH(C)
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -march=armv8-a+sve"
|
||||
AC_MSG_CHECKING([if Arm SVE ACLE is supported])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <arm_sve.h>],
|
||||
[
|
||||
svint32_t r = svdup_n_s32(1);
|
||||
return 0;
|
||||
])],
|
||||
[
|
||||
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])
|
||||
$2SVE_CFLAGS=""
|
||||
]
|
||||
)
|
||||
CFLAGS="$OLD_CFLAGS"
|
||||
AC_LANG_POP(C)
|
||||
fi
|
||||
fi
|
||||
AC_SUBST($2SVE_CFLAGS)
|
||||
])
|
||||
|
||||
AC_DEFUN_ONCE([FLAGS_SETUP_BRANCH_PROTECTION],
|
||||
|
||||
@@ -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
|
||||
@@ -98,7 +98,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
|
||||
# Setup OS-dependent LDFLAGS
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
# FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead.
|
||||
# FIXME: We should really generalize SetSharedLibraryOrigin instead.
|
||||
OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.."
|
||||
OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN -Wl,-reproducible"
|
||||
fi
|
||||
|
||||
@@ -107,6 +107,62 @@ AC_DEFUN([FLAGS_SETUP_NMFLAGS],
|
||||
AC_SUBST(NMFLAGS)
|
||||
])
|
||||
|
||||
# Check whether the compiler supports the Arm C Language Extensions (ACLE)
|
||||
# for SVE. Set SVE_CFLAGS to -march=armv8-a+sve if it does.
|
||||
# ACLE and this flag are required to build the aarch64 SVE related functions
|
||||
# in libvectormath.
|
||||
AC_DEFUN([FLAGS_SETUP_SVE],
|
||||
[
|
||||
AARCH64_SVE_AVAILABLE=false
|
||||
# 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_OS" = "xlinux"; then
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
# check the compiler and binutils support sve or not
|
||||
AC_MSG_CHECKING([if Arm SVE ACLE is supported])
|
||||
AC_LANG_PUSH([C])
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -march=armv8-a+sve $CFLAGS_WARNINGS_ARE_ERRORS ARG_ARGUMENT"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[
|
||||
#include <arm_sve.h>
|
||||
svfloat64_t a() {}
|
||||
],
|
||||
[
|
||||
svint32_t r = svdup_n_s32(1)
|
||||
])],
|
||||
[
|
||||
AARCH64_SVE_AVAILABLE=true
|
||||
]
|
||||
)
|
||||
CFLAGS="$saved_cflags"
|
||||
AC_LANG_POP([C])
|
||||
AC_MSG_RESULT([$AARCH64_SVE_AVAILABLE])
|
||||
fi
|
||||
fi
|
||||
|
||||
UTIL_ARG_ENABLE(NAME: aarch64-sve, DEFAULT: auto,
|
||||
RESULT: AARCH64_SVE_ENABLED,
|
||||
DESC: [Use SVE when compiling libsleef],
|
||||
AVAILABLE: $AARCH64_SVE_AVAILABLE)
|
||||
SVE_CFLAGS=""
|
||||
if test "x$AARCH64_SVE_ENABLED" = xtrue; then
|
||||
SVE_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
|
||||
AC_MSG_CHECKING([Switching the initialization mode with gcc from pattern to zero])
|
||||
INIT_ZERO_FLAG="-ftrivial-auto-var-init=zero"
|
||||
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_ZERO_FLAG],
|
||||
IF_TRUE: [
|
||||
SVE_CFLAGS="${SVE_CFLAGS} $INIT_ZERO_FLAG"
|
||||
]
|
||||
)
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(SVE_CFLAGS)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
# platform independent
|
||||
AC_DEFUN([FLAGS_SETUP_ASFLAGS],
|
||||
|
||||
@@ -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
|
||||
@@ -319,16 +319,10 @@ AC_DEFUN_ONCE([FLAGS_PRE_TOOLCHAIN],
|
||||
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
|
||||
@@ -374,6 +368,7 @@ AC_DEFUN([FLAGS_SETUP_FLAGS],
|
||||
FLAGS_SETUP_RCFLAGS
|
||||
FLAGS_SETUP_NMFLAGS
|
||||
|
||||
FLAGS_SETUP_SVE
|
||||
FLAGS_SETUP_ASFLAGS
|
||||
FLAGS_SETUP_ASFLAGS_CPU_DEP([TARGET])
|
||||
FLAGS_SETUP_ASFLAGS_CPU_DEP([BUILD], [OPENJDK_BUILD_])
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
################################################################################
|
||||
|
||||
# Minimum supported versions
|
||||
JTREG_MINIMUM_VERSION=7.5.2
|
||||
JTREG_MINIMUM_VERSION=8
|
||||
GTEST_MINIMUM_VERSION=1.14.0
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -386,9 +386,22 @@ CAPSTONE_ARCH_AARCH64_NAME := @CAPSTONE_ARCH_AARCH64_NAME@
|
||||
# it in sync.
|
||||
BOOT_JDK := @BOOT_JDK@
|
||||
|
||||
BUILD_JDK := @BUILD_JDK@
|
||||
CREATE_BUILDJDK := @CREATE_BUILDJDK@
|
||||
EXTERNAL_BUILDJDK := @EXTERNAL_BUILDJDK@
|
||||
EXTERNAL_BUILDJDK_PATH := @EXTERNAL_BUILDJDK_PATH@
|
||||
|
||||
ifneq ($(EXTERNAL_BUILDJDK_PATH), )
|
||||
EXTERNAL_BUILDJDK := true
|
||||
CREATE_BUILDJDK := false
|
||||
BUILD_JDK := $(EXTERNAL_BUILDJDK_PATH)
|
||||
else
|
||||
EXTERNAL_BUILDJDK := false
|
||||
ifeq ($(COMPILE_TYPE), cross)
|
||||
CREATE_BUILDJDK := true
|
||||
BUILD_JDK := $(BUILDJDK_OUTPUTDIR)/jdk
|
||||
else
|
||||
CREATE_BUILDJDK := false
|
||||
BUILD_JDK := $(JDK_OUTPUTDIR)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Whether the boot jdk jar supports --date=TIMESTAMP
|
||||
BOOT_JDK_JAR_SUPPORTS_DATE := @BOOT_JDK_JAR_SUPPORTS_DATE@
|
||||
@@ -491,7 +504,6 @@ CXX_VERSION_NUMBER := @CXX_VERSION_NUMBER@
|
||||
# Legacy support
|
||||
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.
|
||||
@@ -624,17 +636,8 @@ ASFLAGS_DEBUG_SYMBOLS := @ASFLAGS_DEBUG_SYMBOLS@
|
||||
# Compress (or not) jars
|
||||
COMPRESS_JARS := @COMPRESS_JARS@
|
||||
|
||||
# Options to linker to specify the library name.
|
||||
# (Note absence of := assignment, because we do not want to evaluate the macro body here)
|
||||
SET_SHARED_LIBRARY_NAME = @SET_SHARED_LIBRARY_NAME@
|
||||
|
||||
SHARED_LIBRARY_FLAGS := @SHARED_LIBRARY_FLAGS@
|
||||
|
||||
# Set origin using the linker, ie use the relative path to the dependent library to find the dependencies.
|
||||
# (Note absence of := assignment, because we do not want to evaluate the macro body here)
|
||||
SET_SHARED_LIBRARY_ORIGIN = @SET_SHARED_LIBRARY_ORIGIN@
|
||||
SET_EXECUTABLE_ORIGIN = @SET_EXECUTABLE_ORIGIN@
|
||||
|
||||
LIBRARY_PREFIX := @LIBRARY_PREFIX@
|
||||
SHARED_LIBRARY_SUFFIX := @SHARED_LIBRARY_SUFFIX@
|
||||
STATIC_LIBRARY_SUFFIX := @STATIC_LIBRARY_SUFFIX@
|
||||
@@ -657,8 +660,8 @@ JAVA_CMD := @JAVA@
|
||||
JAVAC_CMD := @JAVAC@
|
||||
JAVADOC_CMD := @JAVADOC@
|
||||
JAR_CMD := @JAR@
|
||||
JLINK_CMD := @JLINK@
|
||||
JMOD_CMD := @JMOD@
|
||||
JLINK_CMD := @FIXPATH@ $(BUILD_JDK)/bin/jlink
|
||||
JMOD_CMD := @FIXPATH@ $(BUILD_JDK)/bin/jmod
|
||||
# These variables are meant to be used. They are defined with = instead of := to make
|
||||
# it possible to override only the *_CMD variables.
|
||||
JAVA = $(JAVA_CMD) $(JAVA_FLAGS_BIG) $(JAVA_FLAGS)
|
||||
@@ -898,12 +901,14 @@ JDK_MACOSX_BUNDLE_DIR = $(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR)
|
||||
JRE_MACOSX_BUNDLE_DIR = $(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR)
|
||||
JDK_MACOSX_BUNDLE_DIR_SIGNED = $(IMAGES_OUTPUTDIR)/$(JDK_MACOSX_BUNDLE_SUBDIR_SIGNED)
|
||||
JRE_MACOSX_BUNDLE_DIR_SIGNED = $(IMAGES_OUTPUTDIR)/$(JRE_MACOSX_BUNDLE_SUBDIR_SIGNED)
|
||||
JDK_MACOSX_BUNDLE_TOP_DIR = jdk-$(VERSION_NUMBER).jdk
|
||||
JRE_MACOSX_BUNDLE_TOP_DIR = jre-$(VERSION_NUMBER).jre
|
||||
JDK_MACOSX_CONTENTS_SUBDIR = $(JDK_MACOSX_BUNDLE_TOP_DIR)/Contents
|
||||
JRE_MACOSX_CONTENTS_SUBDIR = $(JRE_MACOSX_BUNDLE_TOP_DIR)/Contents
|
||||
JDK_MACOSX_BUNDLE_TOP_SUBDIR = jdk-$(VERSION_NUMBER).jdk
|
||||
JRE_MACOSX_BUNDLE_TOP_SUBDIR = jre-$(VERSION_NUMBER).jre
|
||||
JDK_MACOSX_CONTENTS_SUBDIR = $(JDK_MACOSX_BUNDLE_TOP_SUBDIR)/Contents
|
||||
JRE_MACOSX_CONTENTS_SUBDIR = $(JRE_MACOSX_BUNDLE_TOP_SUBDIR)/Contents
|
||||
JDK_MACOSX_CONTENTS_DIR = $(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_CONTENTS_SUBDIR)
|
||||
JRE_MACOSX_CONTENTS_DIR = $(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_CONTENTS_SUBDIR)
|
||||
JDK_MACOSX_BUNDLE_TOP_DIR = $(JDK_MACOSX_BUNDLE_DIR)/$(JDK_MACOSX_BUNDLE_TOP_SUBDIR)
|
||||
JRE_MACOSX_BUNDLE_TOP_DIR = $(JRE_MACOSX_BUNDLE_DIR)/$(JRE_MACOSX_BUNDLE_TOP_SUBDIR)
|
||||
|
||||
# Bundle names
|
||||
ifneq ($(VERSION_BUILD), )
|
||||
|
||||
@@ -276,9 +276,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
ORG_CFLAGS="$CFLAGS"
|
||||
ORG_CXXFLAGS="$CXXFLAGS"
|
||||
|
||||
# autoconf magic only relies on PATH, so update it if tools dir is specified
|
||||
OLD_PATH="$PATH"
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
|
||||
if test "x$XCODEBUILD" != x; then
|
||||
XCODE_VERSION_OUTPUT=`"$XCODEBUILD" -version 2> /dev/null | $HEAD -n 1`
|
||||
@@ -300,9 +297,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
fi
|
||||
AC_SUBST(TOOLCHAIN_VERSION)
|
||||
|
||||
# Finally prepend TOOLCHAIN_PATH to the PATH, to allow --with-tools-dir to
|
||||
# override all other locations.
|
||||
if test "x$TOOLCHAIN_PATH" != x; then
|
||||
# For the microsoft toolchain the toolchain path needs to be added to the
|
||||
# normal path, or the compiler will not work in some situations in later
|
||||
# configure checks.
|
||||
if test "x$TOOLCHAIN_TYPE" = "xmicrosoft" && test "x$TOOLCHAIN_PATH" != x; then
|
||||
export PATH=$TOOLCHAIN_PATH:$PATH
|
||||
fi
|
||||
])
|
||||
@@ -310,13 +308,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
|
||||
# Restore path, etc
|
||||
AC_DEFUN_ONCE([TOOLCHAIN_POST_DETECTION],
|
||||
[
|
||||
# Restore old path, except for the microsoft toolchain, which requires the
|
||||
# toolchain path to remain in place. Otherwise the compiler will not work in
|
||||
# some situations in later configure checks.
|
||||
if test "x$TOOLCHAIN_TYPE" != "xmicrosoft"; then
|
||||
PATH="$OLD_PATH"
|
||||
fi
|
||||
|
||||
# Restore the flags to the user specified values.
|
||||
# This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2"
|
||||
CFLAGS="$ORG_CFLAGS"
|
||||
|
||||
@@ -458,17 +458,18 @@ AC_DEFUN([UTIL_LOOKUP_PROGS],
|
||||
|
||||
################################################################################
|
||||
# Call UTIL_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool. This will look
|
||||
# first for cross-compilation tools.
|
||||
# first for tools using the cross-compilation prefix, and then for tools without
|
||||
# this prefix. For each of these name variants, it will look first in the
|
||||
# toolchain path, and then in the normal path.
|
||||
# $1: variable to set
|
||||
# $2: executable name (or list of names) to look for
|
||||
# $3: [path]
|
||||
AC_DEFUN([UTIL_LOOKUP_TOOLCHAIN_PROGS],
|
||||
[
|
||||
if test "x$ac_tool_prefix" = x; then
|
||||
UTIL_LOOKUP_PROGS($1, $2, $3)
|
||||
UTIL_LOOKUP_PROGS($1, $2, [$TOOLCHAIN_PATH:$PATH])
|
||||
else
|
||||
prefixed_names=$(for name in $2; do echo ${ac_tool_prefix}${name} $name; done)
|
||||
UTIL_LOOKUP_PROGS($1, $prefixed_names, $3)
|
||||
UTIL_LOOKUP_PROGS($1, $prefixed_names, [$TOOLCHAIN_PATH:$PATH])
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -497,10 +498,9 @@ AC_DEFUN([UTIL_REQUIRE_PROGS],
|
||||
# Like UTIL_LOOKUP_PROGS but fails if no tool was found.
|
||||
# $1: variable to set
|
||||
# $2: executable name (or list of names) to look for
|
||||
# $3: [path]
|
||||
AC_DEFUN([UTIL_REQUIRE_TOOLCHAIN_PROGS],
|
||||
[
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS($1, $2, $3)
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS($1, $2)
|
||||
UTIL_CHECK_NONEMPTY($1)
|
||||
])
|
||||
|
||||
|
||||
+21
-6
@@ -82,6 +82,8 @@ ifeq ($(INCLUDE), true)
|
||||
# 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
|
||||
@@ -146,9 +148,12 @@ define SetupExecuteBody
|
||||
$1_INFO := Running commands for $1
|
||||
endif
|
||||
|
||||
$1_VARDEPS := $$($1_COMMAND) $$($1_PRE_COMMAND) $$($1_POST_COMMAND)
|
||||
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS)
|
||||
|
||||
ifneq ($$($1_PRE_COMMAND), )
|
||||
|
||||
$$($1_PRE_MARKER): $$($1_DEPS)
|
||||
$$($1_PRE_MARKER): $$($1_DEPS) $$($1_VARDEPS_FILE)
|
||||
ifneq ($$($1_WARN), )
|
||||
$$(call LogWarn, $$($1_WARN))
|
||||
endif
|
||||
@@ -161,15 +166,20 @@ define SetupExecuteBody
|
||||
$$(TOUCH) $$@
|
||||
|
||||
$$($1_EXEC_RESULT): $$($1_PRE_MARKER)
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
cd $$($1_WORKING_DIR) && $$($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
|
||||
|
||||
$1 := $$($1_PRE_MARKER) $$($1_EXEC_RESULT)
|
||||
else
|
||||
$$($1_EXEC_RESULT): $$($1_DEPS)
|
||||
$$($1_EXEC_RESULT): $$($1_DEPS) $$($1_VARDEPS_FILE)
|
||||
ifneq ($$($1_WARN), )
|
||||
$$(call LogWarn, $$($1_WARN))
|
||||
endif
|
||||
@@ -177,8 +187,13 @@ define SetupExecuteBody
|
||||
$$(call LogInfo, $$($1_INFO))
|
||||
endif
|
||||
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
|
||||
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
|
||||
cd $$($1_WORKING_DIR) && $$($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
|
||||
|
||||
@@ -30,6 +30,47 @@ ifeq ($(INCLUDE), true)
|
||||
|
||||
include NativeCompilation.gmk
|
||||
|
||||
ifeq ($(call isCompiler, gcc), true)
|
||||
# --disable-new-dtags forces use of RPATH instead of RUNPATH for rpaths.
|
||||
# This protects internal library dependencies within the JDK from being
|
||||
# overridden using LD_LIBRARY_PATH. See JDK-8326891 for more information.
|
||||
SetExecutableOrigin = \
|
||||
-Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
|
||||
SetSharedLibraryOrigin = \
|
||||
-Wl,-z,origin -Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
|
||||
else ifeq ($(call isCompiler, clang), true)
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
SetExecutableOrigin = \
|
||||
-Wl,-rpath,@loader_path$(or $1,/.)
|
||||
SetSharedLibraryOrigin = \
|
||||
-Wl,-rpath,@loader_path$(or $1,/.)
|
||||
else ifeq ($(call isTargetOs, aix), true)
|
||||
SetExecutableOrigin =
|
||||
SetSharedLibraryOrigin =
|
||||
else
|
||||
ifeq ($(call isTargetOs, linux), true)
|
||||
SetExecutableOrigin = \
|
||||
-Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
|
||||
else
|
||||
SetExecutableOrigin = \
|
||||
-Wl,-rpath,\$(DOLLAR)ORIGIN$1
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, arm), true)
|
||||
SetSharedLibraryOrigin = \
|
||||
-Wl,-rpath,\$(DOLLAR)ORIGIN$1
|
||||
else
|
||||
SetSharedLibraryOrigin = \
|
||||
-Wl,-z,origin -Wl,-rpath,\$(DOLLAR)ORIGIN$1
|
||||
endif
|
||||
endif
|
||||
else ifeq ($(call isCompiler, microsoft), true)
|
||||
SetExecutableOrigin =
|
||||
SetSharedLibraryOrigin =
|
||||
else
|
||||
$(error Unknown toolchain)
|
||||
endif
|
||||
|
||||
FindSrcDirsForComponent += \
|
||||
$(call uniq, $(wildcard \
|
||||
$(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/$(strip $2) \
|
||||
@@ -444,9 +485,9 @@ define SetupJdkNativeCompilationBody
|
||||
|
||||
ifneq ($$($1_LD_SET_ORIGIN), false)
|
||||
ifeq ($$($1_TYPE), EXECUTABLE)
|
||||
$1_LDFLAGS += $$(call SET_EXECUTABLE_ORIGIN)
|
||||
$1_LDFLAGS += $$(call SetExecutableOrigin)
|
||||
else
|
||||
$1_LDFLAGS += $$(call SET_SHARED_LIBRARY_ORIGIN)
|
||||
$1_LDFLAGS += $$(call SetSharedLibraryOrigin)
|
||||
endif
|
||||
endif
|
||||
# APPEND_LDFLAGS, if it exists, must be set after the origin flags
|
||||
|
||||
@@ -156,8 +156,8 @@ define SetupBuildLauncherBody
|
||||
DISABLED_WARNINGS_gcc := unused-function unused-variable, \
|
||||
DISABLED_WARNINGS_clang := unused-function, \
|
||||
LDFLAGS := $$($1_LDFLAGS), \
|
||||
LDFLAGS_linux := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
|
||||
LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
|
||||
LDFLAGS_linux := $$(call SetExecutableOrigin,/../lib), \
|
||||
LDFLAGS_macosx := $$(call SetExecutableOrigin,/../lib), \
|
||||
LDFLAGS_FILTER_OUT := $$($1_LDFLAGS_FILTER_OUT), \
|
||||
JDK_LIBS := $$($1_JDK_LIBS), \
|
||||
JDK_LIBS_windows := $$($1_JDK_LIBS_windows), \
|
||||
|
||||
@@ -93,6 +93,14 @@ DEPENDENCY_TARGET_SED_PATTERN := \
|
||||
-e 's/$$$$/ :/' \
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Setup compiler-specific argument to specify output file
|
||||
ifeq ($(call isCompiler, microsoft), true)
|
||||
CC_OUT_OPTION := -Fo
|
||||
else
|
||||
CC_OUT_OPTION := -o$(SPACE)
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Create the recipe needed to compile a single native source file.
|
||||
#
|
||||
@@ -334,7 +342,7 @@ define CreateWindowsResourceFile
|
||||
$$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$($1_BASENAME)))
|
||||
$$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
|
||||
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
|
||||
$$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
|
||||
$$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) -Fo$$@ \
|
||||
$$($1_VERSIONINFO_RESOURCE) 2>&1 ))
|
||||
# Windows RC compiler does not support -showIncludes, so we mis-use CL
|
||||
# for this. Filter out RC specific arguments that are unknown to CL.
|
||||
@@ -344,7 +352,7 @@ define CreateWindowsResourceFile
|
||||
$$(call ExecuteWithLog, $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX), \
|
||||
$$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \
|
||||
$$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
|
||||
$(CC_OUT_OPTION)$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
|
||||
-Fo$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
|
||||
$$($1_VERSIONINFO_RESOURCE)) 2>&1 \
|
||||
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
|
||||
-e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
|
||||
|
||||
@@ -50,6 +50,26 @@ GetEntitlementsFile = \
|
||||
$(if $(wildcard $f), $f, $(DEFAULT_ENTITLEMENTS_FILE)) \
|
||||
)
|
||||
|
||||
ifeq ($(call isCompiler, gcc), true)
|
||||
SetSharedLibraryName = \
|
||||
-Wl,-soname=$1
|
||||
else ifeq ($(call isCompiler, clang), true)
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
SetSharedLibraryName = \
|
||||
-Wl,-install_name,@rpath/$1
|
||||
else ifeq ($(call isTargetOs, aix), true)
|
||||
SetSharedLibraryName =
|
||||
else
|
||||
# Default works for linux, might work on other platforms as well.
|
||||
SetSharedLibraryName = \
|
||||
-Wl,-soname=$1
|
||||
endif
|
||||
else ifeq ($(call isCompiler, microsoft), true)
|
||||
SetSharedLibraryName =
|
||||
else
|
||||
$(error Unknown toolchain)
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
define SetupLinking
|
||||
# Unless specifically set, stripping should only happen if symbols are also
|
||||
@@ -131,7 +151,7 @@ define CreateDynamicLibraryOrExecutable
|
||||
# A shared dynamic library or an executable binary has been specified
|
||||
ifeq ($$($1_TYPE), LIBRARY)
|
||||
# Generating a dynamic library.
|
||||
$1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME))
|
||||
$1_EXTRA_LDFLAGS += $$(call SetSharedLibraryName,$$($1_BASENAME))
|
||||
endif
|
||||
|
||||
ifeq ($(MACOSX_CODESIGN_MODE), hardened)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# Versions and download locations for dependencies used by GitHub Actions (GHA)
|
||||
|
||||
GTEST_VERSION=1.14.0
|
||||
JTREG_VERSION=7.5.2+1
|
||||
JTREG_VERSION=8+2
|
||||
|
||||
LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz
|
||||
|
||||
@@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
|
||||
jtreg: {
|
||||
server: "jpg",
|
||||
product: "jtreg",
|
||||
version: "7.5.2",
|
||||
build_number: "1",
|
||||
file: "bundles/jtreg-7.5.2+1.zip",
|
||||
version: "8",
|
||||
build_number: "2",
|
||||
file: "bundles/jtreg-8+2.zip",
|
||||
environment_name: "JT_HOME",
|
||||
environment_path: input.get("jtreg", "home_path") + "/bin",
|
||||
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
|
||||
|
||||
@@ -152,7 +152,7 @@ $(eval $(call SetupJdkExecutable, BUILD_GTEST_LAUNCHER, \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include, \
|
||||
LD_SET_ORIGIN := false, \
|
||||
LDFLAGS_unix := $(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LDFLAGS_unix := $(call SetSharedLibraryOrigin), \
|
||||
JDK_LIBS := gtest:libjvm, \
|
||||
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
|
||||
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
|
||||
|
||||
@@ -57,7 +57,7 @@ ifeq ($(call check-jvm-feature, zero), true)
|
||||
-DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS)
|
||||
JVM_LIBS_FEATURES += $(LIBFFI_LIBS)
|
||||
ifeq ($(ENABLE_LIBFFI_BUNDLING), true)
|
||||
JVM_LDFLAGS_FEATURES += $(call SET_EXECUTABLE_ORIGIN,/..)
|
||||
JVM_LDFLAGS_FEATURES += $(call SetExecutableOrigin,/..)
|
||||
endif
|
||||
else
|
||||
JVM_EXCLUDE_PATTERNS += /zero/
|
||||
|
||||
@@ -33,7 +33,6 @@ include gensrc/GensrcBuffer.gmk
|
||||
include gensrc/GensrcCharacterData.gmk
|
||||
include gensrc/GensrcCharsetCoder.gmk
|
||||
include gensrc/GensrcCharsetMapping.gmk
|
||||
include gensrc/GensrcExceptions.gmk
|
||||
include gensrc/GensrcMisc.gmk
|
||||
include gensrc/GensrcModuleLoaderMap.gmk
|
||||
include gensrc/GensrcRegex.gmk
|
||||
|
||||
@@ -154,6 +154,8 @@ endif
|
||||
|
||||
################################################################################
|
||||
## Build libsyslookup
|
||||
## The LIBDL dependency on Linux is needed to dynamically access libdl symbols,
|
||||
## which may be needed as part of resolving some standard symbols
|
||||
################################################################################
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBSYSLOOKUP, \
|
||||
@@ -196,7 +198,7 @@ ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, x86_64)+$(INCLUDE_COMPILER2)
|
||||
OPTIMIZATION := HIGH, \
|
||||
CXXFLAGS := -std=c++17, \
|
||||
DISABLED_WARNINGS_gcc := unused-variable, \
|
||||
LIBS_linux := $(LIBDL) $(LIBM), \
|
||||
LIBS_linux := $(LIBM), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBSIMD_SORT)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
# 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)
|
||||
|
||||
################################################################################
|
||||
|
||||
GENSRC_EXCEPTIONS :=
|
||||
|
||||
GENSRC_EXCEPTIONS_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio
|
||||
|
||||
GENSRC_EXCEPTIONS_SRC := $(MODULE_SRC)/share/classes/java/nio
|
||||
GENSRC_EXCEPTIONS_CMD := $(TOPDIR)/make/scripts/genExceptions.sh
|
||||
|
||||
GENSRC_EXCEPTIONS_SRC_DIRS := . charset channels
|
||||
|
||||
$(GENSRC_EXCEPTIONS_DST)/_the.%.marker: $(GENSRC_EXCEPTIONS_SRC)/%/exceptions \
|
||||
$(GENSRC_EXCEPTIONS_CMD)
|
||||
$(call LogInfo, Generating exceptions java.nio $*)
|
||||
$(call MakeDir, $(@D)/$*)
|
||||
SCRIPTS="$(TOPDIR)/make/scripts" AWK="$(AWK)" SH="$(SH)" $(SH) \
|
||||
$(GENSRC_EXCEPTIONS_CMD) $< $(@D)/$* $(LOG_DEBUG)
|
||||
$(TOUCH) $@
|
||||
|
||||
GENSRC_EXCEPTIONS += $(foreach D, $(GENSRC_EXCEPTIONS_SRC_DIRS), $(GENSRC_EXCEPTIONS_DST)/_the.$(D).marker)
|
||||
|
||||
$(GENSRC_EXCEPTIONS): $(BUILD_TOOLS_JDK)
|
||||
|
||||
TARGETS += $(GENSRC_EXCEPTIONS)
|
||||
|
||||
################################################################################
|
||||
|
||||
endif # include guard
|
||||
include MakeIncludeEnd.gmk
|
||||
@@ -51,7 +51,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE, \
|
||||
$(LIBMLIB_IMAGE_CFLAGS), \
|
||||
DISABLED_WARNINGS_gcc := unused-function, \
|
||||
DISABLED_WARNINGS_clang_mlib_ImageCreate.c := unused-function, \
|
||||
LIBS_unix := $(LIBDL) $(LIBM), \
|
||||
LIBS_unix := $(LIBM), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBMLIB_IMAGE)
|
||||
@@ -264,7 +264,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
JDK_LIBS_macosx := libosxapp, \
|
||||
LIBS := $(GIFLIB_LIBS) $(LIBJPEG_LIBS) $(LIBZ_LIBS) $(PNG_LIBS) $(ICONV_LIBS), \
|
||||
LIBS_unix := $(LIBM) $(LIBPTHREAD), \
|
||||
LIBS_linux := $(LIBDL) $(X_LIBS) -lX11 -lXext, \
|
||||
LIBS_linux := $(X_LIBS) -lX11 -lXext, \
|
||||
LIBS_macosx := \
|
||||
-framework ApplicationServices \
|
||||
-framework Cocoa \
|
||||
|
||||
@@ -43,8 +43,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBINSTRUMENT, \
|
||||
JDK_LIBS := java.base:libjava java.base:libjli java.base:libjvm, \
|
||||
LIBS := $(ICONV_LIBS), \
|
||||
LIBS_unix := $(LIBZ_LIBS), \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
LIBS_aix := $(LIBDL), \
|
||||
LIBS_macosx := \
|
||||
-framework ApplicationServices \
|
||||
-framework Cocoa \
|
||||
|
||||
@@ -41,7 +41,7 @@ ifeq ($(call isTargetOs, linux), true)
|
||||
java.base:libnio \
|
||||
java.base:libnio/ch, \
|
||||
JDK_LIBS := java.base:libjava java.base:libnet, \
|
||||
LIBS_linux := $(LIBDL) $(LIBPTHREAD), \
|
||||
LIBS_linux := $(LIBDL), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBSCTP)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. 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.
|
||||
#
|
||||
|
||||
# Parse the first contiguous comment block in this script and generate
|
||||
# a java comment block. If this script is invoked with a copyright
|
||||
# year/year range, the java comment block will contain a Sun copyright.
|
||||
|
||||
COPYRIGHT_YEARS="$1"
|
||||
|
||||
cat <<__END__
|
||||
/*
|
||||
__END__
|
||||
|
||||
if [ "x$COPYRIGHT_YEARS" != x ]; then
|
||||
cat <<__END__
|
||||
* Copyright (c) $COPYRIGHT_YEARS Oracle and/or its affiliates. All rights reserved.
|
||||
__END__
|
||||
fi
|
||||
|
||||
$AWK ' /^#.*Copyright.*Oracle/ { next }
|
||||
/^#([^!]|$)/ { sub(/^#/, " *"); print }
|
||||
/^$/ { print " */"; exit } ' $0
|
||||
@@ -1,116 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 2000, 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.
|
||||
#
|
||||
|
||||
# Generate exception classes
|
||||
|
||||
SPEC=$1
|
||||
DST=$2
|
||||
|
||||
gen() {
|
||||
ID=$1
|
||||
WHAT=$2
|
||||
SVUID=$3
|
||||
ARG_TYPE=$4
|
||||
ARG_ID=$5
|
||||
ARG_PROP=$6
|
||||
ARG_PHRASE=$7
|
||||
ARG_PARAM="$ARG_TYPE$ $ARG_ID"
|
||||
echo '-->' $DST/$ID.java
|
||||
out=$DST/${ID}.java
|
||||
|
||||
$SH ${SCRIPTS}/addNotices.sh "$COPYRIGHT_YEARS" > $out
|
||||
|
||||
cat >>$out <<__END__
|
||||
|
||||
// -- This file was mechanically generated: Do not edit! -- //
|
||||
|
||||
package $PACKAGE;
|
||||
|
||||
|
||||
/**$WHAT
|
||||
*
|
||||
* @since $SINCE
|
||||
*/
|
||||
|
||||
public `if [ ${ABSTRACT:-0} = 1 ];
|
||||
then echo 'abstract '; fi`class $ID
|
||||
extends ${SUPER}
|
||||
{
|
||||
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = $SVUID;
|
||||
__END__
|
||||
|
||||
if [ $ARG_ID ]; then
|
||||
|
||||
cat >>$out <<__END__
|
||||
|
||||
/**
|
||||
* The $ARG_PHRASE.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
private $ARG_TYPE $ARG_ID;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*
|
||||
* @param $ARG_ID
|
||||
* The $ARG_PHRASE
|
||||
*/
|
||||
public $ID($ARG_TYPE $ARG_ID) {
|
||||
super(String.valueOf($ARG_ID));
|
||||
this.$ARG_ID = $ARG_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the $ARG_PHRASE.
|
||||
*
|
||||
* @return The $ARG_PHRASE
|
||||
*/
|
||||
public $ARG_TYPE get$ARG_PROP() {
|
||||
return $ARG_ID;
|
||||
}
|
||||
|
||||
}
|
||||
__END__
|
||||
|
||||
else
|
||||
|
||||
cat >>$out <<__END__
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*/
|
||||
public $ID() { }
|
||||
|
||||
}
|
||||
__END__
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
. $SPEC
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
GREP=grep
|
||||
|
||||
#
|
||||
EXP="Note: Some input files use or override a deprecated API."
|
||||
EXP="${EXP}|Note: Recompile with -Xlint:deprecation for details."
|
||||
EXP="${EXP}|Note: Some input files use unchecked or unsafe operations."
|
||||
EXP="${EXP}|Note: Recompile with -Xlint:unchecked for details."
|
||||
EXP="${EXP}| warning"
|
||||
EXP="${EXP}|uses or overrides a deprecated API."
|
||||
EXP="${EXP}|uses unchecked or unsafe operations."
|
||||
#
|
||||
${GREP} --line-buffered -v -E "${EXP}"
|
||||
@@ -216,11 +216,6 @@ source %{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_ExpandV:
|
||||
if (UseSVE < 2 || is_subword_type(bt)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_VectorMaskToLong:
|
||||
if (UseSVE > 0 && vlen > 64) {
|
||||
return false;
|
||||
@@ -7113,10 +7108,39 @@ instruct vcompressS(vReg dst, vReg src, pReg pg,
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
|
||||
instruct vexpand_neon(vReg dst, vReg src, vReg mask, vReg tmp1, vReg tmp2) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (ExpandV src mask));
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2);
|
||||
format %{ "vexpand_neon $dst, $src, $mask\t# KILL $tmp1, $tmp2" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
int length_in_bytes = (int) Matcher::vector_length_in_bytes(this);
|
||||
__ vector_expand_neon($dst$$FloatRegister, $src$$FloatRegister, $mask$$FloatRegister,
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, bt, length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand_sve(vReg dst, vReg src, pRegGov pg, vReg tmp1, vReg tmp2) %{
|
||||
predicate(UseSVE == 1 || (UseSVE == 2 && type2aelembytes(Matcher::vector_element_basic_type(n)) < 4));
|
||||
match(Set dst (ExpandV src pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2);
|
||||
format %{ "vexpand_sve $dst, $src, $pg\t# KILL $tmp1, $tmp2" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
int length_in_bytes = (int) Matcher::vector_length_in_bytes(this);
|
||||
__ vector_expand_sve($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, bt, length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand_sve2_SD(vReg dst, vReg src, pRegGov pg) %{
|
||||
predicate(UseSVE == 2 && type2aelembytes(Matcher::vector_element_basic_type(n)) >= 4);
|
||||
match(Set dst (ExpandV src pg));
|
||||
effect(TEMP_DEF dst);
|
||||
format %{ "vexpand $dst, $pg, $src" %}
|
||||
format %{ "vexpand_sve2_SD $dst, $src, $pg" %}
|
||||
ins_encode %{
|
||||
// Example input: src = 1 2 3 4 5 6 7 8
|
||||
// pg = 1 0 0 1 1 0 1 1
|
||||
@@ -7127,7 +7151,6 @@ instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
|
||||
// for TBL whose value is used to select the indexed element from src vector.
|
||||
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
assert(UseSVE == 2 && !is_subword_type(bt), "unsupported");
|
||||
Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
|
||||
// dst = 0 0 0 0 0 0 0 0
|
||||
__ sve_dup($dst$$FloatRegister, size, 0);
|
||||
|
||||
@@ -206,11 +206,6 @@ source %{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_ExpandV:
|
||||
if (UseSVE < 2 || is_subword_type(bt)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_VectorMaskToLong:
|
||||
if (UseSVE > 0 && vlen > 64) {
|
||||
return false;
|
||||
@@ -5101,10 +5096,39 @@ instruct vcompressS(vReg dst, vReg src, pReg pg,
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
|
||||
instruct vexpand_neon(vReg dst, vReg src, vReg mask, vReg tmp1, vReg tmp2) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (ExpandV src mask));
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2);
|
||||
format %{ "vexpand_neon $dst, $src, $mask\t# KILL $tmp1, $tmp2" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
int length_in_bytes = (int) Matcher::vector_length_in_bytes(this);
|
||||
__ vector_expand_neon($dst$$FloatRegister, $src$$FloatRegister, $mask$$FloatRegister,
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, bt, length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand_sve(vReg dst, vReg src, pRegGov pg, vReg tmp1, vReg tmp2) %{
|
||||
predicate(UseSVE == 1 || (UseSVE == 2 && type2aelembytes(Matcher::vector_element_basic_type(n)) < 4));
|
||||
match(Set dst (ExpandV src pg));
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2);
|
||||
format %{ "vexpand_sve $dst, $src, $pg\t# KILL $tmp1, $tmp2" %}
|
||||
ins_encode %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
int length_in_bytes = (int) Matcher::vector_length_in_bytes(this);
|
||||
__ vector_expand_sve($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, bt, length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct vexpand_sve2_SD(vReg dst, vReg src, pRegGov pg) %{
|
||||
predicate(UseSVE == 2 && type2aelembytes(Matcher::vector_element_basic_type(n)) >= 4);
|
||||
match(Set dst (ExpandV src pg));
|
||||
effect(TEMP_DEF dst);
|
||||
format %{ "vexpand $dst, $pg, $src" %}
|
||||
format %{ "vexpand_sve2_SD $dst, $src, $pg" %}
|
||||
ins_encode %{
|
||||
// Example input: src = 1 2 3 4 5 6 7 8
|
||||
// pg = 1 0 0 1 1 0 1 1
|
||||
@@ -5115,7 +5139,6 @@ instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
|
||||
// for TBL whose value is used to select the indexed element from src vector.
|
||||
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
assert(UseSVE == 2 && !is_subword_type(bt), "unsupported");
|
||||
Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
|
||||
// dst = 0 0 0 0 0 0 0 0
|
||||
__ sve_dup($dst$$FloatRegister, size, 0);
|
||||
|
||||
@@ -4068,6 +4068,13 @@ public:
|
||||
INSN(sve_brkb, 0b10); // Break before first true condition
|
||||
#undef INSN
|
||||
|
||||
// SVE move prefix (unpredicated)
|
||||
void sve_movprfx(FloatRegister Zd, FloatRegister Zn) {
|
||||
starti;
|
||||
f(0b00000100, 31, 24), f(0b00, 23, 22), f(0b1, 21), f(0b00000, 20, 16);
|
||||
f(0b101111, 15, 10), rf(Zn, 5), rf(Zd, 0);
|
||||
}
|
||||
|
||||
// Element count and increment scalar (SVE)
|
||||
#define INSN(NAME, TYPE) \
|
||||
void NAME(Register Xdn, unsigned imm4 = 1, int pattern = 0b11111) { \
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef CPU_AARCH64_ASSEMBLER_AARCH64_INLINE_HPP
|
||||
#define CPU_AARCH64_ASSEMBLER_AARCH64_INLINE_HPP
|
||||
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "asm/assembler.hpp"
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
|
||||
|
||||
@@ -216,10 +216,10 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
|
||||
|
||||
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
|
||||
__ bind(_entry);
|
||||
if (_compute_lock) {
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
}
|
||||
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
|
||||
ce->store_parameter(_lock_reg->as_register(), 0);
|
||||
// note: non-blocking leaf routine => no call info needed
|
||||
StubId exit_id;
|
||||
|
||||
@@ -409,7 +409,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
||||
MonitorExitStub* stub = nullptr;
|
||||
if (method()->is_synchronized()) {
|
||||
monitor_address(0, FrameMap::r0_opr);
|
||||
stub = new MonitorExitStub(FrameMap::r0_opr, true, 0);
|
||||
stub = new MonitorExitStub(FrameMap::r0_opr, 0);
|
||||
__ unlock_object(r5, r4, r0, r6, *stub->entry());
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
@@ -2481,7 +2481,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
Register lock = op->lock_opr()->as_register();
|
||||
Register temp = op->scratch_opr()->as_register();
|
||||
if (op->code() == lir_lock) {
|
||||
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
|
||||
int null_check_offset = __ lock_object(hdr, obj, lock, temp, *op->stub()->entry());
|
||||
if (op->info() != nullptr) {
|
||||
@@ -2489,7 +2488,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
}
|
||||
// done
|
||||
} else if (op->code() == lir_unlock) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
__ unlock_object(hdr, obj, lock, temp, *op->stub()->entry());
|
||||
} else {
|
||||
Unimplemented();
|
||||
@@ -2585,11 +2583,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));
|
||||
}
|
||||
|
||||
@@ -59,28 +59,28 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
|
||||
}
|
||||
}
|
||||
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, disp_hdr, temp, rscratch2);
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register basic_lock, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, basic_lock, temp, rscratch2);
|
||||
int null_check_offset = -1;
|
||||
|
||||
verify_oop(obj);
|
||||
|
||||
// save object being locked into the BasicObjectLock
|
||||
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
str(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
lightweight_lock(disp_hdr, obj, hdr, temp, rscratch2, slow_case);
|
||||
lightweight_lock(basic_lock, obj, hdr, temp, rscratch2, slow_case);
|
||||
|
||||
return null_check_offset;
|
||||
}
|
||||
|
||||
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, disp_hdr, temp, rscratch2);
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register basic_lock, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, basic_lock, temp, rscratch2);
|
||||
|
||||
// load object
|
||||
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
ldr(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
verify_oop(obj);
|
||||
|
||||
lightweight_unlock(obj, hdr, temp, rscratch2, slow_case);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -55,19 +55,19 @@ using MacroAssembler::null_check;
|
||||
Register result);
|
||||
|
||||
// locking
|
||||
// hdr : must be r0, contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// disp_hdr: must point to the displaced header location, contents preserved
|
||||
// temp : temporary register, must not be rscratch1 or rscratch2
|
||||
// hdr : must be r0, contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// basic_lock: must point to the basic lock, contents preserved
|
||||
// temp : temporary register, must not be rscratch1 or rscratch2
|
||||
// returns code offset at which to add null check debug information
|
||||
int lock_object (Register swap, Register obj, Register disp_hdr, Register temp, Label& slow_case);
|
||||
int lock_object (Register swap, Register obj, Register basic_lock, Register temp, Label& slow_case);
|
||||
|
||||
// unlocking
|
||||
// hdr : contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// disp_hdr: must be r0 & must point to the displaced header location, contents destroyed
|
||||
// temp : temporary register, must not be rscratch1 or rscratch2
|
||||
void unlock_object(Register swap, Register obj, Register lock, Register temp, Label& slow_case);
|
||||
// hdr : contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// basic_lock: must be r0 & must point to the basic lock, contents destroyed
|
||||
// temp : temporary register, must not be rscratch1 or rscratch2
|
||||
void unlock_object(Register swap, Register obj, Register basic_lock, Register temp, Label& slow_case);
|
||||
|
||||
void initialize_object(
|
||||
Register obj, // result: pointer to object after successful allocation
|
||||
|
||||
@@ -2771,3 +2771,90 @@ void C2_MacroAssembler::select_from_two_vectors(FloatRegister dst, FloatRegister
|
||||
select_from_two_vectors_neon(dst, src1, src2, dst, tmp, vector_length_in_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Vector expand implementation. Elements from the src vector are expanded into
|
||||
// the dst vector under the control of the vector mask.
|
||||
// Since there are no native instructions directly corresponding to expand before
|
||||
// SVE2p2, the following implementations mainly leverages the TBL instruction to
|
||||
// implement expand. To compute the index input for TBL, the prefix sum algorithm
|
||||
// (https://en.wikipedia.org/wiki/Prefix_sum) is used. The same algorithm is used
|
||||
// for NEON and SVE, but with different instructions where appropriate.
|
||||
|
||||
// Vector expand implementation for NEON.
|
||||
//
|
||||
// An example of 128-bit Byte vector:
|
||||
// Data direction: high <== low
|
||||
// Input:
|
||||
// src = g f e d c b a 9 8 7 6 5 4 3 2 1
|
||||
// mask = 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1
|
||||
// Expected result:
|
||||
// dst = 0 0 8 7 0 0 6 5 0 0 4 3 0 0 2 1
|
||||
void C2_MacroAssembler::vector_expand_neon(FloatRegister dst, FloatRegister src, FloatRegister mask,
|
||||
FloatRegister tmp1, FloatRegister tmp2, BasicType bt,
|
||||
int vector_length_in_bytes) {
|
||||
assert(vector_length_in_bytes <= 16, "the vector length in bytes for NEON must be <= 16");
|
||||
assert_different_registers(dst, src, mask, tmp1, tmp2);
|
||||
// Since the TBL instruction only supports byte table, we need to
|
||||
// compute indices in byte type for all types.
|
||||
SIMD_Arrangement size = vector_length_in_bytes == 16 ? T16B : T8B;
|
||||
// tmp1 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
dup(tmp1, size, zr);
|
||||
// dst = 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
|
||||
negr(dst, size, mask);
|
||||
// Calculate vector index for TBL with prefix sum algorithm.
|
||||
// dst = 8 8 8 7 6 6 6 5 4 4 4 3 2 2 2 1
|
||||
for (int i = 1; i < vector_length_in_bytes; i <<= 1) {
|
||||
ext(tmp2, size, tmp1, dst, vector_length_in_bytes - i);
|
||||
addv(dst, size, tmp2, dst);
|
||||
}
|
||||
// tmp2 = 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1
|
||||
orr(tmp2, size, mask, mask);
|
||||
// tmp2 = 0 0 8 7 0 0 6 5 0 0 4 3 0 0 2 1
|
||||
bsl(tmp2, size, dst, tmp1);
|
||||
// tmp1 = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||
movi(tmp1, size, 1);
|
||||
// dst = -1 -1 7 6 -1 -1 5 4 -1 -1 3 2 -1 -1 1 0
|
||||
subv(dst, size, tmp2, tmp1);
|
||||
// dst = 0 0 8 7 0 0 6 5 0 0 4 3 0 0 2 1
|
||||
tbl(dst, size, src, 1, dst);
|
||||
}
|
||||
|
||||
// Vector expand implementation for SVE.
|
||||
//
|
||||
// An example of 128-bit Short vector:
|
||||
// Data direction: high <== low
|
||||
// Input:
|
||||
// src = gf ed cb a9 87 65 43 21
|
||||
// pg = 00 01 00 01 00 01 00 01
|
||||
// Expected result:
|
||||
// dst = 00 87 00 65 00 43 00 21
|
||||
void C2_MacroAssembler::vector_expand_sve(FloatRegister dst, FloatRegister src, PRegister pg,
|
||||
FloatRegister tmp1, FloatRegister tmp2, BasicType bt,
|
||||
int vector_length_in_bytes) {
|
||||
assert(UseSVE > 0, "expand implementation only for SVE");
|
||||
assert_different_registers(dst, src, tmp1, tmp2);
|
||||
SIMD_RegVariant size = elemType_to_regVariant(bt);
|
||||
|
||||
// tmp1 = 00 00 00 00 00 00 00 00
|
||||
sve_dup(tmp1, size, 0);
|
||||
sve_movprfx(tmp2, tmp1);
|
||||
// tmp2 = 00 01 00 01 00 01 00 01
|
||||
sve_cpy(tmp2, size, pg, 1, true);
|
||||
// Calculate vector index for TBL with prefix sum algorithm.
|
||||
// tmp2 = 04 04 03 03 02 02 01 01
|
||||
for (int i = type2aelembytes(bt); i < vector_length_in_bytes; i <<= 1) {
|
||||
sve_movprfx(dst, tmp1);
|
||||
// The EXT instruction operates on the full-width sve register. The correct
|
||||
// index calculation method is:
|
||||
// vector_length_in_bytes - i + MaxVectorSize - vector_length_in_bytes =>
|
||||
// MaxVectorSize - i.
|
||||
sve_ext(dst, tmp2, MaxVectorSize - i);
|
||||
sve_add(tmp2, size, dst, tmp2);
|
||||
}
|
||||
// dst = 00 04 00 03 00 02 00 01
|
||||
sve_sel(dst, size, pg, tmp2, tmp1);
|
||||
// dst = -1 03 -1 02 -1 01 -1 00
|
||||
sve_sub(dst, size, 1);
|
||||
// dst = 00 87 00 65 00 43 00 21
|
||||
sve_tbl(dst, size, src, dst);
|
||||
}
|
||||
@@ -204,4 +204,10 @@
|
||||
FloatRegister index, FloatRegister tmp, BasicType bt,
|
||||
unsigned vector_length_in_bytes);
|
||||
|
||||
void vector_expand_neon(FloatRegister dst, FloatRegister src, FloatRegister mask,
|
||||
FloatRegister tmp1, FloatRegister tmp2, BasicType bt,
|
||||
int vector_length_in_bytes);
|
||||
void vector_expand_sve(FloatRegister dst, FloatRegister src, PRegister pg,
|
||||
FloatRegister tmp1, FloatRegister tmp2, BasicType bt,
|
||||
int vector_length_in_bytes);
|
||||
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
||||
|
||||
@@ -86,15 +86,48 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm
|
||||
}
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register start, Register count, Register scratch, RegSet saved_regs) {
|
||||
__ push(saved_regs, sp);
|
||||
assert_different_registers(start, count, scratch);
|
||||
assert_different_registers(c_rarg0, count);
|
||||
__ mov(c_rarg0, start);
|
||||
__ mov(c_rarg1, count);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
|
||||
__ pop(saved_regs, sp);
|
||||
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm,
|
||||
DecoratorSet decorators,
|
||||
Register start,
|
||||
Register count,
|
||||
Register scratch,
|
||||
RegSet saved_regs) {
|
||||
|
||||
Label done;
|
||||
Label loop;
|
||||
Label next;
|
||||
|
||||
__ cbz(count, done);
|
||||
|
||||
// Calculate the number of card marks to set. Since the object might start and
|
||||
// end within a card, we need to calculate this via the card table indexes of
|
||||
// the actual start and last addresses covered by the object.
|
||||
// Temporarily use the count register for the last element address.
|
||||
__ lea(count, Address(start, count, Address::lsl(LogBytesPerHeapOop))); // end = start + count << LogBytesPerHeapOop
|
||||
__ sub(count, count, BytesPerHeapOop); // Use last element address for end.
|
||||
|
||||
__ lsr(start, start, CardTable::card_shift());
|
||||
__ lsr(count, count, CardTable::card_shift());
|
||||
__ sub(count, count, start); // Number of bytes to mark - 1.
|
||||
|
||||
// Add card table base offset to start.
|
||||
__ ldr(scratch, Address(rthread, in_bytes(G1ThreadLocalData::card_table_base_offset())));
|
||||
__ add(start, start, scratch);
|
||||
|
||||
__ bind(loop);
|
||||
if (UseCondCardMark) {
|
||||
__ ldrb(scratch, Address(start, count));
|
||||
// Instead of loading clean_card_val and comparing, we exploit the fact that
|
||||
// the LSB of non-clean cards is always 0, and the LSB of clean cards 1.
|
||||
__ tbz(scratch, 0, next);
|
||||
}
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use zr");
|
||||
__ strb(zr, Address(start, count));
|
||||
__ bind(next);
|
||||
__ subs(count, count, 1);
|
||||
__ br(Assembler::GE, loop);
|
||||
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
static void generate_queue_test_and_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime,
|
||||
@@ -199,13 +232,17 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
||||
|
||||
}
|
||||
|
||||
static void generate_post_barrier_fast_path(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
assert(thread == rthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg, rscratch1);
|
||||
|
||||
// Does store cross heap regions?
|
||||
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
@@ -214,33 +251,19 @@ static void generate_post_barrier_fast_path(MacroAssembler* masm,
|
||||
if (new_val_may_be_null) {
|
||||
__ cbz(new_val, done);
|
||||
}
|
||||
// Storing region crossing non-null, is card young?
|
||||
// Storing region crossing non-null.
|
||||
__ lsr(tmp1, store_addr, CardTable::card_shift()); // tmp1 := card address relative to card table base
|
||||
__ load_byte_map_base(tmp2); // tmp2 := card table base address
|
||||
__ add(tmp1, tmp1, tmp2); // tmp1 := card address
|
||||
__ ldrb(tmp2, Address(tmp1)); // tmp2 := card
|
||||
__ cmpw(tmp2, (int)G1CardTable::g1_young_card_val()); // tmp2 := card == young_card_val?
|
||||
}
|
||||
|
||||
static void generate_post_barrier_slow_path(MacroAssembler* masm,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
Label& runtime) {
|
||||
__ membar(Assembler::StoreLoad); // StoreLoad membar
|
||||
__ ldrb(tmp2, Address(tmp1)); // tmp2 := card
|
||||
__ cbzw(tmp2, done);
|
||||
// Storing a region crossing, non-null oop, card is clean.
|
||||
// Dirty card and log.
|
||||
STATIC_ASSERT(CardTable::dirty_card_val() == 0);
|
||||
__ strb(zr, Address(tmp1)); // *(card address) := dirty_card_val
|
||||
generate_queue_test_and_insertion(masm,
|
||||
G1ThreadLocalData::dirty_card_queue_index_offset(),
|
||||
G1ThreadLocalData::dirty_card_queue_buffer_offset(),
|
||||
runtime,
|
||||
thread, tmp1, tmp2, rscratch1);
|
||||
__ b(done);
|
||||
Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
|
||||
__ ldr(tmp2, card_table_addr); // tmp2 := card table base address
|
||||
if (UseCondCardMark) {
|
||||
__ ldrb(rscratch1, Address(tmp1, tmp2)); // rscratch1 := card
|
||||
// Instead of loading clean_card_val and comparing, we exploit the fact that
|
||||
// the LSB of non-clean cards is always 0, and the LSB of clean cards 1.
|
||||
__ tbz(rscratch1, 0, done);
|
||||
}
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use zr");
|
||||
__ strb(zr, Address(tmp1, tmp2)); // *(card address) := dirty_card_val
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
|
||||
@@ -249,27 +272,8 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
assert(thread == rthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2,
|
||||
rscratch1);
|
||||
assert(store_addr != noreg && new_val != noreg && tmp1 != noreg
|
||||
&& tmp2 != noreg, "expecting a register");
|
||||
|
||||
Label done;
|
||||
Label runtime;
|
||||
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
// If card is young, jump to done
|
||||
__ br(Assembler::EQ, done);
|
||||
generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, done, runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
// save the live input values
|
||||
RegSet saved = RegSet::of(store_addr);
|
||||
__ push(saved, sp);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp1, thread);
|
||||
__ pop(saved, sp);
|
||||
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, false /* new_val_may_be_null */);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
@@ -329,38 +333,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* stub) {
|
||||
assert(thread == rthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2,
|
||||
rscratch1);
|
||||
assert(store_addr != noreg && new_val != noreg && tmp1 != noreg
|
||||
&& tmp2 != noreg, "expecting a register");
|
||||
|
||||
stub->initialize_registers(thread, tmp1, tmp2);
|
||||
|
||||
bool new_val_may_be_null = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0;
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, *stub->continuation(), new_val_may_be_null);
|
||||
// If card is not young, jump to stub (slow path)
|
||||
__ br(Assembler::NE, *stub->entry());
|
||||
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
Label runtime;
|
||||
Register thread = stub->thread();
|
||||
Register tmp1 = stub->tmp1(); // tmp1 holds the card address.
|
||||
Register tmp2 = stub->tmp2();
|
||||
assert(stub->tmp3() == noreg, "not needed in this platform");
|
||||
|
||||
__ bind(*stub->entry());
|
||||
generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, *stub->continuation(), runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
generate_c2_barrier_runtime_call(masm, stub, tmp1, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry));
|
||||
__ b(*stub->continuation());
|
||||
bool new_val_may_be_null) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, new_val_may_be_null);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
@@ -456,20 +432,19 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
|
||||
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
|
||||
__ bind(*stub->entry());
|
||||
assert(stub->addr()->is_register(), "Precondition.");
|
||||
assert(stub->new_val()->is_register(), "Precondition.");
|
||||
Register new_val_reg = stub->new_val()->as_register();
|
||||
__ cbz(new_val_reg, *stub->continuation());
|
||||
ce->store_parameter(stub->addr()->as_pointer_register(), 0);
|
||||
__ far_call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin()));
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
masm->bind(done);
|
||||
}
|
||||
|
||||
#define __ sasm->
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
@@ -521,74 +496,6 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler*
|
||||
__ epilogue();
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
__ prologue("g1_post_barrier", false);
|
||||
|
||||
// arg0: store_address
|
||||
Address store_addr(rfp, 2*BytesPerWord);
|
||||
|
||||
BarrierSet* bs = BarrierSet::barrier_set();
|
||||
CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
|
||||
CardTable* ct = ctbs->card_table();
|
||||
|
||||
Label done;
|
||||
Label runtime;
|
||||
|
||||
// At this point we know new_value is non-null and the new_value crosses regions.
|
||||
// Must check to see if card is already dirty
|
||||
|
||||
const Register thread = rthread;
|
||||
|
||||
Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
|
||||
Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
|
||||
|
||||
const Register card_offset = rscratch2;
|
||||
// LR is free here, so we can use it to hold the byte_map_base.
|
||||
const Register byte_map_base = lr;
|
||||
|
||||
assert_different_registers(card_offset, byte_map_base, rscratch1);
|
||||
|
||||
__ load_parameter(0, card_offset);
|
||||
__ lsr(card_offset, card_offset, CardTable::card_shift());
|
||||
__ load_byte_map_base(byte_map_base);
|
||||
__ ldrb(rscratch1, Address(byte_map_base, card_offset));
|
||||
__ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val());
|
||||
__ br(Assembler::EQ, done);
|
||||
|
||||
assert((int)CardTable::dirty_card_val() == 0, "must be 0");
|
||||
|
||||
__ membar(Assembler::StoreLoad);
|
||||
__ ldrb(rscratch1, Address(byte_map_base, card_offset));
|
||||
__ cbzw(rscratch1, done);
|
||||
|
||||
// storing region crossing non-null, card is clean.
|
||||
// dirty card and log.
|
||||
__ strb(zr, Address(byte_map_base, card_offset));
|
||||
|
||||
// Convert card offset into an address in card_addr
|
||||
Register card_addr = card_offset;
|
||||
__ add(card_addr, byte_map_base, card_addr);
|
||||
|
||||
__ ldr(rscratch1, queue_index);
|
||||
__ cbz(rscratch1, runtime);
|
||||
__ sub(rscratch1, rscratch1, wordSize);
|
||||
__ str(rscratch1, queue_index);
|
||||
|
||||
// Reuse LR to hold buffer_addr
|
||||
const Register buffer_addr = lr;
|
||||
|
||||
__ ldr(buffer_addr, buffer);
|
||||
__ str(card_addr, Address(buffer_addr, rscratch1));
|
||||
__ b(done);
|
||||
|
||||
__ bind(runtime);
|
||||
__ push_call_clobbered_registers();
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
|
||||
__ pop_call_clobbered_registers();
|
||||
__ bind(done);
|
||||
__ epilogue();
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@@ -32,9 +32,7 @@
|
||||
class LIR_Assembler;
|
||||
class StubAssembler;
|
||||
class G1PreBarrierStub;
|
||||
class G1PostBarrierStub;
|
||||
class G1PreBarrierStubC2;
|
||||
class G1PostBarrierStubC2;
|
||||
|
||||
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
|
||||
protected:
|
||||
@@ -65,10 +63,15 @@ protected:
|
||||
public:
|
||||
#ifdef COMPILER1
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
|
||||
void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
|
||||
|
||||
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
|
||||
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
|
||||
|
||||
void g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2);
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER2
|
||||
@@ -87,9 +90,7 @@ public:
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* c2_stub);
|
||||
void generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const;
|
||||
bool new_val_may_be_null);
|
||||
#endif
|
||||
|
||||
void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2024, 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,13 +62,13 @@ static void write_barrier_post(MacroAssembler* masm,
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
if (!G1PostBarrierStubC2::needs_barrier(node)) {
|
||||
if (!G1BarrierStubC2::needs_post_barrier(node)) {
|
||||
return;
|
||||
}
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
|
||||
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, rthread, tmp1, tmp2, stub);
|
||||
bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, rthread, tmp1, tmp2, new_val_may_be_null);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -275,7 +275,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::increment_patching_epoch() {
|
||||
Atomic::inc(&_patching_epoch);
|
||||
AtomicAccess::inc(&_patching_epoch);
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::clear_patching_epoch() {
|
||||
@@ -398,14 +398,18 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register
|
||||
OptoReg::Name BarrierSetAssembler::encode_float_vector_register_size(const Node* node, OptoReg::Name opto_reg) {
|
||||
switch (node->ideal_reg()) {
|
||||
case Op_RegF:
|
||||
case Op_RegI: // RA may place scalar values (Op_RegI/N/L/P) in FP registers when UseFPUForSpilling is enabled
|
||||
case Op_RegN:
|
||||
// No need to refine. The original encoding is already fine to distinguish.
|
||||
assert(opto_reg % 4 == 0, "Float register should only occupy a single slot");
|
||||
assert(opto_reg % 4 == 0, "32-bit register should only occupy a single slot");
|
||||
break;
|
||||
// Use different encoding values of the same fp/vector register to help distinguish different sizes.
|
||||
// Such as V16. The OptoReg::name and its corresponding slot value are
|
||||
// "V16": 64, "V16_H": 65, "V16_J": 66, "V16_K": 67.
|
||||
case Op_RegD:
|
||||
case Op_VecD:
|
||||
case Op_RegL:
|
||||
case Op_RegP:
|
||||
opto_reg &= ~3;
|
||||
opto_reg |= 1;
|
||||
break;
|
||||
|
||||
@@ -112,22 +112,22 @@ public:
|
||||
}
|
||||
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = Atomic::load(guard_addr());
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
|
||||
@@ -275,7 +275,6 @@ public:
|
||||
Label* entry();
|
||||
};
|
||||
|
||||
|
||||
class ZStoreBarrierStubC2Aarch64 : public ZStoreBarrierStubC2 {
|
||||
private:
|
||||
bool _deferred_emit;
|
||||
|
||||
@@ -239,7 +239,6 @@ instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
|
||||
instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp oldval_tmp, iRegPNoSp newval_tmp, rFlagsReg cr) %{
|
||||
match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
|
||||
predicate(UseZGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
|
||||
|
||||
@@ -1623,7 +1623,7 @@ public:
|
||||
FloatRegister p, FloatRegister z, FloatRegister t1);
|
||||
void ghash_reduce_wide(int index, FloatRegister result, FloatRegister lo, FloatRegister hi,
|
||||
FloatRegister p, FloatRegister z, FloatRegister t1);
|
||||
void ghash_processBlocks_wide(address p, Register state, Register subkeyH,
|
||||
void ghash_processBlocks_wide(Label& p, Register state, Register subkeyH,
|
||||
Register data, Register blocks, int unrolls);
|
||||
|
||||
|
||||
|
||||
@@ -507,7 +507,7 @@ void MacroAssembler::ghash_modmul(FloatRegister result,
|
||||
//
|
||||
// Clobbers all vector registers.
|
||||
//
|
||||
void MacroAssembler::ghash_processBlocks_wide(address field_polynomial, Register state,
|
||||
void MacroAssembler::ghash_processBlocks_wide(Label& field_polynomial, Register state,
|
||||
Register subkeyH,
|
||||
Register data, Register blocks, int unrolls) {
|
||||
int register_stride = 7;
|
||||
@@ -531,7 +531,10 @@ void MacroAssembler::ghash_processBlocks_wide(address field_polynomial, Register
|
||||
FloatRegister p = v31;
|
||||
eor(vzr, T16B, vzr, vzr); // zero register
|
||||
|
||||
ldrq(p, field_polynomial); // The field polynomial
|
||||
// load polynomial via label which must identify local data in the
|
||||
// same code stub
|
||||
adr(rscratch1, field_polynomial);
|
||||
ldrq(p, rscratch1); // The field polynomial
|
||||
|
||||
ldrq(v0, Address(state));
|
||||
ldrq(Hprime, Address(subkeyH));
|
||||
|
||||
@@ -683,12 +683,12 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
int comp_args_on_stack,
|
||||
const BasicType *sig_bt,
|
||||
const VMRegPair *regs,
|
||||
AdapterHandlerEntry* handler) {
|
||||
address i2c_entry = __ pc();
|
||||
address entry_address[AdapterBlob::ENTRY_COUNT]) {
|
||||
entry_address[AdapterBlob::I2C] = __ pc();
|
||||
|
||||
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
|
||||
|
||||
address c2i_unverified_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
|
||||
Label skip_fixup;
|
||||
|
||||
Register data = rscratch2;
|
||||
@@ -718,10 +718,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
__ block_comment("} c2i_unverified_entry");
|
||||
}
|
||||
|
||||
address c2i_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I] = __ pc();
|
||||
|
||||
// Class initialization barrier for static methods
|
||||
address c2i_no_clinit_check_entry = nullptr;
|
||||
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
|
||||
if (VM_Version::supports_fast_class_init_checks()) {
|
||||
Label L_skip_barrier;
|
||||
|
||||
@@ -736,15 +736,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
__ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
|
||||
|
||||
__ bind(L_skip_barrier);
|
||||
c2i_no_clinit_check_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
|
||||
}
|
||||
|
||||
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs->c2i_entry_barrier(masm);
|
||||
|
||||
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
|
||||
|
||||
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1763,9 +1761,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
Label lock_done;
|
||||
|
||||
if (method->is_synchronized()) {
|
||||
Label count;
|
||||
const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
|
||||
|
||||
// Get the handle (the 2nd argument)
|
||||
__ mov(oop_handle_reg, c_rarg1);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "runtime/continuation.hpp"
|
||||
#include "runtime/continuationEntry.inline.hpp"
|
||||
#include "runtime/frame.inline.hpp"
|
||||
@@ -802,7 +802,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
//
|
||||
// s and d are adjusted to point to the remaining words to copy
|
||||
//
|
||||
void generate_copy_longs(StubId stub_id, DecoratorSet decorators, Label &start, Register s, Register d, Register count) {
|
||||
address generate_copy_longs(StubId stub_id, DecoratorSet decorators, Register s, Register d, Register count) {
|
||||
BasicType type;
|
||||
copy_direction direction;
|
||||
|
||||
@@ -854,7 +854,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
StubCodeMark mark(this, stub_id);
|
||||
|
||||
__ bind(start);
|
||||
address start = __ pc();
|
||||
|
||||
Label unaligned_copy_long;
|
||||
if (AvoidUnalignedAccesses) {
|
||||
@@ -894,9 +894,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
int prefetch = PrefetchCopyIntervalInBytes;
|
||||
bool use_stride = false;
|
||||
if (direction == copy_backwards) {
|
||||
use_stride = prefetch > 256;
|
||||
prefetch = -prefetch;
|
||||
if (use_stride) __ mov(stride, prefetch);
|
||||
use_stride = prefetch > 256;
|
||||
prefetch = -prefetch;
|
||||
if (use_stride) __ mov(stride, prefetch);
|
||||
}
|
||||
|
||||
__ bind(again);
|
||||
@@ -1026,9 +1026,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
int prefetch = PrefetchCopyIntervalInBytes;
|
||||
bool use_stride = false;
|
||||
if (direction == copy_backwards) {
|
||||
use_stride = prefetch > 256;
|
||||
prefetch = -prefetch;
|
||||
if (use_stride) __ mov(stride, prefetch);
|
||||
use_stride = prefetch > 256;
|
||||
prefetch = -prefetch;
|
||||
if (use_stride) __ mov(stride, prefetch);
|
||||
}
|
||||
|
||||
__ bind(again);
|
||||
@@ -1037,15 +1037,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ prfm(use_stride ? Address(s, stride) : Address(s, prefetch), PLDL1KEEP);
|
||||
|
||||
if (direction == copy_forwards) {
|
||||
// allowing for the offset of -8 the store instructions place
|
||||
// registers into the target 64 bit block at the following
|
||||
// offsets
|
||||
//
|
||||
// t0 at offset 0
|
||||
// t1 at offset 8, t2 at offset 16
|
||||
// t3 at offset 24, t4 at offset 32
|
||||
// t5 at offset 40, t6 at offset 48
|
||||
// t7 at offset 56
|
||||
// allowing for the offset of -8 the store instructions place
|
||||
// registers into the target 64 bit block at the following
|
||||
// offsets
|
||||
//
|
||||
// t0 at offset 0
|
||||
// t1 at offset 8, t2 at offset 16
|
||||
// t3 at offset 24, t4 at offset 32
|
||||
// t5 at offset 40, t6 at offset 48
|
||||
// t7 at offset 56
|
||||
|
||||
bs.copy_store_at_8(Address(d, 1 * unit), t0);
|
||||
bs.copy_store_at_16(Address(d, 2 * unit), t1, t2);
|
||||
@@ -1057,18 +1057,18 @@ class StubGenerator: public StubCodeGenerator {
|
||||
bs.copy_store_at_8(Address(__ pre(d, 8 * unit)), t7);
|
||||
bs.copy_load_at_16(t6, t7, Address(__ pre(s, 8 * unit)));
|
||||
} else {
|
||||
// d was not offset when we started so the registers are
|
||||
// written into the 64 bit block preceding d with the following
|
||||
// offsets
|
||||
//
|
||||
// t1 at offset -8
|
||||
// t3 at offset -24, t0 at offset -16
|
||||
// t5 at offset -48, t2 at offset -32
|
||||
// t7 at offset -56, t4 at offset -48
|
||||
// t6 at offset -64
|
||||
//
|
||||
// note that this matches the offsets previously noted for the
|
||||
// loads
|
||||
// d was not offset when we started so the registers are
|
||||
// written into the 64 bit block preceding d with the following
|
||||
// offsets
|
||||
//
|
||||
// t1 at offset -8
|
||||
// t3 at offset -24, t0 at offset -16
|
||||
// t5 at offset -48, t2 at offset -32
|
||||
// t7 at offset -56, t4 at offset -48
|
||||
// t6 at offset -64
|
||||
//
|
||||
// note that this matches the offsets previously noted for the
|
||||
// loads
|
||||
|
||||
bs.copy_store_at_8(Address(d, 1 * unit), t1);
|
||||
bs.copy_store_at_16(Address(d, 3 * unit), t3, t0);
|
||||
@@ -1109,10 +1109,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
{
|
||||
Label L1, L2;
|
||||
__ tbz(count, exact_log2(4), L1);
|
||||
// this is the same as above but copying only 4 longs hence
|
||||
// with only one intervening stp between the str instructions
|
||||
// but note that the offsets and registers still follow the
|
||||
// same pattern
|
||||
// this is the same as above but copying only 4 longs hence
|
||||
// with only one intervening stp between the str instructions
|
||||
// but note that the offsets and registers still follow the
|
||||
// same pattern
|
||||
bs.copy_load_at_16(t0, t1, Address(s, 2 * unit));
|
||||
bs.copy_load_at_16(t2, t3, Address(__ pre(s, 4 * unit)));
|
||||
if (direction == copy_forwards) {
|
||||
@@ -1127,10 +1127,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bind(L1);
|
||||
|
||||
__ tbz(count, 1, L2);
|
||||
// this is the same as above but copying only 2 longs hence
|
||||
// there is no intervening stp between the str instructions
|
||||
// but note that the offset and register patterns are still
|
||||
// the same
|
||||
// this is the same as above but copying only 2 longs hence
|
||||
// there is no intervening stp between the str instructions
|
||||
// but note that the offset and register patterns are still
|
||||
// the same
|
||||
bs.copy_load_at_16(t0, t1, Address(__ pre(s, 2 * unit)));
|
||||
if (direction == copy_forwards) {
|
||||
bs.copy_store_at_8(Address(d, 1 * unit), t0);
|
||||
@@ -1141,18 +1141,20 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
__ bind(L2);
|
||||
|
||||
// for forwards copy we need to re-adjust the offsets we
|
||||
// applied so that s and d are follow the last words written
|
||||
// for forwards copy we need to re-adjust the offsets we
|
||||
// applied so that s and d are follow the last words written
|
||||
|
||||
if (direction == copy_forwards) {
|
||||
__ add(s, s, 16);
|
||||
__ add(d, d, 8);
|
||||
}
|
||||
if (direction == copy_forwards) {
|
||||
__ add(s, s, 16);
|
||||
__ add(d, d, 8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__ ret(lr);
|
||||
}
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
// Small copy: less than 16 bytes.
|
||||
@@ -1206,10 +1208,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
Label copy_f, copy_b;
|
||||
Label copy_obj_f, copy_obj_b;
|
||||
Label copy_obj_uninit_f, copy_obj_uninit_b;
|
||||
|
||||
// All-singing all-dancing memory copy.
|
||||
//
|
||||
// Copy count units of memory from s to d. The size of a unit is
|
||||
@@ -1447,19 +1445,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
if (direction == copy_forwards) {
|
||||
if (type != T_OBJECT) {
|
||||
__ bl(copy_f);
|
||||
__ bl(StubRoutines::aarch64::copy_byte_f());
|
||||
} else if ((decorators & IS_DEST_UNINITIALIZED) != 0) {
|
||||
__ bl(copy_obj_uninit_f);
|
||||
__ bl(StubRoutines::aarch64::copy_oop_uninit_f());
|
||||
} else {
|
||||
__ bl(copy_obj_f);
|
||||
__ bl(StubRoutines::aarch64::copy_oop_f());
|
||||
}
|
||||
} else {
|
||||
if (type != T_OBJECT) {
|
||||
__ bl(copy_b);
|
||||
__ bl(StubRoutines::aarch64::copy_byte_b());
|
||||
} else if ((decorators & IS_DEST_UNINITIALIZED) != 0) {
|
||||
__ bl(copy_obj_uninit_b);
|
||||
__ bl(StubRoutines::aarch64::copy_oop_uninit_b());
|
||||
} else {
|
||||
__ bl(copy_obj_b);
|
||||
__ bl(StubRoutines::aarch64::copy_oop_b());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1522,11 +1520,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// the hardware handle it. The two dwords within qwords that span
|
||||
// cache line boundaries will still be loaded and stored atomically.
|
||||
//
|
||||
// Side Effects: entry is set to the (post push) entry point so it
|
||||
// can be used by the corresponding conjoint copy
|
||||
// method
|
||||
// Side Effects: nopush_entry is set to the (post push) entry point
|
||||
// so it can be used by the corresponding conjoint
|
||||
// copy method
|
||||
//
|
||||
address generate_disjoint_copy(StubId stub_id, address *entry) {
|
||||
address generate_disjoint_copy(StubId stub_id, address *nopush_entry) {
|
||||
Register s = c_rarg0, d = c_rarg1, count = c_rarg2;
|
||||
RegSet saved_reg = RegSet::of(s, d, count);
|
||||
int size;
|
||||
@@ -1615,8 +1613,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address start = __ pc();
|
||||
__ enter();
|
||||
|
||||
if (entry != nullptr) {
|
||||
*entry = __ pc();
|
||||
if (nopush_entry != nullptr) {
|
||||
*nopush_entry = __ pc();
|
||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||
BLOCK_COMMENT("Entry:");
|
||||
}
|
||||
@@ -1679,10 +1677,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// cache line boundaries will still be loaded and stored atomically.
|
||||
//
|
||||
// Side Effects:
|
||||
// entry is set to the no-overlap entry point so it can be used by
|
||||
// some other conjoint copy method
|
||||
// nopush_entry is set to the no-overlap entry point so it can be
|
||||
// used by some other conjoint copy method
|
||||
//
|
||||
address generate_conjoint_copy(StubId stub_id, address nooverlap_target, address *entry) {
|
||||
address generate_conjoint_copy(StubId stub_id, address nooverlap_target, address *nopush_entry) {
|
||||
Register s = c_rarg0, d = c_rarg1, count = c_rarg2;
|
||||
RegSet saved_regs = RegSet::of(s, d, count);
|
||||
int size;
|
||||
@@ -1769,16 +1767,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address start = __ pc();
|
||||
__ enter();
|
||||
|
||||
if (entry != nullptr) {
|
||||
*entry = __ pc();
|
||||
if (nopush_entry != nullptr) {
|
||||
*nopush_entry = __ pc();
|
||||
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
|
||||
BLOCK_COMMENT("Entry:");
|
||||
}
|
||||
|
||||
// use fwd copy when (d-s) above_equal (count*size)
|
||||
Label L_overlapping;
|
||||
__ sub(rscratch1, d, s);
|
||||
__ cmp(rscratch1, count, Assembler::LSL, exact_log2(size));
|
||||
__ br(Assembler::HS, nooverlap_target);
|
||||
__ br(Assembler::LO, L_overlapping);
|
||||
__ b(RuntimeAddress(nooverlap_target));
|
||||
__ bind(L_overlapping);
|
||||
|
||||
DecoratorSet decorators = IN_HEAP | IS_ARRAY;
|
||||
if (dest_uninitialized) {
|
||||
@@ -1850,7 +1851,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// r0 == 0 - success
|
||||
// r0 == -1^K - failure, where K is partial transfer count
|
||||
//
|
||||
address generate_checkcast_copy(StubId stub_id, address *entry) {
|
||||
address generate_checkcast_copy(StubId stub_id, address *nopush_entry) {
|
||||
bool dest_uninitialized;
|
||||
switch (stub_id) {
|
||||
case StubId::stubgen_checkcast_arraycopy_id:
|
||||
@@ -1911,8 +1912,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#endif //ASSERT
|
||||
|
||||
// Caller of this entry point must set up the argument registers.
|
||||
if (entry != nullptr) {
|
||||
*entry = __ pc();
|
||||
if (nopush_entry != nullptr) {
|
||||
*nopush_entry = __ pc();
|
||||
BLOCK_COMMENT("Entry:");
|
||||
}
|
||||
|
||||
@@ -2724,13 +2725,21 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
void generate_arraycopy_stubs() {
|
||||
address entry;
|
||||
address entry_jbyte_arraycopy;
|
||||
address entry_jshort_arraycopy;
|
||||
address entry_jint_arraycopy;
|
||||
address entry_oop_arraycopy;
|
||||
address entry_jlong_arraycopy;
|
||||
address entry_checkcast_arraycopy;
|
||||
// Some copy stubs publish a normal entry and then a 2nd 'fallback'
|
||||
// entry immediately following their stack push. This can be used
|
||||
// as a post-push branch target for compatible stubs when they
|
||||
// identify a special case that can be handled by the fallback
|
||||
// stub e.g a disjoint copy stub may be use as a special case
|
||||
// fallback for its compatible conjoint copy stub.
|
||||
//
|
||||
// A no push entry is always returned in the following local and
|
||||
// then published by assigning to the appropriate entry field in
|
||||
// class StubRoutines. The entry value is then passed to the
|
||||
// generator for the compatible stub. That means the entry must be
|
||||
// listed when saving to/restoring from the AOT cache, ensuring
|
||||
// that the inter-stub jumps are noted at AOT-cache save and
|
||||
// relocated at AOT cache load.
|
||||
address nopush_entry;
|
||||
|
||||
// generate the common exit first so later stubs can rely on it if
|
||||
// they want an UnsafeMemoryAccess exit non-local to the stub
|
||||
@@ -2738,83 +2747,123 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// register the stub as the default exit with class UnsafeMemoryAccess
|
||||
UnsafeMemoryAccess::set_common_exit_stub_pc(StubRoutines::_unsafecopy_common_exit);
|
||||
|
||||
generate_copy_longs(StubId::stubgen_copy_byte_f_id, IN_HEAP | IS_ARRAY, copy_f, r0, r1, r15);
|
||||
generate_copy_longs(StubId::stubgen_copy_byte_b_id, IN_HEAP | IS_ARRAY, copy_b, r0, r1, r15);
|
||||
// generate and publish arch64-specific bulk copy routines first
|
||||
// so we can call them from other copy stubs
|
||||
StubRoutines::aarch64::_copy_byte_f = generate_copy_longs(StubId::stubgen_copy_byte_f_id, IN_HEAP | IS_ARRAY, r0, r1, r15);
|
||||
StubRoutines::aarch64::_copy_byte_b = generate_copy_longs(StubId::stubgen_copy_byte_b_id, IN_HEAP | IS_ARRAY, r0, r1, r15);
|
||||
|
||||
generate_copy_longs(StubId::stubgen_copy_oop_f_id, IN_HEAP | IS_ARRAY, copy_obj_f, r0, r1, r15);
|
||||
generate_copy_longs(StubId::stubgen_copy_oop_b_id, IN_HEAP | IS_ARRAY, copy_obj_b, r0, r1, r15);
|
||||
StubRoutines::aarch64::_copy_oop_f = generate_copy_longs(StubId::stubgen_copy_oop_f_id, IN_HEAP | IS_ARRAY, r0, r1, r15);
|
||||
StubRoutines::aarch64::_copy_oop_b = generate_copy_longs(StubId::stubgen_copy_oop_b_id, IN_HEAP | IS_ARRAY, r0, r1, r15);
|
||||
|
||||
generate_copy_longs(StubId::stubgen_copy_oop_uninit_f_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_f, r0, r1, r15);
|
||||
generate_copy_longs(StubId::stubgen_copy_oop_uninit_b_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, copy_obj_uninit_b, r0, r1, r15);
|
||||
StubRoutines::aarch64::_copy_oop_uninit_f = generate_copy_longs(StubId::stubgen_copy_oop_uninit_f_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, r0, r1, r15);
|
||||
StubRoutines::aarch64::_copy_oop_uninit_b = generate_copy_longs(StubId::stubgen_copy_oop_uninit_b_id, IN_HEAP | IS_ARRAY | IS_DEST_UNINITIALIZED, r0, r1, r15);
|
||||
|
||||
StubRoutines::aarch64::_zero_blocks = generate_zero_blocks();
|
||||
|
||||
//*** jbyte
|
||||
// Always need aligned and unaligned versions
|
||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_jbyte_arraycopy_id, entry, &entry_jbyte_arraycopy);
|
||||
StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id, entry, nullptr);
|
||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint nopush entry is needed by conjoint copy
|
||||
StubRoutines::_jbyte_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_jbyte_arraycopy_id, StubRoutines::_jbyte_disjoint_arraycopy_nopush, &nopush_entry);
|
||||
// conjoint nopush entry is needed by generic/unsafe copy
|
||||
StubRoutines::_jbyte_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jbyte_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint arrayof nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_jbyte_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jbyte_arraycopy_id, StubRoutines::_arrayof_jbyte_disjoint_arraycopy_nopush, nullptr);
|
||||
|
||||
//*** jshort
|
||||
// Always need aligned and unaligned versions
|
||||
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jshort_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_jshort_arraycopy_id, entry, &entry_jshort_arraycopy);
|
||||
StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jshort_arraycopy_id, entry, nullptr);
|
||||
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jshort_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint nopush entry is needed by conjoint copy
|
||||
StubRoutines::_jshort_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_jshort_arraycopy_id, StubRoutines::_jshort_disjoint_arraycopy_nopush, &nopush_entry);
|
||||
// conjoint nopush entry is used by generic/unsafe copy
|
||||
StubRoutines::_jshort_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jshort_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint arrayof nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_jshort_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jshort_arraycopy_id, StubRoutines::_arrayof_jshort_disjoint_arraycopy_nopush, nullptr);
|
||||
|
||||
//*** jint
|
||||
// Aligned versions
|
||||
StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jint_arraycopy_id, entry, &entry_jint_arraycopy);
|
||||
StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jint_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint arrayof nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_jint_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jint_arraycopy_id, StubRoutines::_arrayof_jint_disjoint_arraycopy_nopush, nullptr);
|
||||
// In 64 bit we need both aligned and unaligned versions of jint arraycopy.
|
||||
// entry_jint_arraycopy always points to the unaligned version
|
||||
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jint_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_jint_arraycopy_id, entry, &entry_jint_arraycopy);
|
||||
// jint_arraycopy_nopush always points to the unaligned version
|
||||
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_jint_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint nopush entry is needed by conjoint copy
|
||||
StubRoutines::_jint_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_jint_arraycopy = generate_conjoint_copy(StubId::stubgen_jint_arraycopy_id, StubRoutines::_jint_disjoint_arraycopy_nopush, &nopush_entry);
|
||||
// conjoint nopush entry is needed by generic/unsafe copy
|
||||
StubRoutines::_jint_arraycopy_nopush = nopush_entry;
|
||||
|
||||
//*** jlong
|
||||
// It is always aligned
|
||||
StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id, &entry);
|
||||
StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jlong_arraycopy_id, entry, &entry_jlong_arraycopy);
|
||||
StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint arrayof nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_jlong_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_copy(StubId::stubgen_arrayof_jlong_arraycopy_id, StubRoutines::_arrayof_jlong_disjoint_arraycopy_nopush, &nopush_entry);
|
||||
// conjoint nopush entry is needed by generic/unsafe copy
|
||||
StubRoutines::_jlong_arraycopy_nopush = nopush_entry;
|
||||
// disjoint normal/nopush and conjoint normal entries are not
|
||||
// generated since the arrayof versions are the same
|
||||
StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy;
|
||||
StubRoutines::_jlong_disjoint_arraycopy_nopush = StubRoutines::_arrayof_jlong_disjoint_arraycopy_nopush;
|
||||
StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy;
|
||||
|
||||
//*** oops
|
||||
{
|
||||
// With compressed oops we need unaligned versions; notice that
|
||||
// we overwrite entry_oop_arraycopy.
|
||||
bool aligned = !UseCompressedOops;
|
||||
|
||||
StubRoutines::_arrayof_oop_disjoint_arraycopy
|
||||
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id, &entry);
|
||||
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id, &nopush_entry);
|
||||
// disjoint arrayof nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_oop_disjoint_arraycopy_nopush = nopush_entry;
|
||||
StubRoutines::_arrayof_oop_arraycopy
|
||||
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy);
|
||||
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_id, StubRoutines::_arrayof_oop_disjoint_arraycopy_nopush, &nopush_entry);
|
||||
// conjoint arrayof nopush entry is needed by generic/unsafe copy
|
||||
StubRoutines::_oop_arraycopy_nopush = nopush_entry;
|
||||
// Aligned versions without pre-barriers
|
||||
StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit
|
||||
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id, &entry);
|
||||
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id, &nopush_entry);
|
||||
// disjoint arrayof+uninit nopush entry is needed by conjoint copy
|
||||
StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit_nopush = nopush_entry;
|
||||
// note that we don't need a returned nopush entry because the
|
||||
// generic/unsafe copy does not cater for uninit arrays.
|
||||
StubRoutines::_arrayof_oop_arraycopy_uninit
|
||||
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, entry, nullptr);
|
||||
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit_nopush, nullptr);
|
||||
}
|
||||
|
||||
// for oop copies reuse arrayof entries for non-arrayof cases
|
||||
StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy;
|
||||
StubRoutines::_oop_disjoint_arraycopy_nopush = StubRoutines::_arrayof_oop_disjoint_arraycopy_nopush;
|
||||
StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy;
|
||||
StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit;
|
||||
StubRoutines::_oop_disjoint_arraycopy_uninit_nopush = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit_nopush;
|
||||
StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit;
|
||||
|
||||
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &entry_checkcast_arraycopy);
|
||||
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &nopush_entry);
|
||||
// checkcast nopush entry is needed by generic copy
|
||||
StubRoutines::_checkcast_arraycopy_nopush = nopush_entry;
|
||||
// note that we don't need a returned nopush entry because the
|
||||
// generic copy does not cater for uninit arrays.
|
||||
StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id, nullptr);
|
||||
|
||||
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(entry_jbyte_arraycopy,
|
||||
entry_jshort_arraycopy,
|
||||
entry_jint_arraycopy,
|
||||
entry_jlong_arraycopy);
|
||||
// unsafe arraycopy may fallback on conjoint stubs
|
||||
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy(StubRoutines::_jbyte_arraycopy_nopush,
|
||||
StubRoutines::_jshort_arraycopy_nopush,
|
||||
StubRoutines::_jint_arraycopy_nopush,
|
||||
StubRoutines::_jlong_arraycopy_nopush);
|
||||
|
||||
StubRoutines::_generic_arraycopy = generate_generic_copy(entry_jbyte_arraycopy,
|
||||
entry_jshort_arraycopy,
|
||||
entry_jint_arraycopy,
|
||||
entry_oop_arraycopy,
|
||||
entry_jlong_arraycopy,
|
||||
entry_checkcast_arraycopy);
|
||||
// generic arraycopy may fallback on conjoint stubs
|
||||
StubRoutines::_generic_arraycopy = generate_generic_copy(StubRoutines::_jbyte_arraycopy_nopush,
|
||||
StubRoutines::_jshort_arraycopy_nopush,
|
||||
StubRoutines::_jint_arraycopy_nopush,
|
||||
StubRoutines::_oop_arraycopy_nopush,
|
||||
StubRoutines::_jlong_arraycopy_nopush,
|
||||
StubRoutines::_checkcast_arraycopy_nopush);
|
||||
|
||||
StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id);
|
||||
StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id);
|
||||
@@ -3402,14 +3451,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// counter = c_rarg7 - 16 bytes of CTR
|
||||
// return - number of processed bytes
|
||||
address generate_galoisCounterMode_AESCrypt() {
|
||||
address ghash_polynomial = __ pc();
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
Label ghash_polynomial; // local data generated after code
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
__ align(CodeEntryAlignment);
|
||||
StubId stub_id = StubId::stubgen_galoisCounterMode_AESCrypt_id;
|
||||
StubCodeMark mark(this, stub_id);
|
||||
address start = __ pc();
|
||||
@@ -3514,7 +3558,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(lr);
|
||||
return start;
|
||||
|
||||
// bind label and generate polynomial data
|
||||
__ align(wordSize * 2);
|
||||
__ bind(ghash_polynomial);
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
class Cached64Bytes {
|
||||
@@ -4559,16 +4613,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// by the second lane from all vectors and so on.
|
||||
address generate_chacha20Block_blockpar() {
|
||||
Label L_twoRounds, L_cc20_const;
|
||||
// The constant data is broken into two 128-bit segments to be loaded
|
||||
// onto FloatRegisters. The first 128 bits are a counter add overlay
|
||||
// that adds +0/+1/+2/+3 to the vector holding replicated state[12].
|
||||
// The second 128-bits is a table constant used for 8-bit left rotations.
|
||||
__ BIND(L_cc20_const);
|
||||
__ emit_int64(0x0000000100000000UL);
|
||||
__ emit_int64(0x0000000300000002UL);
|
||||
__ emit_int64(0x0605040702010003UL);
|
||||
__ emit_int64(0x0E0D0C0F0A09080BUL);
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
StubId stub_id = StubId::stubgen_chacha20Block_id;
|
||||
StubCodeMark mark(this, stub_id);
|
||||
@@ -4716,6 +4760,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave();
|
||||
__ ret(lr);
|
||||
|
||||
// bind label and generate local constant data used by this stub
|
||||
// The constant data is broken into two 128-bit segments to be loaded
|
||||
// onto FloatRegisters. The first 128 bits are a counter add overlay
|
||||
// that adds +0/+1/+2/+3 to the vector holding replicated state[12].
|
||||
// The second 128-bits is a table constant used for 8-bit left rotations.
|
||||
__ BIND(L_cc20_const);
|
||||
__ emit_int64(0x0000000100000000UL);
|
||||
__ emit_int64(0x0000000300000002UL);
|
||||
__ emit_int64(0x0605040702010003UL);
|
||||
__ emit_int64(0x0E0D0C0F0A09080BUL);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@@ -6036,10 +6091,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address generate_kyber12To16() {
|
||||
Label L_F00, L_loop, L_end;
|
||||
|
||||
__ BIND(L_F00);
|
||||
__ emit_int64(0x0f000f000f000f00);
|
||||
__ emit_int64(0x0f000f000f000f00);
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
StubId stub_id = StubId::stubgen_kyber12To16_id;
|
||||
StubCodeMark mark(this, stub_id);
|
||||
@@ -6233,6 +6284,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ mov(r0, zr); // return 0
|
||||
__ ret(lr);
|
||||
|
||||
// bind label and generate constant data used by this stub
|
||||
__ BIND(L_F00);
|
||||
__ emit_int64(0x0f000f000f000f00);
|
||||
__ emit_int64(0x0f000f000f000f00);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@@ -9642,14 +9698,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
StubId stub_id = StubId::stubgen_ghash_processBlocks_id;
|
||||
StubCodeMark mark(this, stub_id);
|
||||
__ align(wordSize * 2);
|
||||
address p = __ pc();
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
|
||||
Label polynomial; // local data generated at end of stub
|
||||
__ align(CodeEntryAlignment);
|
||||
address start = __ pc();
|
||||
|
||||
@@ -9661,7 +9710,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
FloatRegister vzr = v30;
|
||||
__ eor(vzr, __ T16B, vzr, vzr); // zero register
|
||||
|
||||
__ ldrq(v24, p); // The field polynomial
|
||||
__ adr(rscratch1, polynomial);
|
||||
__ ldrq(v24, rscratch1); // The field polynomial
|
||||
|
||||
__ ldrq(v0, Address(state));
|
||||
__ ldrq(v1, Address(subkeyH));
|
||||
@@ -9701,6 +9751,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ st1(v0, __ T16B, state);
|
||||
__ ret(lr);
|
||||
|
||||
// bind label and generate local polynomial data
|
||||
__ align(wordSize * 2);
|
||||
__ bind(polynomial);
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@@ -9709,14 +9768,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
StubId stub_id = StubId::stubgen_ghash_processBlocks_wide_id;
|
||||
StubCodeMark mark(this, stub_id);
|
||||
__ align(wordSize * 2);
|
||||
address p = __ pc();
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
|
||||
Label polynomial; // local data generated after stub
|
||||
__ align(CodeEntryAlignment);
|
||||
address start = __ pc();
|
||||
|
||||
@@ -9738,7 +9790,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ st1(v8, v9, v10, v11, __ T16B, Address(sp));
|
||||
}
|
||||
|
||||
__ ghash_processBlocks_wide(p, state, subkeyH, data, blocks, unroll);
|
||||
__ ghash_processBlocks_wide(polynomial, state, subkeyH, data, blocks, unroll);
|
||||
|
||||
if (unroll > 1) {
|
||||
// And restore state
|
||||
@@ -9751,7 +9803,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
__ ret(lr);
|
||||
|
||||
// bind label and generate polynomial data
|
||||
__ align(wordSize * 2);
|
||||
__ bind(polynomial);
|
||||
__ emit_int64(0x87); // The low-order bits of the field
|
||||
// polynomial (i.e. p = z^7+z^2+z+1)
|
||||
// repeated in the low and high parts of a
|
||||
// 128-bit vector
|
||||
__ emit_int64(0x87);
|
||||
|
||||
return start;
|
||||
|
||||
}
|
||||
|
||||
void generate_base64_encode_simdround(Register src, Register dst,
|
||||
@@ -10265,7 +10327,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
#if defined (LINUX) && !defined (__ARM_FEATURE_ATOMICS)
|
||||
|
||||
// ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX.
|
||||
// ARMv8.1 LSE versions of the atomic stubs used by AtomicAccess::PlatformXX.
|
||||
//
|
||||
// If LSE is in use, generate LSE versions of all the stubs. The
|
||||
// non-LSE versions are in atomic_aarch64.S.
|
||||
|
||||
@@ -3281,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;
|
||||
@@ -3323,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);
|
||||
%}
|
||||
@@ -3373,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;
|
||||
@@ -9053,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);
|
||||
|
||||
@@ -200,9 +200,10 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
|
||||
|
||||
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
|
||||
__ bind(_entry);
|
||||
if (_compute_lock) {
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
}
|
||||
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
|
||||
const Register lock_reg = _lock_reg->as_pointer_register();
|
||||
|
||||
ce->verify_reserved_argument_area_size(1);
|
||||
|
||||
@@ -245,7 +245,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
||||
MonitorExitStub* stub = nullptr;
|
||||
if (method()->is_synchronized()) {
|
||||
monitor_address(0, FrameMap::R0_opr);
|
||||
stub = new MonitorExitStub(FrameMap::R0_opr, true, 0);
|
||||
stub = new MonitorExitStub(FrameMap::R0_opr, 0);
|
||||
__ unlock_object(R2, R1, R0, *stub->entry());
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
@@ -2427,7 +2427,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
Register lock = op->lock_opr()->as_pointer_register();
|
||||
|
||||
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) {
|
||||
add_debug_info_for_null_check(null_check_offset, op->info());
|
||||
@@ -2552,11 +2551,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());
|
||||
|
||||
@@ -176,17 +176,17 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len,
|
||||
initialize_object(obj, tmp1, klass, len, tmp2, tmp3, header_size_in_bytes, -1, /* is_tlab_allocated */ UseTLAB);
|
||||
}
|
||||
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case) {
|
||||
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_different_registers(hdr, obj, basic_lock, tmp2);
|
||||
|
||||
assert(BasicObjectLock::lock_offset() == 0, "adjust this code");
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
// save object being locked into the BasicObjectLock
|
||||
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
str(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
@@ -197,26 +197,26 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
|
||||
b(slow_case, ne);
|
||||
}
|
||||
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
Register t1 = basic_lock; // 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);
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, basic_lock, Rtemp);
|
||||
|
||||
assert(BasicObjectLock::lock_offset() == 0, "adjust this code");
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
ldr(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
|
||||
Register t1 = disp_hdr; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
Register t1 = basic_lock; // Needs saving, probably
|
||||
Register t2 = hdr; // blow
|
||||
Register t3 = Rtemp; // blow
|
||||
|
||||
lightweight_unlock(obj, t1, t2, t3, 1 /* savemask - save t1 */, slow_case);
|
||||
// Success: fall through
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -59,9 +59,9 @@
|
||||
max_array_allocation_length = 0x01000000
|
||||
};
|
||||
|
||||
int lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case);
|
||||
int lock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case);
|
||||
|
||||
void unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case);
|
||||
void unlock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case);
|
||||
|
||||
// This platform only uses signal-based null checks. The Label is not needed.
|
||||
void null_check(Register r, Label *Lnull = nullptr) { MacroAssembler::null_check(r); }
|
||||
|
||||
@@ -198,15 +198,18 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
static void generate_post_barrier_fast_path(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
// Does store cross heap regions?
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
assert(thread == Rthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg);
|
||||
|
||||
// Does store cross heap regions?
|
||||
__ eor(tmp1, store_addr, new_val);
|
||||
__ movs(tmp1, AsmOperand(tmp1, lsr, G1HeapRegion::LogOfHRGrainBytes));
|
||||
__ b(done, eq);
|
||||
@@ -215,76 +218,34 @@ static void generate_post_barrier_fast_path(MacroAssembler* masm,
|
||||
if (new_val_may_be_null) {
|
||||
__ cbz(new_val, done);
|
||||
}
|
||||
// storing region crossing non-null, is card already dirty?
|
||||
const Register card_addr = tmp1;
|
||||
|
||||
CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
|
||||
__ mov_address(tmp2, (address)ct->card_table()->byte_map_base());
|
||||
__ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift()));
|
||||
// storing region crossing non-null, is card already non-clean?
|
||||
Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
|
||||
__ ldr(tmp2, card_table_addr);
|
||||
__ add(tmp1, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift()));
|
||||
|
||||
__ ldrb(tmp2, Address(card_addr));
|
||||
__ cmp(tmp2, (int)G1CardTable::g1_young_card_val());
|
||||
if (UseCondCardMark) {
|
||||
__ ldrb(tmp2, Address(tmp1));
|
||||
// Instead of loading clean_card_val and comparing, we exploit the fact that
|
||||
// the LSB of non-clean cards is always 0, and the LSB of clean cards 1.
|
||||
__ tbz(tmp2, 0, done);
|
||||
}
|
||||
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use zero_register()");
|
||||
__ zero_register(tmp2);
|
||||
__ strb(tmp2, Address(tmp1)); // *(card address) := dirty_card_val
|
||||
}
|
||||
|
||||
static void generate_post_barrier_slow_path(MacroAssembler* masm,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
const Register tmp3,
|
||||
Label& done,
|
||||
Label& runtime) {
|
||||
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp2);
|
||||
assert(CardTable::dirty_card_val() == 0, "adjust this code");
|
||||
// card_addr is loaded by generate_post_barrier_fast_path
|
||||
const Register card_addr = tmp1;
|
||||
__ ldrb(tmp2, Address(card_addr));
|
||||
__ cbz(tmp2, done);
|
||||
|
||||
// storing a region crossing, non-null oop, card is clean.
|
||||
// dirty card and log.
|
||||
|
||||
__ strb(__ zero_register(tmp2), Address(card_addr));
|
||||
generate_queue_test_and_insertion(masm,
|
||||
G1ThreadLocalData::dirty_card_queue_index_offset(),
|
||||
G1ThreadLocalData::dirty_card_queue_buffer_offset(),
|
||||
runtime,
|
||||
thread, card_addr, tmp2, tmp3);
|
||||
__ b(done);
|
||||
}
|
||||
|
||||
|
||||
// G1 post-barrier.
|
||||
// Blows all volatile registers R0-R3, LR).
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
Register tmp3) {
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
Register tmp3) {
|
||||
Label done;
|
||||
Label runtime;
|
||||
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
// If card is young, jump to done
|
||||
// card_addr and card are loaded by generate_post_barrier_fast_path
|
||||
const Register card = tmp2;
|
||||
const Register card_addr = tmp1;
|
||||
__ b(done, eq);
|
||||
generate_post_barrier_slow_path(masm, Rthread, card_addr, tmp2, tmp3, done, runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
|
||||
RegisterSet set = RegisterSet(store_addr) | RegisterSet(R0, R3) | RegisterSet(R12);
|
||||
__ push(set);
|
||||
|
||||
if (card_addr != R0) {
|
||||
__ mov(R0, card_addr);
|
||||
}
|
||||
__ mov(R1, Rthread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), R0, R1);
|
||||
|
||||
__ pop(set);
|
||||
|
||||
generate_post_barrier(masm, store_addr, new_val, Rthread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
@@ -344,35 +305,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
Register tmp3,
|
||||
G1PostBarrierStubC2* stub) {
|
||||
assert(thread == Rthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg);
|
||||
|
||||
stub->initialize_registers(thread, tmp1, tmp2, tmp3);
|
||||
|
||||
bool new_val_may_be_null = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0;
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, *stub->continuation(), new_val_may_be_null);
|
||||
// If card is not young, jump to stub (slow path)
|
||||
__ b(*stub->entry(), ne);
|
||||
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
Label runtime;
|
||||
Register thread = stub->thread();
|
||||
Register tmp1 = stub->tmp1(); // tmp1 holds the card address.
|
||||
Register tmp2 = stub->tmp2();
|
||||
Register tmp3 = stub->tmp3();
|
||||
|
||||
__ bind(*stub->entry());
|
||||
generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, tmp3, *stub->continuation(), runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
generate_c2_barrier_runtime_call(masm, stub, tmp1, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp2);
|
||||
__ b(*stub->continuation());
|
||||
bool new_val_may_be_null) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, new_val_may_be_null);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
@@ -463,20 +399,19 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
|
||||
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
|
||||
__ bind(*stub->entry());
|
||||
assert(stub->addr()->is_register(), "Precondition.");
|
||||
assert(stub->new_val()->is_register(), "Precondition.");
|
||||
Register new_val_reg = stub->new_val()->as_register();
|
||||
__ cbz(new_val_reg, *stub->continuation());
|
||||
ce->verify_reserved_argument_area_size(1);
|
||||
__ str(stub->addr()->as_pointer_register(), Address(SP));
|
||||
__ call(bs->post_barrier_c1_runtime_code_blob()->code_begin(), relocInfo::runtime_call_type);
|
||||
__ b(*stub->continuation());
|
||||
#undef __
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
masm->bind(done);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ sasm->
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
@@ -536,102 +471,6 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler*
|
||||
__ b(done);
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
// Input:
|
||||
// - store_addr, pushed on the stack
|
||||
|
||||
__ set_info("g1_post_barrier_slow_id", false);
|
||||
|
||||
Label done;
|
||||
Label recheck;
|
||||
Label runtime;
|
||||
|
||||
Address queue_index(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
|
||||
Address buffer(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
|
||||
|
||||
AddressLiteral cardtable(ci_card_table_address_as<address>(), relocInfo::none);
|
||||
|
||||
// save at least the registers that need saving if the runtime is called
|
||||
const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
|
||||
const int nb_saved_regs = 6;
|
||||
assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
|
||||
__ push(saved_regs);
|
||||
|
||||
const Register r_card_addr_0 = R0; // must be R0 for the slow case
|
||||
const Register r_obj_0 = R0;
|
||||
const Register r_card_base_1 = R1;
|
||||
const Register r_tmp2 = R2;
|
||||
const Register r_index_2 = R2;
|
||||
const Register r_buffer_3 = R3;
|
||||
const Register tmp1 = Rtemp;
|
||||
|
||||
__ ldr(r_obj_0, Address(SP, nb_saved_regs*wordSize));
|
||||
// Note: there is a comment in x86 code about not using
|
||||
// ExternalAddress / lea, due to relocation not working
|
||||
// properly for that address. Should be OK for arm, where we
|
||||
// explicitly specify that 'cardtable' has a relocInfo::none
|
||||
// type.
|
||||
__ lea(r_card_base_1, cardtable);
|
||||
__ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift()));
|
||||
|
||||
// first quick check without barrier
|
||||
__ ldrb(r_tmp2, Address(r_card_addr_0));
|
||||
|
||||
__ cmp(r_tmp2, (int)G1CardTable::g1_young_card_val());
|
||||
__ b(recheck, ne);
|
||||
|
||||
__ bind(done);
|
||||
|
||||
__ pop(saved_regs);
|
||||
|
||||
__ ret();
|
||||
|
||||
__ bind(recheck);
|
||||
|
||||
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp1);
|
||||
|
||||
// reload card state after the barrier that ensures the stored oop was visible
|
||||
__ ldrb(r_tmp2, Address(r_card_addr_0));
|
||||
|
||||
assert(CardTable::dirty_card_val() == 0, "adjust this code");
|
||||
__ cbz(r_tmp2, done);
|
||||
|
||||
// storing region crossing non-null, card is clean.
|
||||
// dirty card and log.
|
||||
|
||||
assert(0 == (int)CardTable::dirty_card_val(), "adjust this code");
|
||||
if ((ci_card_table_address_as<intptr_t>() & 0xff) == 0) {
|
||||
// Card table is aligned so the lowest byte of the table address base is zero.
|
||||
__ strb(r_card_base_1, Address(r_card_addr_0));
|
||||
} else {
|
||||
__ strb(__ zero_register(r_tmp2), Address(r_card_addr_0));
|
||||
}
|
||||
|
||||
__ ldr(r_index_2, queue_index);
|
||||
__ ldr(r_buffer_3, buffer);
|
||||
|
||||
__ subs(r_index_2, r_index_2, wordSize);
|
||||
__ b(runtime, lt); // go to runtime if now negative
|
||||
|
||||
__ str(r_index_2, queue_index);
|
||||
|
||||
__ str(r_card_addr_0, Address(r_buffer_3, r_index_2));
|
||||
|
||||
__ b(done);
|
||||
|
||||
__ bind(runtime);
|
||||
|
||||
__ save_live_registers();
|
||||
|
||||
assert(r_card_addr_0 == c_rarg0, "card_addr should be in R0");
|
||||
__ mov(c_rarg1, Rthread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), c_rarg0, c_rarg1);
|
||||
|
||||
__ restore_live_registers_without_return();
|
||||
|
||||
__ b(done);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@@ -32,9 +32,7 @@
|
||||
class LIR_Assembler;
|
||||
class StubAssembler;
|
||||
class G1PreBarrierStub;
|
||||
class G1PostBarrierStub;
|
||||
class G1PreBarrierStubC2;
|
||||
class G1PostBarrierStubC2;
|
||||
|
||||
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
|
||||
protected:
|
||||
@@ -66,10 +64,15 @@ public:
|
||||
#ifdef COMPILER1
|
||||
public:
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
|
||||
void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
|
||||
|
||||
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
|
||||
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
|
||||
|
||||
void g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2);
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER2
|
||||
@@ -89,9 +92,7 @@ public:
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
Register tmp3,
|
||||
G1PostBarrierStubC2* c2_stub);
|
||||
void generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const;
|
||||
bool new_val_may_be_null);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2024, 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
|
||||
@@ -63,13 +63,13 @@ static void write_barrier_post(MacroAssembler* masm,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
Register tmp3) {
|
||||
if (!G1PostBarrierStubC2::needs_barrier(node)) {
|
||||
if (!G1BarrierStubC2::needs_post_barrier(node)) {
|
||||
return;
|
||||
}
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
|
||||
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, Rthread, tmp1, tmp2, tmp3, stub);
|
||||
bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, Rthread, tmp1, tmp2, tmp3, new_val_may_be_null);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -48,22 +48,22 @@ class NativeNMethodBarrier: public NativeInstruction {
|
||||
|
||||
public:
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = Atomic::load(guard_addr());
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
|
||||
@@ -617,11 +617,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
int comp_args_on_stack,
|
||||
const BasicType *sig_bt,
|
||||
const VMRegPair *regs,
|
||||
AdapterHandlerEntry* handler) {
|
||||
address i2c_entry = __ pc();
|
||||
address entry_address[AdapterBlob::ENTRY_COUNT]) {
|
||||
entry_address[AdapterBlob::I2C] = __ pc();
|
||||
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
|
||||
|
||||
address c2i_unverified_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
|
||||
Label skip_fixup;
|
||||
const Register receiver = R0;
|
||||
const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure
|
||||
@@ -634,10 +634,9 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
__ b(skip_fixup, eq);
|
||||
__ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
|
||||
|
||||
address c2i_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I] = __ pc();
|
||||
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
|
||||
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
|
||||
|
||||
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1129,7 +1128,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
const Register sync_handle = R5;
|
||||
const Register sync_obj = R6;
|
||||
const Register disp_hdr = altFP_7_11;
|
||||
const Register basic_lock = altFP_7_11;
|
||||
const Register tmp = R8;
|
||||
|
||||
Label slow_lock, lock_done, fast_lock;
|
||||
@@ -1140,7 +1139,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
__ mov(sync_handle, R1);
|
||||
|
||||
log_trace(fastlock)("SharedRuntime lock fast");
|
||||
__ lightweight_lock(sync_obj /* object */, disp_hdr /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
__ lightweight_lock(sync_obj /* object */, basic_lock /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
|
||||
0x7 /* savemask */, slow_lock);
|
||||
// Fall through to lock_done
|
||||
__ bind(lock_done);
|
||||
@@ -1255,7 +1254,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
// last_Java_frame is already set, so do call_VM manually; no exception can occur
|
||||
__ mov(R0, sync_obj);
|
||||
__ mov(R1, disp_hdr);
|
||||
__ mov(R1, basic_lock);
|
||||
__ mov(R2, Rthread);
|
||||
__ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C));
|
||||
|
||||
@@ -1270,12 +1269,12 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
// Clear pending exception before reentering VM.
|
||||
// Can store the oop in register since it is a leaf call.
|
||||
assert_different_registers(Rtmp_save1, sync_obj, disp_hdr);
|
||||
assert_different_registers(Rtmp_save1, sync_obj, basic_lock);
|
||||
__ ldr(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
|
||||
Register zero = __ zero_register(Rtemp);
|
||||
__ str(zero, Address(Rthread, Thread::pending_exception_offset()));
|
||||
__ mov(R0, sync_obj);
|
||||
__ mov(R1, disp_hdr);
|
||||
__ mov(R1, basic_lock);
|
||||
__ mov(R2, Rthread);
|
||||
__ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C));
|
||||
__ str(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
|
||||
|
||||
@@ -421,7 +421,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
|
||||
// As per atomic.hpp the Atomic read-modify-write operations must be logically implemented as:
|
||||
// As per atomicAccess.hpp the atomic read-modify-write operations must be
|
||||
// logically implemented as:
|
||||
// <fence>; <op>; <membar StoreLoad|StoreStore>
|
||||
// But for load-linked/store-conditional based systems a fence here simply means
|
||||
// no load/store can be reordered with respect to the initial load-linked, so we have:
|
||||
@@ -440,7 +441,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// be removed in the future.
|
||||
|
||||
// Implementation of atomic_add(jint add_value, volatile jint* dest)
|
||||
// used by Atomic::add(volatile jint* dest, jint add_value)
|
||||
// used by AtomicAccess::add(volatile jint* dest, jint add_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@@ -492,7 +493,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Implementation of jint atomic_xchg(jint exchange_value, volatile jint* dest)
|
||||
// used by Atomic::add(volatile jint* dest, jint exchange_value)
|
||||
// used by AtomicAccess::add(volatile jint* dest, jint exchange_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@@ -542,7 +543,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Implementation of jint atomic_cmpxchg(jint exchange_value, volatile jint *dest, jint compare_value)
|
||||
// used by Atomic::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
|
||||
// used by AtomicAccess::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
|
||||
//
|
||||
// Arguments :
|
||||
//
|
||||
@@ -582,7 +583,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// Support for jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
|
||||
// Support for jlong AtomicAccess::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
|
||||
// reordered before by a wrapper to (jlong compare_value, jlong exchange_value, volatile jlong *dest)
|
||||
//
|
||||
// Arguments :
|
||||
@@ -3010,6 +3011,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// Note: the disjoint stubs must be generated first, some of
|
||||
// the conjoint stubs use them.
|
||||
|
||||
// Note: chaining of stubs does not rely on branching to an
|
||||
// auxiliary post-push entry because none of the stubs
|
||||
// push/pop a frame.
|
||||
|
||||
// these need always status in case they are called from generic_arraycopy
|
||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id);
|
||||
StubRoutines::_jshort_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_jshort_disjoint_arraycopy_id);
|
||||
@@ -3023,6 +3028,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_primitive_copy(StubId::stubgen_arrayof_jlong_disjoint_arraycopy_id);
|
||||
StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_oop_copy (StubId::stubgen_arrayof_oop_disjoint_arraycopy_id);
|
||||
|
||||
// disjoint copy entry is needed by conjoint copy
|
||||
// these need always status in case they are called from generic_arraycopy
|
||||
StubRoutines::_jbyte_arraycopy = generate_primitive_copy(StubId::stubgen_jbyte_arraycopy_id, StubRoutines::_jbyte_disjoint_arraycopy);
|
||||
StubRoutines::_jshort_arraycopy = generate_primitive_copy(StubId::stubgen_jshort_arraycopy_id, StubRoutines::_jshort_disjoint_arraycopy);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
|
||||
#define CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
|
||||
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "asm/assembler.hpp"
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
@@ -268,9 +268,10 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
|
||||
|
||||
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
|
||||
__ bind(_entry);
|
||||
if (_compute_lock) {
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
}
|
||||
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
|
||||
address stub = Runtime1::entry_for(ce->compilation()->has_fpu_code() ? StubId::c1_monitorexit_id : StubId::c1_monitorexit_nofpu_id);
|
||||
//__ load_const_optimized(R0, stub);
|
||||
__ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
|
||||
|
||||
@@ -227,7 +227,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
||||
MonitorExitStub* stub = nullptr;
|
||||
if (method()->is_synchronized()) {
|
||||
monitor_address(0, FrameMap::R4_opr);
|
||||
stub = new MonitorExitStub(FrameMap::R4_opr, true, 0);
|
||||
stub = new MonitorExitStub(FrameMap::R4_opr, 0);
|
||||
__ unlock_object(R5, R6, R4, *stub->entry());
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
@@ -2614,7 +2614,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
// Obj may not be an oop.
|
||||
if (op->code() == lir_lock) {
|
||||
MonitorEnterStub* stub = (MonitorEnterStub*)op->stub();
|
||||
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) {
|
||||
@@ -2626,7 +2625,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
__ lock_object(hdr, obj, lock, op->scratch_opr()->as_register(), *op->stub()->entry());
|
||||
} else {
|
||||
assert (op->code() == lir_unlock, "Invalid code, expected lir_unlock");
|
||||
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());
|
||||
@@ -2747,11 +2745,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");
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "gc/g1/g1BarrierSetAssembler.hpp"
|
||||
#include "gc/g1/g1BarrierSetRuntime.hpp"
|
||||
#include "gc/g1/g1CardTable.hpp"
|
||||
#include "gc/g1/g1DirtyCardQueue.hpp"
|
||||
#include "gc/g1/g1HeapRegion.hpp"
|
||||
#include "gc/g1/g1SATBMarkQueueSet.hpp"
|
||||
#include "gc/g1/g1ThreadLocalData.hpp"
|
||||
@@ -230,78 +229,52 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, Decorator
|
||||
__ bind(filtered);
|
||||
}
|
||||
|
||||
static void generate_region_crossing_test(MacroAssembler* masm, const Register store_addr, const Register new_val) {
|
||||
__ xorr(R0, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ srdi_(R0, R0, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
}
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
assert_different_registers(store_addr, new_val, tmp1, R0);
|
||||
assert_different_registers(store_addr, tmp1, tmp2, R0);
|
||||
|
||||
static Address generate_card_young_test(MacroAssembler* masm, const Register store_addr, const Register tmp1, const Register tmp2) {
|
||||
CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
|
||||
__ load_const_optimized(tmp1, (address)(ct->card_table()->byte_map_base()), tmp2);
|
||||
__ srdi(tmp2, store_addr, CardTable::card_shift()); // tmp1 := card address relative to card table base
|
||||
__ lbzx(R0, tmp1, tmp2); // tmp1 := card address
|
||||
__ cmpwi(CR0, R0, (int)G1CardTable::g1_young_card_val());
|
||||
return Address(tmp1, tmp2); // return card address
|
||||
}
|
||||
__ xorr(R0, store_addr, new_val); // R0 := store address ^ new value
|
||||
__ srdi_(R0, R0, G1HeapRegion::LogOfHRGrainBytes); // R0 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ beq(CR0, done);
|
||||
|
||||
static void generate_card_dirty_test(MacroAssembler* masm, Address card_addr) {
|
||||
__ membar(Assembler::StoreLoad); // Must reload after StoreLoad membar due to concurrent refinement
|
||||
__ lbzx(R0, card_addr.base(), card_addr.index()); // tmp2 := card
|
||||
__ cmpwi(CR0, R0, (int)G1CardTable::dirty_card_val()); // tmp2 := card == dirty_card_val?
|
||||
// Crosses regions, storing null?
|
||||
if (!new_val_may_be_null) {
|
||||
#ifdef ASSERT
|
||||
__ cmpdi(CR0, new_val, 0);
|
||||
__ asm_assert_ne("null oop not allowed (G1 post)"); // Checked by caller.
|
||||
#endif
|
||||
} else {
|
||||
__ cmpdi(CR0, new_val, 0);
|
||||
__ beq(CR0, done);
|
||||
}
|
||||
|
||||
__ ld(tmp1, G1ThreadLocalData::card_table_base_offset(), thread);
|
||||
__ srdi(tmp2, store_addr, CardTable::card_shift()); // tmp2 := card address relative to card table base
|
||||
if (UseCondCardMark) {
|
||||
__ lbzx(R0, tmp1, tmp2);
|
||||
__ cmpwi(CR0, R0, (int)G1CardTable::clean_card_val());
|
||||
__ bne(CR0, done);
|
||||
}
|
||||
|
||||
__ li(R0, G1CardTable::dirty_card_val());
|
||||
__ stbx(R0, tmp1, tmp2);
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register store_addr, Register new_val,
|
||||
Register tmp1, Register tmp2, Register tmp3,
|
||||
MacroAssembler::PreservationLevel preservation_level) {
|
||||
Register tmp1, Register tmp2) {
|
||||
bool not_null = (decorators & IS_NOT_NULL) != 0;
|
||||
|
||||
Label runtime, filtered;
|
||||
assert_different_registers(store_addr, new_val, tmp1, tmp2);
|
||||
|
||||
CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
|
||||
|
||||
generate_region_crossing_test(masm, store_addr, new_val);
|
||||
__ beq(CR0, filtered);
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (not_null) {
|
||||
#ifdef ASSERT
|
||||
__ cmpdi(CR0, new_val, 0);
|
||||
__ asm_assert_ne("null oop not allowed (G1 post)"); // Checked by caller.
|
||||
#endif
|
||||
} else {
|
||||
__ cmpdi(CR0, new_val, 0);
|
||||
__ beq(CR0, filtered);
|
||||
}
|
||||
|
||||
Address card_addr = generate_card_young_test(masm, store_addr, tmp1, tmp2);
|
||||
__ beq(CR0, filtered);
|
||||
|
||||
generate_card_dirty_test(masm, card_addr);
|
||||
__ beq(CR0, filtered);
|
||||
|
||||
__ li(R0, (int)G1CardTable::dirty_card_val());
|
||||
__ stbx(R0, card_addr.base(), card_addr.index()); // *(card address) := dirty_card_val
|
||||
|
||||
Register Rcard_addr = tmp3;
|
||||
__ add(Rcard_addr, card_addr.base(), card_addr.index()); // This is the address which needs to get enqueued.
|
||||
|
||||
generate_queue_insertion(masm,
|
||||
G1ThreadLocalData::dirty_card_queue_index_offset(),
|
||||
G1ThreadLocalData::dirty_card_queue_buffer_offset(),
|
||||
runtime, Rcard_addr, tmp1);
|
||||
__ b(filtered);
|
||||
|
||||
__ bind(runtime);
|
||||
|
||||
assert(preservation_level == MacroAssembler::PRESERVATION_NONE,
|
||||
"g1_write_barrier_post doesn't support preservation levels higher than PRESERVATION_NONE");
|
||||
|
||||
// Save the live input values.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), Rcard_addr, R16_thread);
|
||||
|
||||
__ bind(filtered);
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, R16_thread, tmp1, tmp2, done, !not_null);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
@@ -333,8 +306,7 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco
|
||||
}
|
||||
g1_write_barrier_post(masm, decorators,
|
||||
base, val,
|
||||
tmp1, tmp2, tmp3,
|
||||
preservation_level);
|
||||
tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,70 +429,29 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* stub,
|
||||
bool new_val_may_be_null,
|
||||
bool decode_new_val) {
|
||||
assert_different_registers(store_addr, new_val, tmp1, R0);
|
||||
assert_different_registers(store_addr, tmp1, tmp2, R0);
|
||||
|
||||
stub->initialize_registers(R16_thread, tmp1, tmp2);
|
||||
Label done;
|
||||
|
||||
bool null_check_required = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0;
|
||||
Register new_val_decoded = new_val;
|
||||
|
||||
if (decode_new_val) {
|
||||
assert(UseCompressedOops, "or should not be here");
|
||||
if (null_check_required && CompressedOops::base() != nullptr) {
|
||||
if (new_val_may_be_null && CompressedOops::base() != nullptr) {
|
||||
// We prefer doing the null check after the region crossing check.
|
||||
// Only compressed oop modes with base != null require a null check here.
|
||||
__ cmpwi(CR0, new_val, 0);
|
||||
__ beq(CR0, *stub->continuation());
|
||||
null_check_required = false;
|
||||
__ beq(CR0, done);
|
||||
new_val_may_be_null = false;
|
||||
}
|
||||
new_val_decoded = __ decode_heap_oop_not_null(tmp2, new_val);
|
||||
}
|
||||
|
||||
generate_region_crossing_test(masm, store_addr, new_val_decoded);
|
||||
__ beq(CR0, *stub->continuation());
|
||||
|
||||
// crosses regions, storing null?
|
||||
if (null_check_required) {
|
||||
__ cmpdi(CR0, new_val_decoded, 0);
|
||||
__ beq(CR0, *stub->continuation());
|
||||
}
|
||||
|
||||
Address card_addr = generate_card_young_test(masm, store_addr, tmp1, tmp2);
|
||||
assert(card_addr.base() == tmp1 && card_addr.index() == tmp2, "needed by post barrier stub");
|
||||
__ bc_far_optimized(Assembler::bcondCRbiIs0, __ bi0(CR0, Assembler::equal), *stub->entry());
|
||||
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
Label runtime;
|
||||
Address card_addr(stub->tmp1(), stub->tmp2()); // See above.
|
||||
|
||||
__ bind(*stub->entry());
|
||||
|
||||
generate_card_dirty_test(masm, card_addr);
|
||||
__ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CR0, Assembler::equal), *stub->continuation());
|
||||
|
||||
__ li(R0, (int)G1CardTable::dirty_card_val());
|
||||
__ stbx(R0, card_addr.base(), card_addr.index()); // *(card address) := dirty_card_val
|
||||
|
||||
Register Rcard_addr = stub->tmp1();
|
||||
__ add(Rcard_addr, card_addr.base(), card_addr.index()); // This is the address which needs to get enqueued.
|
||||
|
||||
generate_queue_insertion(masm,
|
||||
G1ThreadLocalData::dirty_card_queue_index_offset(),
|
||||
G1ThreadLocalData::dirty_card_queue_buffer_offset(),
|
||||
runtime, Rcard_addr, stub->tmp2());
|
||||
__ b(*stub->continuation());
|
||||
|
||||
__ bind(runtime);
|
||||
generate_c2_barrier_runtime_call(masm, stub, Rcard_addr, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry));
|
||||
__ b(*stub->continuation());
|
||||
generate_post_barrier(masm, store_addr, new_val_decoded, R16_thread, tmp1, tmp2, done, new_val_may_be_null);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
@@ -558,28 +489,19 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
|
||||
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
|
||||
__ bind(*stub->entry());
|
||||
#undef __
|
||||
|
||||
assert(stub->addr()->is_register(), "Precondition.");
|
||||
assert(stub->new_val()->is_register(), "Precondition.");
|
||||
Register addr_reg = stub->addr()->as_pointer_register();
|
||||
Register new_val_reg = stub->new_val()->as_register();
|
||||
|
||||
__ cmpdi(CR0, new_val_reg, 0);
|
||||
__ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CR0, Assembler::equal), *stub->continuation());
|
||||
|
||||
address c_code = bs->post_barrier_c1_runtime_code_blob()->code_begin();
|
||||
//__ load_const_optimized(R0, c_code);
|
||||
__ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(c_code));
|
||||
__ mtctr(R0);
|
||||
__ mr(R0, addr_reg); // Pass addr in R0.
|
||||
__ bctrl();
|
||||
__ b(*stub->continuation());
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
masm->bind(done);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ sasm->
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
@@ -642,86 +564,6 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler*
|
||||
__ b(restart);
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
|
||||
|
||||
__ set_info("g1_post_barrier_slow_id", false);
|
||||
|
||||
// Using stack slots: spill addr, spill tmp2
|
||||
const int stack_slots = 2;
|
||||
Register tmp = R0;
|
||||
Register addr = R14;
|
||||
Register tmp2 = R15;
|
||||
CardTable::CardValue* byte_map_base = bs->card_table()->byte_map_base();
|
||||
|
||||
Label restart, refill, ret;
|
||||
|
||||
// Spill
|
||||
__ std(addr, -8, R1_SP);
|
||||
__ std(tmp2, -16, R1_SP);
|
||||
|
||||
__ srdi(addr, R0, CardTable::card_shift()); // Addr is passed in R0.
|
||||
__ load_const_optimized(/*cardtable*/ tmp2, byte_map_base, tmp);
|
||||
__ add(addr, tmp2, addr);
|
||||
__ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
|
||||
|
||||
// Return if young card.
|
||||
__ cmpwi(CR0, tmp, G1CardTable::g1_young_card_val());
|
||||
__ beq(CR0, ret);
|
||||
|
||||
// Return if sequential consistent value is already dirty.
|
||||
__ membar(Assembler::StoreLoad);
|
||||
__ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
|
||||
|
||||
__ cmpwi(CR0, tmp, G1CardTable::dirty_card_val());
|
||||
__ beq(CR0, ret);
|
||||
|
||||
// Not dirty.
|
||||
|
||||
// First, dirty it.
|
||||
__ li(tmp, G1CardTable::dirty_card_val());
|
||||
__ stb(tmp, 0, addr);
|
||||
|
||||
int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
|
||||
int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
|
||||
|
||||
__ bind(restart);
|
||||
|
||||
// Get the index into the update buffer. G1DirtyCardQueue::_index is
|
||||
// a size_t so ld_ptr is appropriate here.
|
||||
__ ld(tmp2, dirty_card_q_index_byte_offset, R16_thread);
|
||||
|
||||
// index == 0?
|
||||
__ cmpdi(CR0, tmp2, 0);
|
||||
__ beq(CR0, refill);
|
||||
|
||||
__ ld(tmp, dirty_card_q_buf_byte_offset, R16_thread);
|
||||
__ addi(tmp2, tmp2, -oopSize);
|
||||
|
||||
__ std(tmp2, dirty_card_q_index_byte_offset, R16_thread);
|
||||
__ add(tmp2, tmp, tmp2);
|
||||
__ std(addr, 0, tmp2); // [_buf + index] := <address_of_card>
|
||||
|
||||
// Restore temp registers and return-from-leaf.
|
||||
__ bind(ret);
|
||||
__ ld(tmp2, -16, R1_SP);
|
||||
__ ld(addr, -8, R1_SP);
|
||||
__ blr();
|
||||
|
||||
__ bind(refill);
|
||||
const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_slots) * BytesPerWord;
|
||||
__ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
|
||||
__ mflr(R0);
|
||||
__ std(R0, _abi0(lr), R1_SP);
|
||||
__ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1DirtyCardQueueSet::handle_zero_index_for_thread), R16_thread);
|
||||
__ pop_frame();
|
||||
__ ld(R0, _abi0(lr), R1_SP);
|
||||
__ mtlr(R0);
|
||||
__ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
|
||||
__ b(restart);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -37,9 +37,7 @@
|
||||
class LIR_Assembler;
|
||||
class StubAssembler;
|
||||
class G1PreBarrierStub;
|
||||
class G1PostBarrierStub;
|
||||
class G1PreBarrierStubC2;
|
||||
class G1PostBarrierStubC2;
|
||||
|
||||
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
|
||||
protected:
|
||||
@@ -56,8 +54,7 @@ protected:
|
||||
MacroAssembler::PreservationLevel preservation_level);
|
||||
void g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register store_addr, Register new_val,
|
||||
Register tmp1, Register tmp2, Register tmp3,
|
||||
MacroAssembler::PreservationLevel preservation_level);
|
||||
Register tmp1, Register tmp2);
|
||||
|
||||
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
Register base, RegisterOrConstant ind_or_offs, Register val,
|
||||
@@ -79,17 +76,21 @@ public:
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* c2_stub,
|
||||
bool new_val_may_be_null,
|
||||
bool decode_new_val);
|
||||
void generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const;
|
||||
#endif
|
||||
#ifdef COMPILER1
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
|
||||
void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
|
||||
|
||||
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
|
||||
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
|
||||
|
||||
void g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2);
|
||||
|
||||
#endif
|
||||
|
||||
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2025 SAP SE. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
@@ -64,13 +64,13 @@ static void post_write_barrier(MacroAssembler* masm,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
bool decode_new_val = false) {
|
||||
if (!G1PostBarrierStubC2::needs_barrier(node)) {
|
||||
if (!G1BarrierStubC2::needs_post_barrier(node)) {
|
||||
return;
|
||||
}
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
|
||||
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, tmp1, tmp2, stub, decode_new_val);
|
||||
bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, tmp1, tmp2, new_val_may_be_null, decode_new_val);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
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);
|
||||
new_mov_instr.u64 = old_mov_instr.u64 = AtomicAccess::load(instr);
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
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);
|
||||
uint64_t v = AtomicAccess::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_relaxed);
|
||||
if (v == old_mov_instr.u64) break;
|
||||
old_mov_instr.u64 = v;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ZBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
Register base, RegisterOrConstant ind_or_offs, Register dst,
|
||||
Register tmp1, Register tmp2,
|
||||
@@ -561,7 +560,6 @@ void ZBarrierSetAssembler::generate_conjoint_oop_copy(MacroAssembler* masm, bool
|
||||
copy_store_at_slow(masm, R4_ARG2, tmp, store_bad, store_good, dest_uninitialized);
|
||||
}
|
||||
|
||||
|
||||
// Verify a colored pointer.
|
||||
void ZBarrierSetAssembler::check_oop(MacroAssembler *masm, Register obj, const char* msg) {
|
||||
if (!VerifyOops) {
|
||||
@@ -583,7 +581,6 @@ void ZBarrierSetAssembler::check_oop(MacroAssembler *masm, Register obj, const c
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
|
||||
void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath) {
|
||||
__ block_comment("try_resolve_jobject_in_native (zgc) {");
|
||||
|
||||
@@ -347,7 +347,7 @@ void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer)
|
||||
// Finally patch out the jump.
|
||||
volatile juint *jump_addr = (volatile juint*)instr_addr;
|
||||
// Release not needed because caller uses invalidate_range after copying the remaining bytes.
|
||||
//Atomic::release_store(jump_addr, *((juint*)code_buffer));
|
||||
//AtomicAccess::release_store(jump_addr, *((juint*)code_buffer));
|
||||
*jump_addr = *((juint*)code_buffer); // atomically store code over branch instruction
|
||||
ICache::ppc64_flush_icache_bytes(instr_addr, NativeGeneralJump::instruction_size);
|
||||
}
|
||||
|
||||
@@ -1199,16 +1199,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
int comp_args_on_stack,
|
||||
const BasicType *sig_bt,
|
||||
const VMRegPair *regs,
|
||||
AdapterHandlerEntry* handler) {
|
||||
address i2c_entry;
|
||||
address c2i_unverified_entry;
|
||||
address c2i_entry;
|
||||
|
||||
|
||||
address entry_address[AdapterBlob::ENTRY_COUNT]) {
|
||||
// entry: i2c
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
i2c_entry = __ pc();
|
||||
entry_address[AdapterBlob::I2C] = __ pc();
|
||||
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
|
||||
|
||||
|
||||
@@ -1216,7 +1211,7 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
BLOCK_COMMENT("c2i unverified entry");
|
||||
c2i_unverified_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
|
||||
|
||||
// inline_cache contains a CompiledICData
|
||||
const Register ic = R19_inline_cache_reg;
|
||||
@@ -1244,10 +1239,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
|
||||
// entry: c2i
|
||||
|
||||
c2i_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I] = __ pc();
|
||||
|
||||
// Class initialization barrier for static methods
|
||||
address c2i_no_clinit_check_entry = nullptr;
|
||||
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
|
||||
if (VM_Version::supports_fast_class_init_checks()) {
|
||||
Label L_skip_barrier;
|
||||
|
||||
@@ -1266,15 +1261,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
|
||||
__ bctr();
|
||||
|
||||
__ bind(L_skip_barrier);
|
||||
c2i_no_clinit_check_entry = __ pc();
|
||||
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
|
||||
}
|
||||
|
||||
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs->c2i_entry_barrier(masm, /* tmp register*/ ic_klass, /* tmp register*/ receiver_klass, /* tmp register*/ code);
|
||||
|
||||
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, call_interpreter, ientry);
|
||||
|
||||
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3277,8 +3277,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// register the stub as the default exit with class UnsafeMemoryAccess
|
||||
UnsafeMemoryAccess::set_common_exit_stub_pc(StubRoutines::_unsafecopy_common_exit);
|
||||
|
||||
// Note: the disjoint stubs must be generated first, some of
|
||||
// the conjoint stubs use them.
|
||||
// Note: the disjoint stubs must be generated first, some of the
|
||||
// conjoint stubs use them.
|
||||
|
||||
// Note: chaining of stubs does not rely on branching to an
|
||||
// auxiliary post-push entry because none of the stubs
|
||||
// push/pop a frame.
|
||||
|
||||
// non-aligned disjoint versions
|
||||
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id);
|
||||
|
||||
@@ -912,6 +912,32 @@ protected:
|
||||
emit(insn);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static uint32_t encode_jal(Register Rd, const int32_t offset) {
|
||||
guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1101111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff));
|
||||
patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1));
|
||||
patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff));
|
||||
patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1));
|
||||
return insn;
|
||||
}
|
||||
|
||||
static uint32_t encode_jalr(Register Rd, Register Rs, const int32_t offset) {
|
||||
guarantee(is_simm12(offset), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1100111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 14, 12, 0b000);
|
||||
patch_reg((address)&insn, 15, Rs);
|
||||
int32_t val = offset & 0xfff;
|
||||
patch((address)&insn, 31, 20, val);
|
||||
return insn;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
enum barrier {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP
|
||||
#define CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP
|
||||
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "asm/assembler.hpp"
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
|
||||
|
||||
@@ -204,10 +204,10 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
|
||||
|
||||
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
|
||||
__ bind(_entry);
|
||||
if (_compute_lock) {
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
}
|
||||
|
||||
// lock_reg was destroyed by fast unlocking attempt => recompute it
|
||||
ce->monitor_address(_monitor_ix, _lock_reg);
|
||||
|
||||
ce->store_parameter(_lock_reg->as_register(), 0);
|
||||
// note: non-blocking leaf routine => no call info needed
|
||||
StubId exit_id;
|
||||
|
||||
@@ -338,7 +338,7 @@ int LIR_Assembler::emit_unwind_handler() {
|
||||
MonitorExitStub* stub = nullptr;
|
||||
if (method()->is_synchronized()) {
|
||||
monitor_address(0, FrameMap::r10_opr);
|
||||
stub = new MonitorExitStub(FrameMap::r10_opr, true, 0);
|
||||
stub = new MonitorExitStub(FrameMap::r10_opr, 0);
|
||||
__ unlock_object(x15, x14, x10, x16, *stub->entry());
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
@@ -1494,14 +1494,12 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
|
||||
Register lock = op->lock_opr()->as_register();
|
||||
Register temp = op->scratch_opr()->as_register();
|
||||
if (op->code() == lir_lock) {
|
||||
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
|
||||
int null_check_offset = __ lock_object(hdr, obj, lock, temp, *op->stub()->entry());
|
||||
if (op->info() != nullptr) {
|
||||
add_debug_info_for_null_check(null_check_offset, op->info());
|
||||
}
|
||||
} else if (op->code() == lir_unlock) {
|
||||
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
|
||||
__ unlock_object(hdr, obj, lock, temp, *op->stub()->entry());
|
||||
} else {
|
||||
Unimplemented();
|
||||
@@ -1590,8 +1588,6 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
}
|
||||
}
|
||||
|
||||
void LIR_Assembler::emit_delay(LIR_OpDelay*) { Unimplemented(); }
|
||||
|
||||
void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) {
|
||||
__ la(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no));
|
||||
}
|
||||
|
||||
@@ -48,27 +48,27 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
|
||||
}
|
||||
}
|
||||
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, disp_hdr, temp, t0, t1);
|
||||
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register basic_lock, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, basic_lock, temp, t0, t1);
|
||||
int null_check_offset = -1;
|
||||
|
||||
verify_oop(obj);
|
||||
|
||||
// save object being locked into the BasicObjectLock
|
||||
sd(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
sd(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
lightweight_lock(disp_hdr, obj, hdr, temp, t1, slow_case);
|
||||
lightweight_lock(basic_lock, obj, hdr, temp, t1, slow_case);
|
||||
|
||||
return null_check_offset;
|
||||
}
|
||||
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, disp_hdr, temp, t0, t1);
|
||||
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register basic_lock, Register temp, Label& slow_case) {
|
||||
assert_different_registers(hdr, obj, basic_lock, temp, t0, t1);
|
||||
|
||||
// load object
|
||||
ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
|
||||
ld(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
|
||||
verify_oop(obj);
|
||||
|
||||
lightweight_unlock(obj, hdr, temp, t1, slow_case);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@@ -56,19 +56,19 @@ using MacroAssembler::null_check;
|
||||
Register result);
|
||||
|
||||
// locking
|
||||
// hdr : must be x10, contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// disp_hdr: must point to the displaced header location, contents preserved
|
||||
// temp : temporary register, must not be scratch register t0 or t1
|
||||
// hdr : must be x10, contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// basic_lock: must point to the basic_lock, contents preserved
|
||||
// temp : temporary register, must not be scratch register t0 or t1
|
||||
// returns code offset at which to add null check debug information
|
||||
int lock_object(Register swap, Register obj, Register disp_hdr, Register temp, Label& slow_case);
|
||||
int lock_object(Register swap, Register obj, Register basic_lock, Register temp, Label& slow_case);
|
||||
|
||||
// unlocking
|
||||
// hdr : contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// disp_hdr: must be x10 & must point to the displaced header location, contents destroyed
|
||||
// temp : temporary register, must not be scratch register t0 or t1
|
||||
void unlock_object(Register swap, Register obj, Register lock, Register temp, Label& slow_case);
|
||||
// hdr : contents destroyed
|
||||
// obj : must point to the object to lock, contents preserved
|
||||
// basic_lock: must be x10 & must point to the basic lock, contents destroyed
|
||||
// temp : temporary register, must not be scratch register t0 or t1
|
||||
void unlock_object(Register swap, Register obj, Register basic_lock, Register temp, Label& slow_case);
|
||||
|
||||
void initialize_object(
|
||||
Register obj, // result: pointer to object after successful allocation
|
||||
|
||||
@@ -87,15 +87,54 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm
|
||||
}
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register start, Register count, Register tmp, RegSet saved_regs) {
|
||||
__ push_reg(saved_regs, sp);
|
||||
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm,
|
||||
DecoratorSet decorators,
|
||||
Register start,
|
||||
Register count,
|
||||
Register tmp,
|
||||
RegSet saved_regs) {
|
||||
assert_different_registers(start, count, tmp);
|
||||
assert_different_registers(c_rarg0, count);
|
||||
__ mv(c_rarg0, start);
|
||||
__ mv(c_rarg1, count);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
|
||||
__ pop_reg(saved_regs, sp);
|
||||
|
||||
Label loop, next, done;
|
||||
|
||||
// Zero count? Nothing to do.
|
||||
__ beqz(count, done);
|
||||
|
||||
// Calculate the number of card marks to set. Since the object might start and
|
||||
// end within a card, we need to calculate this via the card table indexes of
|
||||
// the actual start and last addresses covered by the object.
|
||||
// Temporarily use the count register for the last element address.
|
||||
__ shadd(count, count, start, tmp, LogBytesPerHeapOop); // end = start + count << LogBytesPerHeapOop
|
||||
__ subi(count, count, BytesPerHeapOop); // Use last element address for end.
|
||||
|
||||
__ srli(start, start, CardTable::card_shift());
|
||||
__ srli(count, count, CardTable::card_shift());
|
||||
__ sub(count, count, start); // Number of bytes to mark - 1.
|
||||
|
||||
// Add card table base offset to start.
|
||||
Address card_table_address(xthread, G1ThreadLocalData::card_table_base_offset());
|
||||
__ ld(tmp, card_table_address);
|
||||
__ add(start, start, tmp);
|
||||
|
||||
__ bind(loop);
|
||||
if (UseCondCardMark) {
|
||||
__ add(tmp, start, count);
|
||||
__ lbu(tmp, Address(tmp, 0));
|
||||
static_assert((uint)G1CardTable::clean_card_val() == 0xff, "must be");
|
||||
__ subi(tmp, tmp, G1CardTable::clean_card_val()); // Convert to clean_card_value() to a comparison
|
||||
// against zero to avoid use of an extra temp.
|
||||
__ bnez(tmp, next);
|
||||
}
|
||||
|
||||
__ add(tmp, start, count);
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use zr");
|
||||
__ sb(zr, Address(tmp, 0));
|
||||
|
||||
__ bind(next);
|
||||
__ subi(count, count, 1);
|
||||
__ bgez(count, loop);
|
||||
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
static void generate_queue_test_and_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime,
|
||||
@@ -189,47 +228,40 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
||||
|
||||
}
|
||||
|
||||
static void generate_post_barrier_fast_path(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
assert(thread == xthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg);
|
||||
// Does store cross heap regions?
|
||||
__ xorr(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ srli(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ beqz(tmp1, done);
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
__ beqz(new_val, done);
|
||||
}
|
||||
// Storing region crossing non-null, is card young?
|
||||
// Storing region crossing non-null, is card clean?
|
||||
__ srli(tmp1, store_addr, CardTable::card_shift()); // tmp1 := card address relative to card table base
|
||||
__ load_byte_map_base(tmp2); // tmp2 := card table base address
|
||||
__ add(tmp1, tmp1, tmp2); // tmp1 := card address
|
||||
__ lbu(tmp2, Address(tmp1)); // tmp2 := card
|
||||
}
|
||||
|
||||
static void generate_post_barrier_slow_path(MacroAssembler* masm,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
Label& runtime) {
|
||||
__ membar(MacroAssembler::StoreLoad); // StoreLoad membar
|
||||
__ lbu(tmp2, Address(tmp1)); // tmp2 := card
|
||||
__ beqz(tmp2, done, true);
|
||||
// Storing a region crossing, non-null oop, card is clean.
|
||||
// Dirty card and log.
|
||||
STATIC_ASSERT(CardTable::dirty_card_val() == 0);
|
||||
__ sb(zr, Address(tmp1)); // *(card address) := dirty_card_val
|
||||
generate_queue_test_and_insertion(masm,
|
||||
G1ThreadLocalData::dirty_card_queue_index_offset(),
|
||||
G1ThreadLocalData::dirty_card_queue_buffer_offset(),
|
||||
runtime,
|
||||
thread, tmp1, tmp2, t0);
|
||||
__ j(done);
|
||||
Address card_table_address(xthread, G1ThreadLocalData::card_table_base_offset());
|
||||
__ ld(tmp2, card_table_address); // tmp2 := card table base address
|
||||
__ add(tmp1, tmp1, tmp2); // tmp1 := card address
|
||||
if (UseCondCardMark) {
|
||||
static_assert((uint)G1CardTable::clean_card_val() == 0xff, "must be");
|
||||
__ lbu(tmp2, Address(tmp1, 0)); // tmp2 := card
|
||||
__ subi(tmp2, tmp2, G1CardTable::clean_card_val()); // Convert to clean_card_value() to a comparison
|
||||
// against zero to avoid use of an extra temp.
|
||||
__ bnez(tmp2, done);
|
||||
}
|
||||
static_assert((uint)G1CardTable::dirty_card_val() == 0, "must be to use zr");
|
||||
__ sb(zr, Address(tmp1, 0));
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
|
||||
@@ -238,27 +270,8 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
assert(thread == xthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, t0);
|
||||
assert(store_addr != noreg && new_val != noreg && tmp1 != noreg && tmp2 != noreg,
|
||||
"expecting a register");
|
||||
|
||||
Label done;
|
||||
Label runtime;
|
||||
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
// If card is young, jump to done (tmp2 holds the card value)
|
||||
__ mv(t0, (int)G1CardTable::g1_young_card_val());
|
||||
__ beq(tmp2, t0, done); // card == young_card_val?
|
||||
generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, done, runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
// save the live input values
|
||||
RegSet saved = RegSet::of(store_addr);
|
||||
__ push_reg(saved, sp);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp1, thread);
|
||||
__ pop_reg(saved, sp);
|
||||
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
@@ -318,37 +331,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* stub) {
|
||||
assert(thread == xthread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, t0);
|
||||
assert(store_addr != noreg && new_val != noreg && tmp1 != noreg && tmp2 != noreg,
|
||||
"expecting a register");
|
||||
|
||||
stub->initialize_registers(thread, tmp1, tmp2);
|
||||
|
||||
bool new_val_may_be_null = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0;
|
||||
generate_post_barrier_fast_path(masm, store_addr, new_val, tmp1, tmp2, *stub->continuation(), new_val_may_be_null);
|
||||
// If card is not young, jump to stub (slow path) (tmp2 holds the card value)
|
||||
__ mv(t0, (int)G1CardTable::g1_young_card_val());
|
||||
__ bne(tmp2, t0, *stub->entry(), true);
|
||||
|
||||
__ bind(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
Label runtime;
|
||||
Register thread = stub->thread();
|
||||
Register tmp1 = stub->tmp1(); // tmp1 holds the card address.
|
||||
Register tmp2 = stub->tmp2();
|
||||
|
||||
__ bind(*stub->entry());
|
||||
generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, *stub->continuation(), runtime);
|
||||
|
||||
__ bind(runtime);
|
||||
generate_c2_barrier_runtime_call(masm, stub, tmp1, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry));
|
||||
__ j(*stub->continuation());
|
||||
bool new_val_may_be_null) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, new_val_may_be_null);
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
@@ -443,20 +429,19 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
|
||||
__ j(*stub->continuation());
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
|
||||
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
|
||||
__ bind(*stub->entry());
|
||||
assert(stub->addr()->is_register(), "Precondition");
|
||||
assert(stub->new_val()->is_register(), "Precondition");
|
||||
Register new_val_reg = stub->new_val()->as_register();
|
||||
__ beqz(new_val_reg, *stub->continuation(), /* is_far */ true);
|
||||
ce->store_parameter(stub->addr()->as_pointer_register(), 0);
|
||||
__ far_call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin()));
|
||||
__ j(*stub->continuation());
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
Label done;
|
||||
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
|
||||
masm->bind(done);
|
||||
}
|
||||
|
||||
#define __ sasm->
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
@@ -507,74 +492,6 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler*
|
||||
__ epilogue();
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
|
||||
__ prologue("g1_post_barrier", false);
|
||||
|
||||
// arg0 : store_address
|
||||
Address store_addr(fp, 2 * BytesPerWord); // 2 BytesPerWord from fp
|
||||
|
||||
BarrierSet* bs = BarrierSet::barrier_set();
|
||||
CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
|
||||
|
||||
Label done;
|
||||
Label runtime;
|
||||
|
||||
// At this point we know new_value is non-null and the new_value crosses regions.
|
||||
// Must check to see if card is already dirty
|
||||
const Register thread = xthread;
|
||||
|
||||
Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
|
||||
Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
|
||||
|
||||
const Register card_offset = t1;
|
||||
// RA is free here, so we can use it to hold the byte_map_base.
|
||||
const Register byte_map_base = ra;
|
||||
|
||||
assert_different_registers(card_offset, byte_map_base, t0);
|
||||
|
||||
__ load_parameter(0, card_offset);
|
||||
__ srli(card_offset, card_offset, CardTable::card_shift());
|
||||
__ load_byte_map_base(byte_map_base);
|
||||
|
||||
// Convert card offset into an address in card_addr
|
||||
Register card_addr = card_offset;
|
||||
__ add(card_addr, byte_map_base, card_addr);
|
||||
|
||||
__ lbu(t0, Address(card_addr, 0));
|
||||
__ sub(t0, t0, (int)G1CardTable::g1_young_card_val());
|
||||
__ beqz(t0, done);
|
||||
|
||||
assert((int)CardTable::dirty_card_val() == 0, "must be 0");
|
||||
|
||||
__ membar(MacroAssembler::StoreLoad);
|
||||
__ lbu(t0, Address(card_addr, 0));
|
||||
__ beqz(t0, done);
|
||||
|
||||
// storing region crossing non-null, card is clean.
|
||||
// dirty card and log.
|
||||
__ sb(zr, Address(card_addr, 0));
|
||||
|
||||
__ ld(t0, queue_index);
|
||||
__ beqz(t0, runtime);
|
||||
__ subi(t0, t0, wordSize);
|
||||
__ sd(t0, queue_index);
|
||||
|
||||
// Reuse RA to hold buffer_addr
|
||||
const Register buffer_addr = ra;
|
||||
|
||||
__ ld(buffer_addr, buffer);
|
||||
__ add(t0, buffer_addr, t0);
|
||||
__ sd(card_addr, Address(t0, 0));
|
||||
__ j(done);
|
||||
|
||||
__ bind(runtime);
|
||||
__ push_call_clobbered_registers();
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
|
||||
__ pop_call_clobbered_registers();
|
||||
__ bind(done);
|
||||
__ epilogue();
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -35,9 +35,7 @@ class LIR_Assembler;
|
||||
#endif
|
||||
class StubAssembler;
|
||||
class G1PreBarrierStub;
|
||||
class G1PostBarrierStub;
|
||||
class G1PreBarrierStubC2;
|
||||
class G1PostBarrierStubC2;
|
||||
|
||||
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
|
||||
protected:
|
||||
@@ -68,10 +66,16 @@ protected:
|
||||
public:
|
||||
#ifdef COMPILER1
|
||||
void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
|
||||
void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
|
||||
|
||||
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
|
||||
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
|
||||
|
||||
void g1_write_barrier_post_c1(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER2
|
||||
@@ -90,9 +94,7 @@ public:
|
||||
Register thread,
|
||||
Register tmp1,
|
||||
Register tmp2,
|
||||
G1PostBarrierStubC2* c2_stub);
|
||||
void generate_c2_post_barrier_stub(MacroAssembler* masm,
|
||||
G1PostBarrierStubC2* stub) const;
|
||||
bool new_val_may_be_null);
|
||||
#endif
|
||||
|
||||
void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2024, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
@@ -63,13 +63,13 @@ static void write_barrier_post(MacroAssembler* masm,
|
||||
Register new_val,
|
||||
Register tmp1,
|
||||
Register tmp2) {
|
||||
if (!G1PostBarrierStubC2::needs_barrier(node)) {
|
||||
if (!G1BarrierStubC2::needs_post_barrier(node)) {
|
||||
return;
|
||||
}
|
||||
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
|
||||
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
|
||||
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, stub);
|
||||
bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
|
||||
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, new_val_may_be_null);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -217,7 +217,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::increment_patching_epoch() {
|
||||
Atomic::inc(&_patching_epoch);
|
||||
AtomicAccess::inc(&_patching_epoch);
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::clear_patching_epoch() {
|
||||
|
||||
@@ -106,22 +106,22 @@ public:
|
||||
}
|
||||
|
||||
int get_value() {
|
||||
return Atomic::load_acquire(guard_addr());
|
||||
return AtomicAccess::load_acquire(guard_addr());
|
||||
}
|
||||
|
||||
void set_value(int value, int bit_mask) {
|
||||
if (bit_mask == ~0) {
|
||||
Atomic::release_store(guard_addr(), value);
|
||||
AtomicAccess::release_store(guard_addr(), value);
|
||||
return;
|
||||
}
|
||||
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
|
||||
value &= bit_mask;
|
||||
int old_value = Atomic::load(guard_addr());
|
||||
int old_value = AtomicAccess::load(guard_addr());
|
||||
while (true) {
|
||||
// Only bits in the mask are changed
|
||||
int new_value = value | (old_value & ~bit_mask);
|
||||
if (new_value == old_value) break;
|
||||
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
|
||||
if (v == old_value) break;
|
||||
old_value = v;
|
||||
}
|
||||
|
||||
@@ -3402,6 +3402,8 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
|
||||
|
||||
void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) {
|
||||
assert(UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert_different_registers(dst, tmp);
|
||||
assert_different_registers(src, tmp);
|
||||
|
||||
if (CompressedKlassPointers::base() == nullptr) {
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
@@ -3412,18 +3414,13 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register
|
||||
return;
|
||||
}
|
||||
|
||||
Register xbase = dst;
|
||||
if (dst == src) {
|
||||
xbase = tmp;
|
||||
}
|
||||
Register xbase = tmp;
|
||||
|
||||
assert_different_registers(src, xbase);
|
||||
mv(xbase, (uintptr_t)CompressedKlassPointers::base());
|
||||
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
Register t = src == dst ? dst : t0;
|
||||
assert_different_registers(t, xbase);
|
||||
shadd(dst, src, xbase, t, CompressedKlassPointers::shift());
|
||||
// dst = (src << shift) + xbase
|
||||
shadd(dst, src, xbase, dst /* temporary, dst != xbase */, CompressedKlassPointers::shift());
|
||||
} else {
|
||||
add(dst, xbase, src);
|
||||
}
|
||||
@@ -5874,13 +5871,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) {
|
||||
// in cnt.
|
||||
//
|
||||
// NOTE: This is intended to be used in the zero_blocks() stub. If
|
||||
// you want to use it elsewhere, note that cnt must be >= CacheLineSize.
|
||||
// you want to use it elsewhere, note that cnt must be >= zicboz_block_size.
|
||||
void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tmp1, Register tmp2) {
|
||||
int zicboz_block_size = VM_Version::zicboz_block_size.value();
|
||||
Label initial_table_end, loop;
|
||||
|
||||
// Align base with cache line size.
|
||||
neg(tmp1, base);
|
||||
andi(tmp1, tmp1, CacheLineSize - 1);
|
||||
andi(tmp1, tmp1, zicboz_block_size - 1);
|
||||
|
||||
// tmp1: the number of bytes to be filled to align the base with cache line size.
|
||||
add(base, base, tmp1);
|
||||
@@ -5890,16 +5888,16 @@ void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tm
|
||||
la(tmp1, initial_table_end);
|
||||
sub(tmp2, tmp1, tmp2);
|
||||
jr(tmp2);
|
||||
for (int i = -CacheLineSize + wordSize; i < 0; i += wordSize) {
|
||||
for (int i = -zicboz_block_size + wordSize; i < 0; i += wordSize) {
|
||||
sd(zr, Address(base, i));
|
||||
}
|
||||
bind(initial_table_end);
|
||||
|
||||
mv(tmp1, CacheLineSize / wordSize);
|
||||
mv(tmp1, zicboz_block_size / wordSize);
|
||||
bind(loop);
|
||||
cbo_zero(base);
|
||||
sub(cnt, cnt, tmp1);
|
||||
addi(base, base, CacheLineSize);
|
||||
addi(base, base, zicboz_block_size);
|
||||
bge(cnt, tmp1, loop);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,13 @@
|
||||
#include "code/compiledIC.hpp"
|
||||
#include "nativeInst_riscv.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/orderAccess.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Runtime1.hpp"
|
||||
@@ -52,15 +54,15 @@ address NativeCall::destination() const {
|
||||
address addr = instruction_address();
|
||||
assert(NativeCall::is_at(addr), "unexpected code at call site");
|
||||
|
||||
address destination = MacroAssembler::target_addr_for_insn(addr);
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(addr);
|
||||
|
||||
CodeBlob* cb = CodeCache::find_blob(addr);
|
||||
assert(cb != nullptr && cb->is_nmethod(), "nmethod expected");
|
||||
nmethod *nm = (nmethod *)cb;
|
||||
assert(nm != nullptr, "Sanity");
|
||||
assert(nm->stub_contains(destination), "Sanity");
|
||||
assert(destination != nullptr, "Sanity");
|
||||
return stub_address_destination_at(destination);
|
||||
assert(nm->stub_contains(stub_addr), "Sanity");
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
|
||||
return stub_address_destination_at(stub_addr);
|
||||
}
|
||||
|
||||
address NativeCall::reloc_destination() {
|
||||
@@ -89,6 +91,30 @@ void NativeCall::print() {
|
||||
tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(instruction_address()));
|
||||
}
|
||||
|
||||
void NativeCall::optimize_call(address dest, bool mt_safe) {
|
||||
// Skip over auipc + ld
|
||||
address jmp_ins_pc = instruction_address() + 2 * NativeInstruction::instruction_size;
|
||||
// Rutime calls may be unaligned, but they are never changed after relocation.
|
||||
assert(!mt_safe || is_aligned(jmp_ins_pc, NativeInstruction::instruction_size), "Must be naturally aligned: %p", jmp_ins_pc);
|
||||
// If reachable use JAL
|
||||
if (Assembler::reachable_from_branch_at(jmp_ins_pc, dest)) {
|
||||
int64_t distance = dest - jmp_ins_pc;
|
||||
uint32_t new_jal = Assembler::encode_jal(ra, distance);
|
||||
AtomicAccess::store((uint32_t *)jmp_ins_pc, new_jal);
|
||||
} else if (!MacroAssembler::is_jalr_at(jmp_ins_pc)) { // The jalr is always identical: jalr ra, 0(t1)
|
||||
uint32_t new_jalr = Assembler::encode_jalr(ra, t1, 0);
|
||||
AtomicAccess::store((uint32_t *)jmp_ins_pc, new_jalr);
|
||||
} else {
|
||||
// No change to instruction stream
|
||||
return;
|
||||
}
|
||||
// We changed instruction stream
|
||||
if (mt_safe) {
|
||||
// IC invalidate provides a leading full fence, it thus happens after we changed the instruction stream.
|
||||
ICache::invalidate_range(jmp_ins_pc, NativeInstruction::instruction_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
assert(NativeCall::is_at(instruction_address()), "unexpected code at call site");
|
||||
assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
|
||||
@@ -96,15 +122,17 @@ bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
"concurrent code patching");
|
||||
|
||||
address stub_addr = stub_address();
|
||||
if (stub_addr != nullptr) {
|
||||
set_stub_address_destination_at(stub_addr, dest);
|
||||
return true;
|
||||
}
|
||||
assert(stub_addr != nullptr, "No stub?");
|
||||
set_stub_address_destination_at(stub_addr, dest); // release
|
||||
// optimize_call happens after we stored new address in addr stub.
|
||||
// patches jalr -> jal/jal -> jalr depending on dest
|
||||
optimize_call(dest, true);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCall::reloc_set_destination(address dest) {
|
||||
// The argument passed in is the address to the stub containing the destination
|
||||
bool NativeCall::reloc_set_destination(address stub_addr) {
|
||||
address call_addr = instruction_address();
|
||||
assert(NativeCall::is_at(call_addr), "unexpected code at call site");
|
||||
|
||||
@@ -113,10 +141,12 @@ bool NativeCall::reloc_set_destination(address dest) {
|
||||
|
||||
if (code->is_nmethod()) {
|
||||
// TODO: Need to revisit this when porting the AOT features.
|
||||
assert(dest != nullptr, "Sanity");
|
||||
assert(dest == trampoline_stub_Relocation::get_trampoline_for(call_addr,
|
||||
code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, dest);
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
assert(stub_addr == trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); // patches auipc + ld to stub_addr
|
||||
|
||||
address dest = stub_address_destination_at(stub_addr);
|
||||
optimize_call(dest, false); // patches jalr -> jal/jal -> jalr depending on dest
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -142,9 +172,9 @@ address NativeCall::stub_address() {
|
||||
CodeBlob *code = CodeCache::find_blob(call_addr);
|
||||
assert(code != nullptr, "Could not find the containing code blob");
|
||||
|
||||
address dest = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(dest), "Sanity");
|
||||
return dest;
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(stub_addr), "Sanity");
|
||||
return stub_addr;
|
||||
}
|
||||
|
||||
bool NativeCall::is_at(address addr) {
|
||||
@@ -160,6 +190,15 @@ bool NativeCall::is_at(address addr) {
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
if (MacroAssembler::is_auipc_at(addr) &&
|
||||
MacroAssembler::is_ld_at(addr + instr_size) &&
|
||||
MacroAssembler::is_jal_at(addr + 2 * instr_size) &&
|
||||
(MacroAssembler::extract_rd(addr) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rs1(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +156,10 @@ class NativeCall: private NativeInstruction {
|
||||
static void set_stub_address_destination_at(address dest, address value);
|
||||
// return target address at stub
|
||||
static address stub_address_destination_at(address src);
|
||||
// We either have a jalr or jal depending on distance to old destination.
|
||||
// This method emits a new jal if new destination is within jal reach.
|
||||
// Otherwise restores the jalr which can reach any destination.
|
||||
void optimize_call(address dest, bool mt_safe = true);
|
||||
};
|
||||
|
||||
// An interface for accessing/manipulating native mov reg, imm instructions.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user