1 Commits

Author SHA1 Message Date
DingliZhang c7a5e95ad5 8367293: RISC-V: enable vectorapi test for VectorMask.laneIsSet
OpenJDK GHA Sanity Checks / Prepare the run (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-nopch (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-zero (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-minimal (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-optimized (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static-libs (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-cross-compile (push) Has been cancelled
OpenJDK GHA Sanity Checks / alpine-linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / docs (push) Has been cancelled
2025-09-10 10:18:56 +08:00
1840 changed files with 25587 additions and 140576 deletions
+191
View File
@@ -0,0 +1,191 @@
#
# 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
+237
View File
@@ -0,0 +1,237 @@
#!/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"
+26 -73
View File
@@ -75,9 +75,6 @@ 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>
@@ -86,9 +83,8 @@ 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">&lt;atomic&gt;</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="#inline-variables" id="toc-inline-variables">Inline
Variables</a></li>
<li><a href="#initializing-variables-with-static-storage-duration"
id="toc-initializing-variables-with-static-storage-duration">Initializing
variables with static storage duration</a></li>
@@ -723,14 +719,11 @@ href="http://wg21.link/p0127r2">p0127r2</a>)<br> <code>auto</code> may
be used as a placeholder for the type of a non-type template parameter.
The type is deduced from the value provided in a template
instantiation.</p></li>
</ul>
<p><a name="function-return-type-deduction"></a> * Function return type
deduction (<a
<li><p>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>
<ul>
<li>Class template argument deduction (<a
statements, and generally relatively little other code.</p></li>
<li><p>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.
@@ -743,7 +736,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</li>
this</p></li>
</ul>
<pre><code> ScopeGuard guard{[&amp;]{ ... cleanup code ... }};</code></pre>
<ul>
@@ -778,44 +771,6 @@ 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>-&gt;</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&lt;typename T, typename U&gt; auto add(T t, U u) -&gt; decltype(t + u);</code></pre>
<p>rather than</p>
<pre><code>template&lt;typename T, typename U&gt; 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
@@ -938,18 +893,12 @@ differ from what the Java compilers implement.</p>
"conservative" memory ordering, which may differ from (may be stronger
than) sequentially consistent. There are algorithms in HotSpot that are
believed to rely on that ordering.</p>
<h3 id="variable-templates-and-inline-variables">Variable Templates and
Inline Variables</h3>
<p>The use of variable templates (including static data member
templates) (<a href="https://wg21.link/N3651">N3651</a>) is permitted.
They provide parameterized variables and constants in a simple and
direct form, instead of requiring the use of various workarounds.</p>
<p>Variables with static storage duration and variable templates may be
declared <code>inline</code> (<a
href="https://wg21.link/p0386r2">p0386r2</a>), and this usage is
permitted. This has similar effects as for declaring a function inline:
it can be defined, identically, in multiple translation units, must be
defined in every translation unit in which it is <a
<h3 id="inline-variables">Inline Variables</h3>
<p>Variables with static storage duration may be declared
<code>inline</code> (<a href="https://wg21.link/p0386r2">p0386r2</a>).
This has similar effects as for declaring a function inline: it can be
defined, identically, in multiple translation units, must be defined in
every translation unit in which it is <a
href="https://en.cppreference.com/w/cpp/language/definition"
title="One Definition Rule">ODR used</a>, and the behavior of the
program is as if there is exactly one variable.</p>
@@ -962,17 +911,16 @@ initializations can make initialization order problems worse. The few
ordering constraints that exist for non-inline variables don't apply, as
there isn't a single program-designated translation unit containing the
definition.</p>
<p>A <code>constexpr</code> static data member or static data member
template is implicitly <code>inline</code>. As a consequence, an <a
<p>A <code>constexpr</code> static data member is implicitly
<code>inline</code>. As a consequence, an <a
href="https://en.cppreference.com/w/cpp/language/definition"
title="One Definition Rule">ODR use</a> of such a 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>
title="One Definition Rule">ODR use</a> of such a variable doesn't
require a definition in some .cpp file. (This is a change from
pre-C++17. Beginning with C++17, such a definition is considered a
duplicate definition, and is deprecated.)</p>
<p>Declaring a <code>thread_local</code> variable <code>inline</code> is
forbidden for HotSpot code. <a href="#thread_local">The use of
<code>thread_local</code></a> is already heavily restricted.</p>
<h3
id="initializing-variables-with-static-storage-duration">Initializing
variables with static storage duration</h3>
@@ -1859,6 +1807,11 @@ 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>
+18 -55
View File
@@ -642,7 +642,6 @@ 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`
@@ -692,42 +691,6 @@ 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
@@ -856,19 +819,14 @@ ordering, which may differ from (may be stronger than) sequentially
consistent. There are algorithms in HotSpot that are believed to rely
on that ordering.
### Variable Templates and Inline Variables
### Inline Variables
The use of variable templates (including static data member templates)
([N3651](https://wg21.link/N3651)) is permitted. They provide parameterized
variables and constants in a simple and direct form, instead of requiring the
use of various workarounds.
Variables with static storage duration and variable templates may be declared
`inline` ([p0386r2](https://wg21.link/p0386r2)), and this usage is
permitted. This has similar effects as for declaring a function inline: it can
be defined, identically, in multiple translation units, must be defined in
every translation unit in which it is [ODR used][ODR], and the behavior of the
program is as if there is exactly one variable.
Variables with static storage duration may be declared `inline`
([p0386r2](https://wg21.link/p0386r2)). This has similar effects as for
declaring a function inline: it can be defined, identically, in multiple
translation units, must be defined in every translation unit in which it is
[ODR used][ODR], and the behavior of the program is as if there is exactly one
variable.
Declaring a variable inline allows the complete definition to be in a header
file, rather than having a declaration in a header and the definition in a
@@ -879,15 +837,13 @@ make initialization order problems worse. The few ordering constraints
that exist for non-inline variables don't apply, as there isn't a single
program-designated translation unit containing the definition.
A `constexpr` static data member or static data member template
is implicitly `inline`. As a consequence, an
[ODR use][ODR] of such a member doesn't require a definition in some .cpp
A `constexpr` static data member is implicitly `inline`. As a consequence, an
[ODR use][ODR] of such a variable doesn't require a definition in some .cpp
file. (This is a change from pre-C++17. Beginning with C++17, such a
definition is considered a duplicate definition, and is deprecated.)
Declaring a `thread_local` variable template or `inline` variable is forbidden
in HotSpot code. [The use of `thread_local`](#thread_local) is already
heavily restricted.
Declaring a `thread_local` variable `inline` is forbidden for HotSpot code.
[The use of `thread_local`](#thread_local) is already heavily restricted.
### Initializing variables with static storage duration
@@ -1853,6 +1809,13 @@ 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
View File
@@ -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_SUBDIR) $(LOG_DEBUG)
$(JDK_MACOSX_BUNDLE_DIR_SIGNED)/$(JDK_MACOSX_BUNDLE_TOP_DIR) $(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_SUBDIR) $(LOG_DEBUG)
$(JRE_MACOSX_BUNDLE_DIR_SIGNED)/$(JRE_MACOSX_BUNDLE_TOP_DIR) $(LOG_DEBUG)
$(TOUCH) $@
$(eval $(call SetupBundleFile, BUILD_JRE_BUNDLE, \
+1
View File
@@ -114,6 +114,7 @@ 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 :=
+20 -4
View File
@@ -210,8 +210,17 @@ 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_TOOLCHAIN_PROGS(XCODEBUILD, xcodebuild)
UTIL_LOOKUP_PROGS(XCODEBUILD, xcodebuild)
if test "x$XCODEBUILD" != x; then
XCODEBUILD_OUTPUT=`"$XCODEBUILD" -version 2>&1`
if test $? -ne 0; then
@@ -339,11 +348,21 @@ 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)]
@@ -352,9 +371,6 @@ 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],
+17 -2
View File
@@ -207,14 +207,29 @@ AC_DEFUN([BASIC_CHECK_GNU_MAKE],
UTIL_SETUP_TOOL(MAKE,
[
# Try our hardest to locate a correct version of GNU make
UTIL_LOOKUP_TOOLCHAIN_PROGS(CHECK_GMAKE, gmake)
UTIL_LOOKUP_PROGS(CHECK_GMAKE, gmake)
BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH])
if test "x$FOUND_MAKE" = x; then
UTIL_LOOKUP_TOOLCHAIN_PROGS(CHECK_MAKE, make)
UTIL_LOOKUP_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
+33 -7
View File
@@ -597,9 +597,10 @@ 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@:>@])])
EXTERNAL_BUILDJDK_PATH=""
CREATE_BUILDJDK=false
EXTERNAL_BUILDJDK=false
BUILD_JDK_FOUND="no"
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
@@ -607,15 +608,40 @@ AC_DEFUN([BOOTJDK_SETUP_BUILD_JDK],
AC_MSG_NOTICE([Found potential Build JDK using configure arguments])
fi
])
if test "x$BUILD_JDK_FOUND" != "xyes"; then
EXTERNAL_BUILDJDK=true
else
if test "x$COMPILE_TYPE" = "xcross"; then
BUILD_JDK="\$(BUILDJDK_OUTPUTDIR)/jdk"
BUILD_JDK_FOUND=yes
CREATE_BUILDJDK=true
AC_MSG_CHECKING([for Build JDK])
AC_MSG_RESULT([no])
AC_MSG_ERROR([Could not find a suitable 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])
fi
EXTERNAL_BUILDJDK_PATH="$BUILD_JDK"
fi
AC_SUBST(EXTERNAL_BUILDJDK_PATH)
# 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)
])
# The docs-reference JDK is used to run javadoc for the docs-reference targets.
+6 -1
View File
@@ -162,7 +162,12 @@ AC_DEFUN([BPERF_SETUP_CCACHE],
# Check if ccache is available
CCACHE_AVAILABLE=true
UTIL_LOOKUP_TOOLCHAIN_PROGS(CCACHE, ccache)
OLD_PATH="$PATH"
if test "x$TOOLCHAIN_PATH" != x; then
PATH=$TOOLCHAIN_PATH:$PATH
fi
UTIL_LOOKUP_PROGS(CCACHE, ccache)
PATH="$OLD_PATH"
AC_MSG_CHECKING([if ccache is available])
if test "x$TOOLCHAIN_TYPE" != "xgcc" && test "x$TOOLCHAIN_TYPE" != "xclang"; then
+1 -1
View File
@@ -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/compare-logger.sh $OUTPUTDIR/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
$BASH $TOPDIR/make/scripts/logger.sh $OUTPUTDIR/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
+73
View File
@@ -37,25 +37,56 @@ 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)
])
@@ -903,6 +934,48 @@ 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],
+2 -2
View File
@@ -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_TOOLCHAIN_PROGS(LLD, lld)
UTIL_REQUIRE_PROGS(LLD, lld, $TOOLCHAIN_PATH:$PATH)
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 SetSharedLibraryOrigin instead.
# FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead.
OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.."
OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN -Wl,-reproducible"
fi
-56
View File
@@ -107,62 +107,6 @@ 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],
+7 -2
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -319,10 +319,16 @@ 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
@@ -368,7 +374,6 @@ 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_])
+1 -1
View File
@@ -28,7 +28,7 @@
################################################################################
# Minimum supported versions
JTREG_MINIMUM_VERSION=8
JTREG_MINIMUM_VERSION=7.5.2
GTEST_MINIMUM_VERSION=1.14.0
################################################################################
+19 -24
View File
@@ -386,22 +386,9 @@ CAPSTONE_ARCH_AARCH64_NAME := @CAPSTONE_ARCH_AARCH64_NAME@
# it in sync.
BOOT_JDK := @BOOT_JDK@
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
BUILD_JDK := @BUILD_JDK@
CREATE_BUILDJDK := @CREATE_BUILDJDK@
EXTERNAL_BUILDJDK := @EXTERNAL_BUILDJDK@
# Whether the boot jdk jar supports --date=TIMESTAMP
BOOT_JDK_JAR_SUPPORTS_DATE := @BOOT_JDK_JAR_SUPPORTS_DATE@
@@ -504,6 +491,7 @@ 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.
@@ -636,8 +624,17 @@ 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@
@@ -660,8 +657,8 @@ JAVA_CMD := @JAVA@
JAVAC_CMD := @JAVAC@
JAVADOC_CMD := @JAVADOC@
JAR_CMD := @JAR@
JLINK_CMD := @FIXPATH@ $(BUILD_JDK)/bin/jlink
JMOD_CMD := @FIXPATH@ $(BUILD_JDK)/bin/jmod
JLINK_CMD := @JLINK@
JMOD_CMD := @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)
@@ -901,14 +898,12 @@ 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_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_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_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), )
+13 -4
View File
@@ -276,6 +276,9 @@ 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`
@@ -297,10 +300,9 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION],
fi
AC_SUBST(TOOLCHAIN_VERSION)
# 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
# Finally prepend TOOLCHAIN_PATH to the PATH, to allow --with-tools-dir to
# override all other locations.
if test "x$TOOLCHAIN_PATH" != x; then
export PATH=$TOOLCHAIN_PATH:$PATH
fi
])
@@ -308,6 +310,13 @@ 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"
+6 -6
View File
@@ -458,18 +458,17 @@ AC_DEFUN([UTIL_LOOKUP_PROGS],
################################################################################
# Call UTIL_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool. This will look
# 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.
# first for cross-compilation tools.
# $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, [$TOOLCHAIN_PATH:$PATH])
UTIL_LOOKUP_PROGS($1, $2, $3)
else
prefixed_names=$(for name in $2; do echo ${ac_tool_prefix}${name} $name; done)
UTIL_LOOKUP_PROGS($1, $prefixed_names, [$TOOLCHAIN_PATH:$PATH])
UTIL_LOOKUP_PROGS($1, $prefixed_names, $3)
fi
])
@@ -498,9 +497,10 @@ 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)
UTIL_LOOKUP_TOOLCHAIN_PROGS($1, $2, $3)
UTIL_CHECK_NONEMPTY($1)
])
+6 -21
View File
@@ -82,8 +82,6 @@ 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
@@ -148,12 +146,9 @@ 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_VARDEPS_FILE)
$$($1_PRE_MARKER): $$($1_DEPS)
ifneq ($$($1_WARN), )
$$(call LogWarn, $$($1_WARN))
endif
@@ -166,20 +161,15 @@ define SetupExecuteBody
$$(TOUCH) $$@
$$($1_EXEC_RESULT): $$($1_PRE_MARKER)
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
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
$$(TOUCH) $$@
endif
$1 := $$($1_PRE_MARKER) $$($1_EXEC_RESULT)
else
$$($1_EXEC_RESULT): $$($1_DEPS) $$($1_VARDEPS_FILE)
$$($1_EXEC_RESULT): $$($1_DEPS)
ifneq ($$($1_WARN), )
$$(call LogWarn, $$($1_WARN))
endif
@@ -187,13 +177,8 @@ define SetupExecuteBody
$$(call LogInfo, $$($1_INFO))
endif
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
ifneq ($$($1_DRYRUN), true)
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
else
$$(call LogWarn, DRYRUN enabled for $1, not actually running command)
$$(TOUCH) $$@
endif
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
$$(TOUCH) $$@
endif
+2 -43
View File
@@ -30,47 +30,6 @@ 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) \
@@ -485,9 +444,9 @@ define SetupJdkNativeCompilationBody
ifneq ($$($1_LD_SET_ORIGIN), false)
ifeq ($$($1_TYPE), EXECUTABLE)
$1_LDFLAGS += $$(call SetExecutableOrigin)
$1_LDFLAGS += $$(call SET_EXECUTABLE_ORIGIN)
else
$1_LDFLAGS += $$(call SetSharedLibraryOrigin)
$1_LDFLAGS += $$(call SET_SHARED_LIBRARY_ORIGIN)
endif
endif
# APPEND_LDFLAGS, if it exists, must be set after the origin flags
+2 -2
View File
@@ -156,8 +156,8 @@ define SetupBuildLauncherBody
DISABLED_WARNINGS_gcc := unused-function unused-variable, \
DISABLED_WARNINGS_clang := unused-function, \
LDFLAGS := $$($1_LDFLAGS), \
LDFLAGS_linux := $$(call SetExecutableOrigin,/../lib), \
LDFLAGS_macosx := $$(call SetExecutableOrigin,/../lib), \
LDFLAGS_linux := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN,/../lib), \
LDFLAGS_FILTER_OUT := $$($1_LDFLAGS_FILTER_OUT), \
JDK_LIBS := $$($1_JDK_LIBS), \
JDK_LIBS_windows := $$($1_JDK_LIBS_windows), \
+2 -10
View File
@@ -93,14 +93,6 @@ 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.
#
@@ -342,7 +334,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) -Fo$$@ \
$$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
$$($1_VERSIONINFO_RESOURCE) 2>&1 ))
# Windows RC compiler does not support -showIncludes, so we mis-use CL
# for this. Filter out RC specific arguments that are unknown to CL.
@@ -352,7 +344,7 @@ define CreateWindowsResourceFile
$$(call ExecuteWithLog, $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX), \
$$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \
$$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
-Fo$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
$(CC_OUT_OPTION)$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
$$($1_VERSIONINFO_RESOURCE)) 2>&1 \
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
-e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
+1 -21
View File
@@ -50,26 +50,6 @@ 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
@@ -151,7 +131,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 SetSharedLibraryName,$$($1_BASENAME))
$1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME))
endif
ifeq ($(MACOSX_CODESIGN_MODE), hardened)
+1 -1
View File
@@ -26,7 +26,7 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
GTEST_VERSION=1.14.0
JTREG_VERSION=8+2
JTREG_VERSION=7.5.2+1
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
+3 -3
View File
@@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "jpg",
product: "jtreg",
version: "8",
build_number: "2",
file: "bundles/jtreg-8+2.zip",
version: "7.5.2",
build_number: "1",
file: "bundles/jtreg-7.5.2+1.zip",
environment_name: "JT_HOME",
environment_path: input.get("jtreg", "home_path") + "/bin",
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
+1 -1
View File
@@ -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 SetSharedLibraryOrigin), \
LDFLAGS_unix := $(call SET_SHARED_LIBRARY_ORIGIN), \
JDK_LIBS := gtest:libjvm, \
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
+1 -1
View File
@@ -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 SetExecutableOrigin,/..)
JVM_LDFLAGS_FEATURES += $(call SET_EXECUTABLE_ORIGIN,/..)
endif
else
JVM_EXCLUDE_PATTERNS += /zero/
+1
View File
@@ -33,6 +33,7 @@ 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
+1 -3
View File
@@ -154,8 +154,6 @@ 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, \
@@ -198,7 +196,7 @@ ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, x86_64)+$(INCLUDE_COMPILER2)
OPTIMIZATION := HIGH, \
CXXFLAGS := -std=c++17, \
DISABLED_WARNINGS_gcc := unused-variable, \
LIBS_linux := $(LIBM), \
LIBS_linux := $(LIBDL) $(LIBM), \
))
TARGETS += $(BUILD_LIBSIMD_SORT)
@@ -0,0 +1,57 @@
#
# 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 := $(LIBM), \
LIBS_unix := $(LIBDL) $(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 := $(X_LIBS) -lX11 -lXext, \
LIBS_linux := $(LIBDL) $(X_LIBS) -lX11 -lXext, \
LIBS_macosx := \
-framework ApplicationServices \
-framework Cocoa \
+2
View File
@@ -43,6 +43,8 @@ $(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 \
+1 -1
View File
@@ -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), \
LIBS_linux := $(LIBDL) $(LIBPTHREAD), \
))
TARGETS += $(BUILD_LIBSCTP)
+45
View File
@@ -0,0 +1,45 @@
#! /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
+116
View File
@@ -0,0 +1,116 @@
#! /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,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2019, 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,39 +52,12 @@
# 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
@@ -99,5 +72,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 \
$generator_dir/CreateSymbols.java \
../../../../../make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java \
build-description-incremental symbols include.list
@@ -0,0 +1,36 @@
#!/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}"
@@ -1,6 +1,6 @@
#! /bin/sh -f
#
# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
# 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
@@ -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}/../make/data/license-templates
template_dir=${script_dir}/../data/license-templates
# Check existence of the template directory.
if [ ! -d ${template_dir} ] ; then
@@ -23,19 +23,9 @@
# 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
+8 -31
View File
@@ -216,6 +216,11 @@ 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;
@@ -7108,39 +7113,10 @@ instruct vcompressS(vReg dst, vReg src, pReg pg,
ins_pipe(pipe_slow);
%}
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);
instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
match(Set dst (ExpandV src pg));
effect(TEMP_DEF dst);
format %{ "vexpand_sve2_SD $dst, $src, $pg" %}
format %{ "vexpand $dst, $pg, $src" %}
ins_encode %{
// Example input: src = 1 2 3 4 5 6 7 8
// pg = 1 0 0 1 1 0 1 1
@@ -7151,6 +7127,7 @@ instruct vexpand_sve2_SD(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);
+8 -31
View File
@@ -206,6 +206,11 @@ 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;
@@ -5096,39 +5101,10 @@ instruct vcompressS(vReg dst, vReg src, pReg pg,
ins_pipe(pipe_slow);
%}
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);
instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
match(Set dst (ExpandV src pg));
effect(TEMP_DEF dst);
format %{ "vexpand_sve2_SD $dst, $src, $pg" %}
format %{ "vexpand $dst, $pg, $src" %}
ins_encode %{
// Example input: src = 1 2 3 4 5 6 7 8
// pg = 1 0 0 1 1 0 1 1
@@ -5139,6 +5115,7 @@ instruct vexpand_sve2_SD(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,13 +4068,6 @@ 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.hpp"
#include "asm/assembler.inline.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);
// lock_reg was destroyed by fast unlocking attempt => recompute it
ce->monitor_address(_monitor_ix, _lock_reg);
if (_compute_lock) {
// 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, 0);
stub = new MonitorExitStub(FrameMap::r0_opr, true, 0);
__ unlock_object(r5, r4, r0, r6, *stub->entry());
__ bind(*stub->continuation());
}
@@ -2481,6 +2481,7 @@ 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) {
@@ -2488,6 +2489,7 @@ 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();
@@ -2583,6 +2585,11 @@ 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 basic_lock, Register temp, Label& slow_case) {
assert_different_registers(hdr, obj, basic_lock, temp, rscratch2);
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 null_check_offset = -1;
verify_oop(obj);
// save object being locked into the BasicObjectLock
str(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
null_check_offset = offset();
lightweight_lock(basic_lock, obj, hdr, temp, rscratch2, slow_case);
lightweight_lock(disp_hdr, obj, hdr, temp, rscratch2, slow_case);
return null_check_offset;
}
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);
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);
// load object
ldr(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj);
lightweight_unlock(obj, hdr, temp, rscratch2, slow_case);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -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
// basic_lock: must point to the basic lock, 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
// disp_hdr: must point to the displaced header location, 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 basic_lock, Register temp, Label& slow_case);
int lock_object (Register swap, Register obj, Register disp_hdr, Register temp, Label& slow_case);
// unlocking
// 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);
// 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);
void initialize_object(
Register obj, // result: pointer to object after successful allocation
@@ -2771,90 +2771,3 @@ 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,10 +204,4 @@
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,48 +86,15 @@ 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) {
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);
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);
}
static void generate_queue_test_and_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime,
@@ -232,17 +199,13 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
}
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);
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?
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
@@ -251,19 +214,33 @@ static void generate_post_barrier(MacroAssembler* masm,
if (new_val_may_be_null) {
__ cbz(new_val, done);
}
// Storing region crossing non-null.
// Storing region crossing non-null, is card young?
__ 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?
}
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
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);
}
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
@@ -272,8 +249,27 @@ 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;
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, false /* new_val_may_be_null */);
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);
__ bind(done);
}
@@ -333,10 +329,38 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
Register thread,
Register tmp1,
Register tmp2,
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);
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());
}
#endif // COMPILER2
@@ -432,19 +456,20 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
__ 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);
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 __
#define __ sasm->
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
@@ -496,6 +521,74 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,9 @@
class LIR_Assembler;
class StubAssembler;
class G1PreBarrierStub;
class G1PostBarrierStub;
class G1PreBarrierStubC2;
class G1PostBarrierStubC2;
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
protected:
@@ -63,15 +65,10 @@ 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 g1_write_barrier_post_c1(MacroAssembler* masm,
Register store_addr,
Register new_val,
Register thread,
Register tmp1,
Register tmp2);
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
#endif
#ifdef COMPILER2
@@ -90,7 +87,9 @@ public:
Register thread,
Register tmp1,
Register tmp2,
bool new_val_may_be_null);
G1PostBarrierStubC2* c2_stub);
void generate_c2_post_barrier_stub(MacroAssembler* masm,
G1PostBarrierStubC2* stub) const;
#endif
void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+4 -4
View File
@@ -1,5 +1,5 @@
//
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -62,13 +62,13 @@ static void write_barrier_post(MacroAssembler* masm,
Register new_val,
Register tmp1,
Register tmp2) {
if (!G1BarrierStubC2::needs_post_barrier(node)) {
if (!G1PostBarrierStubC2::needs_barrier(node)) {
return;
}
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
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);
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, rthread, tmp1, tmp2, stub);
}
%}
@@ -275,7 +275,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
}
void BarrierSetAssembler::increment_patching_epoch() {
AtomicAccess::inc(&_patching_epoch);
Atomic::inc(&_patching_epoch);
}
void BarrierSetAssembler::clear_patching_epoch() {
@@ -398,18 +398,14 @@ 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, "32-bit register should only occupy a single slot");
assert(opto_reg % 4 == 0, "Float 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 AtomicAccess::load_acquire(guard_addr());
return Atomic::load_acquire(guard_addr());
}
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
AtomicAccess::release_store(guard_addr(), value);
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = AtomicAccess::load(guard_addr());
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
@@ -275,6 +275,7 @@ public:
Label* entry();
};
class ZStoreBarrierStubC2Aarch64 : public ZStoreBarrierStubC2 {
private:
bool _deferred_emit;
@@ -239,6 +239,7 @@ 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(Label& p, Register state, Register subkeyH,
void ghash_processBlocks_wide(address 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(Label& field_polynomial, Register state,
void MacroAssembler::ghash_processBlocks_wide(address field_polynomial, Register state,
Register subkeyH,
Register data, Register blocks, int unrolls) {
int register_stride = 7;
@@ -531,10 +531,7 @@ void MacroAssembler::ghash_processBlocks_wide(Label& field_polynomial, Register
FloatRegister p = v31;
eor(vzr, T16B, vzr, vzr); // zero register
// 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(p, field_polynomial); // 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,
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
address c2i_unverified_entry = __ pc();
Label skip_fixup;
Register data = rscratch2;
@@ -718,10 +718,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ block_comment("} c2i_unverified_entry");
}
entry_address[AdapterBlob::C2I] = __ pc();
address c2i_entry = __ pc();
// Class initialization barrier for static methods
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
address c2i_no_clinit_check_entry = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@@ -736,13 +736,15 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
__ bind(L_skip_barrier);
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
c2i_no_clinit_check_entry = __ 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;
}
@@ -1761,6 +1763,9 @@ 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);
+158 -220
View File
@@ -42,7 +42,7 @@
#include "prims/methodHandles.hpp"
#include "prims/upcallLinker.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.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
//
address generate_copy_longs(StubId stub_id, DecoratorSet decorators, Register s, Register d, Register count) {
void generate_copy_longs(StubId stub_id, DecoratorSet decorators, Label &start, Register s, Register d, Register count) {
BasicType type;
copy_direction direction;
@@ -854,7 +854,7 @@ class StubGenerator: public StubCodeGenerator {
StubCodeMark mark(this, stub_id);
address start = __ pc();
__ bind(start);
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,20 +1141,18 @@ 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.
@@ -1208,6 +1206,10 @@ 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
@@ -1445,19 +1447,19 @@ class StubGenerator: public StubCodeGenerator {
}
if (direction == copy_forwards) {
if (type != T_OBJECT) {
__ bl(StubRoutines::aarch64::copy_byte_f());
__ bl(copy_f);
} else if ((decorators & IS_DEST_UNINITIALIZED) != 0) {
__ bl(StubRoutines::aarch64::copy_oop_uninit_f());
__ bl(copy_obj_uninit_f);
} else {
__ bl(StubRoutines::aarch64::copy_oop_f());
__ bl(copy_obj_f);
}
} else {
if (type != T_OBJECT) {
__ bl(StubRoutines::aarch64::copy_byte_b());
__ bl(copy_b);
} else if ((decorators & IS_DEST_UNINITIALIZED) != 0) {
__ bl(StubRoutines::aarch64::copy_oop_uninit_b());
__ bl(copy_obj_uninit_b);
} else {
__ bl(StubRoutines::aarch64::copy_oop_b());
__ bl(copy_obj_b);
}
}
@@ -1520,11 +1522,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: nopush_entry is set to the (post push) entry point
// so it can be used by the corresponding conjoint
// copy method
// Side Effects: 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 *nopush_entry) {
address generate_disjoint_copy(StubId stub_id, address *entry) {
Register s = c_rarg0, d = c_rarg1, count = c_rarg2;
RegSet saved_reg = RegSet::of(s, d, count);
int size;
@@ -1613,8 +1615,8 @@ class StubGenerator: public StubCodeGenerator {
address start = __ pc();
__ enter();
if (nopush_entry != nullptr) {
*nopush_entry = __ pc();
if (entry != nullptr) {
*entry = __ pc();
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
BLOCK_COMMENT("Entry:");
}
@@ -1677,10 +1679,10 @@ class StubGenerator: public StubCodeGenerator {
// cache line boundaries will still be loaded and stored atomically.
//
// Side Effects:
// nopush_entry is set to the no-overlap entry point so it can be
// used by some other conjoint copy method
// 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 *nopush_entry) {
address generate_conjoint_copy(StubId stub_id, address nooverlap_target, address *entry) {
Register s = c_rarg0, d = c_rarg1, count = c_rarg2;
RegSet saved_regs = RegSet::of(s, d, count);
int size;
@@ -1767,19 +1769,16 @@ class StubGenerator: public StubCodeGenerator {
address start = __ pc();
__ enter();
if (nopush_entry != nullptr) {
*nopush_entry = __ pc();
if (entry != nullptr) {
*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::LO, L_overlapping);
__ b(RuntimeAddress(nooverlap_target));
__ bind(L_overlapping);
__ br(Assembler::HS, nooverlap_target);
DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
@@ -1851,7 +1850,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 *nopush_entry) {
address generate_checkcast_copy(StubId stub_id, address *entry) {
bool dest_uninitialized;
switch (stub_id) {
case StubId::stubgen_checkcast_arraycopy_id:
@@ -1912,8 +1911,8 @@ class StubGenerator: public StubCodeGenerator {
#endif //ASSERT
// Caller of this entry point must set up the argument registers.
if (nopush_entry != nullptr) {
*nopush_entry = __ pc();
if (entry != nullptr) {
*entry = __ pc();
BLOCK_COMMENT("Entry:");
}
@@ -2725,21 +2724,13 @@ class StubGenerator: public StubCodeGenerator {
}
void generate_arraycopy_stubs() {
// 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;
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;
// generate the common exit first so later stubs can rely on it if
// they want an UnsafeMemoryAccess exit non-local to the stub
@@ -2747,123 +2738,83 @@ 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 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_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);
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_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_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);
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::_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, &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);
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);
//*** jshort
// Always need aligned and unaligned versions
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);
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);
//*** jint
// Aligned versions
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);
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);
// In 64 bit we need both aligned and unaligned versions of 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;
// 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);
//*** jlong
// It is always aligned
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::_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::_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, &nopush_entry);
// disjoint arrayof nopush entry is needed by conjoint copy
StubRoutines::_arrayof_oop_disjoint_arraycopy_nopush = nopush_entry;
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_id, &entry);
StubRoutines::_arrayof_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;
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_id, entry, &entry_oop_arraycopy);
// Aligned versions without pre-barriers
StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit
= 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.
= generate_disjoint_copy(StubId::stubgen_arrayof_oop_disjoint_arraycopy_uninit_id, &entry);
StubRoutines::_arrayof_oop_arraycopy_uninit
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit_nopush, nullptr);
= generate_conjoint_copy(StubId::stubgen_arrayof_oop_arraycopy_uninit_id, entry, 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, &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 = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_id, &entry_checkcast_arraycopy);
StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy(StubId::stubgen_checkcast_arraycopy_uninit_id, nullptr);
// 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::_unsafe_arraycopy = generate_unsafe_copy(entry_jbyte_arraycopy,
entry_jshort_arraycopy,
entry_jint_arraycopy,
entry_jlong_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::_generic_arraycopy = generate_generic_copy(entry_jbyte_arraycopy,
entry_jshort_arraycopy,
entry_jint_arraycopy,
entry_oop_arraycopy,
entry_jlong_arraycopy,
entry_checkcast_arraycopy);
StubRoutines::_jbyte_fill = generate_fill(StubId::stubgen_jbyte_fill_id);
StubRoutines::_jshort_fill = generate_fill(StubId::stubgen_jshort_fill_id);
@@ -3451,9 +3402,14 @@ class StubGenerator: public StubCodeGenerator {
// counter = c_rarg7 - 16 bytes of CTR
// return - number of processed bytes
address generate_galoisCounterMode_AESCrypt() {
Label ghash_polynomial; // local data generated after code
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);
__ align(CodeEntryAlignment);
__ align(CodeEntryAlignment);
StubId stub_id = StubId::stubgen_galoisCounterMode_AESCrypt_id;
StubCodeMark mark(this, stub_id);
address start = __ pc();
@@ -3558,17 +3514,7 @@ class StubGenerator: public StubCodeGenerator {
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(lr);
// 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;
return start;
}
class Cached64Bytes {
@@ -4613,6 +4559,16 @@ 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);
@@ -4760,17 +4716,6 @@ 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;
}
@@ -6091,6 +6036,10 @@ 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);
@@ -6284,11 +6233,6 @@ 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;
}
@@ -9698,7 +9642,14 @@ class StubGenerator: public StubCodeGenerator {
StubId stub_id = StubId::stubgen_ghash_processBlocks_id;
StubCodeMark mark(this, stub_id);
Label polynomial; // local data generated at end of stub
__ 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);
__ align(CodeEntryAlignment);
address start = __ pc();
@@ -9710,8 +9661,7 @@ class StubGenerator: public StubCodeGenerator {
FloatRegister vzr = v30;
__ eor(vzr, __ T16B, vzr, vzr); // zero register
__ adr(rscratch1, polynomial);
__ ldrq(v24, rscratch1); // The field polynomial
__ ldrq(v24, p); // The field polynomial
__ ldrq(v0, Address(state));
__ ldrq(v1, Address(subkeyH));
@@ -9751,15 +9701,6 @@ 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;
}
@@ -9768,7 +9709,14 @@ class StubGenerator: public StubCodeGenerator {
StubId stub_id = StubId::stubgen_ghash_processBlocks_wide_id;
StubCodeMark mark(this, stub_id);
Label polynomial; // local data generated after stub
__ 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);
__ align(CodeEntryAlignment);
address start = __ pc();
@@ -9790,7 +9738,7 @@ class StubGenerator: public StubCodeGenerator {
__ st1(v8, v9, v10, v11, __ T16B, Address(sp));
}
__ ghash_processBlocks_wide(polynomial, state, subkeyH, data, blocks, unroll);
__ ghash_processBlocks_wide(p, state, subkeyH, data, blocks, unroll);
if (unroll > 1) {
// And restore state
@@ -9803,17 +9751,7 @@ 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,
@@ -10327,7 +10265,7 @@ class StubGenerator: public StubCodeGenerator {
#if defined (LINUX) && !defined (__ARM_FEATURE_ATOMICS)
// ARMv8.1 LSE versions of the atomic stubs used by AtomicAccess::PlatformXX.
// ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX.
//
// If LSE is in use, generate LSE versions of all the stubs. The
// non-LSE versions are in atomic_aarch64.S.
+14 -6
View File
@@ -3281,18 +3281,18 @@ pipe_class loadPollP(iRegP poll) %{
%}
pipe_class br(Universe br, label labl) %{
single_instruction;
single_instruction_with_delay_slot;
BR : R;
%}
pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
single_instruction;
single_instruction_with_delay_slot;
cr : E(read);
BR : R;
%}
pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
single_instruction;
single_instruction_with_delay_slot;
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;
single_instruction; has_delay_slot;
fixed_latency(100);
BR : R(1);
MS : R(1);
%}
pipe_class ret(Universe ignore) %{
single_instruction;
single_instruction; has_delay_slot;
BR : R(1);
MS : R(1);
%}
@@ -3373,6 +3373,14 @@ 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;
@@ -9045,7 +9053,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]\n"
" STR.ge $zero,[$base+$temp]\t! delay slot"
" B.gt loop\t\t! Clearing loop\n" %}
ins_encode %{
__ mov($zero$$Register, 0);
+3 -4
View File
@@ -200,10 +200,9 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
// lock_reg was destroyed by fast unlocking attempt => recompute it
ce->monitor_address(_monitor_ix, _lock_reg);
if (_compute_lock) {
ce->monitor_address(_monitor_ix, _lock_reg);
}
const Register lock_reg = _lock_reg->as_pointer_register();
ce->verify_reserved_argument_area_size(1);
+7 -1
View File
@@ -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, 0);
stub = new MonitorExitStub(FrameMap::R0_opr, true, 0);
__ unlock_object(R2, R1, R0, *stub->entry());
__ bind(*stub->continuation());
}
@@ -2427,6 +2427,7 @@ 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());
@@ -2551,6 +2552,11 @@ 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());
+12 -12
View File
@@ -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 basic_lock, Label& slow_case) {
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, 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, basic_lock, tmp2);
assert_different_registers(hdr, obj, disp_hdr, 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(basic_lock, BasicObjectLock::obj_offset()));
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
null_check_offset = offset();
@@ -197,26 +197,26 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register basic_lo
b(slow_case, ne);
}
Register t1 = basic_lock; // Needs saving, probably
Register t2 = hdr; // blow
Register t3 = Rtemp; // blow
Register t1 = disp_hdr; // Needs saving, probably
Register t2 = hdr; // blow
Register t3 = Rtemp; // blow
lightweight_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 basic_lock, Label& slow_case) {
assert_different_registers(hdr, obj, basic_lock, Rtemp);
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
assert_different_registers(hdr, obj, disp_hdr, Rtemp);
assert(BasicObjectLock::lock_offset() == 0, "adjust this code");
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
ldr(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
Register t1 = basic_lock; // Needs saving, probably
Register t2 = hdr; // blow
Register t3 = Rtemp; // blow
Register t1 = disp_hdr; // Needs saving, probably
Register t2 = hdr; // blow
Register t3 = Rtemp; // blow
lightweight_unlock(obj, t1, t2, t3, 1 /* savemask - save t1 */, slow_case);
// Success: fall through
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,9 +59,9 @@
max_array_allocation_length = 0x01000000
};
int lock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case);
int lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case);
void unlock_object(Register hdr, Register obj, Register basic_lock, Label& slow_case);
void unlock_object(Register hdr, Register obj, Register disp_hdr, 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,18 +198,15 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
__ bind(done);
}
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);
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?
__ eor(tmp1, store_addr, new_val);
__ movs(tmp1, AsmOperand(tmp1, lsr, G1HeapRegion::LogOfHRGrainBytes));
__ b(done, eq);
@@ -218,34 +215,76 @@ static void generate_post_barrier(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;
// 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()));
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()));
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
__ ldrb(tmp2, Address(card_addr));
__ cmp(tmp2, (int)G1CardTable::g1_young_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;
generate_post_barrier(masm, store_addr, new_val, Rthread, tmp1, tmp2, done, true /* new_val_may_be_null */);
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);
__ bind(done);
}
@@ -305,10 +344,35 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
Register tmp1,
Register tmp2,
Register tmp3,
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);
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());
}
#endif // COMPILER2
@@ -399,19 +463,20 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
__ 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);
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 __
#define __ sasm->
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
@@ -471,6 +536,102 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,9 @@
class LIR_Assembler;
class StubAssembler;
class G1PreBarrierStub;
class G1PostBarrierStub;
class G1PreBarrierStubC2;
class G1PostBarrierStubC2;
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
protected:
@@ -64,15 +66,10 @@ 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 g1_write_barrier_post_c1(MacroAssembler* masm,
Register store_addr,
Register new_val,
Register thread,
Register tmp1,
Register tmp2);
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
#endif
#ifdef COMPILER2
@@ -92,7 +89,9 @@ public:
Register tmp1,
Register tmp2,
Register tmp3,
bool new_val_may_be_null);
G1PostBarrierStubC2* c2_stub);
void generate_c2_post_barrier_stub(MacroAssembler* masm,
G1PostBarrierStubC2* stub) const;
#endif
};
+4 -4
View File
@@ -1,5 +1,5 @@
//
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -63,13 +63,13 @@ static void write_barrier_post(MacroAssembler* masm,
Register tmp1,
Register tmp2,
Register tmp3) {
if (!G1BarrierStubC2::needs_post_barrier(node)) {
if (!G1PostBarrierStubC2::needs_barrier(node)) {
return;
}
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
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);
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, Rthread, tmp1, tmp2, tmp3, stub);
}
%}
@@ -48,22 +48,22 @@ class NativeNMethodBarrier: public NativeInstruction {
public:
int get_value() {
return AtomicAccess::load_acquire(guard_addr());
return Atomic::load_acquire(guard_addr());
}
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
AtomicAccess::release_store(guard_addr(), value);
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = AtomicAccess::load(guard_addr());
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
+11 -10
View File
@@ -617,11 +617,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
address c2i_unverified_entry = __ pc();
Label skip_fixup;
const Register receiver = R0;
const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure
@@ -634,9 +634,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ b(skip_fixup, eq);
__ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
entry_address[AdapterBlob::C2I] = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
address c2i_entry = __ pc();
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;
}
@@ -1128,7 +1129,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register sync_handle = R5;
const Register sync_obj = R6;
const Register basic_lock = altFP_7_11;
const Register disp_hdr = altFP_7_11;
const Register tmp = R8;
Label slow_lock, lock_done, fast_lock;
@@ -1139,7 +1140,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ mov(sync_handle, R1);
log_trace(fastlock)("SharedRuntime lock fast");
__ lightweight_lock(sync_obj /* object */, basic_lock /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
__ lightweight_lock(sync_obj /* object */, disp_hdr /* t1 */, tmp /* t2 */, Rtemp /* t3 */,
0x7 /* savemask */, slow_lock);
// Fall through to lock_done
__ bind(lock_done);
@@ -1254,7 +1255,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, basic_lock);
__ mov(R1, disp_hdr);
__ mov(R2, Rthread);
__ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C));
@@ -1269,12 +1270,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, basic_lock);
assert_different_registers(Rtmp_save1, sync_obj, disp_hdr);
__ 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, basic_lock);
__ mov(R1, disp_hdr);
__ mov(R2, Rthread);
__ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C));
__ str(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
+5 -11
View File
@@ -421,8 +421,7 @@ class StubGenerator: public StubCodeGenerator {
}
// As per atomicAccess.hpp the atomic read-modify-write operations must be
// logically implemented as:
// As per atomic.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:
@@ -441,7 +440,7 @@ class StubGenerator: public StubCodeGenerator {
// be removed in the future.
// Implementation of atomic_add(jint add_value, volatile jint* dest)
// used by AtomicAccess::add(volatile jint* dest, jint add_value)
// used by Atomic::add(volatile jint* dest, jint add_value)
//
// Arguments :
//
@@ -493,7 +492,7 @@ class StubGenerator: public StubCodeGenerator {
}
// Implementation of jint atomic_xchg(jint exchange_value, volatile jint* dest)
// used by AtomicAccess::add(volatile jint* dest, jint exchange_value)
// used by Atomic::add(volatile jint* dest, jint exchange_value)
//
// Arguments :
//
@@ -543,7 +542,7 @@ class StubGenerator: public StubCodeGenerator {
}
// Implementation of jint atomic_cmpxchg(jint exchange_value, volatile jint *dest, jint compare_value)
// used by AtomicAccess::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
// used by Atomic::cmpxchg(volatile jint *dest, jint compare_value, jint exchange_value)
//
// Arguments :
//
@@ -583,7 +582,7 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Support for jlong AtomicAccess::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
// Support for jlong Atomic::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 :
@@ -3011,10 +3010,6 @@ 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);
@@ -3028,7 +3023,6 @@ 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);
+1 -1
View File
@@ -26,7 +26,7 @@
#ifndef CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
#define CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
#include "runtime/vm_version.hpp"
+3 -4
View File
@@ -268,10 +268,9 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
// lock_reg was destroyed by fast unlocking attempt => recompute it
ce->monitor_address(_monitor_ix, _lock_reg);
if (_compute_lock) {
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));
+8 -1
View File
@@ -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, 0);
stub = new MonitorExitStub(FrameMap::R4_opr, true, 0);
__ unlock_object(R5, R6, R4, *stub->entry());
__ bind(*stub->continuation());
}
@@ -2614,6 +2614,7 @@ 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) {
@@ -2625,6 +2626,7 @@ 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());
@@ -2745,6 +2747,11 @@ 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,6 +28,7 @@
#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"
@@ -229,52 +230,78 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, Decorator
__ bind(filtered);
}
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 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)
}
__ 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 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
}
// 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);
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?
}
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators,
Register store_addr, Register new_val,
Register tmp1, Register tmp2) {
Register tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level) {
bool not_null = (decorators & IS_NOT_NULL) != 0;
Label done;
generate_post_barrier(masm, store_addr, new_val, R16_thread, tmp1, tmp2, done, !not_null);
__ bind(done);
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);
}
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
@@ -306,7 +333,8 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco
}
g1_write_barrier_post(masm, decorators,
base, val,
tmp1, tmp2);
tmp1, tmp2, tmp3,
preservation_level);
}
}
@@ -429,29 +457,70 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
Register new_val,
Register tmp1,
Register tmp2,
bool new_val_may_be_null,
G1PostBarrierStubC2* stub,
bool decode_new_val) {
assert_different_registers(store_addr, new_val, tmp1, R0);
assert_different_registers(store_addr, tmp1, tmp2, R0);
Label done;
stub->initialize_registers(R16_thread, tmp1, tmp2);
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 (new_val_may_be_null && CompressedOops::base() != nullptr) {
if (null_check_required && 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, done);
new_val_may_be_null = false;
__ beq(CR0, *stub->continuation());
null_check_required = false;
}
new_val_decoded = __ decode_heap_oop_not_null(tmp2, new_val);
}
generate_post_barrier(masm, store_addr, new_val_decoded, R16_thread, tmp1, tmp2, done, new_val_may_be_null);
__ bind(done);
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());
}
#endif // COMPILER2
@@ -489,19 +558,28 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
__ b(*stub->continuation());
}
#undef __
void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
__ bind(*stub->entry());
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);
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());
}
#undef __
#define __ sasm->
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
@@ -564,6 +642,86 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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,7 +37,9 @@
class LIR_Assembler;
class StubAssembler;
class G1PreBarrierStub;
class G1PostBarrierStub;
class G1PreBarrierStubC2;
class G1PostBarrierStubC2;
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
protected:
@@ -54,7 +56,8 @@ 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 tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level);
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
@@ -76,21 +79,17 @@ public:
Register new_val,
Register tmp1,
Register tmp2,
bool new_val_may_be_null,
G1PostBarrierStubC2* c2_stub,
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 g1_write_barrier_post_c1(MacroAssembler* masm,
Register store_addr,
Register new_val,
Register thread,
Register tmp1,
Register tmp2);
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
#endif
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+4 -4
View File
@@ -1,5 +1,5 @@
//
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 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 (!G1BarrierStubC2::needs_post_barrier(node)) {
if (!G1PostBarrierStubC2::needs_barrier(node)) {
return;
}
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
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);
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, tmp1, tmp2, stub, 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 = AtomicAccess::load(instr);
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
while (true) {
// Only bits in the mask are changed
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
@@ -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 = AtomicAccess::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_relaxed);
uint64_t v = Atomic::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_relaxed);
if (v == old_mov_instr.u64) break;
old_mov_instr.u64 = v;
}
@@ -114,6 +114,7 @@ public:
}
};
void ZBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register dst,
Register tmp1, Register tmp2,
@@ -560,6 +561,7 @@ 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) {
@@ -581,6 +583,7 @@ 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) {");
+1 -1
View File
@@ -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.
//AtomicAccess::release_store(jump_addr, *((juint*)code_buffer));
//Atomic::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);
}
+13 -6
View File
@@ -1199,11 +1199,16 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
address entry_address[AdapterBlob::ENTRY_COUNT]) {
AdapterHandlerEntry* handler) {
address i2c_entry;
address c2i_unverified_entry;
address c2i_entry;
// entry: i2c
__ align(CodeEntryAlignment);
entry_address[AdapterBlob::I2C] = __ pc();
i2c_entry = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
@@ -1211,7 +1216,7 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ align(CodeEntryAlignment);
BLOCK_COMMENT("c2i unverified entry");
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
c2i_unverified_entry = __ pc();
// inline_cache contains a CompiledICData
const Register ic = R19_inline_cache_reg;
@@ -1239,10 +1244,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
// entry: c2i
entry_address[AdapterBlob::C2I] = __ pc();
c2i_entry = __ pc();
// Class initialization barrier for static methods
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
address c2i_no_clinit_check_entry = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@@ -1261,13 +1266,15 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ bctr();
__ bind(L_skip_barrier);
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
c2i_no_clinit_check_entry = __ 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;
}
+2 -6
View File
@@ -3277,12 +3277,8 @@ 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: chaining of stubs does not rely on branching to an
// auxiliary post-push entry because none of the stubs
// push/pop a frame.
// Note: the disjoint stubs must be generated first, some of
// the conjoint stubs use them.
// non-aligned disjoint versions
StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(StubId::stubgen_jbyte_disjoint_arraycopy_id);
-26
View File
@@ -912,32 +912,6 @@ 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.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
+4 -4
View File
@@ -204,10 +204,10 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
// lock_reg was destroyed by fast unlocking attempt => recompute it
ce->monitor_address(_monitor_ix, _lock_reg);
if (_compute_lock) {
// 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, 0);
stub = new MonitorExitStub(FrameMap::r10_opr, true, 0);
__ unlock_object(x15, x14, x10, x16, *stub->entry());
__ bind(*stub->continuation());
}
@@ -1494,12 +1494,14 @@ 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();
@@ -1588,6 +1590,8 @@ 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 basic_lock, Register temp, Label& slow_case) {
assert_different_registers(hdr, obj, basic_lock, temp, t0, t1);
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 null_check_offset = -1;
verify_oop(obj);
// save object being locked into the BasicObjectLock
sd(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
sd(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
null_check_offset = offset();
lightweight_lock(basic_lock, obj, hdr, temp, t1, slow_case);
lightweight_lock(disp_hdr, obj, hdr, temp, t1, slow_case);
return null_check_offset;
}
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);
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);
// load object
ld(obj, Address(basic_lock, BasicObjectLock::obj_offset()));
ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj);
lightweight_unlock(obj, hdr, temp, t1, slow_case);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -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
// basic_lock: must point to the basic_lock, 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
// disp_hdr: must point to the displaced header location, 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 basic_lock, Register temp, Label& slow_case);
int lock_object(Register swap, Register obj, Register disp_hdr, Register temp, Label& slow_case);
// unlocking
// 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);
// 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);
void initialize_object(
Register obj, // result: pointer to object after successful allocation
@@ -87,54 +87,15 @@ 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) {
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);
assert_different_registers(start, count, tmp);
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);
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);
}
static void generate_queue_test_and_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime,
@@ -228,40 +189,47 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
}
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);
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?
__ 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 clean?
// Storing region crossing non-null, is card young?
__ srli(tmp1, store_addr, CardTable::card_shift()); // tmp1 := card address relative to card table base
Address card_table_address(xthread, G1ThreadLocalData::card_table_base_offset());
__ ld(tmp2, card_table_address); // tmp2 := card table base address
__ load_byte_map_base(tmp2); // 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));
__ 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);
}
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
@@ -270,8 +238,27 @@ 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;
generate_post_barrier(masm, store_addr, new_val, thread, tmp1, tmp2, done, true /* new_val_may_be_null */);
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);
__ bind(done);
}
@@ -331,10 +318,37 @@ void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
Register thread,
Register tmp1,
Register tmp2,
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);
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());
}
#endif // COMPILER2
@@ -429,19 +443,20 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier
__ 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);
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 __
#define __ sasm->
void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
@@ -492,6 +507,74 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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,7 +35,9 @@ class LIR_Assembler;
#endif
class StubAssembler;
class G1PreBarrierStub;
class G1PostBarrierStub;
class G1PreBarrierStubC2;
class G1PostBarrierStubC2;
class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
protected:
@@ -66,16 +68,10 @@ 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 g1_write_barrier_post_c1(MacroAssembler* masm,
Register store_addr,
Register new_val,
Register thread,
Register tmp1,
Register tmp2);
void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
#endif
#ifdef COMPILER2
@@ -94,7 +90,9 @@ public:
Register thread,
Register tmp1,
Register tmp2,
bool new_val_may_be_null);
G1PostBarrierStubC2* c2_stub);
void generate_c2_post_barrier_stub(MacroAssembler* masm,
G1PostBarrierStubC2* stub) const;
#endif
void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+4 -4
View File
@@ -1,5 +1,5 @@
//
// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2024, 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 (!G1BarrierStubC2::needs_post_barrier(node)) {
if (!G1PostBarrierStubC2::needs_barrier(node)) {
return;
}
Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
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);
G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, stub);
}
%}
@@ -217,7 +217,7 @@ address BarrierSetAssembler::patching_epoch_addr() {
}
void BarrierSetAssembler::increment_patching_epoch() {
AtomicAccess::inc(&_patching_epoch);
Atomic::inc(&_patching_epoch);
}
void BarrierSetAssembler::clear_patching_epoch() {
@@ -106,22 +106,22 @@ public:
}
int get_value() {
return AtomicAccess::load_acquire(guard_addr());
return Atomic::load_acquire(guard_addr());
}
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
AtomicAccess::release_store(guard_addr(), value);
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = AtomicAccess::load(guard_addr());
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = AtomicAccess::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
+13 -11
View File
@@ -3402,8 +3402,6 @@ 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) {
@@ -3414,13 +3412,18 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register
return;
}
Register xbase = tmp;
Register xbase = dst;
if (dst == src) {
xbase = tmp;
}
assert_different_registers(src, xbase);
mv(xbase, (uintptr_t)CompressedKlassPointers::base());
if (CompressedKlassPointers::shift() != 0) {
// dst = (src << shift) + xbase
shadd(dst, src, xbase, dst /* temporary, dst != xbase */, CompressedKlassPointers::shift());
Register t = src == dst ? dst : t0;
assert_different_registers(t, xbase);
shadd(dst, src, xbase, t, CompressedKlassPointers::shift());
} else {
add(dst, xbase, src);
}
@@ -5871,14 +5874,13 @@ 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 >= zicboz_block_size.
// you want to use it elsewhere, note that cnt must be >= CacheLineSize.
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, zicboz_block_size - 1);
andi(tmp1, tmp1, CacheLineSize - 1);
// tmp1: the number of bytes to be filled to align the base with cache line size.
add(base, base, tmp1);
@@ -5888,16 +5890,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 = -zicboz_block_size + wordSize; i < 0; i += wordSize) {
for (int i = -CacheLineSize + wordSize; i < 0; i += wordSize) {
sd(zr, Address(base, i));
}
bind(initial_table_end);
mv(tmp1, zicboz_block_size / wordSize);
mv(tmp1, CacheLineSize / wordSize);
bind(loop);
cbo_zero(base);
sub(cnt, cnt, tmp1);
addi(base, base, zicboz_block_size);
addi(base, base, CacheLineSize);
bge(cnt, tmp1, loop);
}
+18 -57
View File
@@ -28,13 +28,11 @@
#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"
@@ -54,15 +52,15 @@ address NativeCall::destination() const {
address addr = instruction_address();
assert(NativeCall::is_at(addr), "unexpected code at call site");
address stub_addr = MacroAssembler::target_addr_for_insn(addr);
address destination = 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->stub_contains(stub_addr), "Sanity");
assert(stub_addr != nullptr, "Sanity");
return stub_address_destination_at(stub_addr);
assert(nm != nullptr, "Sanity");
assert(nm->stub_contains(destination), "Sanity");
assert(destination != nullptr, "Sanity");
return stub_address_destination_at(destination);
}
address NativeCall::reloc_destination() {
@@ -91,30 +89,6 @@ 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()) ||
@@ -122,17 +96,15 @@ bool NativeCall::set_destination_mt_safe(address dest) {
"concurrent code patching");
address stub_addr = stub_address();
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);
if (stub_addr != nullptr) {
set_stub_address_destination_at(stub_addr, dest);
return true;
}
return true;
return false;
}
// The argument passed in is the address to the stub containing the destination
bool NativeCall::reloc_set_destination(address stub_addr) {
bool NativeCall::reloc_set_destination(address dest) {
address call_addr = instruction_address();
assert(NativeCall::is_at(call_addr), "unexpected code at call site");
@@ -141,12 +113,10 @@ bool NativeCall::reloc_set_destination(address stub_addr) {
if (code->is_nmethod()) {
// TODO: Need to revisit this when porting the AOT features.
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
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);
}
return true;
@@ -172,9 +142,9 @@ address NativeCall::stub_address() {
CodeBlob *code = CodeCache::find_blob(call_addr);
assert(code != nullptr, "Could not find the containing code blob");
address stub_addr = MacroAssembler::target_addr_for_insn(call_addr);
assert(code->contains(stub_addr), "Sanity");
return stub_addr;
address dest = MacroAssembler::target_addr_for_insn(call_addr);
assert(code->contains(dest), "Sanity");
return dest;
}
bool NativeCall::is_at(address addr) {
@@ -190,15 +160,6 @@ 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,10 +156,6 @@ 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